1*dda28197Spatrick //===-- FileCache.cpp -----------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Host/FileCache.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Host/File.h"
12061da546Spatrick #include "lldb/Host/FileSystem.h"
13061da546Spatrick
14061da546Spatrick using namespace lldb;
15061da546Spatrick using namespace lldb_private;
16061da546Spatrick
17061da546Spatrick FileCache *FileCache::m_instance = nullptr;
18061da546Spatrick
GetInstance()19061da546Spatrick FileCache &FileCache::GetInstance() {
20061da546Spatrick if (m_instance == nullptr)
21061da546Spatrick m_instance = new FileCache();
22061da546Spatrick
23061da546Spatrick return *m_instance;
24061da546Spatrick }
25061da546Spatrick
OpenFile(const FileSpec & file_spec,File::OpenOptions flags,uint32_t mode,Status & error)26061da546Spatrick lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec,
27061da546Spatrick File::OpenOptions flags, uint32_t mode,
28061da546Spatrick Status &error) {
29061da546Spatrick if (!file_spec) {
30061da546Spatrick error.SetErrorString("empty path");
31061da546Spatrick return UINT64_MAX;
32061da546Spatrick }
33061da546Spatrick auto file = FileSystem::Instance().Open(file_spec, flags, mode);
34061da546Spatrick if (!file) {
35061da546Spatrick error = file.takeError();
36061da546Spatrick return UINT64_MAX;
37061da546Spatrick }
38061da546Spatrick lldb::user_id_t fd = file.get()->GetDescriptor();
39061da546Spatrick m_cache[fd] = std::move(file.get());
40061da546Spatrick return fd;
41061da546Spatrick }
42061da546Spatrick
CloseFile(lldb::user_id_t fd,Status & error)43061da546Spatrick bool FileCache::CloseFile(lldb::user_id_t fd, Status &error) {
44061da546Spatrick if (fd == UINT64_MAX) {
45061da546Spatrick error.SetErrorString("invalid file descriptor");
46061da546Spatrick return false;
47061da546Spatrick }
48061da546Spatrick FDToFileMap::iterator pos = m_cache.find(fd);
49061da546Spatrick if (pos == m_cache.end()) {
50061da546Spatrick error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
51061da546Spatrick return false;
52061da546Spatrick }
53061da546Spatrick FileUP &file_up = pos->second;
54061da546Spatrick if (!file_up) {
55061da546Spatrick error.SetErrorString("invalid host backing file");
56061da546Spatrick return false;
57061da546Spatrick }
58061da546Spatrick error = file_up->Close();
59061da546Spatrick m_cache.erase(pos);
60061da546Spatrick return error.Success();
61061da546Spatrick }
62061da546Spatrick
WriteFile(lldb::user_id_t fd,uint64_t offset,const void * src,uint64_t src_len,Status & error)63061da546Spatrick uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset,
64061da546Spatrick const void *src, uint64_t src_len,
65061da546Spatrick Status &error) {
66061da546Spatrick if (fd == UINT64_MAX) {
67061da546Spatrick error.SetErrorString("invalid file descriptor");
68061da546Spatrick return UINT64_MAX;
69061da546Spatrick }
70061da546Spatrick FDToFileMap::iterator pos = m_cache.find(fd);
71061da546Spatrick if (pos == m_cache.end()) {
72061da546Spatrick error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
73061da546Spatrick return false;
74061da546Spatrick }
75061da546Spatrick FileUP &file_up = pos->second;
76061da546Spatrick if (!file_up) {
77061da546Spatrick error.SetErrorString("invalid host backing file");
78061da546Spatrick return UINT64_MAX;
79061da546Spatrick }
80061da546Spatrick if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
81061da546Spatrick error.Fail())
82061da546Spatrick return UINT64_MAX;
83061da546Spatrick size_t bytes_written = src_len;
84061da546Spatrick error = file_up->Write(src, bytes_written);
85061da546Spatrick if (error.Fail())
86061da546Spatrick return UINT64_MAX;
87061da546Spatrick return bytes_written;
88061da546Spatrick }
89061da546Spatrick
ReadFile(lldb::user_id_t fd,uint64_t offset,void * dst,uint64_t dst_len,Status & error)90061da546Spatrick uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
91061da546Spatrick uint64_t dst_len, Status &error) {
92061da546Spatrick if (fd == UINT64_MAX) {
93061da546Spatrick error.SetErrorString("invalid file descriptor");
94061da546Spatrick return UINT64_MAX;
95061da546Spatrick }
96061da546Spatrick FDToFileMap::iterator pos = m_cache.find(fd);
97061da546Spatrick if (pos == m_cache.end()) {
98061da546Spatrick error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
99061da546Spatrick return false;
100061da546Spatrick }
101061da546Spatrick FileUP &file_up = pos->second;
102061da546Spatrick if (!file_up) {
103061da546Spatrick error.SetErrorString("invalid host backing file");
104061da546Spatrick return UINT64_MAX;
105061da546Spatrick }
106061da546Spatrick if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
107061da546Spatrick error.Fail())
108061da546Spatrick return UINT64_MAX;
109061da546Spatrick size_t bytes_read = dst_len;
110061da546Spatrick error = file_up->Read(dst, bytes_read);
111061da546Spatrick if (error.Fail())
112061da546Spatrick return UINT64_MAX;
113061da546Spatrick return bytes_read;
114061da546Spatrick }
115