1 //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/FileSystem.h"
11
12 #include "llvm/Support/MD5.h"
13
14 #include <algorithm>
15 #include <fstream>
16 #include <vector>
17
18 using namespace lldb;
19 using namespace lldb_private;
20
21 namespace {
22
23 bool
CalcMD5(const FileSpec & file_spec,uint64_t offset,uint64_t length,llvm::MD5::MD5Result & md5_result)24 CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length, llvm::MD5::MD5Result &md5_result)
25 {
26 llvm::MD5 md5_hash;
27 std::ifstream file(file_spec.GetPath(), std::ios::binary);
28 if (!file.is_open())
29 return false;
30
31 if (offset > 0)
32 file.seekg(offset, file.beg);
33
34 std::vector<char> read_buf(4096);
35 uint64_t total_read_bytes = 0;
36 while (!file.eof())
37 {
38 const uint64_t to_read = (length > 0) ?
39 std::min(static_cast<uint64_t>(read_buf.size()), length - total_read_bytes) :
40 read_buf.size();
41 if (to_read == 0)
42 break;
43
44 file.read(&read_buf[0], to_read);
45 const auto read_bytes = file.gcount();
46 if (read_bytes == 0)
47 break;
48
49 md5_hash.update(llvm::StringRef(&read_buf[0], read_bytes));
50 total_read_bytes += read_bytes;
51 }
52
53 md5_hash.final(md5_result);
54 return true;
55 }
56
57 } // namespace
58
59 bool
CalculateMD5(const FileSpec & file_spec,uint64_t & low,uint64_t & high)60 FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high)
61 {
62 return CalculateMD5(file_spec, 0, 0, low, high);
63 }
64
65 bool
CalculateMD5(const FileSpec & file_spec,uint64_t offset,uint64_t length,uint64_t & low,uint64_t & high)66 FileSystem::CalculateMD5(const FileSpec &file_spec,
67 uint64_t offset,
68 uint64_t length,
69 uint64_t &low,
70 uint64_t &high)
71 {
72 llvm::MD5::MD5Result md5_result;
73 if (!CalcMD5(file_spec, offset, length, md5_result))
74 return false;
75
76 const auto uint64_res = reinterpret_cast<const uint64_t*>(md5_result);
77 high = uint64_res[0];
78 low = uint64_res[1];
79
80 return true;
81 }
82
83 bool
CalculateMD5AsString(const FileSpec & file_spec,std::string & digest_str)84 FileSystem::CalculateMD5AsString(const FileSpec &file_spec, std::string& digest_str)
85 {
86 return CalculateMD5AsString(file_spec, 0, 0, digest_str);
87 }
88
89 bool
CalculateMD5AsString(const FileSpec & file_spec,uint64_t offset,uint64_t length,std::string & digest_str)90 FileSystem::CalculateMD5AsString(const FileSpec &file_spec,
91 uint64_t offset,
92 uint64_t length,
93 std::string& digest_str)
94 {
95 llvm::MD5::MD5Result md5_result;
96 if (!CalcMD5(file_spec, offset, length, md5_result))
97 return false;
98
99 llvm::SmallString<32> result_str;
100 llvm::MD5::stringifyResult(md5_result, result_str);
101 digest_str = result_str.c_str();
102 return true;
103 }
104