blob: 1b31be19181ac0b644c10ab35232592fac8ddec3 [file] [log] [blame]
// Copyright 2014 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "scoped_tmp_file.h"
#include <limits.h>
#include <sstream>
#include "file_dir.h"
#include "filesystem.h"
#include "glog/logging.h"
#include "mypath.h"
#include "path.h"
#include "rand_util.h"
#include "scoped_fd.h"
#ifdef _WIN32
# include "posix_helper_win.h"
#endif
namespace devtools_goma {
ScopedTmpFile::ScopedTmpFile(const string& prefix) {
#ifndef _WIN32
static const char kMkstempMarker[] = "XXXXXX";
filename_.assign(file::JoinPath(GetGomaTmpDir(), prefix));
filename_.append(kMkstempMarker);
fd_.reset(mkstemp(&filename_[0]));
#else
char temp_file[MAX_PATH] = {0};
if (GetTempFileNameA(GetGomaTmpDir().c_str(),
prefix.c_str(), 0, temp_file) != 0) {
filename_ = temp_file;
fd_.reset(ScopedFd::Create(filename_, 0600));
}
#endif
if (!fd_.valid()) {
PLOG(ERROR) << "failed to create temp file:"
<< " filename=" << filename_;
}
}
ScopedTmpFile::ScopedTmpFile(const string& prefix, const string& extension) {
DCHECK(!extension.empty());
DCHECK_EQ(extension[0], '.');
static const int kNumRetries = 5;
for (int retry = 0; retry < kNumRetries; ++retry) {
std::ostringstream ss;
ss << prefix;
ss << GetRandomAlphanumeric(10);
ss << extension;
filename_ = file::JoinPath(GetGomaTmpDir(), ss.str());
fd_.reset(ScopedFd::CreateExclusive(filename_, 0600));
if (fd_.valid())
break;
LOG(INFO) << "failed to make a unique file: " << filename_;
}
LOG_IF(ERROR, !fd_.valid()) << "Could not have a valid tmp file."
<< " prefix=" << prefix
<< " extension=" << extension;
}
ScopedTmpFile::~ScopedTmpFile() {
Close();
remove(filename_.c_str());
}
bool ScopedTmpFile::valid() const {
return fd_.valid();
}
ssize_t ScopedTmpFile::Write(const void* ptr, size_t len) const {
return fd_.Write(ptr, len);
}
bool ScopedTmpFile::Close() {
return fd_.Close();
}
ScopedTmpDir::ScopedTmpDir(const string& prefix) {
char tmpdir[PATH_MAX];
CheckTempDirectory(GetGomaTmpDir());
static const char kTmpdirTemplate[] = "%s/%s_XXXXXXXX";
DCHECK_LT(prefix.size() + sizeof(kTmpdirTemplate),
static_cast<size_t>(PATH_MAX));
#ifdef _WIN32
sprintf_s(tmpdir, sizeof(tmpdir), kTmpdirTemplate,
GetGomaTmpDir().c_str(), prefix.c_str());
#else
snprintf(tmpdir, sizeof(tmpdir), kTmpdirTemplate,
GetGomaTmpDir().c_str(), prefix.c_str());
#endif
if (mkdtemp(tmpdir) == nullptr) {
dirname_.clear();
} else {
dirname_ = tmpdir;
}
}
ScopedTmpDir::~ScopedTmpDir() {
if (!valid()) {
return;
}
if (!file::RecursivelyDelete(dirname_, file::Defaults()).ok()) {
LOG(ERROR) << "Failed to delete temporary directory: " << dirname_;
}
}
} // namespace devtools_goma