diff options
Diffstat (limited to 'source/Host/windows/FileSystem.cpp')
| -rw-r--r-- | source/Host/windows/FileSystem.cpp | 120 | 
1 files changed, 96 insertions, 24 deletions
diff --git a/source/Host/windows/FileSystem.cpp b/source/Host/windows/FileSystem.cpp index 2cca12b92711..3e881f5d9b2b 100644 --- a/source/Host/windows/FileSystem.cpp +++ b/source/Host/windows/FileSystem.cpp @@ -15,6 +15,8 @@  #include "lldb/Host/FileSystem.h"  #include "lldb/Host/windows/AutoHandle.h" + +#include "llvm/Support/ConvertUTF.h"  #include "llvm/Support/FileSystem.h"  using namespace lldb_private; @@ -22,6 +24,8 @@ using namespace lldb_private;  const char *  FileSystem::DEV_NULL = "nul"; +const char *FileSystem::PATH_CONVERSION_ERROR = "Error converting path between UTF-8 and native encoding"; +  FileSpec::PathSyntax  FileSystem::GetNativePathSyntax()  { @@ -47,25 +51,32 @@ Error  FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)  {      Error error; +    std::wstring path_buffer; +    if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer)) +    { +        error.SetErrorString(PATH_CONVERSION_ERROR); +        return error; +    }      if (!recurse)      { -        BOOL result = ::RemoveDirectory(file_spec.GetCString()); +        BOOL result = ::RemoveDirectoryW(path_buffer.c_str());          if (!result)              error.SetError(::GetLastError(), lldb::eErrorTypeWin32);      }      else      {          // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to -        // indicate the end of the list. -        std::string path_buffer{file_spec.GetPath()}; +        // indicate the end of the list. The first null terminator is there only in the backing +        // store but not the actual vector contents, and so we need to push twice. +        path_buffer.push_back(0);          path_buffer.push_back(0); -        SHFILEOPSTRUCT shfos = {0}; +        SHFILEOPSTRUCTW shfos = {0};          shfos.wFunc = FO_DELETE; -        shfos.pFrom = path_buffer.c_str(); +        shfos.pFrom = (LPCWSTR)path_buffer.data();          shfos.fFlags = FOF_NO_UI; -        int result = ::SHFileOperation(&shfos); +        int result = ::SHFileOperationW(&shfos);          // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.          if (result != 0)              error.SetErrorStringWithFormat("SHFileOperation failed"); @@ -121,7 +132,10 @@ Error  FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)  {      Error error; -    if (!::CreateHardLink(src.GetCString(), dst.GetCString(), nullptr)) +    std::wstring wsrc, wdst; +    if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) +        error.SetErrorString(PATH_CONVERSION_ERROR); +    else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr))          error.SetError(::GetLastError(), lldb::eErrorTypeWin32);      return error;  } @@ -129,13 +143,12 @@ FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)  int  FileSystem::GetHardlinkCount(const FileSpec &file_spec)  { -    HANDLE file_handle = ::CreateFile(file_spec.GetCString(), -                                      FILE_READ_ATTRIBUTES, -                                      FILE_SHARE_READ, -                                      nullptr, -                                      OPEN_EXISTING, -                                      FILE_ATTRIBUTE_NORMAL, -                                      nullptr); +    std::wstring path; +    if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) +        return -1; + +    HANDLE file_handle = ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, +                                       FILE_ATTRIBUTE_NORMAL, nullptr);      if (file_handle == INVALID_HANDLE_VALUE)        return -1; @@ -152,7 +165,12 @@ Error  FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)  {      Error error; -    DWORD attrib = ::GetFileAttributes(dst.GetCString()); +    std::wstring wsrc, wdst; +    if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst)) +        error.SetErrorString(PATH_CONVERSION_ERROR); +    if (error.Fail()) +        return error; +    DWORD attrib = ::GetFileAttributesW(wdst.c_str());      if (attrib == INVALID_FILE_ATTRIBUTES)      {          error.SetError(::GetLastError(), lldb::eErrorTypeWin32); @@ -160,7 +178,7 @@ FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)      }      bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);      DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; -    BOOL result = ::CreateSymbolicLink(src.GetCString(), dst.GetCString(), flag); +    BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag);      if (!result)          error.SetError(::GetLastError(), lldb::eErrorTypeWin32);      return error; @@ -170,7 +188,13 @@ Error  FileSystem::Unlink(const FileSpec &file_spec)  {      Error error; -    BOOL result = ::DeleteFile(file_spec.GetCString()); +    std::wstring path; +    if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path)) +    { +        error.SetErrorString(PATH_CONVERSION_ERROR); +        return error; +    } +    BOOL result = ::DeleteFileW(path.c_str());      if (!result)          error.SetError(::GetLastError(), lldb::eErrorTypeWin32);      return error; @@ -180,23 +204,31 @@ Error  FileSystem::Readlink(const FileSpec &src, FileSpec &dst)  {      Error error; -    HANDLE h = ::CreateFile(src.GetCString(), GENERIC_READ, -            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, -            FILE_FLAG_OPEN_REPARSE_POINT, NULL); +    std::wstring wsrc; +    if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) +    { +        error.SetErrorString(PATH_CONVERSION_ERROR); +        return error; +    } + +    HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, +                             FILE_FLAG_OPEN_REPARSE_POINT, NULL);      if (h == INVALID_HANDLE_VALUE)      {          error.SetError(::GetLastError(), lldb::eErrorTypeWin32);          return error;      } -    char buf[PATH_MAX]; +    std::vector<wchar_t> buf(PATH_MAX + 1);      // Subtract 1 from the path length since this function does not add a null terminator. -    DWORD result = ::GetFinalPathNameByHandle(h, buf, sizeof(buf) - 1, -            FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); +    DWORD result = ::GetFinalPathNameByHandleW(h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); +    std::string path;      if (result == 0)          error.SetError(::GetLastError(), lldb::eErrorTypeWin32); +    else if (!llvm::convertWideToUTF8(buf.data(), path)) +        error.SetErrorString(PATH_CONVERSION_ERROR);      else -        dst.SetFile(buf, false); +        dst.SetFile(path, false);      ::CloseHandle(h);      return error; @@ -219,3 +251,43 @@ FileSystem::IsLocal(const FileSpec &spec)      return false;  } + +FILE * +FileSystem::Fopen(const char *path, const char *mode) +{ +    std::wstring wpath, wmode; +    if (!llvm::ConvertUTF8toWide(path, wpath)) +        return nullptr; +    if (!llvm::ConvertUTF8toWide(mode, wmode)) +        return nullptr; +    FILE *file; +    if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0) +        return nullptr; +    return file; +} + +int +FileSystem::Stat(const char *path, struct stat *stats) +{ +    std::wstring wpath; +    if (!llvm::ConvertUTF8toWide(path, wpath)) +    { +        errno = EINVAL; +        return -EINVAL; +    } +    int stat_result; +#ifdef _USE_32BIT_TIME_T +    struct _stat32 file_stats; +    stat_result = ::_wstat32(wpath.c_str(), &file_stats); +#else +    struct _stat64i32 file_stats; +    stat_result = ::_wstat64i32(wpath.c_str(), &file_stats); +#endif +    if (stat_result == 0) +    { +        static_assert(sizeof(struct stat) == sizeof(file_stats), +                      "stat and _stat32/_stat64i32 must have the same layout"); +        *stats = *reinterpret_cast<struct stat *>(&file_stats); +    } +    return stat_result; +}  | 
