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 
14*6801be33SOleksiy 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 
237a9e7621SOleksiy Vyalov bool
24*6801be33SOleksiy Vyalov CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length, llvm::MD5::MD5Result &md5_result)
257a9e7621SOleksiy Vyalov {
267a9e7621SOleksiy Vyalov     llvm::MD5 md5_hash;
277a9e7621SOleksiy Vyalov     std::ifstream file(file_spec.GetPath(), std::ios::binary);
287a9e7621SOleksiy Vyalov     if (!file.is_open())
297a9e7621SOleksiy Vyalov         return false;
307a9e7621SOleksiy Vyalov 
31*6801be33SOleksiy Vyalov     if (offset > 0)
32*6801be33SOleksiy Vyalov         file.seekg(offset, file.beg);
33*6801be33SOleksiy Vyalov 
347a9e7621SOleksiy Vyalov     std::vector<char> read_buf(4096);
35*6801be33SOleksiy Vyalov     uint64_t total_read_bytes = 0;
367a9e7621SOleksiy Vyalov     while (!file.eof())
377a9e7621SOleksiy Vyalov     {
38*6801be33SOleksiy Vyalov         const uint64_t to_read = (length > 0) ?
39*6801be33SOleksiy Vyalov             std::min(static_cast<uint64_t>(read_buf.size()), length - total_read_bytes) :
40*6801be33SOleksiy Vyalov             read_buf.size();
41*6801be33SOleksiy Vyalov         if (to_read == 0)
42*6801be33SOleksiy Vyalov             break;
43*6801be33SOleksiy Vyalov 
44*6801be33SOleksiy Vyalov         file.read(&read_buf[0], to_read);
457a9e7621SOleksiy Vyalov         const auto read_bytes = file.gcount();
467a9e7621SOleksiy Vyalov         if (read_bytes == 0)
477a9e7621SOleksiy Vyalov             break;
487a9e7621SOleksiy Vyalov 
497a9e7621SOleksiy Vyalov         md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes));
50*6801be33SOleksiy Vyalov         total_read_bytes += read_bytes;
517a9e7621SOleksiy Vyalov     }
527a9e7621SOleksiy Vyalov 
537a9e7621SOleksiy Vyalov     md5_hash.final(md5_result);
547a9e7621SOleksiy Vyalov     return true;
557a9e7621SOleksiy Vyalov }
567a9e7621SOleksiy Vyalov 
577a9e7621SOleksiy Vyalov }  // namespace
587a9e7621SOleksiy Vyalov 
597a9e7621SOleksiy Vyalov bool
607a9e7621SOleksiy Vyalov FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high)
617a9e7621SOleksiy Vyalov {
62*6801be33SOleksiy Vyalov     return CalculateMD5(file_spec, 0, 0, low, high);
63*6801be33SOleksiy Vyalov }
64*6801be33SOleksiy Vyalov 
65*6801be33SOleksiy Vyalov bool
66*6801be33SOleksiy Vyalov FileSystem::CalculateMD5(const FileSpec &file_spec,
67*6801be33SOleksiy Vyalov                          uint64_t offset,
68*6801be33SOleksiy Vyalov                          uint64_t length,
69*6801be33SOleksiy Vyalov                          uint64_t &low,
70*6801be33SOleksiy Vyalov                          uint64_t &high)
71*6801be33SOleksiy Vyalov {
727a9e7621SOleksiy Vyalov     llvm::MD5::MD5Result md5_result;
73*6801be33SOleksiy Vyalov     if (!CalcMD5(file_spec, offset, length, md5_result))
747a9e7621SOleksiy Vyalov         return false;
757a9e7621SOleksiy Vyalov 
767a9e7621SOleksiy Vyalov     const auto uint64_res = reinterpret_cast<const uint64_t*>(md5_result);
777a9e7621SOleksiy Vyalov     high = uint64_res[0];
787a9e7621SOleksiy Vyalov     low = uint64_res[1];
797a9e7621SOleksiy Vyalov 
807a9e7621SOleksiy Vyalov     return true;
817a9e7621SOleksiy Vyalov }
827a9e7621SOleksiy Vyalov 
837a9e7621SOleksiy Vyalov bool
847a9e7621SOleksiy Vyalov FileSystem::CalculateMD5AsString(const FileSpec &file_spec, std::string& digest_str)
857a9e7621SOleksiy Vyalov {
86*6801be33SOleksiy Vyalov     return CalculateMD5AsString(file_spec, 0, 0, digest_str);
87*6801be33SOleksiy Vyalov }
88*6801be33SOleksiy Vyalov 
89*6801be33SOleksiy Vyalov bool
90*6801be33SOleksiy Vyalov FileSystem::CalculateMD5AsString(const FileSpec &file_spec,
91*6801be33SOleksiy Vyalov                                  uint64_t offset,
92*6801be33SOleksiy Vyalov                                  uint64_t length,
93*6801be33SOleksiy Vyalov                                  std::string& digest_str)
94*6801be33SOleksiy Vyalov {
957a9e7621SOleksiy Vyalov     llvm::MD5::MD5Result md5_result;
96*6801be33SOleksiy Vyalov     if (!CalcMD5(file_spec, offset, length, md5_result))
977a9e7621SOleksiy Vyalov         return false;
987a9e7621SOleksiy Vyalov 
997a9e7621SOleksiy Vyalov     llvm::SmallString<32> result_str;
1007a9e7621SOleksiy Vyalov     llvm::MD5::stringifyResult(md5_result, result_str);
1017a9e7621SOleksiy Vyalov     digest_str = result_str.c_str();
1027a9e7621SOleksiy Vyalov     return true;
1037a9e7621SOleksiy Vyalov }
104