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