blob: a58c5a87e50a921389e5075b2ad6963fb20bc11e [file] [log] [blame]
Oleksiy Vyalov63acdfd2015-03-10 01:15:28 +00001//===--------------------- ModuleCache.cpp ----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ModuleCache.h"
11
12#include "lldb/Core/Module.h"
13#include "lldb/Host/FileSystem.h"
14#include "llvm/Support/FileSystem.h"
15
16#include <assert.h>
17
18#include <cstdio>
19#
20using namespace lldb;
21using namespace lldb_private;
22
23namespace {
24
25const char* kModulesSubdir = ".cache";
26
27FileSpec
28JoinPath (const FileSpec &path1, const char* path2)
29{
30 FileSpec result_spec (path1);
31 result_spec.AppendPathComponent (path2);
32 return result_spec;
33}
34
35Error
36MakeDirectory (const FileSpec &dir_path)
37{
38 if (dir_path.Exists ())
39 {
40 if (!dir_path.IsDirectory ())
41 return Error ("Invalid existing path");
42
43 return Error ();
44 }
45
46 return FileSystem::MakeDirectory (dir_path.GetPath ().c_str (),
47 eFilePermissionsDirectoryDefault);
48}
49
50} // namespace
51
52Error
53ModuleCache::Put (const FileSpec &root_dir_spec,
54 const char *hostname,
55 const UUID &uuid,
56 const FileSpec &platform_module_spec,
57 const FileSpec &tmp_file)
58{
59 const auto module_spec_dir = GetModuleDirectory (root_dir_spec, uuid);
60 auto error = MakeDirectory (module_spec_dir);
61 if (error.Fail ())
62 return error;
63
64 const auto module_file_path = JoinPath (module_spec_dir, platform_module_spec.GetFilename ().AsCString ());
65
66 const auto tmp_file_path = tmp_file.GetPath ();
67 const auto err_code = llvm::sys::fs::copy_file (tmp_file_path.c_str (), module_file_path.GetPath ().c_str ());
68 if (err_code)
69 {
70 error.SetErrorStringWithFormat ("failed to copy file %s to %s: %s",
71 tmp_file_path.c_str (),
72 module_file_path.GetPath ().c_str (),
73 err_code.message ().c_str ());
74 }
75
76 // Create sysroot link to a module.
77 const auto sysroot_module_path_spec = GetHostSysRootModulePath (root_dir_spec, hostname, platform_module_spec);
78 return CreateHostSysRootModuleSymLink (sysroot_module_path_spec, module_file_path);
79}
80
81Error
82ModuleCache::Get (const FileSpec &root_dir_spec,
83 const char *hostname,
84 const UUID &uuid,
85 const FileSpec &platform_module_spec,
86 FileSpec &cached_module_spec)
87{
88 cached_module_spec.Clear ();
89
90 const auto module_spec_dir = GetModuleDirectory (root_dir_spec, uuid);
91 const auto module_file_path = JoinPath (module_spec_dir, platform_module_spec.GetFilename ().AsCString ());
92
93 Error error;
94 if (!module_file_path.Exists ())
95 {
96 error.SetErrorStringWithFormat ("module %s not found", module_file_path.GetPath ().c_str ());
97 return error;
98 }
99 cached_module_spec = module_file_path;
100
101 // We may have already cached module but downloaded from an another host - in this case let's create a symlink to it.
102 const auto sysroot_module_path_spec = GetHostSysRootModulePath (root_dir_spec, hostname, platform_module_spec);
103 if (!sysroot_module_path_spec.Exists ())
104 CreateHostSysRootModuleSymLink (sysroot_module_path_spec, cached_module_spec);
105
106 return error;
107}
108
109FileSpec
110ModuleCache::GetModuleDirectory (const FileSpec &root_dir_spec, const UUID &uuid)
111{
112 const auto modules_dir_spec = JoinPath (root_dir_spec, kModulesSubdir);
113 return JoinPath (modules_dir_spec, uuid.GetAsString ().c_str ());
114}
115
116FileSpec
117ModuleCache::GetHostSysRootModulePath (const FileSpec &root_dir_spec, const char *hostname, const FileSpec &platform_module_spec)
118{
119 const auto sysroot_dir = JoinPath (root_dir_spec, hostname);
120 return JoinPath (sysroot_dir, platform_module_spec.GetPath ().c_str ());
121}
122
123Error
124ModuleCache::CreateHostSysRootModuleSymLink (const FileSpec &sysroot_module_path_spec, const FileSpec &module_file_path)
125{
126 const auto error = MakeDirectory (FileSpec (sysroot_module_path_spec.GetDirectory ().AsCString (), false));
127 if (error.Fail ())
128 return error;
129
130 return FileSystem::Symlink (sysroot_module_path_spec.GetPath ().c_str (),
131 module_file_path.GetPath ().c_str ());
132}