aboutsummaryrefslogtreecommitdiff
path: root/lib/libutil++/libutil++.hh
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutil++/libutil++.hh')
-rw-r--r--lib/libutil++/libutil++.hh230
1 files changed, 230 insertions, 0 deletions
diff --git a/lib/libutil++/libutil++.hh b/lib/libutil++/libutil++.hh
new file mode 100644
index 000000000000..ecf737f2fcb0
--- /dev/null
+++ b/lib/libutil++/libutil++.hh
@@ -0,0 +1,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__ */