1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Chelsio Communications, Inc.
* Written by: John Baldwin <jhb@FreeBSD.org>
*/
#ifndef __LIBUTILPP_HH__
#define __LIBUTILPP_HH__
#include <sys/nv.h>
#include <libutil.h>
#include <netdb.h>
#include <unistd.h>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <memory>
namespace freebsd {
/*
* FILE_up is a std::unique_ptr<> for FILE objects which uses
* fclose() to destroy the wrapped pointer.
*/
struct fclose_deleter {
void operator() (std::FILE *fp) const
{
std::fclose(fp);
}
};
using FILE_up = std::unique_ptr<std::FILE, fclose_deleter>;
/*
* addrinfo_up is a std::unique_ptr<> which uses
* freeaddrinfo() to destroy the wrapped pointer. It is
* intended to wrap arrays allocated by getaddrinfo().
*/
struct freeaddrinfo_deleter {
void operator() (struct addrinfo *ai) const
{
freeaddrinfo(ai);
}
};
using addrinfo_up = std::unique_ptr<addrinfo, freeaddrinfo_deleter>;
/*
* This class is intended to function similar to unique_ptr<>,
* but it contains a file descriptor rather than a pointer to
* an object. On destruction the descriptor is closed via
* close(2).
*
* Similar to unique_ptr<>, release() returns ownership of the
* file descriptor to the caller. reset() closes the current
* file descriptor and takes ownership of a new one. A move
* constructor permits ownership to be transferred via
* std::move(). An integer file descriptor can be assigned
* directly which is equivalent to calling reset().
*
* An explicit bool conversion operator permits testing this
* class in logical expressions. It returns true if it
* contains a valid descriptor.
*
* An implicit int conversion operator returns the underlying
* file descriptor allowing objects of this type to be passed
* directly to APIs such as connect(), listen(), etc.
*/
class fd_up {
public:
fd_up() : fd(-1) {}
fd_up(int _fd) : fd(_fd) {}
fd_up(fd_up &&other) : fd(other.release()) {}
fd_up(fd_up const &) = delete;
~fd_up() { reset(); }
int get() const { return (fd); }
int release()
{
int oldfd = fd;
fd = -1;
return (oldfd);
}
void reset(int newfd = -1)
{
if (fd >= 0)
close(fd);
fd = newfd;
}
fd_up &operator=(fd_up &&other) noexcept
{
if (this == &other)
return *this;
reset(other.release());
return *this;
}
fd_up &operator=(fd_up const &) = delete;
fd_up &operator=(int newfd)
{
reset(newfd);
return *this;
}
explicit operator bool() const { return fd >= 0; }
operator int() const { return fd; }
private:
int fd;
};
/*
* malloc_up<T> is a std::unique_ptr<> which uses free() to
* destroy the wrapped pointer. This can be used to wrap
* pointers allocated implicitly by malloc() such as those
* returned by strdup().
*/
template <class T>
struct free_deleter {
void operator() (T *p) const
{
std::free(p);
}
};
template <class T>
using malloc_up = std::unique_ptr<T, free_deleter<T>>;
/*
* nvlist_up is a std::unique_ptr<> for nvlist_t objects which
* uses nvlist_destroy() to destroy the wrapped pointer.
*/
struct nvlist_deleter {
void operator() (nvlist_t *nvl) const
{
nvlist_destroy(nvl);
}
};
using nvlist_up = std::unique_ptr<nvlist_t, nvlist_deleter>;
/*
* A wrapper class for the pidfile_* API. The destructor
* calls pidfile_remove() when an object is destroyed. This
* class is similar to std::unique_ptr<> in that it retains
* exclusive ownership of the pidfh object.
*
* In addition to release() and reset methods(), write(),
* close(), and fileno() methods are provided as wrappers for
* pidfile_*.
*/
class pidfile {
public:
pidfile() = default;
pidfile(struct pidfh *_pfh) : pfh(_pfh) {}
pidfile(pidfile &&other) : pfh(other.release()) {}
pidfile(pidfile const &) = delete;
~pidfile() { reset(); }
struct pidfh *release()
{
struct pidfh *oldpfh = pfh;
pfh = nullptr;
return (oldpfh);
}
void reset(struct pidfh *newpfh = nullptr)
{
if (pfh != nullptr)
pidfile_remove(pfh);
pfh = newpfh;
}
int write()
{
return (pidfile_write(pfh));
}
int close()
{
int rv = pidfile_close(pfh);
if (rv == 0)
pfh = nullptr;
return (rv);
}
int fileno()
{
return (pidfile_fileno(pfh));
}
pidfile &operator=(pidfile &&other) noexcept
{
if (this == &other)
return *this;
reset(other.release());
return *this;
}
pidfile &operator=(pidfile const &) = delete;
pidfile &operator=(struct pidfh *newpfh)
{
reset(newpfh);
return *this;
}
explicit operator bool() const { return pfh != nullptr; }
private:
struct pidfh *pfh = nullptr;
};
/*
* Returns a std::string containing the same output as
* sprintf(). Throws std::bad_alloc if an error occurs.
*/
std::string stringf(const char *fmt, ...) __printflike(1, 2);
std::string stringf(const char *fmt, std::va_list ap);
}
#endif /* !__LIBUTILPP_HH__ */
|