mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
Share a createUniqueEntity implementation between unix and windows.
The only extra bit of functionality that had to be exposed for this be be implemented in Path.cpp is opening a file in rw mode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202005 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6822655f56
commit
69aeeee4e1
@ -580,7 +580,10 @@ enum OpenFlags {
|
|||||||
|
|
||||||
/// F_Binary - The file should be opened in binary mode on platforms that
|
/// F_Binary - The file should be opened in binary mode on platforms that
|
||||||
/// make this distinction.
|
/// make this distinction.
|
||||||
F_Binary = 4
|
F_Binary = 4,
|
||||||
|
|
||||||
|
/// Open the file for read and write.
|
||||||
|
F_RW = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
|
inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
using llvm::StringRef;
|
using llvm::StringRef;
|
||||||
using llvm::sys::path::is_separator;
|
using llvm::sys::path::is_separator;
|
||||||
@ -162,10 +164,75 @@ enum FSEntity {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Implemented in Unix/Path.inc and Windows/Path.inc.
|
// Implemented in Unix/Path.inc and Windows/Path.inc.
|
||||||
static llvm::error_code
|
static error_code TempDir(SmallVectorImpl<char> &result);
|
||||||
createUniqueEntity(const llvm::Twine &Model, int &ResultFD,
|
|
||||||
llvm::SmallVectorImpl<char> &ResultPath,
|
static error_code createUniqueEntity(const Twine &Model, int &ResultFD,
|
||||||
bool MakeAbsolute, unsigned Mode, FSEntity Type);
|
SmallVectorImpl<char> &ResultPath,
|
||||||
|
bool MakeAbsolute, unsigned Mode,
|
||||||
|
FSEntity Type) {
|
||||||
|
SmallString<128> ModelStorage;
|
||||||
|
Model.toVector(ModelStorage);
|
||||||
|
|
||||||
|
if (MakeAbsolute) {
|
||||||
|
// Make model absolute by prepending a temp directory if it's not already.
|
||||||
|
if (!sys::path::is_absolute(Twine(ModelStorage))) {
|
||||||
|
SmallString<128> TDir;
|
||||||
|
if (error_code EC = TempDir(TDir))
|
||||||
|
return EC;
|
||||||
|
sys::path::append(TDir, Twine(ModelStorage));
|
||||||
|
ModelStorage.swap(TDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From here on, DO NOT modify model. It may be needed if the randomly chosen
|
||||||
|
// path already exists.
|
||||||
|
ResultPath = ModelStorage;
|
||||||
|
// Null terminate.
|
||||||
|
ResultPath.push_back(0);
|
||||||
|
ResultPath.pop_back();
|
||||||
|
|
||||||
|
retry_random_path:
|
||||||
|
// Replace '%' with random chars.
|
||||||
|
for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
|
||||||
|
if (ModelStorage[i] == '%')
|
||||||
|
ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to open + create the file.
|
||||||
|
switch (Type) {
|
||||||
|
case FS_File: {
|
||||||
|
if (error_code EC = sys::fs::openFileForWrite(
|
||||||
|
Twine(ResultPath.begin()), ResultFD,
|
||||||
|
sys::fs::F_RW | sys::fs::F_Excl | sys::fs::F_Binary, Mode)) {
|
||||||
|
if (EC == errc::file_exists)
|
||||||
|
goto retry_random_path;
|
||||||
|
return EC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error_code::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
case FS_Name: {
|
||||||
|
bool Exists;
|
||||||
|
error_code EC = sys::fs::exists(ResultPath.begin(), Exists);
|
||||||
|
if (EC)
|
||||||
|
return EC;
|
||||||
|
if (Exists)
|
||||||
|
goto retry_random_path;
|
||||||
|
return error_code::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
case FS_Dir: {
|
||||||
|
if (error_code EC = sys::fs::create_directory(ResultPath.begin(), false)) {
|
||||||
|
if (EC == errc::file_exists)
|
||||||
|
goto retry_random_path;
|
||||||
|
return EC;
|
||||||
|
}
|
||||||
|
return error_code::success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
llvm_unreachable("Invalid Type");
|
||||||
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace sys {
|
namespace sys {
|
||||||
|
@ -103,76 +103,6 @@ static error_code TempDir(SmallVectorImpl<char> &result) {
|
|||||||
return error_code::success();
|
return error_code::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_code createUniqueEntity(const Twine &Model, int &ResultFD,
|
|
||||||
SmallVectorImpl<char> &ResultPath,
|
|
||||||
bool MakeAbsolute, unsigned Mode,
|
|
||||||
FSEntity Type) {
|
|
||||||
SmallString<128> ModelStorage;
|
|
||||||
Model.toVector(ModelStorage);
|
|
||||||
|
|
||||||
if (MakeAbsolute) {
|
|
||||||
// Make model absolute by prepending a temp directory if it's not already.
|
|
||||||
bool absolute = sys::path::is_absolute(Twine(ModelStorage));
|
|
||||||
if (!absolute) {
|
|
||||||
SmallString<128> TDir;
|
|
||||||
if (error_code ec = TempDir(TDir)) return ec;
|
|
||||||
sys::path::append(TDir, Twine(ModelStorage));
|
|
||||||
ModelStorage.swap(TDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// From here on, DO NOT modify model. It may be needed if the randomly chosen
|
|
||||||
// path already exists.
|
|
||||||
ResultPath = ModelStorage;
|
|
||||||
// Null terminate.
|
|
||||||
ResultPath.push_back(0);
|
|
||||||
ResultPath.pop_back();
|
|
||||||
|
|
||||||
retry_random_path:
|
|
||||||
// Replace '%' with random chars.
|
|
||||||
for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
|
|
||||||
if (ModelStorage[i] == '%')
|
|
||||||
ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to open + create the file.
|
|
||||||
switch (Type) {
|
|
||||||
case FS_File: {
|
|
||||||
int RandomFD = ::open(ResultPath.begin(), O_RDWR | O_CREAT | O_EXCL, Mode);
|
|
||||||
if (RandomFD == -1) {
|
|
||||||
int SavedErrno = errno;
|
|
||||||
// If the file existed, try again, otherwise, error.
|
|
||||||
if (SavedErrno == errc::file_exists)
|
|
||||||
goto retry_random_path;
|
|
||||||
return error_code(SavedErrno, system_category());
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultFD = RandomFD;
|
|
||||||
return error_code::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
case FS_Name: {
|
|
||||||
bool Exists;
|
|
||||||
error_code EC = sys::fs::exists(ResultPath.begin(), Exists);
|
|
||||||
if (EC)
|
|
||||||
return EC;
|
|
||||||
if (Exists)
|
|
||||||
goto retry_random_path;
|
|
||||||
return error_code::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
case FS_Dir: {
|
|
||||||
if (error_code EC = sys::fs::create_directory(ResultPath.begin(), false)) {
|
|
||||||
if (EC == errc::file_exists)
|
|
||||||
goto retry_random_path;
|
|
||||||
return EC;
|
|
||||||
}
|
|
||||||
return error_code::success();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
llvm_unreachable("Invalid Type");
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace sys {
|
namespace sys {
|
||||||
namespace fs {
|
namespace fs {
|
||||||
@ -755,7 +685,12 @@ error_code openFileForWrite(const Twine &Name, int &ResultFD,
|
|||||||
assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
|
assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
|
||||||
"Cannot specify both 'excl' and 'append' file creation flags!");
|
"Cannot specify both 'excl' and 'append' file creation flags!");
|
||||||
|
|
||||||
int OpenFlags = O_WRONLY | O_CREAT;
|
int OpenFlags = O_CREAT;
|
||||||
|
|
||||||
|
if (Flags & F_RW)
|
||||||
|
OpenFlags |= O_RDWR;
|
||||||
|
else
|
||||||
|
OpenFlags |= O_WRONLY;
|
||||||
|
|
||||||
if (Flags & F_Append)
|
if (Flags & F_Append)
|
||||||
OpenFlags |= O_APPEND;
|
OpenFlags |= O_APPEND;
|
||||||
|
@ -44,20 +44,21 @@ using namespace llvm;
|
|||||||
using llvm::sys::windows::UTF8ToUTF16;
|
using llvm::sys::windows::UTF8ToUTF16;
|
||||||
using llvm::sys::windows::UTF16ToUTF8;
|
using llvm::sys::windows::UTF16ToUTF8;
|
||||||
|
|
||||||
static error_code TempDir(SmallVectorImpl<wchar_t> &result) {
|
static error_code TempDir(SmallVectorImpl<char> &Result) {
|
||||||
|
SmallVector<wchar_t, 64> Res;
|
||||||
retry_temp_dir:
|
retry_temp_dir:
|
||||||
DWORD len = ::GetTempPathW(result.capacity(), result.begin());
|
DWORD Len = ::GetTempPathW(Res.capacity(), Res.begin());
|
||||||
|
|
||||||
if (len == 0)
|
if (Len == 0)
|
||||||
return windows_error(::GetLastError());
|
return windows_error(::GetLastError());
|
||||||
|
|
||||||
if (len > result.capacity()) {
|
if (Len > Res.capacity()) {
|
||||||
result.reserve(len);
|
Res.reserve(Len);
|
||||||
goto retry_temp_dir;
|
goto retry_temp_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.set_size(len);
|
Res.set_size(Len);
|
||||||
return error_code::success();
|
return UTF16ToUTF8(Res.begin(), Res.size(), Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_separator(const wchar_t value) {
|
static bool is_separator(const wchar_t value) {
|
||||||
@ -70,128 +71,6 @@ static bool is_separator(const wchar_t value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: mode should be used here and default to user r/w only,
|
|
||||||
// it currently comes in as a UNIX mode.
|
|
||||||
static error_code createUniqueEntity(const Twine &model, int &result_fd,
|
|
||||||
SmallVectorImpl<char> &result_path,
|
|
||||||
bool makeAbsolute, unsigned mode,
|
|
||||||
FSEntity Type) {
|
|
||||||
// Use result_path as temp storage.
|
|
||||||
result_path.set_size(0);
|
|
||||||
StringRef m = model.toStringRef(result_path);
|
|
||||||
|
|
||||||
SmallVector<wchar_t, 128> model_utf16;
|
|
||||||
if (error_code ec = UTF8ToUTF16(m, model_utf16)) return ec;
|
|
||||||
|
|
||||||
if (makeAbsolute) {
|
|
||||||
// Make model absolute by prepending a temp directory if it's not already.
|
|
||||||
bool absolute = sys::path::is_absolute(m);
|
|
||||||
|
|
||||||
if (!absolute) {
|
|
||||||
SmallVector<wchar_t, 64> temp_dir;
|
|
||||||
if (error_code ec = TempDir(temp_dir)) return ec;
|
|
||||||
// Handle c: by removing it.
|
|
||||||
if (model_utf16.size() > 2 && model_utf16[1] == L':') {
|
|
||||||
model_utf16.erase(model_utf16.begin(), model_utf16.begin() + 2);
|
|
||||||
}
|
|
||||||
model_utf16.insert(model_utf16.begin(), temp_dir.begin(), temp_dir.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace '%' with random chars. From here on, DO NOT modify model. It may be
|
|
||||||
// needed if the randomly chosen path already exists.
|
|
||||||
SmallVector<wchar_t, 128> random_path_utf16;
|
|
||||||
|
|
||||||
retry_random_path:
|
|
||||||
random_path_utf16.set_size(0);
|
|
||||||
for (SmallVectorImpl<wchar_t>::const_iterator i = model_utf16.begin(),
|
|
||||||
e = model_utf16.end();
|
|
||||||
i != e; ++i) {
|
|
||||||
if (*i == L'%') {
|
|
||||||
unsigned val = sys::Process::GetRandomNumber();
|
|
||||||
random_path_utf16.push_back(L"0123456789abcdef"[val & 15]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
random_path_utf16.push_back(*i);
|
|
||||||
}
|
|
||||||
// Make random_path_utf16 null terminated.
|
|
||||||
random_path_utf16.push_back(0);
|
|
||||||
random_path_utf16.pop_back();
|
|
||||||
|
|
||||||
HANDLE TempFileHandle = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
switch (Type) {
|
|
||||||
case FS_File: {
|
|
||||||
// Try to create + open the path.
|
|
||||||
TempFileHandle =
|
|
||||||
::CreateFileW(random_path_utf16.begin(), GENERIC_READ | GENERIC_WRITE,
|
|
||||||
FILE_SHARE_READ, NULL,
|
|
||||||
// Return ERROR_FILE_EXISTS if the file
|
|
||||||
// already exists.
|
|
||||||
CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL);
|
|
||||||
if (TempFileHandle == INVALID_HANDLE_VALUE) {
|
|
||||||
// If the file existed, try again, otherwise, error.
|
|
||||||
error_code ec = windows_error(::GetLastError());
|
|
||||||
if (ec == windows_error::file_exists)
|
|
||||||
goto retry_random_path;
|
|
||||||
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the Windows API file handle into a C-runtime handle.
|
|
||||||
int fd = ::_open_osfhandle(intptr_t(TempFileHandle), 0);
|
|
||||||
if (fd == -1) {
|
|
||||||
::CloseHandle(TempFileHandle);
|
|
||||||
::DeleteFileW(random_path_utf16.begin());
|
|
||||||
// MSDN doesn't say anything about _open_osfhandle setting errno or
|
|
||||||
// GetLastError(), so just return invalid_handle.
|
|
||||||
return windows_error::invalid_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
result_fd = fd;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FS_Name: {
|
|
||||||
DWORD attributes = ::GetFileAttributesW(random_path_utf16.begin());
|
|
||||||
if (attributes != INVALID_FILE_ATTRIBUTES)
|
|
||||||
goto retry_random_path;
|
|
||||||
error_code EC = make_error_code(windows_error(::GetLastError()));
|
|
||||||
if (EC != windows_error::file_not_found &&
|
|
||||||
EC != windows_error::path_not_found)
|
|
||||||
return EC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FS_Dir:
|
|
||||||
if (!::CreateDirectoryW(random_path_utf16.begin(), NULL)) {
|
|
||||||
error_code EC = windows_error(::GetLastError());
|
|
||||||
if (EC != windows_error::already_exists)
|
|
||||||
return EC;
|
|
||||||
goto retry_random_path;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set result_path to the utf-8 representation of the path.
|
|
||||||
if (error_code ec = UTF16ToUTF8(random_path_utf16.begin(),
|
|
||||||
random_path_utf16.size(), result_path)) {
|
|
||||||
switch (Type) {
|
|
||||||
case FS_File:
|
|
||||||
::CloseHandle(TempFileHandle);
|
|
||||||
::DeleteFileW(random_path_utf16.begin());
|
|
||||||
case FS_Name:
|
|
||||||
break;
|
|
||||||
case FS_Dir:
|
|
||||||
::RemoveDirectoryW(random_path_utf16.begin());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
return error_code::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace sys {
|
namespace sys {
|
||||||
namespace fs {
|
namespace fs {
|
||||||
@ -973,7 +852,11 @@ error_code openFileForWrite(const Twine &Name, int &ResultFD,
|
|||||||
else
|
else
|
||||||
CreationDisposition = CREATE_ALWAYS;
|
CreationDisposition = CREATE_ALWAYS;
|
||||||
|
|
||||||
HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_WRITE,
|
DWORD Access = GENERIC_WRITE;
|
||||||
|
if (Flags & F_RW)
|
||||||
|
Access |= GENERIC_READ;
|
||||||
|
|
||||||
|
HANDLE H = ::CreateFileW(PathUTF16.begin(), Access,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||||
CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
|
CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user