From nobody Mon Aug 4 19:46:52 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bwnBP6GPgz63RJX; Mon, 04 Aug 2025 19:46:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bwnBN4zFCz4Kcj; Mon, 04 Aug 2025 19:46:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1754336812; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RZ3TyaR3zg4FoAsx8TKaPNOuA4NXOH6LyOBcv2S9fWw=; b=DmARWi2MnDzV+KfmJ6U/PPZURzaaN1ek9WfaKMofYuxJLHa2xVPRaww5Bmd5m+YLOJuzvS hspy2Wrep5nBNpYE8CWxcEQJK2zm3C/rSFbjmeijGnjam4sfQbhJEql6I9etfKlVAWRV08 qcDRXk3zIqbbpiijSMOOeJlKcbE8bHcZzuyZELr/RQEG/i7BBTOpxxqdPW+SFBrGaMT5O4 AMn5BvZRyItC6lmjjwwTT1ssEQJ6ddd21rCKRdV9XKksS9sEg8wVJVaxbQMbFrRd42Gv7x 0VONp9qg5VQE8ZT1A1EcDqcN982nL3LNC+vSWpSEC8ul97+UzND9WNC/JR4X0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1754336812; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RZ3TyaR3zg4FoAsx8TKaPNOuA4NXOH6LyOBcv2S9fWw=; b=m/rTaBR6h+eyTkoeWWKUAioYJ8gm6/69Q7vfwUBu8E01ytXlSyOs54m3FK/gkaAFuJrLyX sM91MEAEJkqdzmYRVCXBT4/7ufLpk9175InyVKKz15wNp7wwc2i2dsvvYjO0+l44UDbOlS to8Li00xqvea3bT79jPlX7CqgGR0eNWWVOxhF8IS5kTWkZcV5WHME1+3F4AOQf3IiBGZEn jiWT6Q0jy25F9I5vI1L8kk8+Kw6A2MG7C+w3U1Ke4XGabxhTgMHtdrPZg2E1748LOCF3sJ H0jxE5hNBvTekf7HrZ1gImBEO1IuaiKv4l11lKQAiBpmxSEZYT8bn+jeN7843A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1754336812; a=rsa-sha256; cv=none; b=BmarV0qTU8epFjZYZRfpVPWtX0A1a1pPtvTySExYrdHIn26uWOCZAHTGhloZbd+Qntqmnn 3RNGp+XVzvWfcqpr0mSKuvOcWAkRzojZNt4ovQTLcwtUzAPvgNzp86Qy0Ka2mfvtHuRtU0 CqsZsR1hB178OA1MHGeCsUpVTGskIdVe855Za+nBWtYLgHzNMQEIwP7d9bJVpQxTRxn7aY y5Z15oGaRi8aMXxwUVsidIe5IA1uahL2GhNmnUSqebZTn00aiKOM6F+f6re+B9S5ZztWRF ykpzbbEIoOM/v9LctcpKxybThCduMgx+hrc0eXecgLEw5PEIj9rjXDT0iIw+UQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bwnBN4ZYzz12W6; Mon, 04 Aug 2025 19:46:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 574JkqF7099206; Mon, 4 Aug 2025 19:46:52 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 574JkqrA099203; Mon, 4 Aug 2025 19:46:52 GMT (envelope-from git) Date: Mon, 4 Aug 2025 19:46:52 GMT Message-Id: <202508041946.574JkqrA099203@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: John Baldwin Subject: git: 937e92b5f7cc - main - libutil++: Add freebsd::fd_up class to manage file descriptors List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 937e92b5f7cc9495368e64f2d5b45312f6595ed2 Auto-Submitted: auto-generated The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=937e92b5f7cc9495368e64f2d5b45312f6595ed2 commit 937e92b5f7cc9495368e64f2d5b45312f6595ed2 Author: John Baldwin AuthorDate: 2025-08-04 19:38:07 +0000 Commit: John Baldwin 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 +.\" +.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 +#include #include #include @@ -43,6 +44,76 @@ namespace freebsd { using addrinfo_up = std::unique_ptr; + /* + * 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 is a std::unique_ptr<> which uses free() to * destroy the wrapped pointer. This can be used to wrap