00001 #ifndef UTIL_TEMPFILE_H
00002 #define UTIL_TEMPFILE_H
00003
00004
00005
00006 #include <climits>
00007 #include <cstdio>
00008 #include <cstdlib>
00009 #include <string>
00010
00011 #if defined(_WIN32) || defined(_WIN64)
00012 #include <windows.h>
00013 #else
00014 #include <unistd.h>
00015 #endif
00016
00017 #include <boost/filesystem.hpp>
00018 #include <boost/noncopyable.hpp>
00019
00020 #include "util/exception.hh"
00021
00022 namespace util
00023 {
00024
00026 std::string temp_location()
00027 {
00028 #if defined(_WIN32) || defined(_WIN64)
00029 char dir_buffer[1000];
00030 if (GetTempPathA(1000, dir_buffer) == 0)
00031 throw std::runtime_error("Could not read temporary directory.");
00032 return std::string(dir_buffer);
00033 #else
00034
00035 const char *const vars[] = {"TMPDIR", "TMP", "TEMPDIR", "TEMP", 0};
00036 for (int i=0; vars[i]; ++i)
00037 {
00038 const char *val = getenv(vars[i]);
00039
00040 if (val && *val) return val;
00041 }
00042
00043 return "/tmp";
00044 #endif
00045 }
00046
00047
00048 #if defined(_WIN32) || defined(_WIN64)
00050 std::string windows_tmpnam()
00051 {
00052 const std::string tmp = temp_location();
00053 char output_buffer[MAX_PATH];
00054 if (GetTempFileNameA(tmp.c_str(), "tmp", 0, output_buffer) == 0)
00055 throw std::runtime_error("Could not create temporary file name.");
00056 return output_buffer;
00057 }
00058 #else
00059
00064 void posix_tmp_template(char *buf)
00065 {
00066 const std::string tmp = temp_location();
00067 const std::string name_template = tmp + "/tmp.XXXXXX";
00068 if (name_template.size() >= PATH_MAX-1)
00069 throw std::runtime_error("Path for temp files is too long: " + tmp);
00070 strcpy(buf, name_template.c_str());
00071 }
00072 #endif
00073
00074
00084 class temp_dir : boost::noncopyable
00085 {
00086 public:
00087 temp_dir()
00088 {
00089 #if defined(_WIN32) || defined(_WIN64)
00090 m_path = windows_tmpnam();
00091 boost::filesystem::create_directory(m_path);
00092 #else
00093 char buf[PATH_MAX];
00094 posix_tmp_template(buf);
00095 m_path = std::string(mkdtemp(buf));
00096 #endif
00097 }
00098
00099 ~temp_dir()
00100 {
00101 boost::filesystem::remove_all(path());
00102 }
00103
00105 const std::string &path() const { return m_path; }
00106
00107 private:
00108 std::string m_path;
00109 };
00110
00111
00119 class temp_file : boost::noncopyable
00120 {
00121 public:
00122 temp_file()
00123 {
00124 #if defined(_WIN32) || defined(_WIN64)
00125 m_path = windows_tmpnam();
00126 std::ofstream out(m_path.c_str());
00127 out.flush();
00128 #else
00129 char buf[PATH_MAX];
00130 posix_tmp_template(buf);
00131 const int fd = mkstemp(buf);
00132 if (fd == -1) throw ErrnoException();
00133 close(fd);
00134 m_path = buf;
00135 #endif
00136 }
00137
00138 ~temp_file()
00139 {
00140 boost::filesystem::remove(path());
00141 }
00142
00144 const std::string &path() const { return m_path; }
00145
00146 private:
00147 std::string m_path;
00148 };
00149
00150 }
00151
00152 #endif