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" 15*cc815568SOleksiy 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; 31*cc815568SOleksiy Vyalov const auto err_code = llvm::sys::fs::create_directories(path, true); 32*cc815568SOleksiy Vyalov if (err_code) 33*cc815568SOleksiy Vyalov { 34*cc815568SOleksiy Vyalov error.SetErrorString(err_code.message().c_str()); 35*cc815568SOleksiy Vyalov } 36*cc815568SOleksiy 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 99c00cf4a0SZachary Turner FileSystem::Symlink(const char *linkname, const char *target) 100c00cf4a0SZachary Turner { 101c00cf4a0SZachary Turner Error error; 102c00cf4a0SZachary Turner DWORD attrib = ::GetFileAttributes(target); 103c00cf4a0SZachary Turner if (attrib == INVALID_FILE_ATTRIBUTES) 104c00cf4a0SZachary Turner { 105c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 106c00cf4a0SZachary Turner return error; 107c00cf4a0SZachary Turner } 108c00cf4a0SZachary Turner bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY); 109c00cf4a0SZachary Turner DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; 110c00cf4a0SZachary Turner BOOL result = ::CreateSymbolicLink(linkname, target, flag); 111c00cf4a0SZachary Turner if (!result) 112c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 113c00cf4a0SZachary Turner return error; 114c00cf4a0SZachary Turner } 115c00cf4a0SZachary Turner 116c00cf4a0SZachary Turner Error 117c00cf4a0SZachary Turner FileSystem::Unlink(const char *path) 118c00cf4a0SZachary Turner { 119c00cf4a0SZachary Turner Error error; 120c00cf4a0SZachary Turner BOOL result = ::DeleteFile(path); 121c00cf4a0SZachary Turner if (!result) 122c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 123c00cf4a0SZachary Turner return error; 124c00cf4a0SZachary Turner } 125c00cf4a0SZachary Turner 126c00cf4a0SZachary Turner Error 127c00cf4a0SZachary Turner FileSystem::Readlink(const char *path, char *buf, size_t buf_len) 128c00cf4a0SZachary Turner { 129c00cf4a0SZachary Turner Error error; 130c00cf4a0SZachary Turner HANDLE h = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 131c00cf4a0SZachary Turner FILE_FLAG_OPEN_REPARSE_POINT, NULL); 132c00cf4a0SZachary Turner if (h == INVALID_HANDLE_VALUE) 133c00cf4a0SZachary Turner { 134c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 135c00cf4a0SZachary Turner return error; 136c00cf4a0SZachary Turner } 137c00cf4a0SZachary Turner 138c00cf4a0SZachary Turner // Subtract 1 from the path length since this function does not add a null terminator. 139c00cf4a0SZachary Turner DWORD result = ::GetFinalPathNameByHandle(h, buf, buf_len - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 140c00cf4a0SZachary Turner if (result == 0) 141c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 142c00cf4a0SZachary Turner 143c00cf4a0SZachary Turner ::CloseHandle(h); 144c00cf4a0SZachary Turner return error; 145c00cf4a0SZachary Turner } 146736888c8SGreg Clayton 147736888c8SGreg Clayton bool 148736888c8SGreg Clayton FileSystem::IsLocal(const FileSpec &spec) 149736888c8SGreg Clayton { 150736888c8SGreg Clayton if (spec) 151736888c8SGreg Clayton { 152736888c8SGreg Clayton // TODO: return true if the file is on a locally mounted file system 153736888c8SGreg Clayton return true; 154736888c8SGreg Clayton } 155736888c8SGreg Clayton 156736888c8SGreg Clayton return false; 157736888c8SGreg Clayton } 158