1 // Copyright 2005-6 Ben Hutchings <ben@decadent.org.uk>.
2 // See the file "COPYING" for licence details.
4 #include "temp_file.hpp"
18 #include <glibmm/fileutils.h>
19 #include <glibmm/miscutils.h>
23 bool try_rmdir_recursive(const std::string & dir_name)
25 Glib::Dir dir(dir_name);
28 for (Glib::Dir::iterator it = dir.begin(), end = dir.end();
32 std::string full_name(Glib::build_filename(dir_name, *it));
33 if (!(Glib::file_test(full_name, Glib::FILE_TEST_IS_DIR)
34 ? try_rmdir_recursive(full_name)
35 : (unlink(full_name.c_str()) == 0 || errno == ENOENT)))
39 return empty && (rmdir(dir_name.c_str()) == 0 || errno == ENOENT);
42 bool do_keep_all = false;
45 temp_file::temp_file(const std::string & base_name)
47 fd_ = Glib::file_open_tmp(name_, base_name);
50 // Workaround bug in glibc <2.2 that may cause the file to be
51 // created with lax permissions.
53 # if !__GLIBC_PREREQ(2, 2)
54 if (fchmod(fd_, S_IREAD|S_IWRITE) != 0 || ftruncate(fd_, 0) != 0)
57 throw std::runtime_error(std::strerror(errno));
63 temp_file::~temp_file()
69 // Don't assert that this is successful. The file could have
70 // been removed by another process.
71 unlink(name_.c_str());
75 void temp_file::close()
79 int result = ::close(fd_);
85 void temp_file::keep_all(bool keep)
90 temp_dir::temp_dir(const std::string & base_name)
92 std::string tmp_dir_name(Glib::get_tmp_dir());
93 std::vector<char> template_name;
94 template_name.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6 + 1);
95 name_.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6);
96 template_name.assign(tmp_dir_name.begin(), tmp_dir_name.end());
97 template_name.insert(template_name.end(), '/');
98 template_name.insert(template_name.end(),
99 base_name.begin(), base_name.end());
100 template_name.insert(template_name.end(), 6, 'X');
101 template_name.insert(template_name.end(), '\0');
102 if (mkdtemp(&template_name[0]))
103 name_.assign(template_name.begin(), template_name.end() - 1);
105 throw std::runtime_error(
106 std::string("mkdtemp: ").append(std::strerror(errno)));
109 temp_dir::~temp_dir()
111 if (!do_keep_all && !try_rmdir_recursive(name_))
112 std::cerr << "WARN: Failed to remove temporary directory "