Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/moses-smt/mosesdecoder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorJeroen Vermeulen <jtv@precisiontranslationtools.com>2015-04-17 20:21:18 +0300
committerJeroen Vermeulen <jtv@precisiontranslationtools.com>2015-04-17 20:21:18 +0300
commitabfdb61bc9c3281de2e5ef26df30634ed2c84d89 (patch)
tree8d276efc076442b3e53eaccedc705a50d46fd4a2 /util
parentd56f317f2ee844beffc7f83e3e6ae2aeb80add61 (diff)
Cross-platform tempfile implementation.
This makes temp_file and temp_dir work both on POSIX-like platforms and on Windows. It also fixes a bug where the temporary files/directories were created in the current working directory, instead of in the system's standard location for temporary files. Unfortunately the Windows and POSIX code diverge quite a bit on that point.
Diffstat (limited to 'util')
-rw-r--r--util/tempfile.hh78
1 files changed, 75 insertions, 3 deletions
diff --git a/util/tempfile.hh b/util/tempfile.hh
index 228238823..9b872a27e 100644
--- a/util/tempfile.hh
+++ b/util/tempfile.hh
@@ -3,18 +3,74 @@
// Utilities for creating temporary files and directories.
+#include <climits>
#include <cstdio>
#include <cstdlib>
#include <string>
+#if defined(_WIN32) || defined(_WIN64)
+#include <windows.h>
+#endif
+
#include <boost/filesystem.hpp>
#include <boost/noncopyable.hpp>
#include "util/exception.hh"
+#include "util/unistd.hh"
namespace util
{
+/// Obtain a directory for temporary files, e.g. /tmp.
+std::string temp_location()
+{
+#if defined(_WIN32) || defined(_WIN64)
+ char dir_buffer[1000];
+ if (GetTempPath(1000, dir_buffer) == 0)
+ throw std::runtime_error("Could not read temporary directory.");
+ return std::string(dir_buffer);
+#else
+ // POSIX says to try these environment variables, in this order:
+ const char *const vars[] = {"TMPDIR", "TMP", "TEMPDIR", "TEMP", 0};
+ for (int i=0; vars[i]; ++i)
+ {
+ const char *val = getenv(vars[i]);
+ // Environment variable is set and nonempty. Use it.
+ if (val && *val) return val;
+ }
+ // No environment variables set. Default to /tmp.
+ return "/tmp";
+#endif
+}
+
+
+#if defined(_WIN32) || defined(_WIN64)
+/// Windows helper: create temporary filename.
+std::string windows_tmpnam()
+{
+ const std::string tmp = temp_location();
+ char output_buffer[MAX_PATH];
+ if (GetTempFileName(tmp.c_str(), "tmp", 0, output_buffer) == 0)
+ throw std::runtime_error("Could not create temporary file name.");
+ return output_buffer;
+}
+#else
+/** POSIX helper: create template for temporary filename.
+ *
+ * Writes the template into buf, which must have room for at least PATH_MAX
+ * bytes. The function fails if the template is too long.
+ */
+void posix_tmp_template(char *buf)
+{
+ const std::string tmp = temp_location();
+ const std::string name_template = tmp + "/tmp.XXXXXX";
+ if (name_template.size() >= PATH_MAX-1)
+ throw std::runtime_error("Path for temp files is too long: " + tmp);
+ strcpy(buf, name_template.c_str());
+}
+#endif
+
+
/** Temporary directory.
*
* Automatically creates, and on destruction deletes, a temporary directory.
@@ -22,15 +78,21 @@ namespace util
* object exists.
*
* If the directory no longer exists by the time the temp_dir is destroyed,
- * no cleanup happens.
+ * cleanup is skipped.
*/
class temp_dir : boost::noncopyable
{
public:
temp_dir()
{
- char buf[] = "tmpdir.XXXXXX";
+#if defined(_WIN32) || defined(_WIN64)
+ m_path = windows_tmpnam();
+ boost::filesystem::create_directory(m_path);
+#else
+ char buf[PATH_MAX];
+ posix_tmp_template(buf);
m_path = std::string(mkdtemp(buf));
+#endif
}
~temp_dir()
@@ -49,17 +111,27 @@ private:
/** Temporary file.
*
* Automatically creates, and on destruction deletes, a temporary file.
+ *
+ * If the file no longer exists by the time the temp_file is destroyed,
+ * cleanup is skipped.
*/
class temp_file : boost::noncopyable
{
public:
temp_file()
{
- char buf[] = "tmp.XXXXXX";
+#if defined(_WIN32) || defined(_WIN64)
+ m_path = windows_tmpnam();
+ std::ofstream out(m_path.c_str());
+ out.flush();
+#else
+ char buf[PATH_MAX];
+ posix_tmp_template(buf);
const int fd = mkstemp(buf);
if (fd == -1) throw ErrnoException();
close(fd);
m_path = buf;
+#endif
}
~temp_file()