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