The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=937e92b5f7cc9495368e64f2d5b45312f6595ed2

commit 937e92b5f7cc9495368e64f2d5b45312f6595ed2
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2025-08-04 19:38:07 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2025-08-04 19:38:07 +0000

    libutil++: Add freebsd::fd_up class to manage file descriptors
    
    This class aims to provide a std::unique_ptr<>-like interface in that
    it assumes exclusive ownership of a file descriptor.  The descriptor
    is closed when the object is destroyed.
    
    Sponsored by:   Chelsio Communications
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1794
---
 lib/libutil++/Makefile         |  1 +
 lib/libutil++/freebsd::fd_up.3 | 78 ++++++++++++++++++++++++++++++++++++++++++
 lib/libutil++/libutil++.hh     | 71 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+)

diff --git a/lib/libutil++/Makefile b/lib/libutil++/Makefile
index d53629b2e4e0..e64c9fe6cb75 100644
--- a/lib/libutil++/Makefile
+++ b/lib/libutil++/Makefile
@@ -6,6 +6,7 @@ SRCS=           stringf.cc
 
 MAN+=  freebsd::FILE_up.3 \
        freebsd::addrinfo_up.3 \
+       freebsd::fd_up.3 \
        freebsd::malloc_up.3 \
        freebsd::stringf.3
 
diff --git a/lib/libutil++/freebsd::fd_up.3 b/lib/libutil++/freebsd::fd_up.3
new file mode 100644
index 000000000000..2ef2241a5c40
--- /dev/null
+++ b/lib/libutil++/freebsd::fd_up.3
@@ -0,0 +1,78 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2025 Chelsio Communications, Inc.
+.\" Written by: John Baldwin <j...@freebsd.org>
+.\"
+.Dd July 31, 2025
+.Dt FREEBSD::STRINGF 3
+.Os
+.Sh NAME
+.Nm freebsd::fd_up
+.Nd own a file descriptor
+.Sh LIBRARY
+.Lb libutil++
+.Sh SYNOPSIS
+.In libutil++.hh
+.Pp
+.Vt class freebsd::fd_up
+{
+.Bd -ragged -offset indent
+.Fn fd_up
+.Fn fd_up "int fd"
+.Fn fd_up "fd_up &&other"
+.Fn ~fd_up
+.Ft int
+.Fn get
+.Ft int
+.Fn release
+.Ft void
+.Fn reset "int newfd = -1"
+.Ft "fd_up &"
+.Fn operator= "fd_up &&other"
+.Ft "fd_up &"
+.Fn operator= "int fd"
+.Fn "explicit operator bool"
+.Fn "operator int"
+.Ed
+};
+.Sh DESCRIPTION
+Each instance of this class owns a file descriptor.
+This class is patterned on std::unique_ptr,
+but instead of owning a pointer to an object,
+this class owns a file descriptor.
+The currently-owned file descriptor is disposed by invoking
+.Xr close 2
+when an instance of this class is destroyed.
+The currently-owned file descriptor is also disposed if it is replaced by the
+.Fn reset
+method or assignment operators.
+.Pp
+The
+.Fn get
+method returns the current file descriptor value while retaining ownership.
+.Pp
+The
+.Fn release
+method relinquishes ownership of the current file descriptor and returns the
+value of the previously-owned file descriptor.
+.Pp
+The explicit
+.Vt bool
+conversion operator permits testing the validity of an object.
+The operator returns true if the instance owns a valid file descriptor.
+.Pp
+The implicit
+.Vt int
+conversion operator permits passing an instance of this class directly as
+an argument to existing functions which expect a file descriptor.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+freebsd::fd_up fd(open("/dev/null", O_RDWR));
+if (!fd)
+       err(1, "open");
+write(fd, "test", 4);
+// `fd' is implicitly closed on destruction
+.Ed
+.Sh SEE ALSO
+.Xr close 2
diff --git a/lib/libutil++/libutil++.hh b/lib/libutil++/libutil++.hh
index e9269b482a5c..616bbecd8a12 100644
--- a/lib/libutil++/libutil++.hh
+++ b/lib/libutil++/libutil++.hh
@@ -9,6 +9,7 @@
 #define        __LIBUTILPP_HH__
 
 #include <netdb.h>
+#include <unistd.h>
 
 #include <cstdarg>
 #include <cstdio>
@@ -43,6 +44,76 @@ namespace freebsd {
 
        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

Reply via email to