117 lines
3.5 KiB
C++
117 lines
3.5 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
|
|
|
#include "stdafx.h"
|
|
#include "FileSystem.h"
|
|
|
|
std::wstring FileSystem::GetRelativePathWithTrailingSeparator(std::wstring from, std::wstring to)
|
|
{
|
|
// once c++17 filesystem is fully supported, this should become something like:
|
|
// return std::filesystem::relative(to, from) + std::filesystem::path::preferred_separator;
|
|
|
|
std::experimental::filesystem::path fromFS(std::experimental::filesystem::canonical(from));
|
|
std::experimental::filesystem::path toFS(std::experimental::filesystem::canonical(to));
|
|
|
|
std::experimental::filesystem::path result;
|
|
auto fromIter = fromFS.begin();
|
|
auto toIter = toFS.begin();
|
|
|
|
while (fromIter != fromFS.end() || toIter != toFS.end())
|
|
{
|
|
const auto& f = *fromIter;
|
|
const auto& t = *toIter;
|
|
if (f == t)
|
|
{
|
|
fromIter++;
|
|
toIter++;
|
|
}
|
|
else
|
|
{
|
|
while (fromIter != fromFS.end())
|
|
{
|
|
result /= "..";
|
|
fromIter++;
|
|
}
|
|
|
|
while (toIter != toFS.end())
|
|
{
|
|
result /= *toIter;
|
|
toIter++;
|
|
}
|
|
|
|
result += std::experimental::filesystem::path::preferred_separator;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
std::wstring FileSystem::GetBasePath(const std::wstring& path)
|
|
{
|
|
std::wstring pathCopy(path);
|
|
wchar_t *basePath = &pathCopy[0];
|
|
if (FAILED(PathCchRemoveFileSpec(basePath, pathCopy.length() + 1)))
|
|
{
|
|
throw std::invalid_argument("Invalid input path.");
|
|
}
|
|
|
|
return std::move(std::wstring(basePath));
|
|
}
|
|
|
|
|
|
std::wstring FileSystem::GetFullPath(const std::wstring& path)
|
|
{
|
|
wchar_t fullPath[MAX_PATH];
|
|
if (GetFullPathName(path.c_str(), ARRAYSIZE(fullPath), fullPath, NULL) == 0)
|
|
{
|
|
throw std::invalid_argument("Invalid input file path.");
|
|
}
|
|
return std::move(std::wstring(fullPath));
|
|
}
|
|
|
|
std::wstring FileSystem::CreateSubFolder(const std::wstring& parentPath, const std::wstring& subFolderName)
|
|
{
|
|
std::wstring errorMessageW = L"Could not create a sub-folder of " + parentPath + L".";
|
|
std::string errorMessage(errorMessageW.begin(), errorMessageW.end());
|
|
|
|
wchar_t subFolderPath[MAX_PATH];
|
|
if (FAILED(PathCchCombine(subFolderPath, ARRAYSIZE(subFolderPath), parentPath.c_str(), (subFolderName + L"\\").c_str())))
|
|
{
|
|
throw std::runtime_error(errorMessage);
|
|
}
|
|
|
|
if (CreateDirectory(subFolderPath, NULL) == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
|
|
{
|
|
throw std::runtime_error(errorMessage);
|
|
}
|
|
|
|
return std::move(std::wstring(subFolderPath));
|
|
}
|
|
|
|
std::wstring FileSystem::CreateTempFolder()
|
|
{
|
|
std::wstring errorMessageW = L"Could not get a temporary folder. Try specifying one in the command line.";
|
|
std::string errorMessage(errorMessageW.begin(), errorMessageW.end());
|
|
|
|
wchar_t tmpDirRaw[MAX_PATH];
|
|
auto returnValue = GetTempPath(MAX_PATH, tmpDirRaw);
|
|
if (returnValue > MAX_PATH || (returnValue == 0))
|
|
{
|
|
throw std::runtime_error(errorMessage);
|
|
}
|
|
|
|
// Get a random folder to drop the files
|
|
GUID guid = { 0 };
|
|
if (FAILED(CoCreateGuid(&guid)))
|
|
{
|
|
throw std::runtime_error(errorMessage);
|
|
}
|
|
|
|
wchar_t guidRaw[MAX_PATH];
|
|
if (StringFromGUID2(guid, guidRaw, ARRAYSIZE(guidRaw)) == 0)
|
|
{
|
|
throw std::runtime_error(errorMessage);
|
|
}
|
|
|
|
return std::move(CreateSubFolder(tmpDirRaw, guidRaw));
|
|
} |