1cfca06d7SDimitry Andric //===-- FileCache.cpp -----------------------------------------------------===//
20cac4ca3SEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60cac4ca3SEd Maste //
70cac4ca3SEd Maste //===----------------------------------------------------------------------===//
80cac4ca3SEd Maste
90cac4ca3SEd Maste #include "lldb/Host/FileCache.h"
100cac4ca3SEd Maste
110cac4ca3SEd Maste #include "lldb/Host/File.h"
1294994d37SDimitry Andric #include "lldb/Host/FileSystem.h"
130cac4ca3SEd Maste
140cac4ca3SEd Maste using namespace lldb;
150cac4ca3SEd Maste using namespace lldb_private;
160cac4ca3SEd Maste
170cac4ca3SEd Maste FileCache *FileCache::m_instance = nullptr;
180cac4ca3SEd Maste
GetInstance()1914f1b3e8SDimitry Andric FileCache &FileCache::GetInstance() {
200cac4ca3SEd Maste if (m_instance == nullptr)
210cac4ca3SEd Maste m_instance = new FileCache();
220cac4ca3SEd Maste
230cac4ca3SEd Maste return *m_instance;
240cac4ca3SEd Maste }
250cac4ca3SEd Maste
OpenFile(const FileSpec & file_spec,File::OpenOptions flags,uint32_t mode,Status & error)26ead24645SDimitry Andric lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec,
27ead24645SDimitry Andric File::OpenOptions flags, uint32_t mode,
28ead24645SDimitry Andric Status &error) {
2994994d37SDimitry Andric if (!file_spec) {
300cac4ca3SEd Maste error.SetErrorString("empty path");
310cac4ca3SEd Maste return UINT64_MAX;
320cac4ca3SEd Maste }
33ead24645SDimitry Andric auto file = FileSystem::Instance().Open(file_spec, flags, mode);
34ead24645SDimitry Andric if (!file) {
35ead24645SDimitry Andric error = file.takeError();
360cac4ca3SEd Maste return UINT64_MAX;
37ead24645SDimitry Andric }
38ead24645SDimitry Andric lldb::user_id_t fd = file.get()->GetDescriptor();
39ead24645SDimitry Andric m_cache[fd] = std::move(file.get());
400cac4ca3SEd Maste return fd;
410cac4ca3SEd Maste }
420cac4ca3SEd Maste
CloseFile(lldb::user_id_t fd,Status & error)43b76161e4SDimitry Andric bool FileCache::CloseFile(lldb::user_id_t fd, Status &error) {
4414f1b3e8SDimitry Andric if (fd == UINT64_MAX) {
450cac4ca3SEd Maste error.SetErrorString("invalid file descriptor");
460cac4ca3SEd Maste return false;
470cac4ca3SEd Maste }
480cac4ca3SEd Maste FDToFileMap::iterator pos = m_cache.find(fd);
4914f1b3e8SDimitry Andric if (pos == m_cache.end()) {
500cac4ca3SEd Maste error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
510cac4ca3SEd Maste return false;
520cac4ca3SEd Maste }
53ead24645SDimitry Andric FileUP &file_up = pos->second;
54ead24645SDimitry Andric if (!file_up) {
550cac4ca3SEd Maste error.SetErrorString("invalid host backing file");
560cac4ca3SEd Maste return false;
570cac4ca3SEd Maste }
58ead24645SDimitry Andric error = file_up->Close();
590cac4ca3SEd Maste m_cache.erase(pos);
600cac4ca3SEd Maste return error.Success();
610cac4ca3SEd Maste }
620cac4ca3SEd Maste
WriteFile(lldb::user_id_t fd,uint64_t offset,const void * src,uint64_t src_len,Status & error)6314f1b3e8SDimitry Andric uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset,
64b76161e4SDimitry Andric const void *src, uint64_t src_len,
65b76161e4SDimitry Andric Status &error) {
6614f1b3e8SDimitry Andric if (fd == UINT64_MAX) {
670cac4ca3SEd Maste error.SetErrorString("invalid file descriptor");
680cac4ca3SEd Maste return UINT64_MAX;
690cac4ca3SEd Maste }
700cac4ca3SEd Maste FDToFileMap::iterator pos = m_cache.find(fd);
7114f1b3e8SDimitry Andric if (pos == m_cache.end()) {
720cac4ca3SEd Maste error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
730cac4ca3SEd Maste return false;
740cac4ca3SEd Maste }
75ead24645SDimitry Andric FileUP &file_up = pos->second;
76ead24645SDimitry Andric if (!file_up) {
770cac4ca3SEd Maste error.SetErrorString("invalid host backing file");
780cac4ca3SEd Maste return UINT64_MAX;
790cac4ca3SEd Maste }
80ead24645SDimitry Andric if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
8114f1b3e8SDimitry Andric error.Fail())
820cac4ca3SEd Maste return UINT64_MAX;
830cac4ca3SEd Maste size_t bytes_written = src_len;
84ead24645SDimitry Andric error = file_up->Write(src, bytes_written);
850cac4ca3SEd Maste if (error.Fail())
860cac4ca3SEd Maste return UINT64_MAX;
870cac4ca3SEd Maste return bytes_written;
880cac4ca3SEd Maste }
890cac4ca3SEd Maste
ReadFile(lldb::user_id_t fd,uint64_t offset,void * dst,uint64_t dst_len,Status & error)9014f1b3e8SDimitry Andric uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
91b76161e4SDimitry Andric uint64_t dst_len, Status &error) {
9214f1b3e8SDimitry Andric if (fd == UINT64_MAX) {
930cac4ca3SEd Maste error.SetErrorString("invalid file descriptor");
940cac4ca3SEd Maste return UINT64_MAX;
950cac4ca3SEd Maste }
960cac4ca3SEd Maste FDToFileMap::iterator pos = m_cache.find(fd);
9714f1b3e8SDimitry Andric if (pos == m_cache.end()) {
980cac4ca3SEd Maste error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
990cac4ca3SEd Maste return false;
1000cac4ca3SEd Maste }
101ead24645SDimitry Andric FileUP &file_up = pos->second;
102ead24645SDimitry Andric if (!file_up) {
1030cac4ca3SEd Maste error.SetErrorString("invalid host backing file");
1040cac4ca3SEd Maste return UINT64_MAX;
1050cac4ca3SEd Maste }
106ead24645SDimitry Andric if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
10714f1b3e8SDimitry Andric error.Fail())
1080cac4ca3SEd Maste return UINT64_MAX;
1090cac4ca3SEd Maste size_t bytes_read = dst_len;
110ead24645SDimitry Andric error = file_up->Read(dst, bytes_read);
1110cac4ca3SEd Maste if (error.Fail())
1120cac4ca3SEd Maste return UINT64_MAX;
1130cac4ca3SEd Maste return bytes_read;
1140cac4ca3SEd Maste }
115