1c00cf4a0SZachary Turner //===-- FileCache.cpp -------------------------------------------*- C++ -*-===//
2c00cf4a0SZachary Turner //
3c00cf4a0SZachary Turner //                     The LLVM Compiler Infrastructure
4c00cf4a0SZachary Turner //
5c00cf4a0SZachary Turner // This file is distributed under the University of Illinois Open Source
6c00cf4a0SZachary Turner // License. See LICENSE.TXT for details.
7c00cf4a0SZachary Turner //
8c00cf4a0SZachary Turner //===----------------------------------------------------------------------===//
9c00cf4a0SZachary Turner 
10c00cf4a0SZachary Turner #include "lldb/Host/FileCache.h"
11c00cf4a0SZachary Turner 
12c00cf4a0SZachary Turner #include "lldb/Host/File.h"
13*50bc1ed2SJonas Devlieghere #include "lldb/Host/FileSystem.h"
14c00cf4a0SZachary Turner 
15c00cf4a0SZachary Turner using namespace lldb;
16c00cf4a0SZachary Turner using namespace lldb_private;
17c00cf4a0SZachary Turner 
18c00cf4a0SZachary Turner FileCache *FileCache::m_instance = nullptr;
19c00cf4a0SZachary Turner 
20b9c1b51eSKate Stone FileCache &FileCache::GetInstance() {
21c00cf4a0SZachary Turner   if (m_instance == nullptr)
22c00cf4a0SZachary Turner     m_instance = new FileCache();
23c00cf4a0SZachary Turner 
24c00cf4a0SZachary Turner   return *m_instance;
25c00cf4a0SZachary Turner }
26c00cf4a0SZachary Turner 
27b9c1b51eSKate Stone lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags,
2897206d57SZachary Turner                                     uint32_t mode, Status &error) {
29*50bc1ed2SJonas Devlieghere   if (!file_spec) {
30c00cf4a0SZachary Turner     error.SetErrorString("empty path");
31c00cf4a0SZachary Turner     return UINT64_MAX;
32c00cf4a0SZachary Turner   }
33c00cf4a0SZachary Turner   FileSP file_sp(new File());
34*50bc1ed2SJonas Devlieghere   error = FileSystem::Instance().Open(*file_sp, file_spec, flags, mode);
35c00cf4a0SZachary Turner   if (file_sp->IsValid() == false)
36c00cf4a0SZachary Turner     return UINT64_MAX;
37c00cf4a0SZachary Turner   lldb::user_id_t fd = file_sp->GetDescriptor();
38c00cf4a0SZachary Turner   m_cache[fd] = file_sp;
39c00cf4a0SZachary Turner   return fd;
40c00cf4a0SZachary Turner }
41c00cf4a0SZachary Turner 
4297206d57SZachary Turner bool FileCache::CloseFile(lldb::user_id_t fd, Status &error) {
43b9c1b51eSKate Stone   if (fd == UINT64_MAX) {
44c00cf4a0SZachary Turner     error.SetErrorString("invalid file descriptor");
45c00cf4a0SZachary Turner     return false;
46c00cf4a0SZachary Turner   }
47c00cf4a0SZachary Turner   FDToFileMap::iterator pos = m_cache.find(fd);
48b9c1b51eSKate Stone   if (pos == m_cache.end()) {
49c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
50c00cf4a0SZachary Turner     return false;
51c00cf4a0SZachary Turner   }
52c00cf4a0SZachary Turner   FileSP file_sp = pos->second;
53b9c1b51eSKate Stone   if (!file_sp) {
54c00cf4a0SZachary Turner     error.SetErrorString("invalid host backing file");
55c00cf4a0SZachary Turner     return false;
56c00cf4a0SZachary Turner   }
57c00cf4a0SZachary Turner   error = file_sp->Close();
58c00cf4a0SZachary Turner   m_cache.erase(pos);
59c00cf4a0SZachary Turner   return error.Success();
60c00cf4a0SZachary Turner }
61c00cf4a0SZachary Turner 
62b9c1b51eSKate Stone uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset,
6397206d57SZachary Turner                               const void *src, uint64_t src_len,
6497206d57SZachary Turner                               Status &error) {
65b9c1b51eSKate Stone   if (fd == UINT64_MAX) {
66c00cf4a0SZachary Turner     error.SetErrorString("invalid file descriptor");
67c00cf4a0SZachary Turner     return UINT64_MAX;
68c00cf4a0SZachary Turner   }
69c00cf4a0SZachary Turner   FDToFileMap::iterator pos = m_cache.find(fd);
70b9c1b51eSKate Stone   if (pos == m_cache.end()) {
71c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
72c00cf4a0SZachary Turner     return false;
73c00cf4a0SZachary Turner   }
74c00cf4a0SZachary Turner   FileSP file_sp = pos->second;
75b9c1b51eSKate Stone   if (!file_sp) {
76c00cf4a0SZachary Turner     error.SetErrorString("invalid host backing file");
77c00cf4a0SZachary Turner     return UINT64_MAX;
78c00cf4a0SZachary Turner   }
79b9c1b51eSKate Stone   if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset ||
80b9c1b51eSKate Stone       error.Fail())
81c00cf4a0SZachary Turner     return UINT64_MAX;
82c00cf4a0SZachary Turner   size_t bytes_written = src_len;
83c00cf4a0SZachary Turner   error = file_sp->Write(src, bytes_written);
84c00cf4a0SZachary Turner   if (error.Fail())
85c00cf4a0SZachary Turner     return UINT64_MAX;
86c00cf4a0SZachary Turner   return bytes_written;
87c00cf4a0SZachary Turner }
88c00cf4a0SZachary Turner 
89b9c1b51eSKate Stone uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
9097206d57SZachary Turner                              uint64_t dst_len, Status &error) {
91b9c1b51eSKate Stone   if (fd == UINT64_MAX) {
92c00cf4a0SZachary Turner     error.SetErrorString("invalid file descriptor");
93c00cf4a0SZachary Turner     return UINT64_MAX;
94c00cf4a0SZachary Turner   }
95c00cf4a0SZachary Turner   FDToFileMap::iterator pos = m_cache.find(fd);
96b9c1b51eSKate Stone   if (pos == m_cache.end()) {
97c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
98c00cf4a0SZachary Turner     return false;
99c00cf4a0SZachary Turner   }
100c00cf4a0SZachary Turner   FileSP file_sp = pos->second;
101b9c1b51eSKate Stone   if (!file_sp) {
102c00cf4a0SZachary Turner     error.SetErrorString("invalid host backing file");
103c00cf4a0SZachary Turner     return UINT64_MAX;
104c00cf4a0SZachary Turner   }
105b9c1b51eSKate Stone   if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset ||
106b9c1b51eSKate Stone       error.Fail())
107c00cf4a0SZachary Turner     return UINT64_MAX;
108c00cf4a0SZachary Turner   size_t bytes_read = dst_len;
109c00cf4a0SZachary Turner   error = file_sp->Read(dst, bytes_read);
110c00cf4a0SZachary Turner   if (error.Fail())
111c00cf4a0SZachary Turner     return UINT64_MAX;
112c00cf4a0SZachary Turner   return bytes_read;
113c00cf4a0SZachary Turner }
114