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 26*d3173f34SChaoren Lin FileSystem::MakeDirectory(const FileSpec &file_spec, 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; 31*d3173f34SChaoren Lin const auto err_code = llvm::sys::fs::create_directories(file_spec.GetPath(), 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 41*d3173f34SChaoren Lin FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) 42c00cf4a0SZachary Turner { 43c00cf4a0SZachary Turner Error error; 44c00cf4a0SZachary Turner if (!recurse) 45c00cf4a0SZachary Turner { 46*d3173f34SChaoren Lin BOOL result = ::RemoveDirectory(file_spec.GetCString()); 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. 54*d3173f34SChaoren Lin std::string path_buffer{file_spec.GetPath()}; 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 71*d3173f34SChaoren Lin FileSystem::GetFilePermissions(const FileSpec &file_spec, 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 79*d3173f34SChaoren Lin FileSystem::SetFilePermissions(const FileSpec &file_spec, 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*d3173f34SChaoren Lin FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) 100a9ea0711SOleksiy Vyalov { 101a9ea0711SOleksiy Vyalov Error error; 102*d3173f34SChaoren Lin if (!::CreateHardLink(src.GetCString(), dst.GetCString(), nullptr)) 103a9ea0711SOleksiy Vyalov error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 104a9ea0711SOleksiy Vyalov return error; 105a9ea0711SOleksiy Vyalov } 106a9ea0711SOleksiy Vyalov 107a9ea0711SOleksiy Vyalov Error 108*d3173f34SChaoren Lin FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) 109c00cf4a0SZachary Turner { 110c00cf4a0SZachary Turner Error error; 111*d3173f34SChaoren Lin DWORD attrib = ::GetFileAttributes(dst.GetCString()); 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; 119*d3173f34SChaoren Lin BOOL result = ::CreateSymbolicLink(src.GetCString(), dst.GetCString(), flag); 120c00cf4a0SZachary Turner if (!result) 121c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 122c00cf4a0SZachary Turner return error; 123c00cf4a0SZachary Turner } 124c00cf4a0SZachary Turner 125c00cf4a0SZachary Turner Error 126*d3173f34SChaoren Lin FileSystem::Unlink(const FileSpec &file_spec) 127c00cf4a0SZachary Turner { 128c00cf4a0SZachary Turner Error error; 129*d3173f34SChaoren Lin BOOL result = ::DeleteFile(file_spec.GetCString()); 130c00cf4a0SZachary Turner if (!result) 131c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 132c00cf4a0SZachary Turner return error; 133c00cf4a0SZachary Turner } 134c00cf4a0SZachary Turner 135c00cf4a0SZachary Turner Error 136*d3173f34SChaoren Lin FileSystem::Readlink(const FileSpec &src, FileSpec &dst) 137c00cf4a0SZachary Turner { 138c00cf4a0SZachary Turner Error error; 139*d3173f34SChaoren Lin HANDLE h = ::CreateFile(src.GetCString(), GENERIC_READ, 140*d3173f34SChaoren Lin FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 141c00cf4a0SZachary Turner FILE_FLAG_OPEN_REPARSE_POINT, NULL); 142c00cf4a0SZachary Turner if (h == INVALID_HANDLE_VALUE) 143c00cf4a0SZachary Turner { 144c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 145c00cf4a0SZachary Turner return error; 146c00cf4a0SZachary Turner } 147c00cf4a0SZachary Turner 148*d3173f34SChaoren Lin char buf[PATH_MAX]; 149c00cf4a0SZachary Turner // Subtract 1 from the path length since this function does not add a null terminator. 150*d3173f34SChaoren Lin DWORD result = ::GetFinalPathNameByHandle(h, buf, sizeof(buf) - 1, 151*d3173f34SChaoren Lin FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 152c00cf4a0SZachary Turner if (result == 0) 153c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 154*d3173f34SChaoren Lin else 155*d3173f34SChaoren Lin dst.SetFile(buf, false); 156c00cf4a0SZachary Turner 157c00cf4a0SZachary Turner ::CloseHandle(h); 158c00cf4a0SZachary Turner return error; 159c00cf4a0SZachary Turner } 160736888c8SGreg Clayton 161736888c8SGreg Clayton bool 162736888c8SGreg Clayton FileSystem::IsLocal(const FileSpec &spec) 163736888c8SGreg Clayton { 164736888c8SGreg Clayton if (spec) 165736888c8SGreg Clayton { 166736888c8SGreg Clayton // TODO: return true if the file is on a locally mounted file system 167736888c8SGreg Clayton return true; 168736888c8SGreg Clayton } 169736888c8SGreg Clayton 170736888c8SGreg Clayton return false; 171736888c8SGreg Clayton } 172