From 8e7294f9953a98cfaae7e3bf5a6c852018cbcb83 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 28 Jun 2013 03:48:47 +0000 Subject: Improvements to unique_file and createUniqueDirectory. * Don't try to create parent directories in unique_file. It had two problem: * It violates the contract that it is atomic. If the directory creation success and the file creation fails, we would return an error but the file system was modified. * When creating a temporary file clang would have to first check if the parent directory existed or not to avoid creating one when it was not supposed to. * More efficient implementations of createUniqueDirectory and the unique_file that produces only the file name. Now all 3 just call into a static function passing what they want (name, file or directory). Clang also has to be updated, so tests might fail if a bot picks up this commit and not the corresponding clang one. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185126 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Path.inc | 156 +++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 86 deletions(-) (limited to 'lib/Support/Unix/Path.inc') diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index 94f872077a..8a94b93599 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -110,6 +110,76 @@ namespace { } } +static error_code createUniqueEntity(const Twine &Model, int &ResultFD, + SmallVectorImpl &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: { + bool Existed; + error_code EC = sys::fs::create_directory(ResultPath.begin(), Existed); + if (EC) + return EC; + if (Existed) + goto retry_random_path; + return error_code::success(); + } + } +} + namespace llvm { namespace sys { namespace fs { @@ -564,92 +634,6 @@ error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { return error_code::success(); } -error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl &result_path, - bool makeAbsolute, unsigned mode) { - SmallString<128> Model; - model.toVector(Model); - // Null terminate. - Model.c_str(); - - if (makeAbsolute) { - // Make model absolute by prepending a temp directory if it's not already. - bool absolute = path::is_absolute(Twine(Model)); - if (!absolute) { - SmallString<128> TDir; - if (error_code ec = TempDir(TDir)) return ec; - path::append(TDir, Twine(Model)); - Model.swap(TDir); - } - } - - // From here on, DO NOT modify model. It may be needed if the randomly chosen - // path already exists. - SmallString<128> RandomPath = Model; - -retry_random_path: - // Replace '%' with random chars. - for (unsigned i = 0, e = Model.size(); i != e; ++i) { - if (Model[i] == '%') - RandomPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; - } - - // Make sure we don't fall into an infinite loop by constantly trying - // to create the parent path. - bool TriedToCreateParent = false; - - // Try to open + create the file. -rety_open_create: - int RandomFD = ::open(RandomPath.c_str(), 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; - // If path prefix doesn't exist, try to create it. - if (SavedErrno == errc::no_such_file_or_directory && !TriedToCreateParent) { - TriedToCreateParent = true; - StringRef p(RandomPath); - SmallString<64> dir_to_create; - for (path::const_iterator i = path::begin(p), - e = --path::end(p); i != e; ++i) { - path::append(dir_to_create, *i); - bool Exists; - if (error_code ec = exists(Twine(dir_to_create), Exists)) return ec; - if (!Exists) { - // Don't try to create network paths. - if (i->size() > 2 && (*i)[0] == '/' && - (*i)[1] == '/' && - (*i)[2] != '/') - return make_error_code(errc::no_such_file_or_directory); - if (::mkdir(dir_to_create.c_str(), 0700) == -1 && - errno != errc::file_exists) - return error_code(errno, system_category()); - } - } - goto rety_open_create; - } - - return error_code(SavedErrno, system_category()); - } - - // Make the path absolute. - char real_path_buff[PATH_MAX + 1]; - if (realpath(RandomPath.c_str(), real_path_buff) == NULL) { - int error = errno; - ::close(RandomFD); - ::unlink(RandomPath.c_str()); - return error_code(error, system_category()); - } - - result_path.clear(); - StringRef d(real_path_buff); - result_path.append(d.begin(), d.end()); - - result_fd = RandomFD; - return error_code::success(); -} - error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) { AutoFD ScopedFD(FD); if (!CloseFD) -- cgit v1.2.3