1*c00cf4a0SZachary Turner //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===//
2*c00cf4a0SZachary Turner //
3*c00cf4a0SZachary Turner //                     The LLVM Compiler Infrastructure
4*c00cf4a0SZachary Turner //
5*c00cf4a0SZachary Turner // This file is distributed under the University of Illinois Open Source
6*c00cf4a0SZachary Turner // License. See LICENSE.TXT for details.
7*c00cf4a0SZachary Turner //
8*c00cf4a0SZachary Turner //===----------------------------------------------------------------------===//
9*c00cf4a0SZachary Turner 
10*c00cf4a0SZachary Turner #include "lldb/Host/windows/windows.h"
11*c00cf4a0SZachary Turner 
12*c00cf4a0SZachary Turner #include <shellapi.h>
13*c00cf4a0SZachary Turner 
14*c00cf4a0SZachary Turner #include "lldb/Host/FileSystem.h"
15*c00cf4a0SZachary Turner 
16*c00cf4a0SZachary Turner using namespace lldb_private;
17*c00cf4a0SZachary Turner 
18*c00cf4a0SZachary Turner FileSpec::PathSyntax
19*c00cf4a0SZachary Turner FileSystem::GetNativePathSyntax()
20*c00cf4a0SZachary Turner {
21*c00cf4a0SZachary Turner     return FileSpec::ePathSyntaxWindows;
22*c00cf4a0SZachary Turner }
23*c00cf4a0SZachary Turner 
24*c00cf4a0SZachary Turner Error
25*c00cf4a0SZachary Turner FileSystem::MakeDirectory(const char *path, uint32_t file_permissions)
26*c00cf4a0SZachary Turner {
27*c00cf4a0SZachary Turner     // On Win32, the mode parameter is ignored, as Windows files and directories support a
28*c00cf4a0SZachary Turner     // different permission model than POSIX.
29*c00cf4a0SZachary Turner     Error error;
30*c00cf4a0SZachary Turner     if (!::CreateDirectory(path, NULL))
31*c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
32*c00cf4a0SZachary Turner     return error;
33*c00cf4a0SZachary Turner }
34*c00cf4a0SZachary Turner 
35*c00cf4a0SZachary Turner Error
36*c00cf4a0SZachary Turner FileSystem::DeleteDirectory(const char *path, bool recurse)
37*c00cf4a0SZachary Turner {
38*c00cf4a0SZachary Turner     Error error;
39*c00cf4a0SZachary Turner     if (!recurse)
40*c00cf4a0SZachary Turner     {
41*c00cf4a0SZachary Turner         BOOL result = ::RemoveDirectory(path);
42*c00cf4a0SZachary Turner         if (!result)
43*c00cf4a0SZachary Turner             error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
44*c00cf4a0SZachary Turner     }
45*c00cf4a0SZachary Turner     else
46*c00cf4a0SZachary Turner     {
47*c00cf4a0SZachary Turner         // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to
48*c00cf4a0SZachary Turner         // indicate the end of the list.
49*c00cf4a0SZachary Turner         std::string path_buffer(path);
50*c00cf4a0SZachary Turner         path_buffer.push_back(0);
51*c00cf4a0SZachary Turner 
52*c00cf4a0SZachary Turner         SHFILEOPSTRUCT shfos = {0};
53*c00cf4a0SZachary Turner         shfos.wFunc = FO_DELETE;
54*c00cf4a0SZachary Turner         shfos.pFrom = path_buffer.c_str();
55*c00cf4a0SZachary Turner         shfos.fFlags = FOF_NO_UI;
56*c00cf4a0SZachary Turner 
57*c00cf4a0SZachary Turner         int result = ::SHFileOperation(&shfos);
58*c00cf4a0SZachary Turner         // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.
59*c00cf4a0SZachary Turner         if (result != 0)
60*c00cf4a0SZachary Turner             error.SetErrorStringWithFormat("SHFileOperation failed");
61*c00cf4a0SZachary Turner     }
62*c00cf4a0SZachary Turner     return error;
63*c00cf4a0SZachary Turner }
64*c00cf4a0SZachary Turner 
65*c00cf4a0SZachary Turner Error
66*c00cf4a0SZachary Turner FileSystem::GetFilePermissions(const char *path, uint32_t &file_permissions)
67*c00cf4a0SZachary Turner {
68*c00cf4a0SZachary Turner     Error error;
69*c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
70*c00cf4a0SZachary Turner     return error;
71*c00cf4a0SZachary Turner }
72*c00cf4a0SZachary Turner 
73*c00cf4a0SZachary Turner Error
74*c00cf4a0SZachary Turner FileSystem::SetFilePermissions(const char *path, uint32_t file_permissions)
75*c00cf4a0SZachary Turner {
76*c00cf4a0SZachary Turner     Error error;
77*c00cf4a0SZachary Turner     error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
78*c00cf4a0SZachary Turner     return error;
79*c00cf4a0SZachary Turner }
80*c00cf4a0SZachary Turner 
81*c00cf4a0SZachary Turner lldb::user_id_t
82*c00cf4a0SZachary Turner FileSystem::GetFileSize(const FileSpec &file_spec)
83*c00cf4a0SZachary Turner {
84*c00cf4a0SZachary Turner     return file_spec.GetByteSize();
85*c00cf4a0SZachary Turner }
86*c00cf4a0SZachary Turner 
87*c00cf4a0SZachary Turner bool
88*c00cf4a0SZachary Turner FileSystem::GetFileExists(const FileSpec &file_spec)
89*c00cf4a0SZachary Turner {
90*c00cf4a0SZachary Turner     return file_spec.Exists();
91*c00cf4a0SZachary Turner }
92*c00cf4a0SZachary Turner 
93*c00cf4a0SZachary Turner Error
94*c00cf4a0SZachary Turner FileSystem::Symlink(const char *linkname, const char *target)
95*c00cf4a0SZachary Turner {
96*c00cf4a0SZachary Turner     Error error;
97*c00cf4a0SZachary Turner     DWORD attrib = ::GetFileAttributes(target);
98*c00cf4a0SZachary Turner     if (attrib == INVALID_FILE_ATTRIBUTES)
99*c00cf4a0SZachary Turner     {
100*c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
101*c00cf4a0SZachary Turner         return error;
102*c00cf4a0SZachary Turner     }
103*c00cf4a0SZachary Turner     bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);
104*c00cf4a0SZachary Turner     DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
105*c00cf4a0SZachary Turner     BOOL result = ::CreateSymbolicLink(linkname, target, flag);
106*c00cf4a0SZachary Turner     if (!result)
107*c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
108*c00cf4a0SZachary Turner     return error;
109*c00cf4a0SZachary Turner }
110*c00cf4a0SZachary Turner 
111*c00cf4a0SZachary Turner Error
112*c00cf4a0SZachary Turner FileSystem::Unlink(const char *path)
113*c00cf4a0SZachary Turner {
114*c00cf4a0SZachary Turner     Error error;
115*c00cf4a0SZachary Turner     BOOL result = ::DeleteFile(path);
116*c00cf4a0SZachary Turner     if (!result)
117*c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
118*c00cf4a0SZachary Turner     return error;
119*c00cf4a0SZachary Turner }
120*c00cf4a0SZachary Turner 
121*c00cf4a0SZachary Turner Error
122*c00cf4a0SZachary Turner FileSystem::Readlink(const char *path, char *buf, size_t buf_len)
123*c00cf4a0SZachary Turner {
124*c00cf4a0SZachary Turner     Error error;
125*c00cf4a0SZachary Turner     HANDLE h = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
126*c00cf4a0SZachary Turner                             FILE_FLAG_OPEN_REPARSE_POINT, NULL);
127*c00cf4a0SZachary Turner     if (h == INVALID_HANDLE_VALUE)
128*c00cf4a0SZachary Turner     {
129*c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
130*c00cf4a0SZachary Turner         return error;
131*c00cf4a0SZachary Turner     }
132*c00cf4a0SZachary Turner 
133*c00cf4a0SZachary Turner     // Subtract 1 from the path length since this function does not add a null terminator.
134*c00cf4a0SZachary Turner     DWORD result = ::GetFinalPathNameByHandle(h, buf, buf_len - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
135*c00cf4a0SZachary Turner     if (result == 0)
136*c00cf4a0SZachary Turner         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
137*c00cf4a0SZachary Turner 
138*c00cf4a0SZachary Turner     ::CloseHandle(h);
139*c00cf4a0SZachary Turner     return error;
140*c00cf4a0SZachary Turner }
141*c00cf4a0SZachary Turner 
142*c00cf4a0SZachary Turner bool
143*c00cf4a0SZachary Turner FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high)
144*c00cf4a0SZachary Turner {
145*c00cf4a0SZachary Turner     return false;
146*c00cf4a0SZachary Turner }
147