2 * Copyright 2014 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/experimental/TestUtil.h"
19 #include <sys/types.h>
23 #include "folly/Conv.h"
24 #include "folly/Exception.h"
31 fs::path generateUniquePath(fs::path path, StringPiece namePrefix) {
33 path = fs::temp_directory_path();
35 if (namePrefix.empty()) {
36 path /= fs::unique_path();
38 path /= fs::unique_path(
39 to<std::string>(namePrefix, ".%%%%-%%%%-%%%%-%%%%"));
46 TemporaryFile::TemporaryFile(StringPiece namePrefix,
49 bool closeOnDestruction)
51 closeOnDestruction_(closeOnDestruction),
53 path_(generateUniquePath(std::move(dir), namePrefix)) {
54 fd_ = open(path_.c_str(), O_RDWR | O_CREAT | O_EXCL, 0644);
55 checkUnixError(fd_, "open failed");
57 if (scope_ == Scope::UNLINK_IMMEDIATELY) {
58 boost::system::error_code ec;
59 fs::remove(path_, ec);
61 LOG(WARNING) << "unlink on construction failed: " << ec;
68 const fs::path& TemporaryFile::path() const {
69 CHECK(scope_ != Scope::UNLINK_IMMEDIATELY);
70 DCHECK(!path_.empty());
74 TemporaryFile::~TemporaryFile() {
75 if (fd_ != -1 && closeOnDestruction_) {
76 if (close(fd_) == -1) {
77 PLOG(ERROR) << "close failed";
81 // If we previously failed to unlink() (UNLINK_IMMEDIATELY), we'll
83 if (scope_ != Scope::PERMANENT && !path_.empty()) {
84 boost::system::error_code ec;
85 fs::remove(path_, ec);
87 LOG(WARNING) << "unlink on destruction failed: " << ec;
92 TemporaryDirectory::TemporaryDirectory(StringPiece namePrefix,
96 path_(generateUniquePath(std::move(dir), namePrefix)) {
97 fs::create_directory(path_);
100 TemporaryDirectory::~TemporaryDirectory() {
101 if (scope_ == Scope::DELETE_ON_DESTRUCTION) {
102 boost::system::error_code ec;
103 fs::remove_all(path_, ec);
105 LOG(WARNING) << "recursive delete on destruction failed: " << ec;