17a9e7621SOleksiy Vyalov //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===//
27a9e7621SOleksiy Vyalov //
37a9e7621SOleksiy Vyalov //                     The LLVM Compiler Infrastructure
47a9e7621SOleksiy Vyalov //
57a9e7621SOleksiy Vyalov // This file is distributed under the University of Illinois Open Source
67a9e7621SOleksiy Vyalov // License. See LICENSE.TXT for details.
77a9e7621SOleksiy Vyalov //
87a9e7621SOleksiy Vyalov //===----------------------------------------------------------------------===//
97a9e7621SOleksiy Vyalov 
107a9e7621SOleksiy Vyalov #include "lldb/Host/FileSystem.h"
117a9e7621SOleksiy Vyalov 
127a9e7621SOleksiy Vyalov #include "llvm/Support/MD5.h"
137a9e7621SOleksiy Vyalov 
146801be33SOleksiy Vyalov #include <algorithm>
157a9e7621SOleksiy Vyalov #include <fstream>
167a9e7621SOleksiy Vyalov #include <vector>
177a9e7621SOleksiy Vyalov 
187a9e7621SOleksiy Vyalov using namespace lldb;
197a9e7621SOleksiy Vyalov using namespace lldb_private;
207a9e7621SOleksiy Vyalov 
217a9e7621SOleksiy Vyalov namespace {
227a9e7621SOleksiy Vyalov 
23*b9c1b51eSKate Stone bool CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length,
24*b9c1b51eSKate Stone              llvm::MD5::MD5Result &md5_result) {
257a9e7621SOleksiy Vyalov   llvm::MD5 md5_hash;
267a9e7621SOleksiy Vyalov   std::ifstream file(file_spec.GetPath(), std::ios::binary);
277a9e7621SOleksiy Vyalov   if (!file.is_open())
287a9e7621SOleksiy Vyalov     return false;
297a9e7621SOleksiy Vyalov 
306801be33SOleksiy Vyalov   if (offset > 0)
316801be33SOleksiy Vyalov     file.seekg(offset, file.beg);
326801be33SOleksiy Vyalov 
337a9e7621SOleksiy Vyalov   std::vector<char> read_buf(4096);
346801be33SOleksiy Vyalov   uint64_t total_read_bytes = 0;
35*b9c1b51eSKate Stone   while (!file.eof()) {
36*b9c1b51eSKate Stone     const uint64_t to_read =
37*b9c1b51eSKate Stone         (length > 0) ? std::min(static_cast<uint64_t>(read_buf.size()),
38*b9c1b51eSKate Stone                                 length - total_read_bytes)
39*b9c1b51eSKate Stone                      : read_buf.size();
406801be33SOleksiy Vyalov     if (to_read == 0)
416801be33SOleksiy Vyalov       break;
426801be33SOleksiy Vyalov 
436801be33SOleksiy Vyalov     file.read(&read_buf[0], to_read);
447a9e7621SOleksiy Vyalov     const auto read_bytes = file.gcount();
457a9e7621SOleksiy Vyalov     if (read_bytes == 0)
467a9e7621SOleksiy Vyalov       break;
477a9e7621SOleksiy Vyalov 
487a9e7621SOleksiy Vyalov     md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes));
496801be33SOleksiy Vyalov     total_read_bytes += read_bytes;
507a9e7621SOleksiy Vyalov   }
517a9e7621SOleksiy Vyalov 
527a9e7621SOleksiy Vyalov   md5_hash.final(md5_result);
537a9e7621SOleksiy Vyalov   return true;
547a9e7621SOleksiy Vyalov }
557a9e7621SOleksiy Vyalov 
567a9e7621SOleksiy Vyalov } // namespace
577a9e7621SOleksiy Vyalov 
58*b9c1b51eSKate Stone bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low,
59*b9c1b51eSKate Stone                               uint64_t &high) {
606801be33SOleksiy Vyalov   return CalculateMD5(file_spec, 0, 0, low, high);
616801be33SOleksiy Vyalov }
626801be33SOleksiy Vyalov 
63*b9c1b51eSKate Stone bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t offset,
64*b9c1b51eSKate Stone                               uint64_t length, uint64_t &low, uint64_t &high) {
657a9e7621SOleksiy Vyalov   llvm::MD5::MD5Result md5_result;
666801be33SOleksiy Vyalov   if (!CalcMD5(file_spec, offset, length, md5_result))
677a9e7621SOleksiy Vyalov     return false;
687a9e7621SOleksiy Vyalov 
697a9e7621SOleksiy Vyalov   const auto uint64_res = reinterpret_cast<const uint64_t *>(md5_result);
707a9e7621SOleksiy Vyalov   high = uint64_res[0];
717a9e7621SOleksiy Vyalov   low = uint64_res[1];
727a9e7621SOleksiy Vyalov 
737a9e7621SOleksiy Vyalov   return true;
747a9e7621SOleksiy Vyalov }
757a9e7621SOleksiy Vyalov 
76*b9c1b51eSKate Stone bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec,
77*b9c1b51eSKate Stone                                       std::string &digest_str) {
786801be33SOleksiy Vyalov   return CalculateMD5AsString(file_spec, 0, 0, digest_str);
796801be33SOleksiy Vyalov }
806801be33SOleksiy Vyalov 
81*b9c1b51eSKate Stone bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec,
82*b9c1b51eSKate Stone                                       uint64_t offset, uint64_t length,
83*b9c1b51eSKate Stone                                       std::string &digest_str) {
847a9e7621SOleksiy Vyalov   llvm::MD5::MD5Result md5_result;
856801be33SOleksiy Vyalov   if (!CalcMD5(file_spec, offset, length, md5_result))
867a9e7621SOleksiy Vyalov     return false;
877a9e7621SOleksiy Vyalov 
887a9e7621SOleksiy Vyalov   llvm::SmallString<32> result_str;
897a9e7621SOleksiy Vyalov   llvm::MD5::stringifyResult(md5_result, result_str);
907a9e7621SOleksiy Vyalov   digest_str = result_str.c_str();
917a9e7621SOleksiy Vyalov   return true;
927a9e7621SOleksiy Vyalov }
93