zucchini_commands.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/zucchini/zucchini_commands.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <ostream>
  8. #include <string>
  9. #include <utility>
  10. #include "base/command_line.h"
  11. #include "base/files/file.h"
  12. #include "base/files/file_path.h"
  13. #include "base/files/memory_mapped_file.h"
  14. #include "base/logging.h"
  15. #include "components/zucchini/buffer_view.h"
  16. #include "components/zucchini/crc32.h"
  17. #include "components/zucchini/io_utils.h"
  18. #include "components/zucchini/mapped_file.h"
  19. #include "components/zucchini/patch_writer.h"
  20. #include "components/zucchini/zucchini_integration.h"
  21. #include "components/zucchini/zucchini_tools.h"
  22. namespace {
  23. /******** Command-line Switches ********/
  24. constexpr char kSwitchDump[] = "dump";
  25. constexpr char kSwitchImpose[] = "impose";
  26. constexpr char kSwitchKeep[] = "keep";
  27. constexpr char kSwitchRaw[] = "raw";
  28. } // namespace
  29. zucchini::status::Code MainGen(MainParams params) {
  30. CHECK_EQ(3U, params.file_paths.size());
  31. return zucchini::Generate(
  32. params.file_paths[0], params.file_paths[1], params.file_paths[2],
  33. params.command_line.HasSwitch(kSwitchKeep),
  34. params.command_line.HasSwitch(kSwitchRaw),
  35. params.command_line.GetSwitchValueASCII(kSwitchImpose));
  36. }
  37. zucchini::status::Code MainApply(MainParams params) {
  38. CHECK_EQ(3U, params.file_paths.size());
  39. return zucchini::Apply(params.file_paths[0], params.file_paths[1],
  40. params.file_paths[2],
  41. params.command_line.HasSwitch(kSwitchKeep));
  42. }
  43. zucchini::status::Code MainVerify(MainParams params) {
  44. CHECK_EQ(1U, params.file_paths.size());
  45. return zucchini::VerifyPatch(params.file_paths[0]);
  46. }
  47. zucchini::status::Code MainRead(MainParams params) {
  48. CHECK_EQ(1U, params.file_paths.size());
  49. base::File input_file(params.file_paths[0],
  50. base::File::FLAG_OPEN | base::File::FLAG_READ |
  51. base::File::FLAG_WIN_SHARE_DELETE);
  52. zucchini::MappedFileReader input(std::move(input_file));
  53. if (input.HasError()) {
  54. LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
  55. << input.error();
  56. return zucchini::status::kStatusFileReadError;
  57. }
  58. bool do_dump = params.command_line.HasSwitch(kSwitchDump);
  59. zucchini::status::Code status = zucchini::ReadReferences(
  60. {input.data(), input.length()}, do_dump, params.out);
  61. if (status != zucchini::status::kStatusSuccess)
  62. params.err << "Fatal error found when dumping references." << std::endl;
  63. return status;
  64. }
  65. zucchini::status::Code MainDetect(MainParams params) {
  66. CHECK_EQ(1U, params.file_paths.size());
  67. base::File input_file(params.file_paths[0],
  68. base::File::FLAG_OPEN | base::File::FLAG_READ |
  69. base::File::FLAG_WIN_SHARE_DELETE);
  70. zucchini::MappedFileReader input(std::move(input_file));
  71. if (input.HasError()) {
  72. LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
  73. << input.error();
  74. return zucchini::status::kStatusFileReadError;
  75. }
  76. std::vector<zucchini::ConstBufferView> sub_image_list;
  77. zucchini::status::Code result = zucchini::DetectAll(
  78. {input.data(), input.length()}, params.out, &sub_image_list);
  79. if (result != zucchini::status::kStatusSuccess)
  80. params.err << "Fatal error found when detecting executables." << std::endl;
  81. return result;
  82. }
  83. zucchini::status::Code MainMatch(MainParams params) {
  84. CHECK_EQ(2U, params.file_paths.size());
  85. using base::File;
  86. File old_file(params.file_paths[0], File::FLAG_OPEN | File::FLAG_READ |
  87. base::File::FLAG_WIN_SHARE_DELETE);
  88. zucchini::MappedFileReader old_image(std::move(old_file));
  89. if (old_image.HasError()) {
  90. LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
  91. << old_image.error();
  92. return zucchini::status::kStatusFileReadError;
  93. }
  94. File new_file(params.file_paths[1], File::FLAG_OPEN | File::FLAG_READ |
  95. base::File::FLAG_WIN_SHARE_DELETE);
  96. zucchini::MappedFileReader new_image(std::move(new_file));
  97. if (new_image.HasError()) {
  98. LOG(ERROR) << "Error with file " << params.file_paths[1].value() << ": "
  99. << new_image.error();
  100. return zucchini::status::kStatusFileReadError;
  101. }
  102. std::string imposed_matches =
  103. params.command_line.GetSwitchValueASCII(kSwitchImpose);
  104. zucchini::status::Code status =
  105. zucchini::MatchAll({old_image.data(), old_image.length()},
  106. {new_image.data(), new_image.length()},
  107. std::move(imposed_matches), params.out);
  108. if (status != zucchini::status::kStatusSuccess)
  109. params.err << "Fatal error found when matching executables." << std::endl;
  110. return status;
  111. }
  112. zucchini::status::Code MainCrc32(MainParams params) {
  113. CHECK_EQ(1U, params.file_paths.size());
  114. base::File image_file(params.file_paths[0],
  115. base::File::FLAG_OPEN | base::File::FLAG_READ |
  116. base::File::FLAG_WIN_SHARE_DELETE);
  117. zucchini::MappedFileReader image(std::move(image_file));
  118. if (image.HasError()) {
  119. LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
  120. << image.error();
  121. return zucchini::status::kStatusFileReadError;
  122. }
  123. uint32_t crc =
  124. zucchini::CalculateCrc32(image.data(), image.data() + image.length());
  125. params.out << "CRC32: " << zucchini::AsHex<8>(crc) << std::endl;
  126. return zucchini::status::kStatusSuccess;
  127. }