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