diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2014-02-24 03:07:41 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2014-02-24 03:07:41 +0000 |
commit | 7a0b640dfa05b9d00746973277bac1fd4cb5b531 (patch) | |
tree | 7c8930d5aeb5b00f0a414226dd7c2ff66765b7b1 /llvm/lib/Support/Path.cpp | |
parent | ad64f6d4e541972ee688fca23eae71b2304e567c (diff) | |
download | bcm5719-llvm-7a0b640dfa05b9d00746973277bac1fd4cb5b531.tar.gz bcm5719-llvm-7a0b640dfa05b9d00746973277bac1fd4cb5b531.zip |
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.
llvm-svn: 202005
Diffstat (limited to 'llvm/lib/Support/Path.cpp')
-rw-r--r-- | llvm/lib/Support/Path.cpp | 75 |
1 files changed, 71 insertions, 4 deletions
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp index 535ff00bae0..5b8be18db3f 100644 --- a/llvm/lib/Support/Path.cpp +++ b/llvm/lib/Support/Path.cpp @@ -27,6 +27,8 @@ #include <io.h> #endif +using namespace llvm; + namespace { using llvm::StringRef; using llvm::sys::path::is_separator; @@ -162,10 +164,75 @@ enum FSEntity { }; // Implemented in Unix/Path.inc and Windows/Path.inc. -static llvm::error_code -createUniqueEntity(const llvm::Twine &Model, int &ResultFD, - llvm::SmallVectorImpl<char> &ResultPath, - bool MakeAbsolute, unsigned Mode, FSEntity Type); +static error_code TempDir(SmallVectorImpl<char> &result); + +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. + 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 sys { |