1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
// Copyright 2005-6 Ben Hutchings <ben@decadent.org.uk>.
// See the file "COPYING" for licence details.
#include "temp_file.hpp"
#include <cassert>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <ostream>
#include <stdexcept>
#include <vector>
#include <fcntl.h>
#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)
{
fd_ = Glib::file_open_tmp(name_, base_name);
assert(fd_ >= 0);
// Workaround bug in glibc <2.2 that may cause the file to be
// created with lax permissions.
# ifdef __GLIBC__
# if !__GLIBC_PREREQ(2, 2)
if (fchmod(fd_, S_IREAD|S_IWRITE) != 0 || ftruncate(fd_, 0) != 0)
{
close(fd_);
throw std::runtime_error(std::strerror(errno));
}
# endif
# endif
}
temp_file::~temp_file()
{
close();
if (!do_keep_all)
{
// Don't assert that this is successful. The file could have
// been removed by another process.
unlink(name_.c_str());
}
}
void temp_file::close()
{
if (fd_ >= 0)
{
int result = ::close(fd_);
assert(result == 0);
fd_ = -1;
}
}
void temp_file::keep_all(bool 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 << "Warning: failed to remove temporary directory "
<< name_ << "\n";
}
|