1 //===-- FileCache.cpp -----------------------------------------------------===// 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, 27 File::OpenOptions flags, uint32_t mode, 28 Status &error) { 29 if (!file_spec) { 30 error.SetErrorString("empty path"); 31 return UINT64_MAX; 32 } 33 auto file = FileSystem::Instance().Open(file_spec, flags, mode); 34 if (!file) { 35 error = file.takeError(); 36 return UINT64_MAX; 37 } 38 lldb::user_id_t fd = file.get()->GetDescriptor(); 39 m_cache[fd] = std::move(file.get()); 40 return fd; 41 } 42 43 bool FileCache::CloseFile(lldb::user_id_t fd, Status &error) { 44 if (fd == UINT64_MAX) { 45 error.SetErrorString("invalid file descriptor"); 46 return false; 47 } 48 FDToFileMap::iterator pos = m_cache.find(fd); 49 if (pos == m_cache.end()) { 50 error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); 51 return false; 52 } 53 FileUP &file_up = pos->second; 54 if (!file_up) { 55 error.SetErrorString("invalid host backing file"); 56 return false; 57 } 58 error = file_up->Close(); 59 m_cache.erase(pos); 60 return error.Success(); 61 } 62 63 uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset, 64 const void *src, uint64_t src_len, 65 Status &error) { 66 if (fd == UINT64_MAX) { 67 error.SetErrorString("invalid file descriptor"); 68 return UINT64_MAX; 69 } 70 FDToFileMap::iterator pos = m_cache.find(fd); 71 if (pos == m_cache.end()) { 72 error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); 73 return false; 74 } 75 FileUP &file_up = pos->second; 76 if (!file_up) { 77 error.SetErrorString("invalid host backing file"); 78 return UINT64_MAX; 79 } 80 if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset || 81 error.Fail()) 82 return UINT64_MAX; 83 size_t bytes_written = src_len; 84 error = file_up->Write(src, bytes_written); 85 if (error.Fail()) 86 return UINT64_MAX; 87 return bytes_written; 88 } 89 90 uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, 91 uint64_t dst_len, Status &error) { 92 if (fd == UINT64_MAX) { 93 error.SetErrorString("invalid file descriptor"); 94 return UINT64_MAX; 95 } 96 FDToFileMap::iterator pos = m_cache.find(fd); 97 if (pos == m_cache.end()) { 98 error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); 99 return false; 100 } 101 FileUP &file_up = pos->second; 102 if (!file_up) { 103 error.SetErrorString("invalid host backing file"); 104 return UINT64_MAX; 105 } 106 if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset || 107 error.Fail()) 108 return UINT64_MAX; 109 size_t bytes_read = dst_len; 110 error = file_up->Read(dst, bytes_read); 111 if (error.Fail()) 112 return UINT64_MAX; 113 return bytes_read; 114 } 115