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