Go to the documentation of this file.00001 #include <utilmm/system/system.hh>
00002
00003 #include <exception>
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006 #include <errno.h>
00007 #include <string.h>
00008 #include <unistd.h>
00009 #include <boost/noncopyable.hpp>
00010 #include <boost/filesystem/operations.hpp>
00011 #include <vector>
00012 #include <stdio.h>
00013
00014 using namespace utilmm;
00015
00016 void unix_error::init_description(std::string const& desc)
00017 {
00018 size_t desc_len = desc.length();
00019 strncpy(m_desc, desc.c_str(), 500);
00020 m_desc[500] = 0;
00021 strcat(m_desc, ": ");
00022
00023
00024 strncat(m_desc, strerror(m_error), 500 - desc_len);
00025 }
00026 unix_error::unix_error(std::string const& desc, int error_ = errno)
00027 : m_error(error_) { init_description(desc); }
00028 unix_error::unix_error(std::string const& desc)
00029 : m_error(errno) { init_description(desc); }
00030 unix_error::unix_error(int error_)
00031 : m_error(error_) { init_description(""); }
00032 unix_error::unix_error()
00033 : m_error(errno) { init_description(""); }
00034 unix_error::~unix_error() throw () {}
00035
00036 int unix_error::error() const { return m_error; }
00037 char const* unix_error::what() const throw()
00038 { return m_desc; }
00039
00040 auto_close::auto_close()
00041 : m_fileno(-1), m_stream(0) {}
00042 auto_close::auto_close(int fileno)
00043 : m_fileno(fileno), m_stream(0) {}
00044 auto_close::auto_close(FILE* stream)
00045 : m_fileno(-1), m_stream(stream) {}
00046 auto_close::~auto_close() { close(); }
00047
00048 void auto_close::close()
00049 {
00050 int ret = 0;
00051 if (m_stream)
00052 ret = fclose(m_stream);
00053 else if (m_fileno != -1)
00054 ret = ::close(m_fileno);
00055
00056 detach();
00057
00058 if (ret == -1)
00059 throw unix_error();
00060 }
00061
00062 void auto_close::detach()
00063 { m_fileno = -1; m_stream = 0; }
00064
00065 template<>
00066 FILE* auto_close::handle<FILE*>() const
00067 {
00068 if (m_stream == 0) throw std::bad_cast();
00069 return m_stream;
00070 }
00071
00072 template<>
00073 int auto_close::handle<int>() const
00074 {
00075 if (m_fileno == -1) throw std::bad_cast();
00076 return m_fileno;
00077 }
00078
00079 void auto_close::reset(int fileno)
00080 {
00081 close();
00082 m_fileno = fileno;
00083 }
00084 void auto_close::reset(FILE* stream)
00085 {
00086 close();
00087 m_stream = stream;
00088 }
00089
00090
00091
00092
00093
00094 FILE* tempfile::create()
00095 {
00096 FILE* fd = tmpfile();
00097 if (!fd)
00098 throw unix_error();
00099 return fd;
00100 }
00101
00102 FILE* tempfile::mkstemp(std::string const& base, boost::filesystem::path& path)
00103 {
00104 int const base_length(base.length());
00105
00106 std::vector<char> value;
00107 value.resize( base_length + 6 + 1 );
00108 strncpy(&value[0], base.c_str(), base_length);
00109 memset(&value[base_length], 'X', 6);
00110 value[base_length + 6] = '\0';
00111
00112 int handle = ::mkstemp(&value[0]);
00113 if (handle < 0)
00114 throw unix_error();
00115
00116 path = std::string(&value[0]);
00117 return fdopen(handle, "w");
00118 }
00119
00120 tempfile::tempfile(std::string const& base)
00121 : m_path(), m_guard(mkstemp(base, m_path))
00122 {
00123 if (! handle())
00124 throw unix_error();
00125 }
00126
00127 tempfile::tempfile()
00128 : m_guard(create()) {}
00129
00130 tempfile::~tempfile()
00131 {
00132 if (! m_path.empty())
00133 {
00134 try {
00135 m_guard.close();
00136 boost::filesystem::remove(m_path);
00137 } catch(...) {}
00138 }
00139 }
00140
00141 FILE* tempfile::handle() const {
00142 if (m_path.empty())
00143 return 0;
00144 else
00145 return m_guard.handle<FILE*>();
00146 }
00147 FILE* tempfile::detach()
00148 {
00149 FILE* h = handle();
00150 m_guard.detach();
00151 m_path = boost::filesystem::path();
00152 return h;
00153 }
00154
00155 boost::filesystem::path tempfile::path() const { return m_path; }
00156