1c00cf4a0SZachary Turner //===-- FileSystem.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/windows/windows.h"
11c00cf4a0SZachary Turner 
12c00cf4a0SZachary Turner #include <shellapi.h>
13c00cf4a0SZachary Turner 
14c00cf4a0SZachary Turner #include "lldb/Host/FileSystem.h"
15cc815568SOleksiy Vyalov #include "llvm/Support/FileSystem.h"
16c00cf4a0SZachary Turner 
17c00cf4a0SZachary Turner using namespace lldb_private;
18c00cf4a0SZachary Turner 
19c00cf4a0SZachary Turner FileSpec::PathSyntax
20c00cf4a0SZachary Turner FileSystem::GetNativePathSyntax()
21c00cf4a0SZachary Turner {
22c00cf4a0SZachary Turner     return FileSpec::ePathSyntaxWindows;
23c00cf4a0SZachary Turner }
24c00cf4a0SZachary Turner 
25c00cf4a0SZachary Turner Error
26c00cf4a0SZachary Turner FileSystem::MakeDirectory(const char *path, uint32_t file_permissions)
27c00cf4a0SZachary Turner {
28c00cf4a0SZachary Turner     // On Win32, the mode parameter is ignored, as Windows files and directories support a
29c00cf4a0SZachary Turner     // different permission model than POSIX.
30c00cf4a0SZachary Turner     Error error;
31cc815568SOleksiy Vyalov     const auto err_code = llvm::sys::fs::create_directories(path, true);
32cc815568SOleksiy Vyalov     if (err_code)
33cc815568SOleksiy Vyalov     {
34cc815568SOleksiy Vyalov         error.SetErrorString(err_code.message().c_str());
35cc815568SOleksiy Vyalov     }
36cc815568SOleksiy Vyalov 
37c00cf4a0SZachary Turner     return error;
38c00cf4a0SZachary Turner }
39c00cf4a0SZachary Turner 
40c00cf4a0SZachary Turner Error
41c00cf4a0SZachary Turner FileSystem::DeleteDirectory(const char *path, bool recurse)
42c00cf4a0SZachary Turner {
43c00cf4a0SZachary Turner     Error error;
44c00cf4a0SZachary Turner     if (!recurse)
45c00cf4a0SZachary Turner     {
46c00cf4a0SZachary Turner         BOOL result = ::RemoveDirectory(path);
47c00cf4a0SZachary Turner         if (!result)
48c00cf4a0SZachary Turner             error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
49c00cf4a0SZachary Turner     }
50c00cf4a0SZachary Turner     else
51c00cf4a0SZachary Turner     {
52c00cf4a0SZachary Turner         // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to
53c00cf4a0SZachary Turner         // indicate the end of the list.
54c00cf4a0SZachary Turner         std::string path_buffer(path);
55c00cf4a0SZachary Turner         path_buffer.push_back(0);
56c00cf4a0SZachary Turner 
57c00cf4a0SZachary Turner         SHFILEOPSTRUCT shfos = {0};
58c00cf4a0SZachary Turner         shfos.wFunc = FO_DELETE;
59c00cf4a0SZachary Turner         shfos.pFrom = path_buffer.c_str();
60c00cf4a0SZachary Turner         shfos.fFlags = FOF_NO_UI;
61c00cf4a0SZachary Turner 
62c00cf4a0SZachary Turner         int result = ::SHFileOperation(&shfos);
63c00cf4a0SZachary Turner         // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.
64c00cf4a0SZachary Turner         if (result != 0)
65c00cf4a0SZachary Turner             error.SetErrorStringWithFormat("SHFileOperation failed");
66c00cf4a0SZachary Turner     }
67c00cf4a0SZachary Turner     return error;
68c00cf4a0SZachary Turner }
69c00cf4a0SZachary Turner 
70c00cf4a0SZachary Turner Error
71c00cf4a0SZachary Turner FileSystem::GetFilePermissions(const char *path, uint32_t &file_permissions)
72c00cf4a0SZachary Turner {
73c00cf4a0SZachary Turner     Error error;
74c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
75c00cf4a0SZachary Turner     return error;
76c00cf4a0SZachary Turner }
77c00cf4a0SZachary Turner 
78c00cf4a0SZachary Turner Error
79c00cf4a0SZachary Turner FileSystem::SetFilePermissions(const char *path, uint32_t file_permissions)
80c00cf4a0SZachary Turner {
81c00cf4a0SZachary Turner     Error error;
82c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
83c00cf4a0SZachary Turner     return error;
84c00cf4a0SZachary Turner }
85c00cf4a0SZachary Turner 
86c00cf4a0SZachary Turner lldb::user_id_t
87c00cf4a0SZachary Turner FileSystem::GetFileSize(const FileSpec &file_spec)
88c00cf4a0SZachary Turner {
89c00cf4a0SZachary Turner     return file_spec.GetByteSize();
90c00cf4a0SZachary Turner }
91c00cf4a0SZachary Turner 
92c00cf4a0SZachary Turner bool
93c00cf4a0SZachary Turner FileSystem::GetFileExists(const FileSpec &file_spec)
94c00cf4a0SZachary Turner {
95c00cf4a0SZachary Turner     return file_spec.Exists();
96c00cf4a0SZachary Turner }
97c00cf4a0SZachary Turner 
98c00cf4a0SZachary Turner Error
99*a9ea0711SOleksiy Vyalov FileSystem::Hardlink(const char *linkname, const char *target)
100*a9ea0711SOleksiy Vyalov {
101*a9ea0711SOleksiy Vyalov     Error error;
102*a9ea0711SOleksiy Vyalov     if (!::CreateHardLink(linkname, target, nullptr))
103*a9ea0711SOleksiy Vyalov         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
104*a9ea0711SOleksiy Vyalov     return error;
105*a9ea0711SOleksiy Vyalov }
106*a9ea0711SOleksiy Vyalov 
107*a9ea0711SOleksiy Vyalov Error
108c00cf4a0SZachary Turner FileSystem::Symlink(const char *linkname, const char *target)
109c00cf4a0SZachary Turner {
110c00cf4a0SZachary Turner     Error error;
111c00cf4a0SZachary Turner     DWORD attrib = ::GetFileAttributes(target);
112c00cf4a0SZachary Turner     if (attrib == INVALID_FILE_ATTRIBUTES)
113c00cf4a0SZachary Turner     {
114c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
115c00cf4a0SZachary Turner         return error;
116c00cf4a0SZachary Turner     }
117c00cf4a0SZachary Turner     bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);
118c00cf4a0SZachary Turner     DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
119c00cf4a0SZachary Turner     BOOL result = ::CreateSymbolicLink(linkname, target, flag);
120c00cf4a0SZachary Turner     if (!result)
121c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
122c00cf4a0SZachary Turner     return error;
123c00cf4a0SZachary Turner }
124c00cf4a0SZachary Turner 
125c00cf4a0SZachary Turner Error
126c00cf4a0SZachary Turner FileSystem::Unlink(const char *path)
127c00cf4a0SZachary Turner {
128c00cf4a0SZachary Turner     Error error;
129c00cf4a0SZachary Turner     BOOL result = ::DeleteFile(path);
130c00cf4a0SZachary Turner     if (!result)
131c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
132c00cf4a0SZachary Turner     return error;
133c00cf4a0SZachary Turner }
134c00cf4a0SZachary Turner 
135c00cf4a0SZachary Turner Error
136c00cf4a0SZachary Turner FileSystem::Readlink(const char *path, char *buf, size_t buf_len)
137c00cf4a0SZachary Turner {
138c00cf4a0SZachary Turner     Error error;
139c00cf4a0SZachary Turner     HANDLE h = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
140c00cf4a0SZachary Turner                             FILE_FLAG_OPEN_REPARSE_POINT, NULL);
141c00cf4a0SZachary Turner     if (h == INVALID_HANDLE_VALUE)
142c00cf4a0SZachary Turner     {
143c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
144c00cf4a0SZachary Turner         return error;
145c00cf4a0SZachary Turner     }
146c00cf4a0SZachary Turner 
147c00cf4a0SZachary Turner     // Subtract 1 from the path length since this function does not add a null terminator.
148c00cf4a0SZachary Turner     DWORD result = ::GetFinalPathNameByHandle(h, buf, buf_len - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
149c00cf4a0SZachary Turner     if (result == 0)
150c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
151c00cf4a0SZachary Turner 
152c00cf4a0SZachary Turner     ::CloseHandle(h);
153c00cf4a0SZachary Turner     return error;
154c00cf4a0SZachary Turner }
155736888c8SGreg Clayton 
156736888c8SGreg Clayton bool
157736888c8SGreg Clayton FileSystem::IsLocal(const FileSpec &spec)
158736888c8SGreg Clayton {
159736888c8SGreg Clayton     if (spec)
160736888c8SGreg Clayton     {
161736888c8SGreg Clayton         // TODO: return true if the file is on a locally mounted file system
162736888c8SGreg Clayton         return true;
163736888c8SGreg Clayton     }
164736888c8SGreg Clayton 
165736888c8SGreg Clayton     return false;
166736888c8SGreg Clayton }
167