Caffe2 - C++ API
A deep learning, cross platform ML framework
tempfile.h
1 #pragma once
2 
3 #include <c10/util/Exception.h>
4 #include <c10/util/Optional.h>
5 
6 #include <cerrno>
7 #include <cstdio>
8 #include <cstdlib>
9 #include <cstring>
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 #if !defined(_WIN32)
15 #include <unistd.h>
16 #endif
17 
18 namespace c10 {
19 namespace detail {
20 // Creates the filename pattern passed to and completed by `mkstemp`.
21 // Returns std::vector<char> because `mkstemp` needs a (non-const) `char*` and
22 // `std::string` only provides `const char*` before C++17.
23 #if !defined(_WIN32)
24 inline std::vector<char> make_filename(std::string name_prefix) {
25  // The filename argument to `mkstemp` needs "XXXXXX" at the end according to
26  // http://pubs.opengroup.org/onlinepubs/009695399/functions/mkstemp.html
27  static const std::string kRandomPattern = "XXXXXX";
28 
29  // We see if any of these environment variables is set and use their value, or
30  // else default the temporary directory to `/tmp`.
31  static const char* env_variables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
32 
33  std::string tmp_directory = "/tmp";
34  for (const char* variable : env_variables) {
35  if (const char* path = getenv(variable)) {
36  tmp_directory = path;
37  break;
38  }
39  }
40 
41  std::vector<char> filename;
42  filename.reserve(
43  tmp_directory.size() + name_prefix.size() + kRandomPattern.size() + 2);
44 
45  filename.insert(filename.end(), tmp_directory.begin(), tmp_directory.end());
46  filename.push_back('/');
47  filename.insert(filename.end(), name_prefix.begin(), name_prefix.end());
48  filename.insert(filename.end(), kRandomPattern.begin(), kRandomPattern.end());
49  filename.push_back('\0');
50 
51  return filename;
52 }
53 #endif // !defined(_WIN32)
54 } // namespace detail
55 
56 struct TempFile {
57 #if !defined(_WIN32)
58  TempFile(std::string name, int fd) : fd(fd), name(std::move(name)) {}
59 
60  ~TempFile() {
61  unlink(name.c_str());
62  close(fd);
63  }
64 
65  const int fd;
66 #endif // !defined(_WIN32)
67 
68  const std::string name;
69 };
70 
82  std::string name_prefix = "torch-file-") {
83 #if defined(_WIN32)
84  return TempFile{std::tmpnam(nullptr)};
85 #else
86  std::vector<char> filename = detail::make_filename(std::move(name_prefix));
87  const int fd = mkstemp(filename.data());
88  if (fd == -1) {
89  return c10::nullopt;
90  }
91  return TempFile(std::string(filename.begin(), filename.end()), fd);
92 #endif // defined(_WIN32)
93 }
94 
97 inline TempFile make_tempfile(std::string name_prefix = "torch-file-") {
98  if (auto tempfile = try_make_tempfile(std::move(name_prefix))) {
99  return *tempfile;
100  }
101  AT_ERROR("Error generating temporary file: ", std::strerror(errno));
102 }
103 } // namespace c10
c10::optional< TempFile > try_make_tempfile(std::string name_prefix="torch-file-")
Attempts to return a temporary file or returns nullopt if an error ocurred.
Definition: tempfile.h:81
To register your own kernel for an operator, do in one (!) cpp file: C10_REGISTER_KERNEL(OperatorHand...
Definition: alias_info.h:7
TempFile make_tempfile(std::string name_prefix="torch-file-")
Like try_make_tempfile, but throws an exception if a temporary file could not be returned.
Definition: tempfile.h:97