xref: /freebsd-src/contrib/llvm-project/lldb/source/Host/common/FileCache.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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