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 
12*1408bf72SPavel Labath #include "llvm/Support/FileSystem.h"
137a9e7621SOleksiy Vyalov #include "llvm/Support/MD5.h"
147a9e7621SOleksiy Vyalov 
156801be33SOleksiy Vyalov #include <algorithm>
167a9e7621SOleksiy Vyalov #include <fstream>
177a9e7621SOleksiy Vyalov #include <vector>
187a9e7621SOleksiy Vyalov 
197a9e7621SOleksiy Vyalov using namespace lldb;
207a9e7621SOleksiy Vyalov using namespace lldb_private;
217a9e7621SOleksiy Vyalov 
227a9e7621SOleksiy Vyalov namespace {
237a9e7621SOleksiy Vyalov 
24b9c1b51eSKate Stone bool CalcMD5(const FileSpec &file_spec, uint64_t offset, uint64_t length,
25b9c1b51eSKate Stone              llvm::MD5::MD5Result &md5_result) {
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 
316801be33SOleksiy Vyalov   if (offset > 0)
326801be33SOleksiy Vyalov     file.seekg(offset, file.beg);
336801be33SOleksiy Vyalov 
347a9e7621SOleksiy Vyalov   std::vector<char> read_buf(4096);
356801be33SOleksiy Vyalov   uint64_t total_read_bytes = 0;
36b9c1b51eSKate Stone   while (!file.eof()) {
37b9c1b51eSKate Stone     const uint64_t to_read =
38b9c1b51eSKate Stone         (length > 0) ? std::min(static_cast<uint64_t>(read_buf.size()),
39b9c1b51eSKate Stone                                 length - total_read_bytes)
40b9c1b51eSKate Stone                      : read_buf.size();
416801be33SOleksiy Vyalov     if (to_read == 0)
426801be33SOleksiy Vyalov       break;
436801be33SOleksiy Vyalov 
446801be33SOleksiy 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));
506801be33SOleksiy 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 
59b9c1b51eSKate Stone bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low,
60b9c1b51eSKate Stone                               uint64_t &high) {
616801be33SOleksiy Vyalov   return CalculateMD5(file_spec, 0, 0, low, high);
626801be33SOleksiy Vyalov }
636801be33SOleksiy Vyalov 
64b9c1b51eSKate Stone bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t offset,
65b9c1b51eSKate Stone                               uint64_t length, uint64_t &low, uint64_t &high) {
667a9e7621SOleksiy Vyalov   llvm::MD5::MD5Result md5_result;
676801be33SOleksiy Vyalov   if (!CalcMD5(file_spec, offset, length, md5_result))
687a9e7621SOleksiy Vyalov     return false;
697a9e7621SOleksiy Vyalov 
707a9e7621SOleksiy Vyalov   const auto uint64_res = reinterpret_cast<const uint64_t *>(md5_result);
717a9e7621SOleksiy Vyalov   high = uint64_res[0];
727a9e7621SOleksiy Vyalov   low = uint64_res[1];
737a9e7621SOleksiy Vyalov 
747a9e7621SOleksiy Vyalov   return true;
757a9e7621SOleksiy Vyalov }
767a9e7621SOleksiy Vyalov 
77b9c1b51eSKate Stone bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec,
78b9c1b51eSKate Stone                                       std::string &digest_str) {
796801be33SOleksiy Vyalov   return CalculateMD5AsString(file_spec, 0, 0, digest_str);
806801be33SOleksiy Vyalov }
816801be33SOleksiy Vyalov 
82b9c1b51eSKate Stone bool FileSystem::CalculateMD5AsString(const FileSpec &file_spec,
83b9c1b51eSKate Stone                                       uint64_t offset, uint64_t length,
84b9c1b51eSKate Stone                                       std::string &digest_str) {
857a9e7621SOleksiy Vyalov   llvm::MD5::MD5Result md5_result;
866801be33SOleksiy Vyalov   if (!CalcMD5(file_spec, offset, length, md5_result))
877a9e7621SOleksiy Vyalov     return false;
887a9e7621SOleksiy Vyalov 
897a9e7621SOleksiy Vyalov   llvm::SmallString<32> result_str;
907a9e7621SOleksiy Vyalov   llvm::MD5::stringifyResult(md5_result, result_str);
917a9e7621SOleksiy Vyalov   digest_str = result_str.c_str();
927a9e7621SOleksiy Vyalov   return true;
937a9e7621SOleksiy Vyalov }
94*1408bf72SPavel Labath 
95*1408bf72SPavel Labath llvm::sys::TimePoint<>
96*1408bf72SPavel Labath FileSystem::GetModificationTime(const FileSpec &file_spec) {
97*1408bf72SPavel Labath   llvm::sys::fs::file_status status;
98*1408bf72SPavel Labath   std::error_code ec = llvm::sys::fs::status(file_spec.GetPath(), status);
99*1408bf72SPavel Labath   if (ec)
100*1408bf72SPavel Labath     return llvm::sys::TimePoint<>();
101*1408bf72SPavel Labath   return status.getLastModificationTime();
102*1408bf72SPavel Labath }
103