1c00cf4a0SZachary Turner //===-- FileCache.cpp -------------------------------------------*- C++ -*-===//
2c00cf4a0SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c00cf4a0SZachary Turner //
7c00cf4a0SZachary Turner //===----------------------------------------------------------------------===//
8c00cf4a0SZachary Turner 
9c00cf4a0SZachary Turner #include "lldb/Host/FileCache.h"
10c00cf4a0SZachary Turner 
11c00cf4a0SZachary Turner #include "lldb/Host/File.h"
1250bc1ed2SJonas Devlieghere #include "lldb/Host/FileSystem.h"
13c00cf4a0SZachary Turner 
14c00cf4a0SZachary Turner using namespace lldb;
15c00cf4a0SZachary Turner using namespace lldb_private;
16c00cf4a0SZachary Turner 
17c00cf4a0SZachary Turner FileCache *FileCache::m_instance = nullptr;
18c00cf4a0SZachary Turner 
19b9c1b51eSKate Stone FileCache &FileCache::GetInstance() {
20c00cf4a0SZachary Turner   if (m_instance == nullptr)
21c00cf4a0SZachary Turner     m_instance = new FileCache();
22c00cf4a0SZachary Turner 
23c00cf4a0SZachary Turner   return *m_instance;
24c00cf4a0SZachary Turner }
25c00cf4a0SZachary Turner 
26b9c1b51eSKate Stone lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags,
2797206d57SZachary Turner                                     uint32_t mode, Status &error) {
2850bc1ed2SJonas Devlieghere   if (!file_spec) {
29c00cf4a0SZachary Turner     error.SetErrorString("empty path");
30c00cf4a0SZachary Turner     return UINT64_MAX;
31c00cf4a0SZachary Turner   }
32*2fce1137SLawrence D'Anna   auto file = FileSystem::Instance().Open(file_spec, flags, mode);
33*2fce1137SLawrence D'Anna   if (!file) {
34*2fce1137SLawrence D'Anna     error = file.takeError();
35c00cf4a0SZachary Turner     return UINT64_MAX;
36*2fce1137SLawrence D'Anna   }
37*2fce1137SLawrence D'Anna   lldb::user_id_t fd = file.get()->GetDescriptor();
38*2fce1137SLawrence D'Anna   m_cache[fd] = std::move(file.get());
39c00cf4a0SZachary Turner   return fd;
40c00cf4a0SZachary Turner }
41c00cf4a0SZachary Turner 
4297206d57SZachary Turner bool FileCache::CloseFile(lldb::user_id_t fd, Status &error) {
43b9c1b51eSKate Stone   if (fd == UINT64_MAX) {
44c00cf4a0SZachary Turner     error.SetErrorString("invalid file descriptor");
45c00cf4a0SZachary Turner     return false;
46c00cf4a0SZachary Turner   }
47c00cf4a0SZachary Turner   FDToFileMap::iterator pos = m_cache.find(fd);
48b9c1b51eSKate Stone   if (pos == m_cache.end()) {
49c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
50c00cf4a0SZachary Turner     return false;
51c00cf4a0SZachary Turner   }
52*2fce1137SLawrence D'Anna   FileUP &file_up = pos->second;
53*2fce1137SLawrence D'Anna   if (!file_up) {
54c00cf4a0SZachary Turner     error.SetErrorString("invalid host backing file");
55c00cf4a0SZachary Turner     return false;
56c00cf4a0SZachary Turner   }
57*2fce1137SLawrence D'Anna   error = file_up->Close();
58c00cf4a0SZachary Turner   m_cache.erase(pos);
59c00cf4a0SZachary Turner   return error.Success();
60c00cf4a0SZachary Turner }
61c00cf4a0SZachary Turner 
62b9c1b51eSKate Stone uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset,
6397206d57SZachary Turner                               const void *src, uint64_t src_len,
6497206d57SZachary Turner                               Status &error) {
65b9c1b51eSKate Stone   if (fd == UINT64_MAX) {
66c00cf4a0SZachary Turner     error.SetErrorString("invalid file descriptor");
67c00cf4a0SZachary Turner     return UINT64_MAX;
68c00cf4a0SZachary Turner   }
69c00cf4a0SZachary Turner   FDToFileMap::iterator pos = m_cache.find(fd);
70b9c1b51eSKate Stone   if (pos == m_cache.end()) {
71c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
72c00cf4a0SZachary Turner     return false;
73c00cf4a0SZachary Turner   }
74*2fce1137SLawrence D'Anna   FileUP &file_up = pos->second;
75*2fce1137SLawrence D'Anna   if (!file_up) {
76c00cf4a0SZachary Turner     error.SetErrorString("invalid host backing file");
77c00cf4a0SZachary Turner     return UINT64_MAX;
78c00cf4a0SZachary Turner   }
79*2fce1137SLawrence D'Anna   if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
80b9c1b51eSKate Stone       error.Fail())
81c00cf4a0SZachary Turner     return UINT64_MAX;
82c00cf4a0SZachary Turner   size_t bytes_written = src_len;
83*2fce1137SLawrence D'Anna   error = file_up->Write(src, bytes_written);
84c00cf4a0SZachary Turner   if (error.Fail())
85c00cf4a0SZachary Turner     return UINT64_MAX;
86c00cf4a0SZachary Turner   return bytes_written;
87c00cf4a0SZachary Turner }
88c00cf4a0SZachary Turner 
89b9c1b51eSKate Stone uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
9097206d57SZachary Turner                              uint64_t dst_len, Status &error) {
91b9c1b51eSKate Stone   if (fd == UINT64_MAX) {
92c00cf4a0SZachary Turner     error.SetErrorString("invalid file descriptor");
93c00cf4a0SZachary Turner     return UINT64_MAX;
94c00cf4a0SZachary Turner   }
95c00cf4a0SZachary Turner   FDToFileMap::iterator pos = m_cache.find(fd);
96b9c1b51eSKate Stone   if (pos == m_cache.end()) {
97c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
98c00cf4a0SZachary Turner     return false;
99c00cf4a0SZachary Turner   }
100*2fce1137SLawrence D'Anna   FileUP &file_up = pos->second;
101*2fce1137SLawrence D'Anna   if (!file_up) {
102c00cf4a0SZachary Turner     error.SetErrorString("invalid host backing file");
103c00cf4a0SZachary Turner     return UINT64_MAX;
104c00cf4a0SZachary Turner   }
105*2fce1137SLawrence D'Anna   if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
106b9c1b51eSKate Stone       error.Fail())
107c00cf4a0SZachary Turner     return UINT64_MAX;
108c00cf4a0SZachary Turner   size_t bytes_read = dst_len;
109*2fce1137SLawrence D'Anna   error = file_up->Read(dst, bytes_read);
110c00cf4a0SZachary Turner   if (error.Fail())
111c00cf4a0SZachary Turner     return UINT64_MAX;
112c00cf4a0SZachary Turner   return bytes_read;
113c00cf4a0SZachary Turner }
114