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