Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions src/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,25 @@ std::wstring from_utf8(const std::string &str) {
return wstr;
}

// Prepend \\?\ to the path if it's an absolute drive path and doesn't
// already have it. This is needed for some Windows APIs that don't
// support long paths otherwise.
std::wstring to_long_path(const std::string &str) {
std::wstring wstr = from_utf8(str);
for (auto &c : wstr) {
if (c == L'/') {
c = L'\\';
}
}
bool is_absolute_drive_path = wstr.size() >= 2 &&
((wstr[0] >= L'A' && wstr[0] <= L'Z') || (wstr[0] >= L'a' && wstr[0] <= L'z')) &&
wstr[1] == L':';
if (is_absolute_drive_path && wstr.rfind(LR"(\\?\)", 0) != 0) {
wstr = LR"(\\?\)" + wstr;
}
return wstr;
}

} // namespace
#endif

Expand Down Expand Up @@ -316,7 +335,7 @@ std::string strip_namespaces(const std::string &name) {

bool file_exists(const std::string &name) {
#ifdef _MSC_VER
return _access(name.c_str(), 0) == 0;
return _waccess(to_long_path(name).c_str(), 0) == 0;
#else
return ::access(name.c_str(), F_OK) == 0;
#endif
Expand All @@ -332,7 +351,7 @@ void assert_no_file_exists(const std::string &name) {

void file_unlink(const std::string &name) {
#ifdef _MSC_VER
_unlink(name.c_str());
DeleteFileW(to_long_path(name).c_str());
#else
::unlink(name.c_str());
#endif
Expand All @@ -347,7 +366,7 @@ void ensure_no_file_exists(const std::string &name) {

void dir_rmdir(const std::string &name) {
#ifdef _MSC_VER
std::wstring wname = from_utf8(name);
std::wstring wname = to_long_path(name);
internal_assert(RemoveDirectoryW(wname.c_str()))
<< "RemoveDirectoryW() failed to remove " << name << "; error " << GetLastError() << "\n";
#else
Expand All @@ -359,7 +378,7 @@ void dir_rmdir(const std::string &name) {
FileStat file_stat(const std::string &name) {
#ifdef _MSC_VER
struct _stat a;
if (_stat(name.c_str(), &a) != 0) {
if (_wstat(to_long_path(name).c_str(), &a) != 0) {
user_error << "Could not stat " << name << "\n";
}
#else
Expand Down Expand Up @@ -463,7 +482,7 @@ std::string dir_make_temp() {
name << (int)guid.Data4[i];
}
std::string dir = tmp_dir + name.str();
std::wstring wdir = from_utf8(dir);
std::wstring wdir = to_long_path(dir);
BOOL success = CreateDirectoryW(wdir.c_str(), nullptr);
if (success) {
debug(1) << "temp dir is: " << dir << "\n";
Expand All @@ -489,7 +508,11 @@ std::string dir_make_temp() {
}

std::vector<char> read_entire_file(const std::string &pathname) {
#ifdef _MSC_VER
std::ifstream f(to_long_path(pathname).c_str(), std::ios::in | std::ios::binary);
#else
std::ifstream f(pathname, std::ios::in | std::ios::binary);
#endif
std::vector<char> result;

f.seekg(0, std::ifstream::end);
Expand All @@ -503,7 +526,11 @@ std::vector<char> read_entire_file(const std::string &pathname) {
}

void write_entire_file(const std::string &pathname, const void *source, size_t source_len) {
#ifdef _MSC_VER
std::ofstream f(to_long_path(pathname).c_str(), std::ios::out | std::ios::binary);
#else
std::ofstream f(pathname, std::ios::out | std::ios::binary);
#endif

f.write(reinterpret_cast<const char *>(source), source_len);
f.flush();
Expand Down Expand Up @@ -536,7 +563,7 @@ int run_process(std::vector<std::string> args, const std::string &stdout_path, c
int saved_stdout = -1, saved_stderr = -1;
if (!stdout_path.empty()) {
saved_stdout = _dup(_fileno(stdout));
int fd = _open(stdout_path.c_str(), _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, _S_IWRITE);
int fd = _wopen(to_long_path(stdout_path).c_str(), _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, _S_IWRITE);
if (fd == -1) {
if (saved_stdout != -1) {
_close(saved_stdout);
Expand All @@ -555,7 +582,7 @@ int run_process(std::vector<std::string> args, const std::string &stdout_path, c
// writes would clobber each other instead of concatenating.
_dup2(_fileno(stdout), _fileno(stderr));
} else {
int fd = _open(stderr_path.c_str(), _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, _S_IWRITE);
int fd = _wopen(to_long_path(stderr_path).c_str(), _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, _S_IWRITE);
if (fd == -1) {
if (saved_stdout != -1) {
_dup2(saved_stdout, _fileno(stdout));
Expand Down
Loading