Skip to content

Commit 6847dd7

Browse files
authored
Remove open_native_handle (#181)
Implement two different `create_file` functions for POSIX and Windows
1 parent ef65646 commit 6847dd7

File tree

3 files changed

+93
-73
lines changed

3 files changed

+93
-73
lines changed

src/create.cpp

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -116,90 +116,103 @@ const wchar_t* make_mdstring(std::ios::openmode mode) noexcept {
116116
#endif
117117
} // namespace
118118

119-
open_handle_type create_file(std::ios::openmode mode) {
119+
fs::path create_directory(std::string_view prefix) {
120+
validate_prefix(prefix); // throws std::invalid_argument with a proper text
121+
120122
std::error_code ec;
121-
open_handle_type handle = create_file(mode, ec);
123+
fs::path directory = create_directory(prefix, ec);
122124

123125
if (ec) {
124-
throw fs::filesystem_error("Cannot create a temporary file", ec);
126+
throw fs::filesystem_error("Cannot create a temporary directory", ec);
125127
}
126128

127-
return handle;
129+
return directory;
128130
}
129131

130-
open_handle_type create_file(std::ios::openmode mode, std::error_code& ec) {
132+
fs::path create_directory(std::string_view prefix, std::error_code& ec) {
133+
if (!is_prefix_valid(prefix)) {
134+
ec = std::make_error_code(std::errc::invalid_argument);
135+
return fs::path();
136+
}
137+
131138
#ifdef _WIN32
132-
fs::path::string_type path = make_path("");
139+
fs::path::string_type path = make_path(prefix);
133140
#else
134-
fs::path::string_type path = make_pattern("");
141+
fs::path::string_type path = make_pattern(prefix);
135142
#endif
136143

144+
#ifdef _WIN32
145+
if (!CreateDirectory(path.c_str(), nullptr)) {
146+
ec = std::error_code(GetLastError(), std::system_category());
147+
}
148+
#else
149+
if (mkdtemp(path.data()) == nullptr) {
150+
ec = std::error_code(errno, std::system_category());
151+
}
152+
#endif
153+
154+
return path;
155+
}
156+
157+
#if defined(_WIN32)
158+
std::FILE* create_file(std::ios::openmode mode) {
159+
std::error_code ec;
160+
std::FILE* handle = create_file(mode, ec);
161+
162+
if (ec) {
163+
throw fs::filesystem_error("Cannot create a temporary file", ec);
164+
}
165+
166+
return handle;
167+
}
168+
169+
std::FILE* create_file(std::ios::openmode mode, std::error_code& ec) {
170+
fs::path::string_type path = make_path("");
171+
137172
mode |= std::ios::in | std::ios::out;
138173

139-
#ifdef _WIN32
140174
std::FILE* handle;
141175

142176
// FIXME: use _wfopen_s
143177
if (const wchar_t* mdstr = make_mdstring(mode)) {
144178
handle = _wfopen(path.c_str(), mdstr);
145179
if (handle == nullptr) {
146180
ec = std::error_code(errno, std::system_category());
147-
return {};
181+
return nullptr;
148182
}
149183
} else {
150184
ec = std::make_error_code(std::errc::invalid_argument);
151-
return {};
152-
}
153-
#else
154-
int handle = mkstemp(path.data());
155-
if (handle == -1) {
156-
ec = std::error_code(errno, std::system_category());
157-
return {};
185+
return nullptr;
158186
}
159187

160-
unlink(path.c_str());
161-
#endif
162-
163-
(void)mode;
164188
ec.clear();
165189
return handle;
166190
}
167-
168-
fs::path create_directory(std::string_view prefix) {
169-
validate_prefix(prefix); // throws std::invalid_argument with a proper text
170-
191+
#else
192+
int create_file() {
171193
std::error_code ec;
172-
fs::path directory = create_directory(prefix, ec);
194+
int handle = create_file(ec);
173195

174196
if (ec) {
175-
throw fs::filesystem_error("Cannot create a temporary directory", ec);
197+
throw fs::filesystem_error("Cannot create a temporary file", ec);
176198
}
177199

178-
return directory;
200+
return handle;
179201
}
180202

181-
fs::path create_directory(std::string_view prefix, std::error_code& ec) {
182-
if (!is_prefix_valid(prefix)) {
183-
ec = std::make_error_code(std::errc::invalid_argument);
184-
return fs::path();
185-
}
186-
187-
#ifdef _WIN32
188-
fs::path::string_type path = make_path(prefix);
189-
#else
190-
fs::path::string_type path = make_pattern(prefix);
191-
#endif
203+
int create_file(std::error_code& ec) {
204+
fs::path::string_type path = make_pattern("");
192205

193-
#ifdef _WIN32
194-
if (!CreateDirectory(path.c_str(), nullptr)) {
195-
ec = std::error_code(GetLastError(), std::system_category());
196-
}
197-
#else
198-
if (mkdtemp(path.data()) == nullptr) {
206+
int handle = mkstemp(path.data());
207+
if (handle == -1) {
199208
ec = std::error_code(errno, std::system_category());
209+
return -1;
200210
}
201-
#endif
202211

203-
return path;
212+
unlink(path.c_str());
213+
214+
ec.clear();
215+
return handle;
204216
}
217+
#endif
205218
} // namespace tmp

src/create.hpp

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,10 @@
55
#include <ios>
66
#include <string_view>
77
#include <system_error>
8-
#include <utility>
98

109
namespace tmp {
1110
namespace fs = std::filesystem;
1211

13-
/// Implementation-defined handle type to the open file
14-
#if defined(_WIN32)
15-
using open_handle_type = std::FILE*;
16-
#elif __has_include(<unistd.h>)
17-
using open_handle_type = int; // POSIX file descriptor
18-
#else
19-
#error "Target platform not supported"
20-
#endif
21-
22-
/// Creates a temporary file in the system's temporary directory,
23-
/// and opens it for reading and writing
24-
/// @param[in] mode Specifies stream open mode
25-
/// @returns A handle to the created temporary file
26-
/// @throws fs::filesystem_error if cannot create a temporary file
27-
open_handle_type create_file(std::ios::openmode mode);
28-
29-
/// Creates a temporary file in the system's temporary directory,
30-
/// and opens it for reading and writing
31-
/// @param[in] mode Specifies stream open mode
32-
/// @param[out] ec Parameter for error reporting
33-
/// @returns A handle to the created temporary file
34-
open_handle_type create_file(std::ios::openmode mode, std::error_code& ec);
35-
3612
/// Creates a temporary directory with the given prefix in the system's
3713
/// temporary directory
3814
/// @param[in] prefix A prefix to attach to the temporary directory name
@@ -44,9 +20,39 @@ fs::path create_directory(std::string_view prefix);
4420
/// Creates a temporary directory with the given prefix in the system's
4521
/// temporary directory
4622
/// @param[in] prefix A prefix to attach to the temporary directory name
47-
/// @param[out] ec Parameter for error reporting
23+
/// @param[out] ec Parameter for error reporting
4824
/// @returns A path to the created temporary directory
4925
fs::path create_directory(std::string_view prefix, std::error_code& ec);
26+
27+
#if defined(_WIN32)
28+
/// Creates a temporary file in the system's temporary directory,
29+
/// and opens it for reading and writing
30+
/// @param[in] mode Specifies stream open mode
31+
/// @returns A handle to the created temporary file
32+
/// @throws fs::filesystem_error if cannot create a temporary file
33+
std::FILE* create_file(std::ios::openmode mode);
34+
35+
/// Creates a temporary file in the system's temporary directory,
36+
/// and opens it for reading and writing
37+
/// @param[in] mode Specifies stream open mode
38+
/// @param[out] ec Parameter for error reporting
39+
/// @returns A handle to the created temporary file
40+
std::FILE* create_file(std::ios::openmode mode, std::error_code& ec);
41+
#elif __has_include(<unistd.h>)
42+
/// Creates a temporary file in the system's temporary directory,
43+
/// and opens it for reading and writing
44+
/// @returns A handle to the created temporary file
45+
/// @throws fs::filesystem_error if cannot create a temporary file
46+
int create_file();
47+
48+
/// Creates a temporary file in the system's temporary directory,
49+
/// and opens it for reading and writing
50+
/// @param[out] ec Parameter for error reporting
51+
/// @returns A handle to the created temporary file
52+
int create_file(std::error_code& ec);
53+
#else
54+
#error "Target platform not supported"
55+
#endif
5056
} // namespace tmp
5157

5258
#endif // TMP_CREATE_H

src/file.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,22 +151,23 @@ file::file(std::ios::openmode mode)
151151
#endif
152152
{
153153
mode |= std::ios::in | std::ios::out;
154-
open_handle_type handle = create_file(mode);
155154

156155
#if defined(__GLIBCXX__)
156+
int handle = create_file();
157157
sb = __gnu_cxx::stdio_filebuf<char>(handle, mode);
158158
if (!sb.is_open()) {
159159
close(handle);
160160
throw fs::filesystem_error("", std::make_error_code(std::io_errc::stream));
161161
}
162162
#elif defined(_LIBCPP_VERSION)
163-
this->handle = handle;
163+
this->handle = create_file();
164164
sb.__open(handle, mode);
165165
if (!sb.is_open()) {
166166
close(handle);
167167
throw fs::filesystem_error("", std::make_error_code(std::io_errc::stream));
168168
}
169169
#else // MSVC
170+
std::FILE* handle = create_file(mode);
170171
underlying.reset(handle);
171172
sb = std::filebuf(underlying.get());
172173
#endif

0 commit comments

Comments
 (0)