pytorch
1#include <c10/util/Exception.h>2#include <c10/util/tempfile.h>3#include <fmt/format.h>4
5#if !defined(_WIN32)6#include <unistd.h>7#include <cerrno>8#else // defined(_WIN32)9#include <Windows.h>10#include <fcntl.h>11#include <fileapi.h>12#include <io.h>13#endif // defined(_WIN32)14
15// Creates the filename pattern passed to and completed by `mkstemp`.
16#if !defined(_WIN32)17static std::string make_filename(std::string_view name_prefix) {18// The filename argument to `mkstemp` needs "XXXXXX" at the end according to19// http://pubs.opengroup.org/onlinepubs/009695399/functions/mkstemp.html20constexpr const char* kRandomPattern = "XXXXXX";21
22// We see if any of these environment variables is set and use their value, or23// else default the temporary directory to `/tmp`.24
25const char* tmp_directory = "/tmp";26for (const char* variable : {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}) {27if (const char* path = getenv(variable)) {28tmp_directory = path;29break;30}31}32return fmt::format("{}/{}{}", tmp_directory, name_prefix, kRandomPattern);33}
34#else35static std::string make_filename() {36char name[L_tmpnam_s]{};37auto res = tmpnam_s(name, L_tmpnam_s);38if (res != 0) {39TORCH_WARN("Error generating temporary file");40return "";41}42return name;43}
44#endif // !defined(_WIN32)45
46namespace c10 {47/// Attempts to return a temporary file or returns `nullopt` if an error
48/// occurred.
49std::optional<TempFile> try_make_tempfile(std::string_view name_prefix) {50#if defined(_WIN32)51auto filename = make_filename();52#else53auto filename = make_filename(name_prefix);54#endif55if (filename.empty()) {56return std::nullopt;57}58#if defined(_WIN32)59return TempFile(std::move(filename));60#else61const int fd = mkstemp(filename.data());62if (fd == -1) {63return std::nullopt;64}65return TempFile(std::move(filename), fd);66#endif // defined(_WIN32)67}
68
69/// Like `try_make_tempfile`, but throws an exception if a temporary file could
70/// not be returned.
71TempFile make_tempfile(std::string_view name_prefix) {72if (auto tempfile = try_make_tempfile(name_prefix)) {73return std::move(*tempfile);74}75TORCH_CHECK(false, "Error generating temporary file: ", std::strerror(errno));76}
77
78/// Attempts to return a temporary directory or returns `nullopt` if an error
79/// occurred.
80std::optional<TempDir> try_make_tempdir(std::string_view name_prefix) {81#if defined(_WIN32)82for (int i = 0; i < 10; i++) {83auto dirname = make_filename();84if (dirname.empty()) {85return std::nullopt;86}87if (CreateDirectoryA(dirname.c_str(), nullptr)) {88return TempDir(dirname);89}90if (GetLastError() == ERROR_SUCCESS) {91return std::nullopt;92}93}94return std::nullopt;95#else96auto filename = make_filename(name_prefix);97const char* dirname = mkdtemp(filename.data());98if (!dirname) {99return std::nullopt;100}101return TempDir(dirname);102#endif // defined(_WIN32)103}
104
105#if defined(_WIN32)106bool TempFile::open() {107if (fd != -1) {108return false;109}110auto err = _sopen_s(111&fd,112name.c_str(),113_O_CREAT | _O_TEMPORARY | _O_EXCL | _O_BINARY | _O_RDWR,114_SH_DENYNO,115_S_IREAD | _S_IWRITE);116if (err != 0) {117fd = -1;118return false;119}120return true;121}
122#endif123
124TempFile::~TempFile() {125if (!name.empty()) {126#if !defined(_WIN32)127if (fd >= 0) {128unlink(name.c_str());129close(fd);130}131#else132if (fd >= 0) {133_close(fd);134}135#endif136}137}
138
139TempDir::~TempDir() {140if (!name.empty()) {141#if !defined(_WIN32)142rmdir(name.c_str());143#else // defined(_WIN32)144RemoveDirectoryA(name.c_str());145#endif // defined(_WIN32)146}147}
148
149/// Like `try_make_tempdir`, but throws an exception if a temporary directory
150/// could not be returned.
151TempDir make_tempdir(std::string_view name_prefix) {152if (auto tempdir = try_make_tempdir(name_prefix)) {153return std::move(*tempdir);154}155#if !defined(_WIN32)156TORCH_CHECK(157false, "Error generating temporary directory: ", std::strerror(errno));158#else // defined(_WIN32)159TORCH_CHECK(false, "Error generating temporary directory");160#endif // defined(_WIN32)161}
162} // namespace c10163