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> 13633594c2SAdrian McCarthy #include <sys/stat.h> 14633594c2SAdrian McCarthy #include <sys/types.h> 15c00cf4a0SZachary Turner 16c00cf4a0SZachary Turner #include "lldb/Host/FileSystem.h" 172b38f33bSOleksiy Vyalov #include "lldb/Host/windows/AutoHandle.h" 18*8d48cd60SZachary Turner #include "lldb/Host/windows/PosixApi.h" 19190fadcdSZachary Turner 20190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 21cc815568SOleksiy Vyalov #include "llvm/Support/FileSystem.h" 22c00cf4a0SZachary Turner 23c00cf4a0SZachary Turner using namespace lldb_private; 24c00cf4a0SZachary Turner 25b9c1b51eSKate Stone const char *FileSystem::DEV_NULL = "nul"; 264eff2d31SZachary Turner 27b9c1b51eSKate Stone const char *FileSystem::PATH_CONVERSION_ERROR = 28b9c1b51eSKate Stone "Error converting path between UTF-8 and native encoding"; 29190fadcdSZachary Turner 30b9c1b51eSKate Stone Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { 31c00cf4a0SZachary Turner Error error; 32190fadcdSZachary Turner std::wstring wsrc, wdst; 33b9c1b51eSKate Stone if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || 34b9c1b51eSKate Stone !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) 35190fadcdSZachary Turner error.SetErrorString(PATH_CONVERSION_ERROR); 36190fadcdSZachary Turner if (error.Fail()) 37190fadcdSZachary Turner return error; 38190fadcdSZachary Turner DWORD attrib = ::GetFileAttributesW(wdst.c_str()); 39b9c1b51eSKate Stone if (attrib == INVALID_FILE_ATTRIBUTES) { 40c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 41c00cf4a0SZachary Turner return error; 42c00cf4a0SZachary Turner } 43c00cf4a0SZachary Turner bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY); 44c00cf4a0SZachary Turner DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; 45190fadcdSZachary Turner BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag); 46c00cf4a0SZachary Turner if (!result) 47c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 48c00cf4a0SZachary Turner return error; 49c00cf4a0SZachary Turner } 50c00cf4a0SZachary Turner 51b9c1b51eSKate Stone Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { 52c00cf4a0SZachary Turner Error error; 53190fadcdSZachary Turner std::wstring wsrc; 54b9c1b51eSKate Stone if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) { 55190fadcdSZachary Turner error.SetErrorString(PATH_CONVERSION_ERROR); 56190fadcdSZachary Turner return error; 57190fadcdSZachary Turner } 58190fadcdSZachary Turner 59b9c1b51eSKate Stone HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, 60b9c1b51eSKate Stone FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 61b9c1b51eSKate Stone OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL); 62b9c1b51eSKate Stone if (h == INVALID_HANDLE_VALUE) { 63c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 64c00cf4a0SZachary Turner return error; 65c00cf4a0SZachary Turner } 66c00cf4a0SZachary Turner 67190fadcdSZachary Turner std::vector<wchar_t> buf(PATH_MAX + 1); 68b9c1b51eSKate Stone // Subtract 1 from the path length since this function does not add a null 69b9c1b51eSKate Stone // terminator. 70b9c1b51eSKate Stone DWORD result = ::GetFinalPathNameByHandleW( 71b9c1b51eSKate Stone h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); 72190fadcdSZachary Turner std::string path; 73c00cf4a0SZachary Turner if (result == 0) 74c00cf4a0SZachary Turner error.SetError(::GetLastError(), lldb::eErrorTypeWin32); 75190fadcdSZachary Turner else if (!llvm::convertWideToUTF8(buf.data(), path)) 76190fadcdSZachary Turner error.SetErrorString(PATH_CONVERSION_ERROR); 77d3173f34SChaoren Lin else 78190fadcdSZachary Turner dst.SetFile(path, false); 79c00cf4a0SZachary Turner 80c00cf4a0SZachary Turner ::CloseHandle(h); 81c00cf4a0SZachary Turner return error; 82c00cf4a0SZachary Turner } 83736888c8SGreg Clayton 84b9c1b51eSKate Stone Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { 859077e9f8SSean Callanan return Error("ResolveSymbolicLink() isn't implemented on Windows"); 869077e9f8SSean Callanan } 879077e9f8SSean Callanan 88b9c1b51eSKate Stone FILE *FileSystem::Fopen(const char *path, const char *mode) { 89190fadcdSZachary Turner std::wstring wpath, wmode; 90190fadcdSZachary Turner if (!llvm::ConvertUTF8toWide(path, wpath)) 91190fadcdSZachary Turner return nullptr; 92190fadcdSZachary Turner if (!llvm::ConvertUTF8toWide(mode, wmode)) 93190fadcdSZachary Turner return nullptr; 94190fadcdSZachary Turner FILE *file; 95190fadcdSZachary Turner if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0) 96190fadcdSZachary Turner return nullptr; 97190fadcdSZachary Turner return file; 98190fadcdSZachary Turner } 99