10127ef0fSEd Maste //===-- FileCache.cpp -------------------------------------------*- C++ -*-===//
20127ef0fSEd Maste //
30127ef0fSEd Maste //                     The LLVM Compiler Infrastructure
40127ef0fSEd Maste //
50127ef0fSEd Maste // This file is distributed under the University of Illinois Open Source
60127ef0fSEd Maste // License. See LICENSE.TXT for details.
70127ef0fSEd Maste //
80127ef0fSEd Maste //===----------------------------------------------------------------------===//
90127ef0fSEd Maste 
100127ef0fSEd Maste #include "lldb/Host/FileCache.h"
110127ef0fSEd Maste 
120127ef0fSEd Maste #include "lldb/Host/File.h"
13*b5893f02SDimitry Andric #include "lldb/Host/FileSystem.h"
140127ef0fSEd Maste 
150127ef0fSEd Maste using namespace lldb;
160127ef0fSEd Maste using namespace lldb_private;
170127ef0fSEd Maste 
180127ef0fSEd Maste FileCache *FileCache::m_instance = nullptr;
190127ef0fSEd Maste 
GetInstance()20435933ddSDimitry Andric FileCache &FileCache::GetInstance() {
210127ef0fSEd Maste   if (m_instance == nullptr)
220127ef0fSEd Maste     m_instance = new FileCache();
230127ef0fSEd Maste 
240127ef0fSEd Maste   return *m_instance;
250127ef0fSEd Maste }
260127ef0fSEd Maste 
OpenFile(const FileSpec & file_spec,uint32_t flags,uint32_t mode,Status & error)27435933ddSDimitry Andric lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags,
285517e702SDimitry Andric                                     uint32_t mode, Status &error) {
29*b5893f02SDimitry Andric   if (!file_spec) {
300127ef0fSEd Maste     error.SetErrorString("empty path");
310127ef0fSEd Maste     return UINT64_MAX;
320127ef0fSEd Maste   }
330127ef0fSEd Maste   FileSP file_sp(new File());
34*b5893f02SDimitry Andric   error = FileSystem::Instance().Open(*file_sp, file_spec, flags, mode);
35*b5893f02SDimitry Andric   if (!file_sp->IsValid())
360127ef0fSEd Maste     return UINT64_MAX;
370127ef0fSEd Maste   lldb::user_id_t fd = file_sp->GetDescriptor();
380127ef0fSEd Maste   m_cache[fd] = file_sp;
390127ef0fSEd Maste   return fd;
400127ef0fSEd Maste }
410127ef0fSEd Maste 
CloseFile(lldb::user_id_t fd,Status & error)425517e702SDimitry Andric bool FileCache::CloseFile(lldb::user_id_t fd, Status &error) {
43435933ddSDimitry Andric   if (fd == UINT64_MAX) {
440127ef0fSEd Maste     error.SetErrorString("invalid file descriptor");
450127ef0fSEd Maste     return false;
460127ef0fSEd Maste   }
470127ef0fSEd Maste   FDToFileMap::iterator pos = m_cache.find(fd);
48435933ddSDimitry Andric   if (pos == m_cache.end()) {
490127ef0fSEd Maste     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
500127ef0fSEd Maste     return false;
510127ef0fSEd Maste   }
520127ef0fSEd Maste   FileSP file_sp = pos->second;
53435933ddSDimitry Andric   if (!file_sp) {
540127ef0fSEd Maste     error.SetErrorString("invalid host backing file");
550127ef0fSEd Maste     return false;
560127ef0fSEd Maste   }
570127ef0fSEd Maste   error = file_sp->Close();
580127ef0fSEd Maste   m_cache.erase(pos);
590127ef0fSEd Maste   return error.Success();
600127ef0fSEd Maste }
610127ef0fSEd Maste 
WriteFile(lldb::user_id_t fd,uint64_t offset,const void * src,uint64_t src_len,Status & error)62435933ddSDimitry Andric uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset,
635517e702SDimitry Andric                               const void *src, uint64_t src_len,
645517e702SDimitry Andric                               Status &error) {
65435933ddSDimitry Andric   if (fd == UINT64_MAX) {
660127ef0fSEd Maste     error.SetErrorString("invalid file descriptor");
670127ef0fSEd Maste     return UINT64_MAX;
680127ef0fSEd Maste   }
690127ef0fSEd Maste   FDToFileMap::iterator pos = m_cache.find(fd);
70435933ddSDimitry Andric   if (pos == m_cache.end()) {
710127ef0fSEd Maste     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
720127ef0fSEd Maste     return false;
730127ef0fSEd Maste   }
740127ef0fSEd Maste   FileSP file_sp = pos->second;
75435933ddSDimitry Andric   if (!file_sp) {
760127ef0fSEd Maste     error.SetErrorString("invalid host backing file");
770127ef0fSEd Maste     return UINT64_MAX;
780127ef0fSEd Maste   }
79435933ddSDimitry Andric   if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset ||
80435933ddSDimitry Andric       error.Fail())
810127ef0fSEd Maste     return UINT64_MAX;
820127ef0fSEd Maste   size_t bytes_written = src_len;
830127ef0fSEd Maste   error = file_sp->Write(src, bytes_written);
840127ef0fSEd Maste   if (error.Fail())
850127ef0fSEd Maste     return UINT64_MAX;
860127ef0fSEd Maste   return bytes_written;
870127ef0fSEd Maste }
880127ef0fSEd Maste 
ReadFile(lldb::user_id_t fd,uint64_t offset,void * dst,uint64_t dst_len,Status & error)89435933ddSDimitry Andric uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
905517e702SDimitry Andric                              uint64_t dst_len, Status &error) {
91435933ddSDimitry Andric   if (fd == UINT64_MAX) {
920127ef0fSEd Maste     error.SetErrorString("invalid file descriptor");
930127ef0fSEd Maste     return UINT64_MAX;
940127ef0fSEd Maste   }
950127ef0fSEd Maste   FDToFileMap::iterator pos = m_cache.find(fd);
96435933ddSDimitry Andric   if (pos == m_cache.end()) {
970127ef0fSEd Maste     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
980127ef0fSEd Maste     return false;
990127ef0fSEd Maste   }
1000127ef0fSEd Maste   FileSP file_sp = pos->second;
101435933ddSDimitry Andric   if (!file_sp) {
1020127ef0fSEd Maste     error.SetErrorString("invalid host backing file");
1030127ef0fSEd Maste     return UINT64_MAX;
1040127ef0fSEd Maste   }
105435933ddSDimitry Andric   if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset ||
106435933ddSDimitry Andric       error.Fail())
1070127ef0fSEd Maste     return UINT64_MAX;
1080127ef0fSEd Maste   size_t bytes_read = dst_len;
1090127ef0fSEd Maste   error = file_sp->Read(dst, bytes_read);
1100127ef0fSEd Maste   if (error.Fail())
1110127ef0fSEd Maste     return UINT64_MAX;
1120127ef0fSEd Maste   return bytes_read;
1130127ef0fSEd Maste }
114