From cd66c1f47fbfc53d60d37d883c9c709c93e54a36 Mon Sep 17 00:00:00 2001 From: Klaus Aehlig Date: Mon, 27 Nov 2023 16:17:08 +0100 Subject: hash_function: support hashing of files Extend our internal hash-function abstraction to support hashing of files. In this way, we can provide a way to compute the hash of a potentially large file without having to fully read it to memory first, while still keeping the details of the used hash function abstracted away. --- src/buildtool/crypto/hash_function.cpp | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/buildtool/crypto/hash_function.cpp (limited to 'src/buildtool/crypto/hash_function.cpp') diff --git a/src/buildtool/crypto/hash_function.cpp b/src/buildtool/crypto/hash_function.cpp new file mode 100644 index 00000000..89bb0cb8 --- /dev/null +++ b/src/buildtool/crypto/hash_function.cpp @@ -0,0 +1,56 @@ +// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/buildtool/crypto/hash_function.hpp" + +#include +#include + +#include "src/buildtool/logging/log_level.hpp" +#include "src/buildtool/logging/logger.hpp" + +[[nodiscard]] auto HashFunction::ComputeHashFile( + const std::filesystem::path& file_path, + bool as_tree) noexcept + -> std::optional> { + static constexpr std::size_t kChunkSize{4048}; + try { + auto hasher = Hasher(); + auto size = std::filesystem::file_size(file_path); + if (HashType() == JustHash::Native) { + hasher.Update( + (as_tree ? std::string{"tree "} : std::string{"blob "}) + + std::to_string(size) + '\0'); + } + std::string chunk{}; + chunk.resize(kChunkSize); + std::ifstream file_reader(file_path.string(), std::ios::binary); + if (file_reader.is_open()) { + auto chunk_size = gsl::narrow(chunk.size()); + do { + file_reader.read(chunk.data(), chunk_size); + auto count = file_reader.gcount(); + hasher.Update(chunk.substr(0, gsl::narrow(count))); + } while (file_reader.good()); + file_reader.close(); + return std::make_pair(std::move(hasher).Finalize(), size); + } + } catch (std::exception const& e) { + Logger::Log(LogLevel::Debug, + "Error while trying to hash {}: {}", + file_path.string(), + e.what()); + } + return std::nullopt; +} -- cgit v1.2.3