1*80814287SRaphael Isemann //===-- FileSystem.cpp ----------------------------------------------------===//
2c00cf4a0SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c00cf4a0SZachary Turner //
7c00cf4a0SZachary Turner //===----------------------------------------------------------------------===//
8c00cf4a0SZachary Turner
9c00cf4a0SZachary Turner #include "lldb/Host/windows/windows.h"
10c00cf4a0SZachary Turner
11a63417feSHaibo Huang #include <share.h>
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"
188d48cd60SZachary 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
Symlink(const FileSpec & src,const FileSpec & dst)3097206d57SZachary Turner Status FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) {
3197206d57SZachary Turner Status 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
Readlink(const FileSpec & src,FileSpec & dst)5197206d57SZachary Turner Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
5297206d57SZachary Turner Status 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
7854bb3161SAleksandr Urakov dst.SetFile(path, FileSpec::Style::native);
79c00cf4a0SZachary Turner
80c00cf4a0SZachary Turner ::CloseHandle(h);
81c00cf4a0SZachary Turner return error;
82c00cf4a0SZachary Turner }
83736888c8SGreg Clayton
ResolveSymbolicLink(const FileSpec & src,FileSpec & dst)8497206d57SZachary Turner Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) {
8597206d57SZachary Turner return Status("ResolveSymbolicLink() isn't implemented on Windows");
869077e9f8SSean Callanan }
879077e9f8SSean Callanan
Fopen(const char * path,const char * mode)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 }
99d7c2b798SJonas Devlieghere
Open(const char * path,int flags,int mode)100d7c2b798SJonas Devlieghere int FileSystem::Open(const char *path, int flags, int mode) {
101d7c2b798SJonas Devlieghere std::wstring wpath;
102d7c2b798SJonas Devlieghere if (!llvm::ConvertUTF8toWide(path, wpath))
103d7c2b798SJonas Devlieghere return -1;
104d7c2b798SJonas Devlieghere int result;
105d7c2b798SJonas Devlieghere ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode);
106d7c2b798SJonas Devlieghere return result;
107d7c2b798SJonas Devlieghere }
108