Logo Search packages:      
Sourcecode: videolink version File versions  Download package

temp_file.cpp

// 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";
}

Generated by  Doxygen 1.6.0   Back to index