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
This commit is contained in:
Rafael Espindola
2013-06-28 03:48:47 +00:00
parent 1300638d50
commit 8e7294f995
3 changed files with 237 additions and 243 deletions

View File

@ -153,6 +153,18 @@ namespace {
}
} // end unnamed namespace
enum FSEntity {
FS_Dir,
FS_File,
FS_Name
};
// 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);
namespace llvm {
namespace sys {
namespace path {
@ -625,32 +637,31 @@ bool is_relative(const Twine &path) {
namespace fs {
error_code unique_file(const Twine &Model, SmallVectorImpl<char> &ResultPath,
bool MakeAbsolute) {
// FIXME: This is really inefficient. unique_path creates a path an tries to
// open it. We should factor the code so that we just don't create/open the
// file when we don't need it.
int FD;
error_code Ret = unique_file(Model, FD, ResultPath, MakeAbsolute, all_read);
if (Ret)
return Ret;
if (close(FD))
return error_code(errno, system_category());
StringRef P(ResultPath.begin(), ResultPath.size());
return fs::remove(P);
// This is a mkostemps with a different pattern. Unfortunatelly OS X (ond *BSD)
// don't have it. It might be worth experimenting with mkostemps on systems
// that have it.
error_code unique_file(const Twine &Model, int &ResultFD,
SmallVectorImpl<char> &ResultPath, bool MakeAbsolute,
unsigned Mode) {
return createUniqueEntity(Model, ResultFD, ResultPath, MakeAbsolute, Mode,
FS_File);
}
// This is a mktemp with a differet pattern. We use createUniqueEntity mostly
// for consistency. It might be worth it experimenting with mktemp.
error_code unique_file(const Twine &Model, SmallVectorImpl<char> &ResultPath,
bool MakeAbsolute) {
int Dummy;
return createUniqueEntity(Model, Dummy, ResultPath, MakeAbsolute, 0, FS_Name);
}
// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
// for consistency. It might be worth it experimenting with mkdtemp.
error_code createUniqueDirectory(const Twine &Prefix,
SmallVectorImpl<char> &ResultPath) {
// FIXME: This is double inefficient. We compute a unique file name, created
// it, delete it and keep only the directory.
error_code EC = unique_file(Prefix + "-%%%%%%/dummy", ResultPath);
if (EC)
return EC;
path::remove_filename(ResultPath);
return error_code::success();
int Dummy;
return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
true, 0, FS_Dir);
}
error_code make_absolute(SmallVectorImpl<char> &path) {