#include "Util.hpp"
#include <core/exceptions.hpp>
+#include <fmtmacros.hpp>
+
+#include <cstdlib>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
#ifdef _WIN32
# include "third_party/win32/mktemp.h"
#endif
-TemporaryFile::TemporaryFile(std::string_view path_prefix)
- : path(std::string(path_prefix) + ".XXXXXX")
+TemporaryFile::TemporaryFile(std::string_view path_prefix,
+ std::string_view suffix)
+ : path(FMT("{}.XXXXXX{}", path_prefix, suffix))
{
Util::ensure_dir_exists(Util::dir_name(path));
#ifdef _WIN32
- // MSVC lacks mkstemp() and Mingw-w64's implementation[1] is problematic, as
+ // MSVC lacks mkstemps() and Mingw-w64's implementation[1] is problematic, as
// it can reuse the names of recently-deleted files unless the caller
// remembers to call srand().
// [1]: <https://github.com/Alexpux/mingw-w64/blob/
// d0d7f784833bbb0b2d279310ddc6afb52fe47a46/mingw-w64-crt/misc/mkstemp.c>
- fd = Fd(bsd_mkstemp(&path[0]));
+ fd = Fd(bsd_mkstemps(&path[0], suffix.length()));
#else
- fd = Fd(mkstemp(&path[0]));
+ fd = Fd(mkstemps(&path[0], suffix.length()));
#endif
if (!fd) {
throw core::Fatal(
{
public:
// `path_prefix` is the base path. The resulting filename will be this path
- // plus a unique suffix. If `path_prefix` refers to a nonexistent directory
- // the directory will be created if possible.`
- TemporaryFile(std::string_view path_prefix);
+ // plus a unique string plus `suffix`. If `path_prefix` refers to a
+ // nonexistent directory the directory will be created if possible.`
+ TemporaryFile(std::string_view path_prefix, std::string_view suffix = {});
TemporaryFile(TemporaryFile&& other) noexcept = default;
} else {
// Run cpp on the input file to obtain the .i.
- TemporaryFile tmp_stdout(
- FMT("{}/tmp.cpp_stdout", ctx.config.temporary_dir()));
- ctx.register_pending_tmp_file(tmp_stdout.path);
-
// stdout_path needs the proper cpp_extension for the compiler to do its
// thing correctly.
- stdout_path = FMT("{}.{}", tmp_stdout.path, ctx.config.cpp_extension());
- Util::hard_link(tmp_stdout.path, stdout_path);
+ TemporaryFile tmp_stdout(
+ FMT("{}/tmp.cpp_stdout", ctx.config.temporary_dir()),
+ FMT(".{}", ctx.config.cpp_extension()));
+ stdout_path = tmp_stdout.path;
ctx.register_pending_tmp_file(stdout_path);
TemporaryFile tmp_stderr(
-#ifndef CCACHE_THIRD_PARTY_WIN32_MKTEMP_H_
-#define CCACHE_THIRD_PARTY_WIN32_MKTEMP_H_
+#pragma once
#include <stddef.h>
extern "C" {
#endif
-int bsd_mkstemp(char *);
+int bsd_mkstemps(char* path, int slen);
// Exposed for testing.
-void bsd_mkstemp_set_random_source(void (*)(void *buf, size_t n));
+void bsd_mkstemp_set_random_source(void (*)(void* buf, size_t n));
#ifdef __cplusplus
}
#endif
-#endif
} // namespace
-TEST_SUITE_BEGIN("bsd_mkstemp");
+TEST_SUITE_BEGIN("bsd_mkstemps");
-TEST_CASE("bsd_mkstemp")
+TEST_CASE("bsd_mkstemps")
{
TestContext test_context;
SUBCASE("successful")
{
std::string path = "XXXXXX";
- Fd fd(bsd_mkstemp(&path[0]));
+ Fd fd(bsd_mkstemps(&path[0], 0));
CHECK_MESSAGE(fd, "errno=" << errno);
CHECK(path == "AAAAAA");
}
+ SUBCASE("successful with suffix")
+ {
+ std::string path = "XXXXXX123";
+ Fd fd(bsd_mkstemps(&path[0], 3));
+ CHECK_MESSAGE(fd, "errno=" << errno);
+ CHECK(path == "AAAAAA123");
+ }
+
SUBCASE("existing file")
{
ScopedHANDLE handle(CreateFileA("AAAAAA",
CHECK_MESSAGE(handle, "errno=" << errno);
std::string path = "XXXXXX";
- Fd fd(bsd_mkstemp(&path[0]));
+ Fd fd(bsd_mkstemps(&path[0], 0));
CHECK_MESSAGE(fd, "errno=" << errno);
CHECK(path == "BBBBBB");
}
"errno=" << errno);
std::string path = "XXXXXX";
- Fd fd(bsd_mkstemp(&path[0]));
+ Fd fd(bsd_mkstemps(&path[0], 0));
CHECK_MESSAGE(fd, "errno=" << errno);
CHECK(path == "BBBBBB");
}
CHECK_MESSAGE(CreateDirectoryA("AAAAAA", nullptr), "errno=" << errno);
std::string path = "XXXXXX";
- Fd fd(bsd_mkstemp(&path[0]));
+ Fd fd(bsd_mkstemps(&path[0], 0));
CHECK_MESSAGE(fd, "errno=" << errno);
CHECK(path == "BBBBBB");
}
if (!broken_acls) {
std::string path = "my_readonly_dir/XXXXXX";
- CHECK(!Fd(bsd_mkstemp(&path[0])));
+ CHECK(!Fd(bsd_mkstemps(&path[0], 0)));
CHECK(errno == EACCES);
} else {
MESSAGE("ACLs do not appear to function properly on this filesystem");