1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/utils/io/tmpfile.h"
16
17 #include <unistd.h>
18 #include <limits>
19
20 #include "src/debug.h"
21
22 namespace tint {
23 namespace utils {
24
25 namespace {
26
TmpFilePath(std::string ext)27 std::string TmpFilePath(std::string ext) {
28 char const* dir = getenv("TMPDIR");
29 if (dir == nullptr) {
30 dir = "/tmp";
31 }
32
33 // mkstemps requires an `int` for the file extension name but STL represents
34 // size_t. Pre-C++20 there the behavior for unsigned-to-signed conversion
35 // (when the source value exceeds the representable range) is implementation
36 // defined. While such a large file extension is unlikely in practice, we
37 // enforce this here at runtime.
38 TINT_ASSERT(Utils, ext.length() <=
39 static_cast<size_t>(std::numeric_limits<int>::max()));
40 std::string name = std::string(dir) + "/tint_XXXXXX" + ext;
41 int file = mkstemps(&name[0], static_cast<int>(ext.length()));
42 if (file != -1) {
43 close(file);
44 return name;
45 }
46 return "";
47 }
48
49 } // namespace
50
TmpFile(std::string extension)51 TmpFile::TmpFile(std::string extension)
52 : path_(TmpFilePath(std::move(extension))) {}
53
~TmpFile()54 TmpFile::~TmpFile() {
55 if (!path_.empty()) {
56 remove(path_.c_str());
57 }
58 }
59
Append(const void * data,size_t size) const60 bool TmpFile::Append(const void* data, size_t size) const {
61 if (auto* file = fopen(path_.c_str(), "ab")) {
62 fwrite(data, size, 1, file);
63 fclose(file);
64 return true;
65 }
66 return false;
67 }
68
69 } // namespace utils
70 } // namespace tint
71