-// Copyright 2005 Ben Hutchings <ben@decadentplace.org.uk>.
+// Copyright 2005-6 Ben Hutchings <ben@decadent.org.uk>.
// See the file "COPYING" for licence details.
#include "temp_file.hpp"
#include <cerrno>
#include <cstdlib>
#include <cstring>
+#include <iostream>
+#include <ostream>
#include <stdexcept>
#include <vector>
#include <unistd.h>
#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+
+namespace
+{
+ bool try_rmdir_recursive(const std::string & dir_name)
+ {
+ Glib::Dir dir(dir_name);
+ bool empty = true;
+
+ for (Glib::Dir::iterator it = dir.begin(), end = dir.end();
+ it != end;
+ ++it)
+ {
+ std::string full_name(Glib::build_filename(dir_name, *it));
+ if (!(Glib::file_test(full_name, Glib::FILE_TEST_IS_DIR)
+ ? try_rmdir_recursive(full_name)
+ : (unlink(full_name.c_str()) == 0 || errno == ENOENT)))
+ empty = false;
+ }
+
+ return empty && (rmdir(dir_name.c_str()) == 0 || errno == ENOENT);
+ }
+
+ bool do_keep_all = false;
+}
temp_file::temp_file(const std::string & base_name)
{
{
close();
- if (!keep_)
+ if (!do_keep_all)
{
// Don't assert that this is successful. The file could have
// been removed by another process.
}
}
-bool temp_file::keep_ = false;
-
void temp_file::keep_all(bool keep)
{
- keep_ = keep;
+ do_keep_all = keep;
+}
+
+temp_dir::temp_dir(const std::string & base_name)
+{
+ std::string tmp_dir_name(Glib::get_tmp_dir());
+ std::vector<char> template_name;
+ template_name.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6 + 1);
+ name_.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6);
+ template_name.assign(tmp_dir_name.begin(), tmp_dir_name.end());
+ template_name.insert(template_name.end(), '/');
+ template_name.insert(template_name.end(),
+ base_name.begin(), base_name.end());
+ template_name.insert(template_name.end(), 6, 'X');
+ template_name.insert(template_name.end(), '\0');
+ if (mkdtemp(&template_name[0]))
+ name_.assign(template_name.begin(), template_name.end() - 1);
+ else
+ throw std::runtime_error(
+ std::string("mkdtemp: ").append(std::strerror(errno)));
+}
+
+temp_dir::~temp_dir()
+{
+ if (!do_keep_all && !try_rmdir_recursive(name_))
+ std::cerr << "WARN: Failed to remove temporary directory "
+ << name_ << "\n";
}