mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 20:13:05 +02:00
3fbe0a2701
Signed-off-by: David Sommerseth <davids@openvpn.net>
164 lines
4.2 KiB
C++
164 lines
4.2 KiB
C++
// OpenVPN -- An application to securely tunnel IP networks
|
|
// over a single port, with support for SSL/TLS-based
|
|
// session authentication and key exchange,
|
|
// packet encryption, packet authentication, and
|
|
// packet compression.
|
|
//
|
|
// Copyright (C) 2012-2020 OpenVPN Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License Version 3
|
|
// as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program in the COPYING file.
|
|
// If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#ifndef OPENVPN_COMMON_TEMPFILE_H
|
|
#define OPENVPN_COMMON_TEMPFILE_H
|
|
|
|
#include <openvpn/common/platform.hpp>
|
|
|
|
#if defined(OPENVPN_PLATFORM_WIN)
|
|
#error temporary file methods not supported on Windows
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <cstring> // for memcpy
|
|
#include <unistd.h> // for write, unlink, lseek
|
|
#include <sys/types.h> // for lseek
|
|
|
|
#include <string>
|
|
#include <memory>
|
|
|
|
#include <openvpn/common/exception.hpp>
|
|
#include <openvpn/common/scoped_fd.hpp>
|
|
#include <openvpn/common/write.hpp>
|
|
#include <openvpn/common/strerror.hpp>
|
|
#include <openvpn/buffer/bufread.hpp>
|
|
|
|
namespace openvpn {
|
|
class TempFile
|
|
{
|
|
public:
|
|
OPENVPN_EXCEPTION(tempfile_exception);
|
|
|
|
TempFile(const std::string& fn_template,
|
|
const bool fn_delete)
|
|
: fn(new char[fn_template.length()+1]),
|
|
del(fn_delete)
|
|
{
|
|
std::memcpy(fn.get(), fn_template.c_str(), fn_template.length()+1);
|
|
const size_t pos = fn_template.find("XXXXXX");
|
|
if (pos != std::string::npos)
|
|
{
|
|
const int suffixlen = fn_template.length() - pos - 6;
|
|
if (suffixlen > 0)
|
|
fd.reset(::mkstemps(fn.get(), suffixlen));
|
|
else
|
|
fd.reset(::mkstemp(fn.get()));
|
|
if (!fd.defined())
|
|
{
|
|
const int eno = errno;
|
|
OPENVPN_THROW(tempfile_exception, "error creating temporary file from template: " << fn_template << " : " << strerror_str(eno));
|
|
}
|
|
}
|
|
else
|
|
OPENVPN_THROW(tempfile_exception, "badly formed temporary file template: " << fn_template);
|
|
}
|
|
|
|
~TempFile()
|
|
{
|
|
fd.close();
|
|
delete_file();
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
const off_t off = ::lseek(fd(), 0, SEEK_SET);
|
|
if (off < 0)
|
|
{
|
|
const int eno = errno;
|
|
OPENVPN_THROW(tempfile_exception, "seek error on temporary file: " << filename() << " : " << strerror_str(eno));
|
|
}
|
|
if (off)
|
|
OPENVPN_THROW(tempfile_exception, "unexpected seek on temporary file: " << filename());
|
|
}
|
|
|
|
void truncate()
|
|
{
|
|
reset();
|
|
if (::ftruncate(fd(), 0) < 0)
|
|
{
|
|
const int eno = errno;
|
|
OPENVPN_THROW(tempfile_exception, "ftruncate error on temporary file: " << filename() << " : " << strerror_str(eno));
|
|
}
|
|
}
|
|
|
|
void write(const std::string& content)
|
|
{
|
|
const ssize_t size = write_retry(fd(), content.c_str(), content.length());
|
|
if (size < 0)
|
|
{
|
|
const int eno = errno;
|
|
OPENVPN_THROW(tempfile_exception, "error writing to temporary file: " << filename() << " : " << strerror_str(eno));
|
|
}
|
|
else if (static_cast<std::string::size_type>(size) != content.length())
|
|
{
|
|
OPENVPN_THROW(tempfile_exception, "incomplete write to temporary file: " << filename());
|
|
}
|
|
}
|
|
|
|
std::string read()
|
|
{
|
|
BufferList buflist = buf_read(fd(), filename());
|
|
return buflist.to_string();
|
|
}
|
|
|
|
std::string filename() const
|
|
{
|
|
if (fn)
|
|
return fn.get();
|
|
else
|
|
return "";
|
|
}
|
|
|
|
void close_file()
|
|
{
|
|
if (!fd.close())
|
|
{
|
|
const int eno = errno;
|
|
OPENVPN_THROW(tempfile_exception, "error closing temporary file: " << filename() << " : " << strerror_str(eno));
|
|
}
|
|
}
|
|
|
|
void set_delete(const bool del_flag)
|
|
{
|
|
del = del_flag;
|
|
}
|
|
|
|
void delete_file()
|
|
{
|
|
if (fn && del)
|
|
{
|
|
::unlink(fn.get());
|
|
del = false;
|
|
}
|
|
}
|
|
|
|
ScopedFD fd;
|
|
|
|
private:
|
|
std::unique_ptr<char[]> fn;
|
|
bool del;
|
|
};
|
|
}
|
|
|
|
#endif
|