OpenVPN 3 Core Library
Loading...
Searching...
No Matches
tempfile.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#ifndef OPENVPN_COMMON_TEMPFILE_H
13#define OPENVPN_COMMON_TEMPFILE_H
14
16
17#if defined(OPENVPN_PLATFORM_WIN)
18#error temporary file methods not supported on Windows
19#endif
20
21#include <stdlib.h>
22#include <errno.h>
23#include <cstring> // for memcpy
24#include <unistd.h> // for write, unlink, lseek
25#include <sys/types.h> // for lseek
26
27#include <string>
28#include <memory>
29
36
38
39namespace openvpn {
41{
42 public:
43 OPENVPN_EXCEPTION(tempfile_exception);
44
45 TempFile(const std::string &fn_template,
46 const bool fn_delete)
47 : fn(new char[fn_template.length() + 1]),
48 del(fn_delete)
49 {
50 constexpr char pattern[] = "XXXXXX";
51 constexpr size_t patternLen = sizeof(pattern) - 1;
52 std::memcpy(fn.get(), fn_template.c_str(), fn_template.length() + 1);
53 const size_t pos = fn_template.rfind(pattern);
54 if (pos != std::string::npos)
55 {
56 if (fn_template.length() > pos + patternLen)
57 {
58 const auto suffixlen = fn_template.length() - pos - patternLen;
59 fd.reset(::mkstemps(fn.get(), numeric_cast<int>(suffixlen)));
60 }
61 else
62 fd.reset(::mkstemp(fn.get()));
63 if (!fd.defined())
64 {
65 const int eno = errno;
66 OPENVPN_THROW(tempfile_exception, "error creating temporary file from template: " << fn_template << " : " << strerror_str(eno));
67 }
68 }
69 else
70 OPENVPN_THROW(tempfile_exception, "badly formed temporary file template: " << fn_template);
71 }
72
74 {
75 fd.close();
77 }
78
79 void reset()
80 {
81 const off_t off = ::lseek(fd(), 0, SEEK_SET);
82 if (off < 0)
83 {
84 const int eno = errno;
85 OPENVPN_THROW(tempfile_exception, "seek error on temporary file: " << filename() << " : " << strerror_str(eno));
86 }
87 if (off)
88 OPENVPN_THROW(tempfile_exception, "unexpected seek on temporary file: " << filename());
89 }
90
91 void truncate()
92 {
93 reset();
94 if (::ftruncate(fd(), 0) < 0)
95 {
96 const int eno = errno;
97 OPENVPN_THROW(tempfile_exception, "ftruncate error on temporary file: " << filename() << " : " << strerror_str(eno));
98 }
99 }
100
101 void write(const std::string &content)
102 {
103 const ssize_t size = write_retry(fd(), content.c_str(), content.length());
104 if (size < 0)
105 {
106 const int eno = errno;
107 OPENVPN_THROW(tempfile_exception, "error writing to temporary file: " << filename() << " : " << strerror_str(eno));
108 }
109 else if (static_cast<std::string::size_type>(size) != content.length())
110 {
111 OPENVPN_THROW(tempfile_exception, "incomplete write to temporary file: " << filename());
112 }
113 }
114
115 std::string read()
116 {
117 BufferList buflist = buf_read(fd(), filename());
118 return buflist.to_string();
119 }
120
121 std::string filename() const
122 {
123 if (fn)
124 return fn.get();
125 else
126 return "";
127 }
128
130 {
131 if (!fd.close())
132 {
133 const int eno = errno;
134 OPENVPN_THROW(tempfile_exception, "error closing temporary file: " << filename() << " : " << strerror_str(eno));
135 }
136 }
137
138 void set_delete(const bool del_flag)
139 {
140 del = del_flag;
141 }
142
144 {
145 if (fn && del)
146 {
147 ::unlink(fn.get());
148 del = false;
149 }
150 }
151
153
154 private:
155 std::unique_ptr<char[]> fn;
156 bool del;
157};
158} // namespace openvpn
159
160#endif
void reset(const int fd_arg)
Definition scoped_fd.hpp:68
bool defined() const
Definition scoped_fd.hpp:58
void set_delete(const bool del_flag)
Definition tempfile.hpp:138
std::string read()
Definition tempfile.hpp:115
std::string filename() const
Definition tempfile.hpp:121
void write(const std::string &content)
Definition tempfile.hpp:101
OPENVPN_EXCEPTION(tempfile_exception)
std::unique_ptr< char[]> fn
Definition tempfile.hpp:155
TempFile(const std::string &fn_template, const bool fn_delete)
Definition tempfile.hpp:45
#define OPENVPN_THROW(exc, stuff)
OutT numeric_cast(InT inVal)
Tests attempted casts to ensure the input value does not exceed the capacity of the output type.
bool buf_read(const int fd, Buffer &buf, const std::string &title)
Definition bufread.hpp:29
ssize_t write_retry(int fd, const void *buf, size_t count)
Definition write.hpp:20
std::string strerror_str(const int errnum)
Definition strerror.hpp:21
std::string to_string() const
Definition buflist.hpp:72