aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile14
-rw-r--r--lib/atf/Makefile.inc2
-rw-r--r--lib/atf/libatf-c++/Makefile1
-rw-r--r--lib/atf/libatf-c++/tests/Makefile2
-rw-r--r--lib/atf/libatf-c/Makefile1
-rw-r--r--lib/atf/libatf-c/tests/Makefile2
-rw-r--r--lib/clang/freebsd_cc_version.h2
-rw-r--r--lib/clang/include/lld/Common/Version.inc2
-rw-r--r--lib/libarchive/config_freebsd.h1
-rw-r--r--lib/libarchive/tests/Makefile6
-rw-r--r--lib/libbe/Makefile1
-rw-r--r--lib/libblacklist/Makefile7
-rw-r--r--lib/libblocklist/Makefile30
-rw-r--r--lib/libblocklist/Makefile.depend16
-rw-r--r--lib/libbluetooth/Makefile2
-rw-r--r--lib/libbsdstat/bsdstat.h2
-rw-r--r--lib/libbsm/Makefile9
-rw-r--r--lib/libbsnmp/libbsnmp/Makefile2
-rw-r--r--lib/libbz2/Makefile17
-rw-r--r--lib/libbz2/bzip2.pc.in11
-rw-r--r--lib/libc/Makefile1
-rw-r--r--lib/libc/Versions.def6
-rw-r--r--lib/libc/aarch64/string/timingsafe_memcmp.S2
-rw-r--r--lib/libc/amd64/string/memrchr.S224
-rw-r--r--lib/libc/db/hash/hash.c24
-rw-r--r--lib/libc/db/man/dbm.35
-rw-r--r--lib/libc/db/man/dbopen.35
-rw-r--r--lib/libc/gdtoa/_hdtoa.c3
-rw-r--r--lib/libc/gdtoa/_hldtoa.c3
-rw-r--r--lib/libc/gen/Symbol.map2
-rw-r--r--lib/libc/gen/_rand48.c34
-rw-r--r--lib/libc/gen/drand48.c6
-rw-r--r--lib/libc/gen/erand48.c9
-rw-r--r--lib/libc/gen/exec.c227
-rw-r--r--lib/libc/gen/fdopendir.c10
-rw-r--r--lib/libc/gen/fts-compat.c2
-rw-r--r--lib/libc/gen/fts-compat11.c2
-rw-r--r--lib/libc/gen/fts.3195
-rw-r--r--lib/libc/gen/fts.c3
-rw-r--r--lib/libc/gen/gen-compat.h48
-rw-r--r--lib/libc/gen/getgrouplist.350
-rw-r--r--lib/libc/gen/getgrouplist.c6
-rw-r--r--lib/libc/gen/initgroups.3105
-rw-r--r--lib/libc/gen/initgroups.c55
-rw-r--r--lib/libc/gen/jrand48.c7
-rw-r--r--lib/libc/gen/lcong48.c12
-rw-r--r--lib/libc/gen/lrand48.c6
-rw-r--r--lib/libc/gen/mrand48.c8
-rw-r--r--lib/libc/gen/nrand48.c6
-rw-r--r--lib/libc/gen/psignal.39
-rw-r--r--lib/libc/gen/rand48.35
-rw-r--r--lib/libc/gen/rand48.h61
-rw-r--r--lib/libc/gen/readdir.c2
-rw-r--r--lib/libc/gen/seed48.c18
-rw-r--r--lib/libc/gen/srand48.c13
-rw-r--r--lib/libc/gen/sysconf.c2
-rw-r--r--lib/libc/gen/sysctl.37
-rw-r--r--lib/libc/i386/gen/makecontext.c2
-rw-r--r--lib/libc/include/compat.h4
-rw-r--r--lib/libc/include/port_before.h1
-rw-r--r--lib/libc/inet/inet_net_ntop.c206
-rw-r--r--lib/libc/inet/inet_net_pton.c363
-rw-r--r--lib/libc/md/Makefile.inc3
-rw-r--r--lib/libc/net/gai_strerror.c44
-rw-r--r--lib/libc/net/gethostbydns.c6
-rw-r--r--lib/libc/net/res_config.h4
-rw-r--r--lib/libc/nls/Makefile.inc5
-rw-r--r--lib/libc/powerpc64/gen/_ctx_start.S14
-rw-r--r--lib/libc/powerpc64/gen/makecontext.c3
-rw-r--r--lib/libc/regex/regcomp.c1
-rw-r--r--lib/libc/resolv/Symbol.map1
-rw-r--r--lib/libc/resolv/res_debug.h2
-rw-r--r--lib/libc/resolv/res_init.c67
-rw-r--r--lib/libc/resolv/res_mkquery.c5
-rw-r--r--lib/libc/resolv/res_mkupdate.c4
-rw-r--r--lib/libc/resolv/res_query.c5
-rw-r--r--lib/libc/resolv/res_send.c49
-rw-r--r--lib/libc/rpc/rpc_generic.c4
-rw-r--r--lib/libc/stdio/Symbol.map1
-rw-r--r--lib/libc/stdio/fdopen.c18
-rw-r--r--lib/libc/stdio/freopen.c10
-rw-r--r--lib/libc/stdio/vfscanf.c5
-rw-r--r--lib/libc/stdio/vfwscanf.c5
-rw-r--r--lib/libc/stdlib/Makefile.inc3
-rw-r--r--lib/libc/stdlib/Symbol.map4
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/Makefile.inc14
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h91
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h54
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h481
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h4
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h69
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h10
-rw-r--r--lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_defs.h55
-rw-r--r--lib/libc/stdlib/qsort.c13
-rw-r--r--lib/libc/stdlib/reallocarray.337
-rw-r--r--lib/libc/stdlib/reallocarray.c14
-rw-r--r--lib/libc/stdlib/realpath.312
-rw-r--r--lib/libc/stdlib/realpath.c14
-rw-r--r--lib/libc/stdlib/recallocarray.c (renamed from lib/libopenbsd/recallocarray.c)15
-rw-r--r--lib/libc/stdtime/Makefile.inc4
-rw-r--r--lib/libc/stdtime/Symbol.map6
-rw-r--r--lib/libc/stdtime/ctime.339
-rw-r--r--lib/libc/stdtime/strptime.32
-rw-r--r--lib/libc/stdtime/strptime.c3
-rw-r--r--lib/libc/stdtime/tzset.357
-rw-r--r--lib/libc/string/memchr.322
-rw-r--r--lib/libc/sys/accept.c2
-rw-r--r--lib/libc/sys/accept4.c2
-rw-r--r--lib/libc/sys/aio_suspend.c2
-rw-r--r--lib/libc/sys/clock_nanosleep.c2
-rw-r--r--lib/libc/sys/close.c2
-rw-r--r--lib/libc/sys/connect.c2
-rw-r--r--lib/libc/sys/fork.c2
-rw-r--r--lib/libc/sys/fsync.c2
-rw-r--r--lib/libc/sys/kevent.c2
-rw-r--r--lib/libc/sys/msync.c2
-rw-r--r--lib/libc/sys/nanosleep.c2
-rw-r--r--lib/libc/sys/open.c2
-rw-r--r--lib/libc/sys/openat.c1
-rw-r--r--lib/libc/sys/poll.c2
-rw-r--r--lib/libc/sys/ppoll.c2
-rw-r--r--lib/libc/sys/pselect.c2
-rw-r--r--lib/libc/sys/read.c2
-rw-r--r--lib/libc/sys/readv.c2
-rw-r--r--lib/libc/sys/recvfrom.c2
-rw-r--r--lib/libc/sys/recvmsg.c2
-rw-r--r--lib/libc/sys/select.c2
-rw-r--r--lib/libc/sys/sendmsg.c2
-rw-r--r--lib/libc/sys/sendto.c2
-rw-r--r--lib/libc/sys/setcontext.c1
-rw-r--r--lib/libc/sys/sigaction.c1
-rw-r--r--lib/libc/sys/sigprocmask.c1
-rw-r--r--lib/libc/sys/sigsuspend.c1
-rw-r--r--lib/libc/sys/sigtimedwait.c2
-rw-r--r--lib/libc/sys/sigwaitinfo.c2
-rw-r--r--lib/libc/sys/swapcontext.c1
-rw-r--r--lib/libc/sys/wait4.c2
-rw-r--r--lib/libc/sys/wait6.c2
-rw-r--r--lib/libc/sys/write.c2
-rw-r--r--lib/libc/sys/writev.c2
-rw-r--r--lib/libc/tests/db/Makefile4
-rw-r--r--lib/libc/tests/db/dbm_nextkey_test.c53
-rw-r--r--lib/libc/tests/db/dbm_open_test.c52
-rw-r--r--lib/libc/tests/db/dbm_perm_test.c98
-rw-r--r--lib/libc/tests/gen/posix_spawn_test.c50
-rw-r--r--lib/libc/tests/gen/realpath2_test.c106
-rw-r--r--lib/libc/tests/net/Makefile2
-rw-r--r--lib/libc/tests/net/inet_net_test.cc333
-rw-r--r--lib/libc/tests/stdio/flushlbuf_test.c10
-rw-r--r--lib/libc/tests/stdio/printfloat_test.c13
-rw-r--r--lib/libc/tests/stdio/sscanf_test.c25
-rw-r--r--lib/libc/tests/stdio/swscanf_test.c25
-rw-r--r--lib/libc/tests/stdlib/Makefile1
-rw-r--r--lib/libc/tests/stdlib/qsort_bench.c113
-rw-r--r--lib/libc/tests/stdtime/Makefile8
-rw-r--r--lib/libc/tests/stdtime/detect_tz_changes_test.c477
-rw-r--r--lib/libc/tests/string/memcmp_test.c12
-rw-r--r--lib/libc/tests/sys/Makefile4
-rw-r--r--lib/libc/tests/sys/swapcontext_test.c63
-rw-r--r--lib/libc/tests/tls/dso/Makefile1
-rw-r--r--lib/libc/tests/tls_dso/Makefile1
-rw-r--r--lib/libcasper/services/cap_fileargs/cap_fileargs.3174
-rw-r--r--lib/libcasper/services/cap_fileargs/cap_fileargs.h2
-rw-r--r--lib/libcasper/services/cap_net/tests/net_test.c168
-rw-r--r--lib/libcom_err/Makefile3
-rw-r--r--lib/libcrypt/Makefile2
-rw-r--r--lib/libdiff/Makefile2
-rw-r--r--lib/libedit/Makefile3
-rw-r--r--lib/libedit/Makefile.inc1
-rw-r--r--lib/libelftc/Makefile1
-rw-r--r--lib/libexpat/expat_config.h18
-rw-r--r--lib/libexpat/libbsdxml.34
-rw-r--r--lib/libfetch/common.c7
-rw-r--r--lib/libfido2/Makefile1
-rw-r--r--lib/libgpio/Makefile4
-rw-r--r--lib/libgpio/gpio.368
-rw-r--r--lib/libgpio/gpio.c20
-rw-r--r--lib/libgpio/libgpio.h13
-rw-r--r--lib/libifconfig/Makefile2
-rw-r--r--lib/libifconfig/Symbol.map2
-rw-r--r--lib/libifconfig/libifconfig.h14
-rw-r--r--lib/libifconfig/libifconfig_bridge.c12
-rw-r--r--lib/libifconfig/libifconfig_nl.c72
-rw-r--r--lib/libiscsiutil/Makefile1
-rw-r--r--lib/libjail/jail.c74
-rw-r--r--lib/libkvm/kvm_proc.c9
-rw-r--r--lib/liblzma/Makefile4
-rw-r--r--lib/libmilter/Makefile2
-rw-r--r--lib/libmixer/Makefile2
-rw-r--r--lib/libnetbsd/Makefile1
-rw-r--r--lib/libnvmf/Makefile1
-rw-r--r--lib/libnvmf/libnvmf.h11
-rw-r--r--lib/libnvmf/nvmf_controller.c50
-rw-r--r--lib/libnvmf/nvmf_tcp.c2
-rw-r--r--lib/libopenbsd/Makefile9
-rw-r--r--lib/libopencsd/Makefile6
-rw-r--r--lib/libpam/modules/modules.inc2
-rw-r--r--lib/libpam/modules/pam_krb5/Makefile3
-rw-r--r--lib/libpam/modules/pam_ksu/pam_ksu.c31
-rw-r--r--lib/libpam/modules/pam_xdg/pam_xdg.81
-rw-r--r--lib/libpfctl/Makefile1
-rw-r--r--lib/libpfctl/libpfctl.c191
-rw-r--r--lib/libpfctl/libpfctl.h28
-rw-r--r--lib/libpmc/Makefile4
-rw-r--r--lib/libpmcstat/Makefile1
-rw-r--r--lib/libprocstat/libprocstat.c13
-rw-r--r--lib/libregex/tests/gnuext.in6
-rw-r--r--lib/librpcsec_gss/Makefile6
-rw-r--r--lib/libsamplerate/Makefile20
-rw-r--r--lib/libsdp/Makefile3
-rw-r--r--lib/libsdp/sdp.34
-rw-r--r--lib/libsdp/sdp.h2
-rw-r--r--lib/libsdp/service.c2
-rw-r--r--lib/libsecureboot/h/libsecureboot.h1
-rw-r--r--lib/libsm/Makefile1
-rw-r--r--lib/libsmdb/Makefile1
-rw-r--r--lib/libsmutil/Makefile1
-rw-r--r--lib/libstdbuf/Makefile1
-rw-r--r--lib/libstdthreads/Makefile2
-rw-r--r--lib/libsys/Makefile.sys22
-rw-r--r--lib/libsys/Symbol.map6
-rw-r--r--lib/libsys/Symbol.sys.map6
-rw-r--r--lib/libsys/_libsys.h20
-rw-r--r--lib/libsys/amd64/amd64_get_fsbase.c7
-rw-r--r--lib/libsys/amd64/amd64_get_gsbase.c7
-rw-r--r--lib/libsys/amd64/amd64_set_fsbase.c7
-rw-r--r--lib/libsys/amd64/amd64_set_gsbase.c7
-rw-r--r--lib/libsys/chroot.249
-rw-r--r--lib/libsys/copy_file_range.235
-rw-r--r--lib/libsys/fhopen.24
-rw-r--r--lib/libsys/getgroups.296
-rw-r--r--lib/libsys/getsockopt.29
-rw-r--r--lib/libsys/jail.2197
-rw-r--r--lib/libsys/kqueue.289
-rw-r--r--lib/libsys/mkdir.22
-rw-r--r--lib/libsys/pathconf.28
-rw-r--r--lib/libsys/setcred.27
-rw-r--r--lib/libsys/setgroups.2123
-rw-r--r--lib/libsys/shm_open.25
-rw-r--r--lib/libsys/socket.2302
-rw-r--r--lib/libsys/stat.25
-rw-r--r--lib/libsys/statfs.26
-rw-r--r--lib/libsys/syscalls.map14
-rw-r--r--lib/libsysdecode/Makefile2
-rw-r--r--lib/libsysdecode/Makefile.depend2
-rw-r--r--lib/libsysdecode/sysdecode.32
-rw-r--r--lib/libsysdecode/sysdecode_abi_to_freebsd_errno.32
-rw-r--r--lib/libsysdecode/sysdecode_syscallname.3 (renamed from lib/libsysdecode/sysdecode_syscallnames.3)6
-rw-r--r--lib/libtelnet/Makefile1
-rw-r--r--lib/libthr/thread/thr_getthreadid_np.c2
-rw-r--r--lib/libthr/thread/thr_init.c1
-rw-r--r--lib/libthr/thread/thr_sig.c8
-rw-r--r--lib/libufs/Makefile4
-rw-r--r--lib/libunbound/Makefile37
-rw-r--r--lib/libunbound/config.h521
-rw-r--r--lib/libusb/libusb.361
-rw-r--r--lib/libusb/libusb.h37
-rw-r--r--lib/libusb/libusb10.c21
-rw-r--r--lib/libusb/libusb10_desc.c51
-rw-r--r--lib/libusb/libusb10_hotplug.c18
-rw-r--r--lib/libusb/libusb10_io.c28
-rw-r--r--lib/libutil++/Makefile23
-rw-r--r--lib/libutil++/freebsd__FILE_up.341
-rw-r--r--lib/libutil++/freebsd__addrinfo_up.345
-rw-r--r--lib/libutil++/freebsd__fd_up.378
-rw-r--r--lib/libutil++/freebsd__malloc_up.350
-rw-r--r--lib/libutil++/freebsd__nvlist_up.337
-rw-r--r--lib/libutil++/freebsd__pidfile.3110
-rw-r--r--lib/libutil++/freebsd__stringf.348
-rw-r--r--lib/libutil++/libutil++.hh230
-rw-r--r--lib/libutil++/stringf.cc57
-rw-r--r--lib/libutil++/tests/Makefile12
-rw-r--r--lib/libutil++/tests/pidfile_test.cc44
-rw-r--r--lib/libutil++/tests/stringf_test.cc52
-rw-r--r--lib/libutil++/tests/up_test.cc33
-rw-r--r--lib/libutil/Makefile186
-rw-r--r--lib/libutil/Symbol.map135
-rw-r--r--lib/libutil/auth.c44
-rw-r--r--lib/libutil/cpuset.351
-rw-r--r--lib/libutil/cpuset.c98
-rw-r--r--lib/libutil/expand_number.3104
-rw-r--r--lib/libutil/expand_number.c123
-rw-r--r--lib/libutil/libutil.h19
-rw-r--r--lib/libutil/login.conf.511
-rw-r--r--lib/libutil/login_auth.34
-rw-r--r--lib/libutil/login_cap.31
-rw-r--r--lib/libutil/mntopts.310
-rw-r--r--lib/libutil/mntopts.c52
-rw-r--r--lib/libutil/pidfile.368
-rw-r--r--lib/libutil/pw_util.31
-rw-r--r--lib/libutil/tests/expand_number_test.c292
-rw-r--r--lib/libutil/uucplock.31
-rw-r--r--lib/libvmmapi/Makefile2
-rw-r--r--lib/libvmmapi/internal.h11
-rw-r--r--lib/libvmmapi/vmmapi.c181
-rw-r--r--lib/libvmmapi/vmmapi.h22
-rw-r--r--lib/libxo/tests/encoder/Makefile1
-rw-r--r--lib/liby/Makefile2
-rw-r--r--lib/msun/bsdsrc/b_tgamma.c2
-rw-r--r--lib/msun/src/e_fmod.c30
-rw-r--r--lib/msun/src/e_fmodf.c16
-rw-r--r--lib/msun/src/e_remainder.c4
-rw-r--r--lib/msun/src/math_private.h35
-rw-r--r--lib/msun/src/s_ccosh.c23
-rw-r--r--lib/msun/src/s_ccoshf.c18
-rw-r--r--lib/msun/src/s_cpow.c5
-rw-r--r--lib/msun/src/s_cpowf.c5
-rw-r--r--lib/msun/src/s_cpowl.c5
-rw-r--r--lib/msun/src/s_csinh.c23
-rw-r--r--lib/msun/src/s_csinhf.c18
-rw-r--r--lib/msun/src/s_ilogb.c13
-rw-r--r--lib/msun/src/s_ilogbf.c5
-rw-r--r--lib/msun/src/s_remquo.c30
-rw-r--r--lib/msun/src/s_remquof.c16
-rw-r--r--lib/ncurses/Makefile.inc2
-rw-r--r--lib/ncurses/form/Makefile1
-rw-r--r--lib/ncurses/ncurses/Makefile1
-rw-r--r--lib/ncurses/panel/Makefile1
-rw-r--r--lib/ncurses/tinfo/Makefile10
-rw-r--r--lib/nss_tacplus/Makefile4
-rw-r--r--lib/virtual_oss/Makefile9
-rw-r--r--lib/virtual_oss/Makefile.inc5
-rw-r--r--lib/virtual_oss/bt/Makefile19
-rw-r--r--lib/virtual_oss/bt/avdtp.c720
-rw-r--r--lib/virtual_oss/bt/avdtp_signal.h139
-rw-r--r--lib/virtual_oss/bt/bt.c1061
-rw-r--r--lib/virtual_oss/bt/bt.h116
-rw-r--r--lib/virtual_oss/bt/cosdata-gen/Makefile12
-rw-r--r--lib/virtual_oss/bt/cosdata-gen/cosdata.c177
-rw-r--r--lib/virtual_oss/bt/sbc_coeffs.h69
-rw-r--r--lib/virtual_oss/bt/sbc_encode.c701
-rw-r--r--lib/virtual_oss/bt/sbc_encode.h82
-rw-r--r--lib/virtual_oss/null/Makefile10
-rw-r--r--lib/virtual_oss/null/null.c102
-rw-r--r--lib/virtual_oss/oss/Makefile10
-rw-r--r--lib/virtual_oss/oss/oss.c197
-rw-r--r--lib/virtual_oss/sndio/Makefile12
-rw-r--r--lib/virtual_oss/sndio/sndio.c203
338 files changed, 11331 insertions, 2467 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 3417e7b30cb4..75a2355aa452 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -92,6 +92,7 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
librss \
librt \
librtld_db \
+ libsamplerate \
libsbuf \
libsmb \
libstdbuf \
@@ -105,6 +106,7 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
libugidfw \
libulog \
libutil \
+ libutil++ \
${_libvgl} \
libwrap \
libxo \
@@ -135,7 +137,9 @@ SUBDIR_DEPEND_libdevstat= libkvm
SUBDIR_DEPEND_libdpv= libfigpar ncurses libutil
SUBDIR_DEPEND_libedit= ncurses
SUBDIR_DEPEND_libgeom= libexpat libsbuf
+.if ${MK_MITKRB5} == "no"
SUBDIR_DEPEND_librpcsec_gss= libgssapi
+.endif
SUBDIR_DEPEND_libmagic= libz
SUBDIR_DEPEND_libmemstat= libkvm
SUBDIR_DEPEND_libpam= libcrypt ${_libradius} librpcsvc libtacplus libutil ${_libypclnt} ${_libcom_err}
@@ -153,11 +157,13 @@ SUBDIR_DEPEND_liblzma= libthr
SUBDIR_DEPEND_libpcap= ofed
.endif
SUBDIR_DEPEND_nss_tacplus= libtacplus
+SUBDIR_DEPEND_virtual_oss= libsamplerate
# NB: keep these sorted by MK_* knobs
SUBDIR.${MK_BEARSSL}+= libbearssl libsecureboot
SUBDIR.${MK_BLACKLIST}+=libblacklist
+SUBDIR.${MK_BLOCKLIST}+=libblocklist
SUBDIR.${MK_BLUETOOTH}+=libbluetooth libsdp
SUBDIR.${MK_BSNMP}+= libbsnmp
@@ -169,15 +175,19 @@ SUBDIR+= clang
.endif
SUBDIR.${MK_CUSE}+= libcuse
+SUBDIR.${MK_CUSE}+= virtual_oss
SUBDIR.${MK_TOOLCHAIN}+=libpe
SUBDIR.${MK_DIALOG}+= libdpv libfigpar
SUBDIR.${MK_FDT}+= libfdt
SUBDIR.${MK_FILE}+= libmagic
SUBDIR.${MK_GPIO}+= libgpio
-SUBDIR.${MK_GSSAPI}+= libgssapi librpcsec_gss
+.if ${MK_MITKRB5} == "no"
+SUBDIR.${MK_KERBEROS}+= libgssapi
+.endif
+SUBDIR.${MK_KERBEROS}+= librpcsec_gss
SUBDIR.${MK_ICONV}+= libiconv_modules
.if ${MK_MITKRB5} == "no"
-SUBDIR.${MK_KERBEROS_SUPPORT}+= libcom_err
+SUBDIR.${MK_KERBEROS}+= libcom_err
.endif
SUBDIR.${MK_LDNS}+= libldns
SUBDIR.${MK_STATS}+= libstats
diff --git a/lib/atf/Makefile.inc b/lib/atf/Makefile.inc
index f8f329842eb4..bebed0280596 100644
--- a/lib/atf/Makefile.inc
+++ b/lib/atf/Makefile.inc
@@ -24,6 +24,8 @@
# SUCH DAMAGE.
#
+PACKAGE= atf
+LIB_PACKAGE=
CFLAGS+= -DHAVE_CONFIG_H
WARNS?= 3
diff --git a/lib/atf/libatf-c++/Makefile b/lib/atf/libatf-c++/Makefile
index 985a79b7dc03..4f4f7f12ec05 100644
--- a/lib/atf/libatf-c++/Makefile
+++ b/lib/atf/libatf-c++/Makefile
@@ -27,7 +27,6 @@
.include <src.opts.mk>
.include <bsd.init.mk>
-PACKAGE= tests
LIB_CXX= atf-c++
PRIVATELIB= true
SHLIB_MAJOR= 2
diff --git a/lib/atf/libatf-c++/tests/Makefile b/lib/atf/libatf-c++/tests/Makefile
index dc052c19df67..839c6902d6b1 100644
--- a/lib/atf/libatf-c++/tests/Makefile
+++ b/lib/atf/libatf-c++/tests/Makefile
@@ -1,7 +1,5 @@
.include <bsd.init.mk>
-PACKAGE= tests
-
TESTS_SUBDIRS= detail
ATF= ${SRCTOP}/contrib/atf
diff --git a/lib/atf/libatf-c/Makefile b/lib/atf/libatf-c/Makefile
index 4cfee2ed824f..c0890abc7640 100644
--- a/lib/atf/libatf-c/Makefile
+++ b/lib/atf/libatf-c/Makefile
@@ -27,7 +27,6 @@
.include <src.opts.mk>
.include <bsd.init.mk>
-PACKAGE= tests
LIB= atf-c
PRIVATELIB= true
SHLIB_MAJOR= 1
diff --git a/lib/atf/libatf-c/tests/Makefile b/lib/atf/libatf-c/tests/Makefile
index c81c18a91f00..5647e7b9fcbe 100644
--- a/lib/atf/libatf-c/tests/Makefile
+++ b/lib/atf/libatf-c/tests/Makefile
@@ -1,7 +1,5 @@
.include <bsd.init.mk>
-PACKAGE= tests
-
TESTS_SUBDIRS= detail
ATF= ${SRCTOP}/contrib/atf
diff --git a/lib/clang/freebsd_cc_version.h b/lib/clang/freebsd_cc_version.h
index 277744ae8624..b493dc96db5e 100644
--- a/lib/clang/freebsd_cc_version.h
+++ b/lib/clang/freebsd_cc_version.h
@@ -1 +1 @@
-#define FREEBSD_CC_VERSION 1500000
+#define FREEBSD_CC_VERSION 1600000
diff --git a/lib/clang/include/lld/Common/Version.inc b/lib/clang/include/lld/Common/Version.inc
index 0643da4abbf4..0def3da7469c 100644
--- a/lib/clang/include/lld/Common/Version.inc
+++ b/lib/clang/include/lld/Common/Version.inc
@@ -1,4 +1,4 @@
// Local identifier in __FreeBSD_version style
-#define LLD_FREEBSD_VERSION 1500001
+#define LLD_FREEBSD_VERSION 1600000
#define LLD_VERSION_STRING "19.1.7 (FreeBSD llvmorg-19.1.7-0-gcd708029e0b2-" __XSTRING(LLD_FREEBSD_VERSION) ")"
diff --git a/lib/libarchive/config_freebsd.h b/lib/libarchive/config_freebsd.h
index a3a0216169bf..1601adddd0de 100644
--- a/lib/libarchive/config_freebsd.h
+++ b/lib/libarchive/config_freebsd.h
@@ -165,7 +165,6 @@
#define HAVE_POSIX_SPAWNP 1
#define HAVE_PTHREAD_H 1
#define HAVE_PWD_H 1
-#define HAVE_READDIR_R 1
#define HAVE_READLINK 1
#define HAVE_READLINKAT 1
#ifndef __linux__
diff --git a/lib/libarchive/tests/Makefile b/lib/libarchive/tests/Makefile
index 07c5fe24dd30..930250d974c5 100644
--- a/lib/libarchive/tests/Makefile
+++ b/lib/libarchive/tests/Makefile
@@ -185,6 +185,7 @@ TESTS_SRCS= \
test_read_format_rar_overflow.c \
test_read_format_raw.c \
test_read_format_tar.c \
+ test_read_format_tar_V_negative_size.c \
test_read_format_tar_concatenated.c \
test_read_format_tar_empty_filename.c \
test_read_format_tar_empty_pax.c \
@@ -607,6 +608,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_different_solid_window_size.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_different_window_size.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_different_winsize_on_merge.rar.uu
+${PACKAGE}FILES+= test_read_format_rar5_dirdata.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_distance_overflow.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_encrypted.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_encrypted_filenames.rar.uu
@@ -616,6 +618,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_extra_field_version.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_fileattr.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_hardlink.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_invalid_dict_reference.rar.uu
+${PACKAGE}FILES+= test_read_format_rar5_invalid_hash_valid_htime_exfld.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_leftshift1.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_leftshift2.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiarchive.part01.rar.uu
@@ -633,6 +636,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_multiarchive_solid.part04.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiple_files.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_multiple_files_solid.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_nonempty_dir_stream.rar.uu
+${PACKAGE}FILES+= test_read_format_rar5_only_crypt_exfld.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_owner.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_readtables_overflow.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_sfx.exe.uu
@@ -642,12 +646,14 @@ ${PACKAGE}FILES+= test_read_format_rar5_stored_manyfiles.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_symlink.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_truncated_huff.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_unicode.rar.uu
+${PACKAGE}FILES+= test_read_format_rar5_unsupported_exfld.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_win32.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_window_buf_and_size_desync.rar.uu
${PACKAGE}FILES+= test_read_format_raw.bufr.uu
${PACKAGE}FILES+= test_read_format_raw.data.Z.uu
${PACKAGE}FILES+= test_read_format_raw.data.gz.uu
${PACKAGE}FILES+= test_read_format_raw.data.uu
+${PACKAGE}FILES+= test_read_format_tar_V_negative_size.tar.uu
${PACKAGE}FILES+= test_read_format_tar_concatenated.tar.uu
${PACKAGE}FILES+= test_read_format_tar_empty_filename.tar.uu
${PACKAGE}FILES+= test_read_format_tar_empty_with_gnulabel.tar.uu
diff --git a/lib/libbe/Makefile b/lib/libbe/Makefile
index b04becc38d74..3ba456aee4b7 100644
--- a/lib/libbe/Makefile
+++ b/lib/libbe/Makefile
@@ -3,6 +3,7 @@ SHLIBDIR?= /lib
.include <src.opts.mk>
PACKAGE= zfs
+LIB_PACKAGE=
LIB= be
SHLIB_MAJOR= 1
SHLIB_MINOR= 0
diff --git a/lib/libblacklist/Makefile b/lib/libblacklist/Makefile
index bfd9edb9614c..cac023d69bb7 100644
--- a/lib/libblacklist/Makefile
+++ b/lib/libblacklist/Makefile
@@ -1,6 +1,6 @@
BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist
-.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include
+.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include ${BLOCKLIST_DIR}/port
PACKAGE= blocklist
LIB= blacklist
@@ -13,9 +13,10 @@ CFLAGS.clang+=-Wno-thread-safety-analysis
CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \
-D_REENTRANT -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \
-DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_GETPROGNAME \
- -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN
+ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN \
+ -DHAVE_SYS_CDEFS_H
-SRCS= bl.c blacklist.c
+SRCS= old_bl.c blacklist.c vsyslog_r.c
INCS= blacklist.h
MAN= libblacklist.3
diff --git a/lib/libblocklist/Makefile b/lib/libblocklist/Makefile
new file mode 100644
index 000000000000..127abb23f43e
--- /dev/null
+++ b/lib/libblocklist/Makefile
@@ -0,0 +1,30 @@
+BLOCKLIST_DIR=${SRCTOP}/contrib/blocklist
+
+.PATH: ${BLOCKLIST_DIR}/lib ${BLOCKLIST_DIR}/include ${BLOCKLIST_DIR}/port
+
+PACKAGE= blocklist
+LIB= blocklist
+SHLIB_MAJOR= 0
+
+LIBADD+= pthread
+
+CFLAGS.clang+=-Wno-thread-safety-analysis
+
+CFLAGS+=-I${BLOCKLIST_DIR}/include -I${BLOCKLIST_DIR}/port \
+ -D_REENTRANT -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \
+ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_GETPROGNAME \
+ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN \
+ -DHAVE_SYS_CDEFS_H
+
+SRCS= bl.c blocklist.c vsyslog_r.c
+INCS= blocklist.h
+MAN= libblocklist.3
+
+MLINKS= libblocklist.3 blocklist_open.3 \
+ libblocklist.3 blocklist_close.3 \
+ libblocklist.3 blocklist.3 \
+ libblocklist.3 blocklist_r.3 \
+ libblocklist.3 blocklist_sa.3 \
+ libblocklist.3 blocklist_sa_r.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libblocklist/Makefile.depend b/lib/libblocklist/Makefile.depend
new file mode 100644
index 000000000000..577dc5747f1e
--- /dev/null
+++ b/lib/libblocklist/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libthr \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/lib/libbluetooth/Makefile b/lib/libbluetooth/Makefile
index a6ac291a0bf8..b935bdf3fc78 100644
--- a/lib/libbluetooth/Makefile
+++ b/lib/libbluetooth/Makefile
@@ -1,6 +1,8 @@
# $Id: Makefile,v 1.5 2003/07/22 18:38:04 max Exp $
PACKAGE= bluetooth
+LIB_PACKAGE=
+
CONFS= hosts protocols
CONFSDIR= /etc/bluetooth
CONFSMODE_protocols= 444
diff --git a/lib/libbsdstat/bsdstat.h b/lib/libbsdstat/bsdstat.h
index 1b0d1f24e93f..b293cd652a72 100644
--- a/lib/libbsdstat/bsdstat.h
+++ b/lib/libbsdstat/bsdstat.h
@@ -76,7 +76,7 @@ struct fmt {
* classes derived from it are useful.
*/
struct bsdstat {
- const char *name; /* statistics name, e.g. wlanstats */
+ const char *name; /* statistics name, e.g. wlanstat */
const struct fmt *stats; /* statistics in class */
int nstats; /* number of stats */
#define FMTS_IS_STAT 0x80 /* the following two bytes are the stat id */
diff --git a/lib/libbsm/Makefile b/lib/libbsm/Makefile
index 67802eef62ac..4413a5dd79f7 100644
--- a/lib/libbsm/Makefile
+++ b/lib/libbsm/Makefile
@@ -1,9 +1,8 @@
-#
-#
+PACKAGE= audit
+LIB_PACKAGE=
-PACKAGE= lib${LIB}
-OPENBSMDIR= ${SRCTOP}/contrib/openbsm
-_LIBBSMDIR= ${OPENBSMDIR}/libbsm
+OPENBSMDIR= ${SRCTOP}/contrib/openbsm
+_LIBBSMDIR= ${OPENBSMDIR}/libbsm
LIB= bsm
SHLIB_MAJOR= 3
diff --git a/lib/libbsnmp/libbsnmp/Makefile b/lib/libbsnmp/libbsnmp/Makefile
index 6bdb4003fdf4..2e2770b56c4a 100644
--- a/lib/libbsnmp/libbsnmp/Makefile
+++ b/lib/libbsnmp/libbsnmp/Makefile
@@ -7,7 +7,7 @@ CONTRIB= ${SRCTOP}/contrib/bsnmp/lib
.PATH: ${CONTRIB}
LIB= bsnmp
-SHLIB_MAJOR= 6
+SHLIB_MAJOR= 7
LD_FATAL_WARNINGS= no
CFLAGS+= -I${CONTRIB} -DHAVE_ERR_H -DHAVE_GETADDRINFO -DHAVE_STRLCPY
diff --git a/lib/libbz2/Makefile b/lib/libbz2/Makefile
index f7ea21b1a085..2aedbaed4328 100644
--- a/lib/libbz2/Makefile
+++ b/lib/libbz2/Makefile
@@ -1,4 +1,6 @@
-PACKAGE= lib${LIB}
+PACKAGE= bzip2
+LIB_PACKAGE=
+
BZ2DIR= ${SRCTOP}/contrib/bzip2
.PATH: ${BZ2DIR}
@@ -11,4 +13,17 @@ CFLAGS+= -I${BZ2DIR}
WARNS?= 3
+BZIP2_VERSION!= sed -n '/bzip2\/libbzip2 version /{s/.*version //;s/ of.*//p;q;}' ${BZ2DIR}/bzlib.h
+
+bzip2.pc: bzip2.pc.in
+ sed -e 's,@prefix@,/usr,g ; \
+ s,@exec_prefix@,$${prefix},g ; \
+ s,@libdir@,${LIBDIR},g ; \
+ s,@sharedlibdir@,${SHLIBDIR},g ; \
+ s,@includedir@,${INCLUDEDIR},g ; \
+ s,@VERSION@,${BZIP2_VERSION},g ;' \
+ ${.ALLSRC} > ${.TARGET}
+
+PCFILES= bzip2.pc
+
.include <bsd.lib.mk>
diff --git a/lib/libbz2/bzip2.pc.in b/lib/libbz2/bzip2.pc.in
new file mode 100644
index 000000000000..d91c9931a58a
--- /dev/null
+++ b/lib/libbz2/bzip2.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+sharedlibdir=@sharedlibdir@
+includedir=@includedir@
+
+Name: bzip2
+Description: bzip2 compression library
+Version: @VERSION@
+Libs: -L${libdir} -lbz2
+Cflags: -I${includedir}
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index d0c254e33396..8705568f6d34 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -109,7 +109,6 @@ NOASM=
.include "${LIBC_SRCTOP}/inet/Makefile.inc"
.include "${LIBC_SRCTOP}/isc/Makefile.inc"
.include "${LIBC_SRCTOP}/locale/Makefile.inc"
-.include "${LIBC_SRCTOP}/md/Makefile.inc"
.include "${LIBC_SRCTOP}/nameser/Makefile.inc"
.include "${LIBC_SRCTOP}/net/Makefile.inc"
.include "${LIBC_SRCTOP}/nls/Makefile.inc"
diff --git a/lib/libc/Versions.def b/lib/libc/Versions.def
index 184e107d225a..1c7b34bef35b 100644
--- a/lib/libc/Versions.def
+++ b/lib/libc/Versions.def
@@ -42,6 +42,10 @@ FBSD_1.7 {
FBSD_1.8 {
} FBSD_1.7;
+# This version was first added to 16.0-current.
+FBSD_1.9 {
+} FBSD_1.8;
+
# This is our private namespace. Any global interfaces that are
# strictly for use only by other FreeBSD applications and libraries
# are listed here. We use a separate namespace so we can write
@@ -49,4 +53,4 @@ FBSD_1.8 {
#
# Please do NOT increment the version of this namespace.
FBSDprivate_1.0 {
-} FBSD_1.8;
+} FBSD_1.9;
diff --git a/lib/libc/aarch64/string/timingsafe_memcmp.S b/lib/libc/aarch64/string/timingsafe_memcmp.S
index 28fdd911a387..4cc10a152aa8 100644
--- a/lib/libc/aarch64/string/timingsafe_memcmp.S
+++ b/lib/libc/aarch64/string/timingsafe_memcmp.S
@@ -114,4 +114,4 @@ ENTRY(timingsafe_memcmp)
csetm w0, lo
csinc w0, w0, wzr, ls
ret
-END(timingsafe_bcmp)
+END(timingsafe_memcmp)
diff --git a/lib/libc/amd64/string/memrchr.S b/lib/libc/amd64/string/memrchr.S
index 4f6c5a238daa..80fb306af2a3 100644
--- a/lib/libc/amd64/string/memrchr.S
+++ b/lib/libc/amd64/string/memrchr.S
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2023 Robert Clausecker
+ * Copyright (c) 2023, 2025 Robert Clausecker <fuz@FreeBSD.org>
*/
#include <machine/asm.h>
@@ -16,150 +16,142 @@ ARCHFUNCS(memrchr)
ENDARCHFUNCS(memrchr)
ARCHENTRY(memrchr, scalar)
- xor %eax, %eax # prospective return value
- sub $4, %rdx # 4 bytes left to process?
- jb 1f
+ lea -1(%rdi, %rdx, 1), %rax # point to last char in buffer
+ sub $4, %rdx # 4 bytes left to process?
+ jb .Ltail
ALIGN_TEXT
-0: xor %r8, %r8
- lea 2(%rdi), %r10
- cmp %sil, 2(%rdi)
- cmovne %r8, %r10 # point to null if no match
+0: cmp %sil, (%rax) # match at last entry?
+ je 1f
- cmp %sil, (%rdi)
- cmove %rdi, %r8 # point to first char if match
+ cmp %sil, -1(%rax) # match at second to last entry?
+ je 2f
- lea 1(%rdi), %r9
- cmp %sil, 1(%rdi)
- cmovne %r8, %r9 # point to first result if no match in second
+ cmp %sil, -2(%rax) # match at third to last entry?
+ je 3f
- lea 3(%rdi), %r11
- cmp %sil, 3(%rdi)
- cmovne %r10, %r11
+ cmp %sil, -3(%rax) # match at fourth to last entry?
+ je 4f
- test %r11, %r11
- cmovz %r9, %r11 # take first pair match if none in second
+ sub $4, %rax
+ sub $4, %rdx
+ jae 0b
- test %r11, %r11
- cmovnz %r11, %rax # take match in current set if any
+.Ltail: cmp $-3, %edx # at least one character left to process?
+ jb .Lnotfound
- add $4, %rdi
- sub $4, %rdx
- jae 0b
+ cmp %sil, (%rax)
+ je 1f
-1: cmp $-3, %edx # a least one character left to process?
- jb 2f
+ cmp $-2, %edx # at least two characters left to process?
+ jb .Lnotfound
- cmp %sil, (%rdi)
- cmove %rdi, %rax
+ cmp %sil, -1(%rax)
+ je 2f
- lea 1(%rdi), %rcx
- cmp $-2, %edx # at least two characters left to process?
- jb 2f
+ cmp $-1, %edx # at least three characters left to process?
+ jb .Lnotfound
- cmp %sil, 1(%rdi)
- cmove %rcx, %rax
+ cmp %sil, -2(%rax)
+ je 3f
- lea 2(%rdi), %rcx
- cmp $-1, %edx # at least three character left to process?
- jb 2f
-
- cmp %sil, 2(%rdi)
- cmove %rcx, %rax
+.Lnotfound:
+ xor %eax, %eax
+ ret
-2: ret
+ /* match found -- adjust rax to point to matching byte */
+4: dec %rax
+3: dec %rax
+2: dec %rax
+1: ret
ARCHEND(memrchr, scalar)
ARCHENTRY(memrchr, baseline)
- movd %esi, %xmm4
- test %rdx, %rdx # empty buffer?
- jz .L0 # if yes, return immediately
+ test %rdx, %rdx # empty input?
+ je .Lnomatchb
+
+
+ lea (%rdi, %rdx, 1), %ecx # pointer to end of buffer
+ lea -1(%rdi, %rdx, 1), %rdx # pointer to last char in buffer
+ movd %esi, %xmm2
+ and $~0x1f, %rdx # pointer to final 32 buffer bytes
+ movdqa (%rdx), %xmm0 # load last 32 bytes
+ movdqa 16(%rdx), %xmm1
+
+ punpcklbw %xmm2, %xmm2 # c -> cc
- punpcklbw %xmm4, %xmm4 # c -> cc
- mov %edi, %ecx
- punpcklwd %xmm4, %xmm4 # cc -> cccc
- and $~0xf, %rdi # align source pointer
- pshufd $0, %xmm4, %xmm4 # cccc -> cccccccccccccccc
- and $0xf, %ecx
- movdqa %xmm4, %xmm0
mov $-1, %r8d
- pcmpeqb (%rdi), %xmm0 # compare aligned head
- shl %cl, %r8d # mask of bytes in the head of the buffer
- pmovmskb %xmm0, %eax
+ neg %ecx
+ mov %r8d, %r9d
+ shr %cl, %r8d # mask with zeroes after the string
- sub $16, %rcx
- and %r8d, %eax # match mask
- add %rcx, %rdx # advance past head
- cmc
- jbe .Lrunt # did the string end in the buffer?
+ punpcklwd %xmm2, %xmm2 # cc -> cccc
- mov %rdi, %rsi # pointer to matching chunk
- add $16, %rdi
- sub $16, %rdx # enough left for another round?
- jbe 1f
+ mov %edi, %ecx
+ mov %r9d, %eax
+ shl %cl, %r9d # mask with zeroes before the string
- /* main loop unrolled twice */
- ALIGN_TEXT
-0: movdqa %xmm4, %xmm0
- pcmpeqb (%rdi), %xmm0
- pmovmskb %xmm0, %r8d
+ pshufd $0, %xmm2, %xmm2 # cccc -> cccccccccccccccc
- cmp $16, %rdx # enough left for second chunk?
- jbe 2f
+ cmp %rdx, %rdi # tail is beginning of buffer?
+ cmovae %r9d, %eax # if yes, do combined head/tail processing
+ and %r8d, %eax # mak of bytes in tail part of string
- movdqa %xmm4, %xmm0
- pcmpeqb 16(%rdi), %xmm0
+ /* process tail */
+ pcmpeqb %xmm2, %xmm1
+ pcmpeqb %xmm2, %xmm0
+ pmovmskb %xmm1, %esi
pmovmskb %xmm0, %ecx
+ shl $16, %esi
+ or %esi, %ecx # locations of matches
+ and %ecx, %eax # any match inside buffer?
+ jnz .Lprecisematchb
- lea 16(%rdi), %r9
- test %ecx, %ecx # match found in second chunk?
- cmovz %r8d, %ecx # if not, use match data from first chunk
- cmovz %rdi, %r9
-
- test %ecx, %ecx # any match found?
- cmovnz %ecx, %eax # if yes, overwrite previously found match
- cmovnz %r9, %rsi
-
- add $32, %rdi # advance to next iteration
- sub $32, %rdx # advance to next chunks
- ja 0b
-
- /* process remaining 1--16 bytes */
-1: pcmpeqb (%rdi), %xmm4
- mov $0xffff, %r8d
- xor %ecx, %ecx
- sub %edx, %ecx # number of bytes to be masked out
- pmovmskb %xmm4, %r9d
- shr %cl, %r8d # mask of bytes to be kept in the buffer
- and %r9d, %r8d
- cmovnz %r8d, %eax
- cmovnz %rdi, %rsi
- bsr %eax, %eax
- lea (%rsi, %rax, 1), %rsi # pointer to match (or junk)
- cmovnz %rsi, %rax # if any match was found, return it
- ret
+ cmp %rdx, %rdi # did the buffer begin here?
+ jae .Lnomatchb # if yes, we are done
- /* end of chunk reached within first half iteration */
-2: test %r8d, %r8d # match in previous chunk?
- cmovnz %r8d, %eax # if yes, overwrite previous chunks
- cmovnz %rdi, %rsi
- add $16, %rdi # point to tail
- sub $16, %edx
- jmp 1b # handle tail the same otherwise
-
- /* runt: string ends within head, edx has negated amount of invalid head bytes */
-.Lrunt: mov $0xffff, %r8d
- xor %ecx, %ecx
- sub %edx, %ecx
- shr %cl, %r8d
- and %r8d, %eax
- bsr %eax, %eax
- lea (%rdi, %rax, 1), %rdi
- cmovnz %rdi, %rax
+ /* main loop */
+ ALIGN_TEXT
+0: movdqa -32(%rdx), %xmm0 # load previous string chunk
+ movdqa -16(%rdx), %xmm1
+ sub $32, %rdx # beginning of string reached?
+ cmp %rdx, %rdi
+ jae .Ltailb
+
+ pcmpeqb %xmm2, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ por %xmm1, %xmm0 # match in either half?
+ pmovmskb %xmm0, %eax
+ test %eax, %eax
+ jz 0b
+
+.Lmatchb:
+ pcmpeqb (%rdx), %xmm2 # redo comparison of first 16 bytes
+ pmovmskb %xmm1, %ecx
+ pmovmskb %xmm2, %eax
+ shl $16, %ecx
+ or %ecx, %eax # location of matches
+
+.Lprecisematchb:
+ bsr %eax, %eax # find location of match
+ add %rdx, %rax # point to matching byte
ret
- /* empty buffer: return a null pointer */
-.L0: xor %eax, %eax
+.Ltailb:
+ pcmpeqb %xmm2, %xmm1
+ pcmpeqb %xmm2, %xmm0
+ pmovmskb %xmm1, %ecx
+ pmovmskb %xmm0, %eax
+ shl $16, %ecx
+ or %ecx, %eax # location of matches
+ and %r9d, %eax # mask out matches before buffer
+ bsr %eax, %edi # location of match
+ lea (%rdx, %rdi, 1), %rdx # pointer to match (if any)
+ cmovnz %rdx, %rax # point to match if present,
+ ret # else null pointer
+
+.Lnomatchb:
+ xor %eax, %eax # return null pointer
ret
ARCHEND(memrchr, baseline)
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
index 7a66f5443d94..88a3ffeab828 100644
--- a/lib/libc/db/hash/hash.c
+++ b/lib/libc/db/hash/hash.c
@@ -99,11 +99,6 @@ __hash_open(const char *file, int flags, int mode,
DB *dbp;
int bpages, hdrsize, new_table, nsegs, save_errno;
- if ((flags & O_ACCMODE) == O_WRONLY) {
- errno = EINVAL;
- return (NULL);
- }
-
if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
return (NULL);
hashp->fp = -1;
@@ -115,12 +110,17 @@ __hash_open(const char *file, int flags, int mode,
* we can check accesses.
*/
hashp->flags = flags;
+ if ((flags & O_ACCMODE) == O_WRONLY) {
+ flags &= ~O_WRONLY;
+ flags |= O_RDWR;
+ }
if (file) {
if ((hashp->fp = _open(file, flags | O_CLOEXEC, mode)) == -1)
RETURN_ERROR(errno, error0);
new_table = _fstat(hashp->fp, &statbuf) == 0 &&
- statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY;
+ statbuf.st_size == 0 &&
+ ((flags & O_ACCMODE) != O_RDONLY || (flags & O_CREAT) != 0);
} else
new_table = 1;
@@ -179,7 +179,7 @@ __hash_open(const char *file, int flags, int mode,
__buf_init(hashp, DEF_BUFSIZE);
hashp->new_file = new_table;
- hashp->save_file = file && (hashp->flags & O_RDWR);
+ hashp->save_file = file && (flags & O_RDWR);
hashp->cbucket = -1;
if (!(dbp = (DB *)malloc(sizeof(DB)))) {
save_errno = errno;
@@ -523,6 +523,10 @@ hash_get(const DB *dbp, const DBT *key, DBT *data, u_int32_t flag)
hashp->error = errno = EINVAL;
return (ERROR);
}
+ if ((hashp->flags & O_ACCMODE) == O_WRONLY) {
+ hashp->error = errno = EPERM;
+ return (ERROR);
+ }
return (hash_access(hashp, HASH_GET, (DBT *)key, data));
}
@@ -700,17 +704,19 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
u_int16_t *bp, ndx;
hashp = (HTAB *)dbp->internal;
- if (flag && flag != R_FIRST && flag != R_NEXT) {
+ if (flag != R_FIRST && flag != R_NEXT) {
hashp->error = errno = EINVAL;
return (ERROR);
}
#ifdef HASH_STATISTICS
hash_accesses++;
#endif
- if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
+ if (flag == R_FIRST) {
hashp->cbucket = 0;
hashp->cndx = 1;
hashp->cpage = NULL;
+ } else if (hashp->cbucket < 0) { /* R_NEXT */
+ return (ABNORMAL);
}
next_bucket:
for (bp = NULL; !bp || !bp[0]; ) {
diff --git a/lib/libc/db/man/dbm.3 b/lib/libc/db/man/dbm.3
index c5a83c7acef4..30787600ad2d 100644
--- a/lib/libc/db/man/dbm.3
+++ b/lib/libc/db/man/dbm.3
@@ -13,7 +13,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 2, 2022
+.Dd July 25, 2025
.Dt DBM 3
.Os
.Sh NAME
@@ -99,9 +99,6 @@ is a typical value for
.Li 0660
is a typical value for
.Fa mode .
-.Dv O_WRONLY
-is not allowed in
-.Fa flags .
The pointer returned by
.Fn dbm_open
identifies the database and is the
diff --git a/lib/libc/db/man/dbopen.3 b/lib/libc/db/man/dbopen.3
index 64cef88506d8..7fe515f17849 100644
--- a/lib/libc/db/man/dbopen.3
+++ b/lib/libc/db/man/dbopen.3
@@ -76,13 +76,10 @@ are as specified to the
.Xr open 2
routine, however, only the
.Dv O_CREAT , O_EXCL , O_EXLOCK , O_NOFOLLOW , O_NONBLOCK ,
-.Dv O_RDONLY , O_RDWR , O_SHLOCK , O_SYNC
+.Dv O_RDONLY , O_RDWR , O_SHLOCK , O_SYNC, O_WRONLY,
and
.Dv O_TRUNC
flags are meaningful.
-(Note, opening a database file
-.Dv O_WRONLY
-is not possible.)
.\"Three additional options may be specified by
.\".Em or Ns 'ing
.\"them into the
diff --git a/lib/libc/gdtoa/_hdtoa.c b/lib/libc/gdtoa/_hdtoa.c
index 8ae739acf0db..9c42630cd918 100644
--- a/lib/libc/gdtoa/_hdtoa.c
+++ b/lib/libc/gdtoa/_hdtoa.c
@@ -40,6 +40,7 @@
#define DBL_ADJ (DBL_MAX_EXP - 2)
#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1)
+#define MAX_HEX_DIGITS ((DBL_MANT_DIG + 3 - 1) / 4 + 1)
static const float one[] = { 1.0f, -1.0f };
@@ -111,7 +112,7 @@ __hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
s0 = rv_alloc(bufsize);
/* Round to the desired number of digits. */
- if (SIGFIGS > ndigits && ndigits > 0) {
+ if (MAX_HEX_DIGITS > ndigits && ndigits > 0) {
float redux = one[u.bits.sign];
int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG;
u.bits.exp = offset;
diff --git a/lib/libc/gdtoa/_hldtoa.c b/lib/libc/gdtoa/_hldtoa.c
index 965d2349d103..5f10d12c5c09 100644
--- a/lib/libc/gdtoa/_hldtoa.c
+++ b/lib/libc/gdtoa/_hldtoa.c
@@ -65,6 +65,7 @@ typedef uint32_t manl_t;
#define LDBL_ADJ (LDBL_MAX_EXP - 2)
#define SIGFIGS ((LDBL_MANT_DIG + 3) / 4 + 1)
+#define MAX_HEX_DIGITS ((LDBL_MANT_DIG + 3 - 1) / 4 + 1)
static const float one[] = { 1.0f, -1.0f };
@@ -125,7 +126,7 @@ __hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
s0 = rv_alloc(bufsize);
/* Round to the desired number of digits. */
- if (SIGFIGS > ndigits && ndigits > 0) {
+ if (MAX_HEX_DIGITS > ndigits && ndigits > 0) {
float redux = one[u.bits.sign];
int offset = 4 * ndigits + LDBL_MAX_EXP - 4 - LDBL_MANT_DIG;
#ifdef __i386__
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 26f638568efc..494b65bc5cc1 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -193,7 +193,6 @@ FBSD_1.0 {
__isinff;
__isinfl;
isatty;
- initgroups;
jrand48;
lcong48;
ldexp;
@@ -462,6 +461,7 @@ FBSD_1.8 {
fdscandir_b;
fts_open_b;
glob_b;
+ initgroups;
inotify_add_watch;
inotify_init;
inotify_init1;
diff --git a/lib/libc/gen/_rand48.c b/lib/libc/gen/_rand48.c
index 990e2c86949b..114c1595b33d 100644
--- a/lib/libc/gen/_rand48.c
+++ b/lib/libc/gen/_rand48.c
@@ -13,34 +13,6 @@
#include "rand48.h"
-unsigned short _rand48_seed[3] = {
- RAND48_SEED_0,
- RAND48_SEED_1,
- RAND48_SEED_2
-};
-unsigned short _rand48_mult[3] = {
- RAND48_MULT_0,
- RAND48_MULT_1,
- RAND48_MULT_2
-};
-unsigned short _rand48_add = RAND48_ADD;
-
-void
-_dorand48(unsigned short xseed[3])
-{
- unsigned long accu;
- unsigned short temp[2];
-
- accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] +
- (unsigned long) _rand48_add;
- temp[0] = (unsigned short) accu; /* lower 16 bits */
- accu >>= sizeof(unsigned short) * 8;
- accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] +
- (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0];
- temp[1] = (unsigned short) accu; /* middle 16 bits */
- accu >>= sizeof(unsigned short) * 8;
- accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0];
- xseed[0] = temp[0];
- xseed[1] = temp[1];
- xseed[2] = (unsigned short) accu;
-}
+uint48 _rand48_seed = RAND48_SEED;
+uint48 _rand48_mult = RAND48_MULT;
+uint48 _rand48_add = RAND48_ADD;
diff --git a/lib/libc/gen/drand48.c b/lib/libc/gen/drand48.c
index cec04a6a2425..f7f43ff20468 100644
--- a/lib/libc/gen/drand48.c
+++ b/lib/libc/gen/drand48.c
@@ -13,10 +13,10 @@
#include "rand48.h"
-extern unsigned short _rand48_seed[3];
-
double
drand48(void)
{
- return erand48(_rand48_seed);
+ ERAND48_BEGIN;
+ _DORAND48(_rand48_seed);
+ ERAND48_END(_rand48_seed);
}
diff --git a/lib/libc/gen/erand48.c b/lib/libc/gen/erand48.c
index 286904c27839..38d4774a9fe6 100644
--- a/lib/libc/gen/erand48.c
+++ b/lib/libc/gen/erand48.c
@@ -16,8 +16,9 @@
double
erand48(unsigned short xseed[3])
{
- _dorand48(xseed);
- return ldexp((double) xseed[0], -48) +
- ldexp((double) xseed[1], -32) +
- ldexp((double) xseed[2], -16);
+ uint48 tmp;
+
+ ERAND48_BEGIN;
+ DORAND48(tmp, xseed);
+ ERAND48_END(tmp);
}
diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c
index 926c50d64852..12020a79f6b4 100644
--- a/lib/libc/gen/exec.c
+++ b/lib/libc/gen/exec.c
@@ -32,8 +32,10 @@
#include "namespace.h"
#include <sys/param.h>
#include <sys/stat.h>
+#include <assert.h>
#include <errno.h>
#include <unistd.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -139,26 +141,129 @@ execvp(const char *name, char * const *argv)
return (__libc_execvpe(name, argv, environ));
}
+/*
+ * Returns 0 if we don't consider this a terminal condition, -1 if we do.
+ */
+static int
+execvPe_prog(const char *path, char * const *argv, char * const *envp)
+{
+ struct stat sb;
+ const char **memp;
+ size_t cnt;
+ int save_errno;
+
+ (void)_execve(path, argv, envp);
+ /* Grouped roughly by never terminal vs. usually terminal conditions */
+ switch (errno) {
+ case ELOOP:
+ case ENAMETOOLONG:
+ case ENOENT:
+ case ENOTDIR:
+ /* Non-terminal: property of the path we're trying */
+ break;
+ case ENOEXEC:
+ /*
+ * Failures here are considered terminal because we must handle
+ * this via the ENOEXEC fallback path; doing any further
+ * searching would be categorically incorrect.
+ */
+
+ for (cnt = 0; argv[cnt] != NULL; ++cnt)
+ ;
+
+ /*
+ * cnt may be 0 above; always allocate at least
+ * 3 entries so that we can at least fit "sh", path, and
+ * the NULL terminator. We can rely on cnt to take into
+ * account the NULL terminator in all other scenarios,
+ * as we drop argv[0].
+ */
+ memp = alloca(MAX(3, cnt + 2) * sizeof(char *));
+ assert(memp != NULL);
+ if (cnt > 0) {
+ memp[0] = argv[0];
+ memp[1] = path;
+ memcpy(&memp[2], &argv[1], cnt * sizeof(char *));
+ } else {
+ memp[0] = "sh";
+ memp[1] = path;
+ memp[2] = NULL;
+ }
+
+ (void)_execve(_PATH_BSHELL, __DECONST(char **, memp), envp);
+ return (-1);
+ case ENOMEM:
+ case E2BIG:
+ /* Terminal: persistent condition */
+ return (-1);
+ case ETXTBSY:
+ /*
+ * Terminal: we used to retry here, but sh(1) doesn't.
+ */
+ return (-1);
+ default:
+ /*
+ * EACCES may be for an inaccessible directory or
+ * a non-executable file. Call stat() to decide
+ * which. This also handles ambiguities for EFAULT
+ * and EIO, and undocumented errors like ESTALE.
+ * We hope that the race for a stat() is unimportant.
+ */
+ save_errno = errno;
+ if (stat(path, &sb) == -1) {
+ /*
+ * We force errno to ENOENT here to disambiguate the
+ * EACCESS case; the results of execve(2) are somewhat
+ * inconclusive because either the file did not exist or
+ * we just don't have search permissions, but the caller
+ * only really wants to see EACCES if the file did exist
+ * but was not accessible.
+ */
+ if (save_errno == EACCES)
+ errno = ENOENT;
+ break;
+ }
+
+ errno = save_errno;
+
+ /*
+ * Non-terminal: the file did exist and we just didn't have
+ * access to it, so we surface the EACCES and let the search
+ * continue for a candidate that we do have access to.
+ */
+ if (errno == EACCES)
+ break;
+
+ /*
+ * All other errors here are terminal, as prescribed by exec(3).
+ */
+ return (-1);
+ }
+
+ return (0);
+}
+
static int
execvPe(const char *name, const char *path, char * const *argv,
char * const *envp)
{
- const char **memp;
- size_t cnt, lp, ln;
- int eacces, save_errno;
char buf[MAXPATHLEN];
- const char *bp, *np, *op, *p;
- struct stat sb;
+ size_t ln, lp;
+ const char *np, *op, *p;
+ bool eacces;
- eacces = 0;
+ eacces = false;
/* If it's an absolute or relative path name, it's easy. */
- if (strchr(name, '/')) {
- bp = name;
- op = NULL;
- goto retry;
+ if (strchr(name, '/') != NULL) {
+ /*
+ * We ignore non-terminal conditions because we don't have any
+ * further paths to try -- we can just bubble up the errno from
+ * execve(2) here.
+ */
+ (void)execvPe_prog(name, argv, envp);
+ return (-1);
}
- bp = buf;
/* If it's an empty path name, fail in the usual POSIX way. */
if (*name == '\0') {
@@ -192,9 +297,13 @@ execvPe(const char *name, const char *path, char * const *argv,
op = np + 1;
/*
- * If the path is too long complain. This is a possible
- * security issue; given a way to make the path too long
- * the user may execute the wrong program.
+ * If the path is too long, then complain. This is a possible
+ * security issue: given a way to make the path too long, the
+ * user may execute the wrong program.
+ *
+ * Remember to exercise caution here with assembling our final
+ * buf and any output, as we may be running in a vfork() context
+ * via posix_spawnp().
*/
if (lp + ln + 2 > sizeof(buf)) {
(void)_write(STDERR_FILENO, execvPe_err_preamble,
@@ -202,82 +311,40 @@ execvPe(const char *name, const char *path, char * const *argv,
(void)_write(STDERR_FILENO, p, lp);
(void)_write(STDERR_FILENO, execvPe_err_trailer,
sizeof(execvPe_err_trailer) - 1);
+
continue;
}
- bcopy(p, buf, lp);
+
+ memcpy(&buf[0], p, lp);
buf[lp] = '/';
- bcopy(name, buf + lp + 1, ln);
+ memcpy(&buf[lp + 1], name, ln);
buf[lp + ln + 1] = '\0';
-retry: (void)_execve(bp, argv, envp);
- switch (errno) {
- case E2BIG:
- goto done;
- case ELOOP:
- case ENAMETOOLONG:
- case ENOENT:
- break;
- case ENOEXEC:
- for (cnt = 0; argv[cnt]; ++cnt)
- ;
-
- /*
- * cnt may be 0 above; always allocate at least
- * 3 entries so that we can at least fit "sh", bp, and
- * the NULL terminator. We can rely on cnt to take into
- * account the NULL terminator in all other scenarios,
- * as we drop argv[0].
- */
- memp = alloca(MAX(3, cnt + 2) * sizeof(char *));
- if (memp == NULL) {
- /* errno = ENOMEM; XXX override ENOEXEC? */
- goto done;
- }
- if (cnt > 0) {
- memp[0] = argv[0];
- memp[1] = bp;
- bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
- } else {
- memp[0] = "sh";
- memp[1] = bp;
- memp[2] = NULL;
- }
- (void)_execve(_PATH_BSHELL,
- __DECONST(char **, memp), envp);
- goto done;
- case ENOMEM:
- goto done;
- case ENOTDIR:
- break;
- case ETXTBSY:
- /*
- * We used to retry here, but sh(1) doesn't.
- */
- goto done;
- default:
- /*
- * EACCES may be for an inaccessible directory or
- * a non-executable file. Call stat() to decide
- * which. This also handles ambiguities for EFAULT
- * and EIO, and undocumented errors like ESTALE.
- * We hope that the race for a stat() is unimportant.
- */
- save_errno = errno;
- if (stat(bp, &sb) != 0)
- break;
- if (save_errno == EACCES) {
- eacces = 1;
- continue;
- }
- errno = save_errno;
- goto done;
- }
+ /*
+ * For terminal conditions we can just return immediately. If
+ * it was non-terminal, we just need to note if we had an
+ * EACCES -- execvPe_prog would do a stat(2) and leave us with
+ * an errno of EACCES only if the file did exist; otherwise it
+ * would coerce it to an ENOENT because we may not know if a
+ * file actually existed there or not.
+ */
+ if (execvPe_prog(buf, argv, envp) == -1)
+ return (-1);
+ if (errno == EACCES)
+ eacces = true;
}
+
+ /*
+ * We don't often preserve errors encountering during the PATH search,
+ * so we override it here. ENOENT would be misleading if we found a
+ * candidate but couldn't access it, but most of the other conditions
+ * are either terminal or indicate that nothing was there.
+ */
if (eacces)
errno = EACCES;
else
errno = ENOENT;
-done:
+
return (-1);
}
diff --git a/lib/libc/gen/fdopendir.c b/lib/libc/gen/fdopendir.c
index df6709fbcb85..9393cbe28f85 100644
--- a/lib/libc/gen/fdopendir.c
+++ b/lib/libc/gen/fdopendir.c
@@ -48,8 +48,16 @@
DIR *
fdopendir(int fd)
{
+ int flags, rc;
- if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
+ flags = _fcntl(fd, F_GETFD, 0);
+ if (flags == -1)
return (NULL);
+
+ if ((flags & FD_CLOEXEC) == 0) {
+ rc = _fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ if (rc == -1)
+ return (NULL);
+ }
return (__opendir_common(fd, DTF_HIDEW | DTF_NODUP, true));
}
diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c
index f87cabf085f7..62a1e0a81f62 100644
--- a/lib/libc/gen/fts-compat.c
+++ b/lib/libc/gen/fts-compat.c
@@ -44,9 +44,9 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "gen-compat.h"
#include "fts-compat.h"
#include "un-namespace.h"
+#include "gen-compat.h"
#include "gen-private.h"
diff --git a/lib/libc/gen/fts-compat11.c b/lib/libc/gen/fts-compat11.c
index 0351ce5ac690..5abb378f5f08 100644
--- a/lib/libc/gen/fts-compat11.c
+++ b/lib/libc/gen/fts-compat11.c
@@ -43,9 +43,9 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "gen-compat.h"
#include "fts-compat11.h"
#include "un-namespace.h"
+#include "gen-compat.h"
#include "gen-private.h"
diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3
index ee558b892c8c..da304e59ee72 100644
--- a/lib/libc/gen/fts.3
+++ b/lib/libc/gen/fts.3
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 30, 2025
+.Dd October 6, 2025
.Dt FTS 3
.Os
.Sh NAME
@@ -69,14 +69,15 @@ on a file hierarchy, which is then supplied to
the other
.Nm
functions.
-The function
+The
.Fn fts_read
-returns a pointer to a structure describing one of the files in the file
-hierarchy.
-The function
+function returns a pointer to a structure describing one of the files
+in the file hierarchy.
+The
.Fn fts_children
-returns a pointer to a linked list of structures, each of which describes
-one of the files contained in a directory in the hierarchy.
+function returns a pointer to a linked list of structures, each of
+which describes one of the files contained in a directory in the
+hierarchy.
In general, directories are visited two distinguishable times; in pre-order
(before any of their descendants are visited) and in post-order (after all
of their descendants have been visited).
@@ -376,7 +377,44 @@ The
.Fa fts_name
field is always
.Dv NUL Ns -terminated .
-.Sh FTS_OPEN
+.Ss Thread Safety
+The
+.Nm
+functions can safely be used in multi-threaded programs provided no
+two threads access the same
+.Vt FTS
+or
+.Vt FTSENT
+structure simultaneously.
+However, unless the
+.Dv FTS_NOCHDIR
+flag was passed to
+.Fn fts_open
+or
+.Fn fts_open_b ,
+calls to
+.Fn fts_read
+and
+.Fn fts_children
+may change the current working directory, which will affect all
+threads.
+Conversely, changing the current working directory either during or
+between calls to
+.Fn fts_read
+or
+.Fn fts_children
+(even in a single-thread program) may cause
+.Nm
+to malfunction unless the
+.Dv FTS_NOCHDIR
+flag was passed to
+.Fn fts_open
+or
+.Fn fts_open_b
+and all paths in
+.Va path_argv
+were absolute.
+.Ss Fn fts_open
The
.Fn fts_open
function takes a pointer to an array of character pointers naming one
@@ -507,10 +545,10 @@ from descending into directories that have a different device number
than the file from which the descent began.
.El
.Pp
-The argument
-.Fn compar
-specifies a user-defined function which may be used to order the traversal
-of the hierarchy.
+The
+.Fa compar
+argument points to a user-defined function which may be used to order
+the traversal of the hierarchy.
It
takes two pointers to pointers to
.Vt FTSENT
@@ -545,7 +583,7 @@ the directory traversal order is in the order listed in
.Fa path_argv
for the root paths, and in the order listed in the directory for
everything else.
-.Sh FTS_OPEN_B
+.Ss Fn fts_open_b
The
.Fn fts_open_b
function is identical to
@@ -554,7 +592,7 @@ except that it takes a block pointer instead of a function pointer.
The block is copied before
.Fn fts_open_b
returns, so the original can safely go out of scope or be released.
-.Sh FTS_READ
+.Ss Fn fts_read
The
.Fn fts_read
function returns a pointer to an
@@ -588,6 +626,15 @@ structure is returned, and
.Va errno
may or may not have been set (see
.Fa fts_info ) .
+Note that
+.Fn fts_read
+will not set
+.Va errno
+to 0 if called again with the same
+.Fa ftsp
+argument after the
+.Dv FTS_STOP
+flag has been set or the end of the stream has been reached.
.Pp
The
.Vt FTSENT
@@ -602,10 +649,10 @@ directory, in which case they will not be overwritten until after a call to
.Fn fts_read
after the
.Vt FTSENT
-structure has been returned by the function
+structure has been returned by the
.Fn fts_read
-in post-order.
-.Sh FTS_CHILDREN
+function in post-order.
+.Ss Fn fts_children
The
.Fn fts_children
function returns a pointer to an
@@ -679,11 +726,11 @@ and
.Fa fts_namelen
fields.
.El
-.Sh FTS_SET
-The function
+.Ss Fn fts_set
+The
.Fn fts_set
-allows the user application to determine further processing for the
-file
+function allows the user application to determine further processing
+for the file
.Fa f
of the stream
.Fa ftsp .
@@ -749,7 +796,40 @@ The file may be one of those most recently returned by either
or
.Fn fts_read .
.El
-.Sh FTS_CLOSE
+.Ss Fn fts_set_clientptr , Fn fts_get_clientptr
+The
+.Fn fts_set_clientptr
+function sets the client data pointer for the stream
+.Fa ftsp
+to
+.Fa clientdata .
+The
+.Fn fts_get_clientptr
+function returns the client data pointer associated with
+.Fa ftsp .
+This can be used to pass per-stream data to the comparison function.
+.Pp
+For performance reasons,
+.Fn fts_get_clientptr
+may be shadowed by a preprocessor macro.
+.Ss Fn fts_get_stream
+The
+.Fn fts_get_stream
+function returns the
+.Nm
+stream associated with the file entry
+.Fa f .
+A typical use for this would be for a comparison function to first call
+.Fn fts_get_stream
+on one of its arguments, then call
+.Fn fts_get_clientptr
+to obtain the client data pointer, which in turn points to information
+necessary to correctly order the two entries.
+.Pp
+For performance reasons,
+.Fn fts_get_stream
+may be shadowed by a preprocessor macro.
+.Ss Fn fts_close
The
.Fn fts_close
function closes a file hierarchy stream
@@ -760,6 +840,75 @@ or
.Fn fts_open_b
was called to open
.Fa ftsp .
+.Sh RETURN VALUES
+The
+.Fn fts_open
+and
+.Fn fts_open_b
+functions return a pointer to the new
+.Nm
+stream on success and
+.Dv NULL
+on failure.
+.Pp
+The
+.Fn fts_read
+function returns a pointer to the next file entry on success, or if an
+error occurs that relates specifically to that file entry.
+On reaching the end of the file hierarchy, it returns
+.Dv NULL
+and sets the external variable
+.Va errno
+to 0.
+On failure, it returns
+.Dv NULL
+and sets
+.Va errno
+to an appropriate non-zero value.
+If called again after the
+.Dv FTS_STOP
+flag has been set or the end of the stream has been reached,
+.Fn fts_read
+returns
+.Dv NULL
+and leaves
+.Va errno
+untouched.
+.Pp
+The
+.Fn fts_children
+function returns a pointer to a linked list of file entries on
+success.
+On reaching the end of the file hierarchy, it returns
+.Dv NULL
+and sets the external variable
+.Va errno
+to 0.
+On failure, it returns
+.Dv NULL
+and sets
+.Va errno
+to an appropriate non-zero value.
+.Pp
+The
+.Fn fts_set
+function returns 0 on success and \-1 if its
+.Fa instr
+argument is invalid.
+.Pp
+The
+.Fn fts_get_clientptr
+function returns the client data pointer associated with its argument,
+or
+.Dv NULL
+if none has been set.
+.Pp
+The
+.Fn fts_get_stream
+function returns a pointer to the
+.Nm
+stream associated with its argument.
+.Pp
The
.Fn fts_close
function
@@ -816,7 +965,7 @@ functions may fail and set
as follows:
.Bl -tag -width Er
.It Bq Er EINVAL
-The options were invalid, or the list were empty.
+The options were invalid, or the list was empty.
.El
.Sh SEE ALSO
.Xr find 1 ,
diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c
index cce959ba836a..4aa386d777cd 100644
--- a/lib/libc/gen/fts.c
+++ b/lib/libc/gen/fts.c
@@ -106,7 +106,6 @@ struct _fts_private {
* This assumption only holds for UFS-like filesystems that implement
* links and directories this way, so we must punt for others.
*/
-
static const char *ufslike_filesystems[] = {
"ufs",
"zfs",
@@ -679,7 +678,6 @@ fts_children(FTS *sp, int instr)
void *
(fts_get_clientptr)(FTS *sp)
{
-
return (fts_get_clientptr(sp));
}
@@ -696,7 +694,6 @@ FTS *
void
fts_set_clientptr(FTS *sp, void *clientptr)
{
-
sp->fts_clientptr = clientptr;
}
diff --git a/lib/libc/gen/gen-compat.h b/lib/libc/gen/gen-compat.h
index 08e80ede6b6e..19b9addb4321 100644
--- a/lib/libc/gen/gen-compat.h
+++ b/lib/libc/gen/gen-compat.h
@@ -40,16 +40,50 @@ struct freebsd11_statfs;
struct freebsd11_dirent *freebsd11_readdir(DIR *);
int freebsd11_readdir_r(DIR *, struct freebsd11_dirent *,
struct freebsd11_dirent **);
-int freebsd11_stat(const char *, struct freebsd11_stat *);
-int freebsd11_lstat(const char *, struct freebsd11_stat *);
-int freebsd11_fstat(int, struct freebsd11_stat *);
-int freebsd11_fstatat(int, const char *, struct freebsd11_stat *, int);
-int freebsd11_statfs(const char *, struct freebsd11_statfs *);
-int freebsd11_getfsstat(struct freebsd11_statfs *, long, int);
int freebsd11_getmntinfo(struct freebsd11_statfs **, int);
char *freebsd11_devname(__uint32_t dev, __mode_t type);
-char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf, int len);
+char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf,
+ int len);
+
+/*
+ * We want freebsd11_fstat in C source to result in resolution to
+ * - fstat@FBSD_1.0 for libc.so (but we do not need the _definition_
+ * of this fstat, it is provided by libsys.so which we want to use).
+ * - freebsd11_fstat for libc.a (since if we make it fstat@FBSD_1.0
+ * for libc.a, then final linkage into static object ignores version
+ * and would reference fstat, which is the current syscall, not the
+ * compat syscall). libc.a provides the freebsd11_fstat implementation.
+ * Note that freebsd11_fstat from libc.a is not used for anything, but
+ * we make it correct nonetheless, just in case it would.
+ * This is arranged by COMPAT_SYSCALL, and libc can just use freebsd11_fstat.
+ */
+#ifdef PIC
+#define COMPAT_SYSCALL(rtype, fun, args, sym, ver) \
+ rtype fun args; __sym_compat(sym, fun, ver);
+#else
+#define COMPAT_SYSCALL(rtype, fun, args, sym, ver) \
+ rtype fun args;
+#endif
+
+COMPAT_SYSCALL(int, freebsd11_stat, (const char *, struct freebsd11_stat *),
+ stat, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_lstat, (const char *, struct freebsd11_stat *),
+ lstat, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_fstat, (int, struct freebsd11_stat *),
+ fstat, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_fstatat, (int, const char *,
+ struct freebsd11_stat *, int), fstatat, FBSD_1.1);
+
+COMPAT_SYSCALL(int, freebsd11_statfs, (const char *,
+ struct freebsd11_statfs *), statfs, FBSD_1.0);
+COMPAT_SYSCALL(int, freebsd11_getfsstat, (struct freebsd11_statfs *, long,
+ int), getfsstat, FBSD_1.0);
+
+COMPAT_SYSCALL(int, freebsd14_setgroups, (int gidsize, const __gid_t *gidset),
+ setgroups, FBSD_1.0);
+
+#undef COMPAT_SYSCALL
#endif /* _GEN_COMPAT_H_ */
diff --git a/lib/libc/gen/getgrouplist.3 b/lib/libc/gen/getgrouplist.3
index e9a980f99751..9e05ff7e7a29 100644
--- a/lib/libc/gen/getgrouplist.3
+++ b/lib/libc/gen/getgrouplist.3
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 26, 2014
+.Dd October 9, 2025
.Dt GETGROUPLIST 3
.Os
.Sh NAME
.Nm getgrouplist
-.Nd calculate group access list
+.Nd produce a user's effective group list
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -40,36 +48,44 @@
.Sh DESCRIPTION
The
.Fn getgrouplist
-function reads through the group file and calculates
-the group access list for the user specified in
-.Fa name .
-The
+function retrieves from the group database the supplementary groups for the user
+specified in
+.Fa name
+and returns the effective group list, whose first group is the value of
+.Fa basegid
+and the others are the supplementary groups.
.Fa basegid
-is automatically included in the groups list.
-Typically this value is given as
-the group number from the password file.
+typically is the user's initial numerical group ID from the password database.
.Pp
-The resulting group list is returned in the array pointed to by
+The effective group list is returned in the array pointed to by
.Fa groups .
-The caller specifies the size of the
+The caller specifies the length of the
.Fa groups
array in the integer pointed to by
-.Fa ngroups ;
-the actual number of groups found is returned in
+.Fa ngroups .
+The number of groups of the effective group list, which may be greater than the
+.Fa groups
+array's length, is returned through
.Fa ngroups .
.Sh RETURN VALUES
The
.Fn getgrouplist
-function
-returns 0 on success and \-1 if the size of the group list is too small to
-hold all the user's groups.
-Here, the group array will be filled with as many groups as will fit.
+function returns 0 on success and \-1 if the length of the group list is too
+small to hold all the user's groups.
+In the latter case, the
+.Fa groups
+array is filled with as many groups as possible from the start of the effective
+group list, and the length pointed to by
+.Fa ngroups
+is set to the full length of the latter, thus to a value strictly greater than
+before the call.
.Sh FILES
.Bl -tag -width /etc/group -compact
.It Pa /etc/group
group membership list
.El
.Sh SEE ALSO
+.Xr setcred 2 ,
.Xr setgroups 2 ,
.Xr initgroups 3
.Sh HISTORY
diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c
index 5bd06bc5121f..9c57b7031336 100644
--- a/lib/libc/gen/getgrouplist.c
+++ b/lib/libc/gen/getgrouplist.c
@@ -29,13 +29,8 @@
* SUCH DAMAGE.
*/
-/*
- * get credential
- */
#include <sys/types.h>
-#include <grp.h>
-#include <string.h>
#include <unistd.h>
#include <ssp/ssp.h>
@@ -46,4 +41,3 @@ __ssp_real(getgrouplist)(const char *uname, gid_t agroup, gid_t *groups, int *gr
{
return __getgroupmembership(uname, agroup, groups, *grpcnt, grpcnt);
}
-
diff --git a/lib/libc/gen/initgroups.3 b/lib/libc/gen/initgroups.3
index 03bd07494fc9..74133e7d7048 100644
--- a/lib/libc/gen/initgroups.3
+++ b/lib/libc/gen/initgroups.3
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 26, 2014
+.Dd October 9, 2025
.Dt INITGROUPS 3
.Os
.Sh NAME
.Nm initgroups
-.Nd initialize group access list
+.Nd initialize supplementary groups as per the group database
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -40,19 +48,18 @@
.Sh DESCRIPTION
The
.Fn initgroups
-function
-uses the
-.Xr getgrouplist 3
-function to calculate the group access list for the user
-specified in
+function initializes the current process' supplementary groups as prescribed by
+its arguments and the system's group database.
+.Pp
+It first uses the
+.Fn getgrouplist
+function to compute a list of groups containing the passed
+.Fa basegid ,
+which typically is the user's initial numerical group ID from the password
+database, and the supplementary groups in the group database for the user named
.Fa name .
-This group list is then setup for the current process using
-.Xr setgroups 2 .
-The
-.Fa basegid
-is automatically included in the groups list.
-Typically this value is given as
-the group number from the password file.
+It then installs this list as the current process' supplementary groups using
+.Fn setgroups .
.Sh RETURN VALUES
.Rv -std initgroups
.Sh ERRORS
@@ -60,9 +67,9 @@ The
.Fn initgroups
function may fail and set
.Va errno
-for any of the errors specified for the library function
-.Xr setgroups 2 .
-It may also return:
+to any of the errors specified for the
+.Xr setgroups 2
+system call, or to:
.Bl -tag -width Er
.It Bq Er ENOMEM
The
@@ -77,3 +84,67 @@ The
.Fn initgroups
function appeared in
.Bx 4.2 .
+.Pp
+The
+.Fn initgroups
+function changed semantics in
+.Fx 15 ,
+following that of
+.Xr setgroups 2
+in the same release.
+Before that, it would also set the effective group ID to
+.Fa basegid ,
+and would not include the latter in the supplementary groups except before
+.Fx 8 .
+Its current behavior in these respects is known to be compatible with that of
+the following systems up to the specified versions that are current at time of
+this writing:
+.Bl -dash -width "-" -compact
+.It
+Linux (up to 6.6) with the GNU libc (up to 2.42)
+.It
+.Nx 1.1 and greater (up to 10)
+.It
+.Ox (up to 7.7)
+.It
+Systems based on illumos (up to August 2025 sources)
+.El
+.Sh SECURITY CONSIDERATIONS
+As
+.Fa basegid
+is typically the user's initial numerical group ID, to which the current
+process' effective group ID is generally initialized, processes using functions
+to change their effective group ID
+.Pq via Xr setgid 2 or similar
+or that are spawned from executables with the set-group-ID mode bit set will not
+be able to relinquish the access rights deriving from being a member of
+.Fa basegid ,
+as these functions do not change the supplementary groups.
+.Pp
+This behavior is generally desirable in order to paper over the difference of
+treatment between the effective group and supplementary ones in this situation,
+as they are all in the end indiscriminately used in traditional UNIX
+discretionary access checks.
+It blends well with the practice of allocating each user its own private group,
+as processes launched from a set-group-ID executable keep the same user and
+consistently stay also in the same user's group.
+Finally, it was also chosen for compatibility with other systems
+.Po
+see the
+.Sx HISTORY
+section
+.Pc .
+.Pp
+This convention of including
+.Fa basegid
+in the supplementary groups is however only enforced by the
+.Fn initgroups
+function, and not by the
+.Xr setgroups 2
+system call, so applications expressly wanting to include in the supplementary
+groups only those specified by the group database can themselves call
+.Fn getgrouplist
+and then
+.Fn setgroups
+on the result with the first element skipped
+.Pq see Xr getgrouplist 3 .
diff --git a/lib/libc/gen/initgroups.c b/lib/libc/gen/initgroups.c
index b6697dd7ed8f..a1a7d92250e2 100644
--- a/lib/libc/gen/initgroups.c
+++ b/lib/libc/gen/initgroups.c
@@ -3,6 +3,11 @@
*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Olivier Certner
+ * <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+ * Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,34 +34,52 @@
* SUCH DAMAGE.
*/
-#include <sys/param.h>
+/* For __sym_compat(). */
+#include <sys/cdefs.h>
-#include "namespace.h"
-#include <err.h>
-#include "un-namespace.h"
#include <errno.h>
-#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-int
-initgroups(const char *uname, gid_t agroup)
+/* For freebsd14_setgroups(). */
+#include "gen-compat.h"
+
+static int
+initgroups_impl(const char *uname, gid_t agroup,
+ int (*setgroups)(int, const gid_t *))
{
- int ngroups, ret;
- long ngroups_max;
gid_t *groups;
+ long ngroups_max;
+ int ngroups, ret;
/*
- * Provide space for one group more than possible to allow
- * setgroups to fail and set errno.
+ * Provide space for one group more than possible to allow setgroups()
+ * to fail and set 'errno' in case we get back more than {NGROUPS_MAX} +
+ * 1 groups.
*/
ngroups_max = sysconf(_SC_NGROUPS_MAX) + 2;
- if ((groups = malloc(sizeof(*groups) * ngroups_max)) == NULL)
- return (ENOMEM);
+ groups = malloc(sizeof(*groups) * ngroups_max);
+ if (groups == NULL)
+ return (-1); /* malloc() set 'errno'. */
ngroups = (int)ngroups_max;
- getgrouplist(uname, agroup, groups, &ngroups);
- ret = setgroups(ngroups, groups);
+ (void)getgrouplist(uname, agroup, groups, &ngroups);
+ ret = (*setgroups)(ngroups, groups);
+
free(groups);
- return (ret);
+ return (ret); /* setgroups() set 'errno'. */
}
+
+int
+initgroups(const char *uname, gid_t agroup)
+{
+ return (initgroups_impl(uname, agroup, setgroups));
+}
+
+int
+freebsd14_initgroups(const char *uname, gid_t agroup)
+{
+ return (initgroups_impl(uname, agroup, freebsd14_setgroups));
+}
+
+__sym_compat(initgroups, freebsd14_initgroups, FBSD_1.0);
diff --git a/lib/libc/gen/jrand48.c b/lib/libc/gen/jrand48.c
index 0a9f780a9e5c..93442439d49e 100644
--- a/lib/libc/gen/jrand48.c
+++ b/lib/libc/gen/jrand48.c
@@ -11,14 +11,13 @@
* to anyone/anything when using this software.
*/
-#include <stdint.h>
-
#include "rand48.h"
long
jrand48(unsigned short xseed[3])
{
+ uint48 tmp;
- _dorand48(xseed);
- return ((int32_t)(((uint32_t)xseed[2] << 16) | (uint32_t)xseed[1]));
+ DORAND48(tmp, xseed);
+ return ((int)((tmp >> 16) & 0xffffffff));
}
diff --git a/lib/libc/gen/lcong48.c b/lib/libc/gen/lcong48.c
index f13826b3d3f3..871b2110ed94 100644
--- a/lib/libc/gen/lcong48.c
+++ b/lib/libc/gen/lcong48.c
@@ -13,18 +13,10 @@
#include "rand48.h"
-extern unsigned short _rand48_seed[3];
-extern unsigned short _rand48_mult[3];
-extern unsigned short _rand48_add;
-
void
lcong48(unsigned short p[7])
{
- _rand48_seed[0] = p[0];
- _rand48_seed[1] = p[1];
- _rand48_seed[2] = p[2];
- _rand48_mult[0] = p[3];
- _rand48_mult[1] = p[4];
- _rand48_mult[2] = p[5];
+ LOADRAND48(_rand48_seed, &p[0]);
+ LOADRAND48(_rand48_mult, &p[3]);
_rand48_add = p[6];
}
diff --git a/lib/libc/gen/lrand48.c b/lib/libc/gen/lrand48.c
index a3d0111cf4d5..cc07044b8af9 100644
--- a/lib/libc/gen/lrand48.c
+++ b/lib/libc/gen/lrand48.c
@@ -13,11 +13,9 @@
#include "rand48.h"
-extern unsigned short _rand48_seed[3];
-
long
lrand48(void)
{
- _dorand48(_rand48_seed);
- return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1);
+ _DORAND48(_rand48_seed);
+ return (_rand48_seed >> 17) & 0x7fffffff;
}
diff --git a/lib/libc/gen/mrand48.c b/lib/libc/gen/mrand48.c
index 15b0bfb1bd6e..f9128a6d4188 100644
--- a/lib/libc/gen/mrand48.c
+++ b/lib/libc/gen/mrand48.c
@@ -15,13 +15,9 @@
#include "rand48.h"
-extern unsigned short _rand48_seed[3];
-
long
mrand48(void)
{
-
- _dorand48(_rand48_seed);
- return ((int32_t)(((uint32_t)_rand48_seed[2] << 16) |
- (uint32_t)_rand48_seed[1]));
+ _DORAND48(_rand48_seed);
+ return ((int)((_rand48_seed >> 16) & 0xffffffff));
}
diff --git a/lib/libc/gen/nrand48.c b/lib/libc/gen/nrand48.c
index 6c54065e7e0f..f6f4e231105c 100644
--- a/lib/libc/gen/nrand48.c
+++ b/lib/libc/gen/nrand48.c
@@ -16,6 +16,8 @@
long
nrand48(unsigned short xseed[3])
{
- _dorand48(xseed);
- return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
+ uint48 tmp;
+
+ DORAND48(tmp, xseed);
+ return ((tmp >> 17) & 0x7fffffff);
}
diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3
index 098b7b02a9b9..bf6a99b4b113 100644
--- a/lib/libc/gen/psignal.3
+++ b/lib/libc/gen/psignal.3
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 10, 2025
+.Dd September 23, 2025
.Dt PSIGNAL 3
.Os
.Sh NAME
@@ -141,6 +141,13 @@ The name in
can be either the name of the signal, with or without the
.Dq SIG
prefix, or a decimal number.
+.Sh RETURN VALUES
+The
+.Fn sig2str
+and
+.Fn str2sig
+return 0 on success and -1 on translation failure.
+In the latter case the memory to store the translation result is left intact.
.Sh SEE ALSO
.Xr sigaction 2 ,
.Xr perror 3 ,
diff --git a/lib/libc/gen/rand48.3 b/lib/libc/gen/rand48.3
index 1e47c843058e..3ea649354270 100644
--- a/lib/libc/gen/rand48.3
+++ b/lib/libc/gen/rand48.3
@@ -9,7 +9,7 @@
.\" of any kind. I shall in no event be liable for anything that happens
.\" to anyone/anything when using this software.
.\"
-.Dd September 4, 2012
+.Dd September 11, 2025
.Dt RAND48 3
.Os
.Sh NAME
@@ -183,5 +183,8 @@ generator calls.
.Xr arc4random 3 ,
.Xr rand 3 ,
.Xr random 3
+.Sh STANDARDS
+The functions described in this page are expected to conform to
+.St -p1003.1-2008 .
.Sh AUTHORS
.An Martin Birgmeier
diff --git a/lib/libc/gen/rand48.h b/lib/libc/gen/rand48.h
index 9861e99683cb..d3326e851491 100644
--- a/lib/libc/gen/rand48.h
+++ b/lib/libc/gen/rand48.h
@@ -14,10 +14,11 @@
#ifndef _RAND48_H_
#define _RAND48_H_
+#include <sys/types.h>
#include <math.h>
#include <stdlib.h>
-void _dorand48(unsigned short[3]);
+#include "fpmath.h"
#define RAND48_SEED_0 (0x330e)
#define RAND48_SEED_1 (0xabcd)
@@ -27,4 +28,62 @@ void _dorand48(unsigned short[3]);
#define RAND48_MULT_2 (0x0005)
#define RAND48_ADD (0x000b)
+typedef uint64_t uint48;
+
+extern uint48 _rand48_seed;
+extern uint48 _rand48_mult;
+extern uint48 _rand48_add;
+
+#define TOUINT48(x, y, z) \
+ ((uint48)(x) + (((uint48)(y)) << 16) + (((uint48)(z)) << 32))
+
+#define RAND48_SEED TOUINT48(RAND48_SEED_0, RAND48_SEED_1, RAND48_SEED_2)
+#define RAND48_MULT TOUINT48(RAND48_MULT_0, RAND48_MULT_1, RAND48_MULT_2)
+
+#define LOADRAND48(l, x) do { \
+ (l) = TOUINT48((x)[0], (x)[1], (x)[2]); \
+} while (0)
+
+#define STORERAND48(l, x) do { \
+ (x)[0] = (unsigned short)(l); \
+ (x)[1] = (unsigned short)((l) >> 16); \
+ (x)[2] = (unsigned short)((l) >> 32); \
+} while (0)
+
+#define _DORAND48(l) do { \
+ (l) = (l) * _rand48_mult + _rand48_add; \
+} while (0)
+
+#define DORAND48(l, x) do { \
+ LOADRAND48(l, x); \
+ _DORAND48(l); \
+ STORERAND48(l, x); \
+} while (0)
+
+#define ERAND48_BEGIN \
+ union { \
+ union IEEEd2bits ieee; \
+ uint64_t u64; \
+ } u; \
+ int s
+
+/*
+ * Optimization for speed: assume doubles are IEEE 754 and use bit fiddling
+ * rather than converting to double. Specifically, clamp the result to 48 bits
+ * and convert to a double in [0.0, 1.0) via division by 2^48. Normalize by
+ * shifting the most significant bit into the implicit one position and
+ * adjusting the exponent accordingly. The store to the exponent field
+ * overwrites the implicit one.
+ */
+#define ERAND48_END(x) do { \
+ u.u64 = ((x) & 0xffffffffffffULL); \
+ if (u.u64 == 0) \
+ return (0.0); \
+ u.u64 <<= 5; \
+ for (s = 0; !(u.u64 & (1LL << 52)); s++, u.u64 <<= 1) \
+ ; \
+ u.ieee.bits.exp = 1022 - s; \
+ return (u.ieee.d); \
+} while (0)
+
#endif /* _RAND48_H_ */
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c
index b70102954df1..94d2b2e8d877 100644
--- a/lib/libc/gen/readdir.c
+++ b/lib/libc/gen/readdir.c
@@ -134,3 +134,5 @@ __readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
}
__strong_reference(__readdir_r, readdir_r);
+__warn_references(readdir_r,
+ "warning: this program uses readdir_r(), which is unsafe.");
diff --git a/lib/libc/gen/seed48.c b/lib/libc/gen/seed48.c
index 258c4bac3c9f..f57656ce1121 100644
--- a/lib/libc/gen/seed48.c
+++ b/lib/libc/gen/seed48.c
@@ -13,24 +13,14 @@
#include "rand48.h"
-extern unsigned short _rand48_seed[3];
-extern unsigned short _rand48_mult[3];
-extern unsigned short _rand48_add;
-
unsigned short *
seed48(unsigned short xseed[3])
{
static unsigned short sseed[3];
- sseed[0] = _rand48_seed[0];
- sseed[1] = _rand48_seed[1];
- sseed[2] = _rand48_seed[2];
- _rand48_seed[0] = xseed[0];
- _rand48_seed[1] = xseed[1];
- _rand48_seed[2] = xseed[2];
- _rand48_mult[0] = RAND48_MULT_0;
- _rand48_mult[1] = RAND48_MULT_1;
- _rand48_mult[2] = RAND48_MULT_2;
+ STORERAND48(_rand48_seed, sseed);
+ LOADRAND48(_rand48_seed, xseed);
+ _rand48_mult = RAND48_MULT;
_rand48_add = RAND48_ADD;
- return sseed;
+ return (sseed);
}
diff --git a/lib/libc/gen/srand48.c b/lib/libc/gen/srand48.c
index fd369a094c51..4b82ece72db8 100644
--- a/lib/libc/gen/srand48.c
+++ b/lib/libc/gen/srand48.c
@@ -13,18 +13,11 @@
#include "rand48.h"
-extern unsigned short _rand48_seed[3];
-extern unsigned short _rand48_mult[3];
-extern unsigned short _rand48_add;
-
void
srand48(long seed)
{
- _rand48_seed[0] = RAND48_SEED_0;
- _rand48_seed[1] = (unsigned short) seed;
- _rand48_seed[2] = (unsigned short) (seed >> 16);
- _rand48_mult[0] = RAND48_MULT_0;
- _rand48_mult[1] = RAND48_MULT_1;
- _rand48_mult[2] = RAND48_MULT_2;
+ _rand48_seed = TOUINT48(RAND48_SEED_0, (unsigned short)seed,
+ (unsigned short)(seed >> 16));
+ _rand48_mult = RAND48_MULT;
_rand48_add = RAND48_ADD;
}
diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c
index 66562d0e29f0..b5b732eed05d 100644
--- a/lib/libc/gen/sysconf.c
+++ b/lib/libc/gen/sysconf.c
@@ -51,7 +51,7 @@
#include "un-namespace.h"
#include "../stdlib/atexit.h"
-#include "tzdir.h" /* from ../../../contrib/tzcode/stdtime */
+#include "tzdir.h" /* from ../../../contrib/tzcode */
#include "libc_private.h"
#define _PATH_ZONEINFO TZDIR /* from tzfile.h */
diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3
index 95e33dc802be..ef897c653728 100644
--- a/lib/libc/gen/sysctl.3
+++ b/lib/libc/gen/sysctl.3
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 16, 2023
+.Dd July 31, 2025
.Dt SYSCTL 3
.Os
.Sh NAME
@@ -527,8 +527,12 @@ The path of the process' text file is returned.
The in-kernel call stacks for the threads of the specified process.
.It Dv KERN_PROC_VMMAP
The description of the map entries for the process.
+Also refer to
+.Xr kinfo_getvmmap 3 .
.It Dv KERN_PROC_FILEDESC
The file descriptors for files opened in the specified process.
+Also refer to
+.Xr kinfo_getfile 3 .
.It Dv KERN_PROC_GROUPS
Groups associated with the process.
.It Dv KERN_PROC_ENV
@@ -949,6 +953,7 @@ A process without appropriate privilege attempts to set a value.
.El
.Sh SEE ALSO
.Xr confstr 3 ,
+.Xr kinfo_getproc 3 ,
.Xr kvm 3 ,
.Xr sysconf 3 ,
.Xr sysctl 8
diff --git a/lib/libc/i386/gen/makecontext.c b/lib/libc/i386/gen/makecontext.c
index 7b4845ac6bee..9fedd8b99c47 100644
--- a/lib/libc/i386/gen/makecontext.c
+++ b/lib/libc/i386/gen/makecontext.c
@@ -124,7 +124,7 @@ __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
/*
* Setup the top of the stack with the user start routine
- * followed by all of its aguments and the pointer to the
+ * followed by all of its arguments and the pointer to the
* ucontext. We need to leave a spare spot at the top of
* the stack because setcontext will move eip to the top
* of the stack before returning.
diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h
index 70fb8dcd97f3..630ffe7daae3 100644
--- a/lib/libc/include/compat.h
+++ b/lib/libc/include/compat.h
@@ -69,6 +69,9 @@ __sym_compat(kevent, freebsd11_kevent, FBSD_1.0);
__sym_compat(swapoff, freebsd13_swapoff, FBSD_1.0);
+__sym_compat(getgroups, freebsd14_getgroups, FBSD_1.0);
+__sym_compat(setgroups, freebsd14_setgroups, FBSD_1.0);
+
#undef __sym_compat
#define __weak_reference(sym,alias) \
@@ -77,4 +80,3 @@ __sym_compat(swapoff, freebsd13_swapoff, FBSD_1.0);
#undef __weak_reference
#endif /* __LIBC_COMPAT_H__ */
-
diff --git a/lib/libc/include/port_before.h b/lib/libc/include/port_before.h
index cfc43c53f157..aa2cd394104a 100644
--- a/lib/libc/include/port_before.h
+++ b/lib/libc/include/port_before.h
@@ -5,7 +5,6 @@
#define _LIBC 1
#define DO_PTHREADS 1
#define USE_POLL 1
-#define HAVE_MD5 1
#define ISC_SOCKLEN_T socklen_t
#define ISC_FORMAT_PRINTF(fmt, args) \
diff --git a/lib/libc/inet/inet_net_ntop.c b/lib/libc/inet/inet_net_ntop.c
index 9d98dbb5ca99..30dd5c0571f2 100644
--- a/lib/libc/inet/inet_net_ntop.c
+++ b/lib/libc/inet/inet_net_ntop.c
@@ -1,20 +1,23 @@
-/*-
- * SPDX-License-Identifier: ISC
+/* $OpenBSD: inet_net_ntop.c,v 1.9 2019/07/03 03:24:04 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2012 by Gilles Chehade <gilles@openbsd.org>
+ * Copyright (c) 1996 by Internet Software Consortium.
*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1996,1999 by Internet Software Consortium.
+ * SPDX-License-Identifier: ISC
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#include "port_before.h"
@@ -31,18 +34,10 @@
#include "port_after.h"
-#ifdef SPRINTF_CHAR
-# define SPRINTF(x) strlen(sprintf/**/x)
-#else
-# define SPRINTF(x) ((size_t)sprintf x)
-#endif
-
-static char * inet_net_ntop_ipv4(const u_char *src, int bits, char *dst,
- size_t size);
-static char * inet_net_ntop_ipv6(const u_char *src, int bits, char *dst,
- size_t size);
+static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t);
+static char *inet_net_ntop_ipv6(const u_char *, int, char *, size_t);
-/*%
+/*
* char *
* inet_net_ntop(af, src, bits, dst, size)
* convert network number from network to presentation format.
@@ -66,7 +61,7 @@ inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
}
}
-/*%
+/*
* static char *
* inet_net_ntop_ipv4(src, bits, dst, size)
* convert IPv4 network number from network to presentation format.
@@ -83,53 +78,63 @@ static char *
inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
{
char *odst = dst;
- char *t;
u_int m;
int b;
+ char *ep;
+ int advance;
+
+ ep = dst + size;
+ if (ep <= dst)
+ goto emsgsize;
if (bits < 0 || bits > 32) {
errno = EINVAL;
return (NULL);
}
-
if (bits == 0) {
- if (size < sizeof "0")
+ if (ep - dst < sizeof "0")
goto emsgsize;
*dst++ = '0';
- size--;
*dst = '\0';
}
/* Format whole octets. */
for (b = bits / 8; b > 0; b--) {
- if (size <= sizeof "255.")
+ if (ep - dst < sizeof "255.")
+ goto emsgsize;
+ advance = snprintf(dst, ep - dst, "%u", *src++);
+ if (advance <= 0 || advance >= ep - dst)
goto emsgsize;
- t = dst;
- dst += SPRINTF((dst, "%u", *src++));
+ dst += advance;
if (b > 1) {
+ if (dst + 1 >= ep)
+ goto emsgsize;
*dst++ = '.';
*dst = '\0';
}
- size -= (size_t)(dst - t);
}
/* Format partial octet. */
b = bits % 8;
if (b > 0) {
- if (size <= sizeof ".255")
+ if (ep - dst < sizeof ".255")
goto emsgsize;
- t = dst;
if (dst != odst)
*dst++ = '.';
m = ((1 << b) - 1) << (8 - b);
- dst += SPRINTF((dst, "%u", *src & m));
- size -= (size_t)(dst - t);
+ advance = snprintf(dst, ep - dst, "%u", *src & m);
+ if (advance <= 0 || advance >= ep - dst)
+ goto emsgsize;
+ dst += advance;
}
/* Format CIDR /width. */
- if (size <= sizeof "/32")
+ if (ep - dst < sizeof "/32")
+ goto emsgsize;
+ advance = snprintf(dst, ep - dst, "/%u", bits);
+ if (advance <= 0 || advance >= ep - dst)
goto emsgsize;
- dst += SPRINTF((dst, "/%u", bits));
+ dst += advance;
return (odst);
emsgsize:
@@ -137,132 +142,27 @@ inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
return (NULL);
}
-/*%
- * static char *
- * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
- * convert IPv6 network number from network to presentation format.
- * generates CIDR style result always. Picks the shortest representation
- * unless the IP is really IPv4.
- * always prints specified number of bits (bits).
- * return:
- * pointer to dst, or NULL if an error occurred (check errno).
- * note:
- * network byte order assumed. this means 192.5.5.240/28 has
- * 0b11110000 in its fourth octet.
- * author:
- * Vadim Kogan (UCB), June 2001
- * Original version (IPv4) by Paul Vixie (ISC), July 1996
- */
-
static char *
-inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
- u_int m;
- int b;
- int p;
- int zero_s, zero_l, tmp_zero_s, tmp_zero_l;
- int i;
- int is_ipv4 = 0;
- unsigned char inbuf[16];
- char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
- char *cp;
- int words;
- u_char *s;
+inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
+{
+ int ret;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128")];
if (bits < 0 || bits > 128) {
errno = EINVAL;
return (NULL);
}
- cp = outbuf;
-
- if (bits == 0) {
- *cp++ = ':';
- *cp++ = ':';
- *cp = '\0';
- } else {
- /* Copy src to private buffer. Zero host part. */
- p = (bits + 7) / 8;
- memcpy(inbuf, src, p);
- memset(inbuf + p, 0, 16 - p);
- b = bits % 8;
- if (b != 0) {
- m = ~0 << (8 - b);
- inbuf[p-1] &= m;
- }
-
- s = inbuf;
-
- /* how many words need to be displayed in output */
- words = (bits + 15) / 16;
- if (words == 1)
- words = 2;
-
- /* Find the longest substring of zero's */
- zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
- for (i = 0; i < (words * 2); i += 2) {
- if ((s[i] | s[i+1]) == 0) {
- if (tmp_zero_l == 0)
- tmp_zero_s = i / 2;
- tmp_zero_l++;
- } else {
- if (tmp_zero_l && zero_l < tmp_zero_l) {
- zero_s = tmp_zero_s;
- zero_l = tmp_zero_l;
- tmp_zero_l = 0;
- }
- }
- }
-
- if (tmp_zero_l && zero_l < tmp_zero_l) {
- zero_s = tmp_zero_s;
- zero_l = tmp_zero_l;
- }
-
- if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
- ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
- ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
- is_ipv4 = 1;
-
- /* Format whole words. */
- for (p = 0; p < words; p++) {
- if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) {
- /* Time to skip some zeros */
- if (p == zero_s)
- *cp++ = ':';
- if (p == words - 1)
- *cp++ = ':';
- s++;
- s++;
- continue;
- }
+ if (inet_ntop(AF_INET6, src, buf, size) == NULL)
+ return (NULL);
- if (is_ipv4 && p > 5 ) {
- *cp++ = (p == 6) ? ':' : '.';
- cp += SPRINTF((cp, "%u", *s++));
- /* we can potentially drop the last octet */
- if (p != 7 || bits > 120) {
- *cp++ = '.';
- cp += SPRINTF((cp, "%u", *s++));
- }
- } else {
- if (cp != outbuf)
- *cp++ = ':';
- cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
- s += 2;
- }
- }
+ ret = snprintf(dst, size, "%s/%d", buf, bits);
+ if (ret < 0 || ret >= size) {
+ errno = EMSGSIZE;
+ return (NULL);
}
- /* Format CIDR /width. */
- sprintf(cp, "/%u", bits);
- if (strlen(outbuf) + 1 > size)
- goto emsgsize;
- strcpy(dst, outbuf);
return (dst);
-
-emsgsize:
- errno = EMSGSIZE;
- return (NULL);
}
/*
@@ -271,5 +171,3 @@ emsgsize:
*/
#undef inet_net_ntop
__weak_reference(__inet_net_ntop, inet_net_ntop);
-
-/*! \file */
diff --git a/lib/libc/inet/inet_net_pton.c b/lib/libc/inet/inet_net_pton.c
index d566a0e1d3c3..14c88eb72014 100644
--- a/lib/libc/inet/inet_net_pton.c
+++ b/lib/libc/inet/inet_net_pton.c
@@ -1,20 +1,23 @@
-/*-
- * SPDX-License-Identifier: ISC
+/* $OpenBSD: inet_net_pton.c,v 1.14 2022/12/27 17:10:06 jmc Exp $ */
+
+/*
+ * Copyright (c) 2012 by Gilles Chehade <gilles@openbsd.org>
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
*
- * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (C) 1996, 1998, 1999, 2001, 2003 Internet Software Consortium.
+ * SPDX-License-Identifier: ISC
*
- * Permission to use, copy, modify, and/or distribute this software for any
+ * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#include "port_before.h"
@@ -22,7 +25,6 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <assert.h>
@@ -34,13 +36,37 @@
#include "port_after.h"
-#ifdef SPRINTF_CHAR
-# define SPRINTF(x) strlen(sprintf/**/x)
-#else
-# define SPRINTF(x) ((size_t)sprintf x)
-#endif
+static int inet_net_pton_ipv4(const char *, u_char *, size_t);
+static int inet_net_pton_ipv6(const char *, u_char *, size_t);
-/*%
+/*
+ * static int
+ * inet_net_pton(af, src, dst, size)
+ * convert network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not a valid network specification.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(int af, const char *src, void *dst, size_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ case AF_INET6:
+ return (inet_net_pton_ipv6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+/*
* static int
* inet_net_pton_ipv4(src, dst, size)
* convert IPv4 network number from presentation to network format.
@@ -57,22 +83,24 @@
* Paul Vixie (ISC), June 1996
*/
static int
-inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
- static const char xdigits[] = "0123456789abcdef";
- static const char digits[] = "0123456789";
- int n, ch, tmp = 0, dirty, bits;
+inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
+{
+ static const char
+ xdigits[] = "0123456789abcdef",
+ digits[] = "0123456789";
+ int n, ch, tmp, dirty, bits;
const u_char *odst = dst;
- ch = *src++;
+ ch = (unsigned char)*src++;
if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
- && isascii((unsigned char)(src[1]))
- && isxdigit((unsigned char)(src[1]))) {
+ && isascii((unsigned char)src[1]) && isxdigit((unsigned char)src[1])) {
/* Hexadecimal: Eat nybble string. */
- if (size <= 0U)
+ if (size == 0)
goto emsgsize;
- dirty = 0;
- src++; /*%< skip x or X. */
- while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
+ tmp = 0, dirty = 0;
+ src++; /* skip x or X. */
+ while ((ch = (unsigned char)*src++) != '\0' &&
+ isascii(ch) && isxdigit(ch)) {
if (isupper(ch))
ch = tolower(ch);
n = strchr(xdigits, ch) - xdigits;
@@ -82,14 +110,14 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
else
tmp = (tmp << 4) | n;
if (++dirty == 2) {
- if (size-- <= 0U)
+ if (size-- == 0)
goto emsgsize;
*dst++ = (u_char) tmp;
dirty = 0;
}
}
- if (dirty) { /*%< Odd trailing nybble? */
- if (size-- <= 0U)
+ if (dirty) { /* Odd trailing nybble? */
+ if (size-- == 0)
goto emsgsize;
*dst++ = (u_char) (tmp << 4);
}
@@ -104,16 +132,16 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
tmp += n;
if (tmp > 255)
goto enoent;
- } while ((ch = *src++) != '\0' &&
+ } while ((ch = (unsigned char)*src++) != '\0' &&
isascii(ch) && isdigit(ch));
- if (size-- <= 0U)
+ if (size-- == 0)
goto emsgsize;
*dst++ = (u_char) tmp;
if (ch == '\0' || ch == '/')
break;
if (ch != '.')
goto enoent;
- ch = *src++;
+ ch = (unsigned char)*src++;
if (!isascii(ch) || !isdigit(ch))
goto enoent;
}
@@ -121,10 +149,10 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
goto enoent;
bits = -1;
- if (ch == '/' && isascii((unsigned char)(src[0])) &&
- isdigit((unsigned char)(src[0])) && dst > odst) {
+ if (ch == '/' && isascii((unsigned char)src[0]) &&
+ isdigit((unsigned char)src[0]) && dst > odst) {
/* CIDR width specifier. Nothing can follow it. */
- ch = *src++; /*%< Skip over the /. */
+ ch = (unsigned char)*src++; /* Skip over the /. */
bits = 0;
do {
n = strchr(digits, ch) - digits;
@@ -132,8 +160,9 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
bits *= 10;
bits += n;
if (bits > 32)
- goto enoent;
- } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ goto emsgsize;
+ } while ((ch = (unsigned char)*src++) != '\0' &&
+ isascii(ch) && isdigit(ch));
if (ch != '\0')
goto enoent;
}
@@ -147,29 +176,23 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
goto enoent;
/* If no CIDR spec was given, infer width from net class. */
if (bits == -1) {
- if (*odst >= 240) /*%< Class E */
+ if (*odst >= 240) /* Class E */
bits = 32;
- else if (*odst >= 224) /*%< Class D */
- bits = 8;
- else if (*odst >= 192) /*%< Class C */
+ else if (*odst >= 224) /* Class D */
+ bits = 4;
+ else if (*odst >= 192) /* Class C */
bits = 24;
- else if (*odst >= 128) /*%< Class B */
+ else if (*odst >= 128) /* Class B */
bits = 16;
- else /*%< Class A */
+ else /* Class A */
bits = 8;
/* If imputed mask is narrower than specified octets, widen. */
if (bits < ((dst - odst) * 8))
bits = (dst - odst) * 8;
- /*
- * If there are no additional bits specified for a class D
- * address adjust bits to 4.
- */
- if (bits == 8 && *odst == 224)
- bits = 4;
}
/* Extend network to cover the actual mask. */
while (bits > ((dst - odst) * 8)) {
- if (size-- <= 0U)
+ if (size-- == 0)
goto emsgsize;
*dst++ = '\0';
}
@@ -184,222 +207,48 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
return (-1);
}
-static int
-getbits(const char *src, int *bitsp) {
- static const char digits[] = "0123456789";
- int n;
- int val;
- char ch;
-
- val = 0;
- n = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
-
- pch = strchr(digits, ch);
- if (pch != NULL) {
- if (n++ != 0 && val == 0) /*%< no leading zeros */
- return (0);
- val *= 10;
- val += (pch - digits);
- if (val > 128) /*%< range */
- return (0);
- continue;
- }
- return (0);
- }
- if (n == 0)
- return (0);
- *bitsp = val;
- return (1);
-}
static int
-getv4(const char *src, u_char *dst, int *bitsp) {
- static const char digits[] = "0123456789";
- u_char *odst = dst;
- int n;
- u_int val;
- char ch;
-
- val = 0;
- n = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
+inet_net_pton_ipv6(const char *src, u_char *dst, size_t size)
+{
+ struct in6_addr in6;
+ int ret;
+ int bits;
+ size_t bytes;
+ char buf[INET6_ADDRSTRLEN + sizeof("/128")];
+ char *sep;
+ const char *errstr;
- pch = strchr(digits, ch);
- if (pch != NULL) {
- if (n++ != 0 && val == 0) /*%< no leading zeros */
- return (0);
- val *= 10;
- val += (pch - digits);
- if (val > 255) /*%< range */
- return (0);
- continue;
- }
- if (ch == '.' || ch == '/') {
- if (dst - odst > 3) /*%< too many octets? */
- return (0);
- *dst++ = val;
- if (ch == '/')
- return (getbits(src, bitsp));
- val = 0;
- n = 0;
- continue;
- }
- return (0);
+ if (strlcpy(buf, src, sizeof buf) >= sizeof buf) {
+ errno = EMSGSIZE;
+ return (-1);
}
- if (n == 0)
- return (0);
- if (dst - odst > 3) /*%< too many octets? */
- return (0);
- *dst++ = val;
- return (1);
-}
-static int
-inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) {
- static const char xdigits_l[] = "0123456789abcdef",
- xdigits_u[] = "0123456789ABCDEF";
- u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
- const char *xdigits, *curtok;
- int ch, saw_xdigit;
- u_int val;
- int digits;
- int bits;
- size_t bytes;
- int words;
- int ipv4;
+ sep = strchr(buf, '/');
+ if (sep != NULL)
+ *sep++ = '\0';
- memset((tp = tmp), '\0', NS_IN6ADDRSZ);
- endp = tp + NS_IN6ADDRSZ;
- colonp = NULL;
- /* Leading :: requires some special handling. */
- if (*src == ':')
- if (*++src != ':')
- goto enoent;
- curtok = src;
- saw_xdigit = 0;
- val = 0;
- digits = 0;
- bits = -1;
- ipv4 = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
+ ret = inet_pton(AF_INET6, buf, &in6);
+ if (ret != 1)
+ return (-1);
- if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
- pch = strchr((xdigits = xdigits_u), ch);
- if (pch != NULL) {
- val <<= 4;
- val |= (pch - xdigits);
- if (++digits > 4)
- goto enoent;
- saw_xdigit = 1;
- continue;
- }
- if (ch == ':') {
- curtok = src;
- if (!saw_xdigit) {
- if (colonp)
- goto enoent;
- colonp = tp;
- continue;
- } else if (*src == '\0')
- goto enoent;
- if (tp + NS_INT16SZ > endp)
- return (0);
- *tp++ = (u_char) (val >> 8) & 0xff;
- *tp++ = (u_char) val & 0xff;
- saw_xdigit = 0;
- digits = 0;
- val = 0;
- continue;
- }
- if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
- getv4(curtok, tp, &bits) > 0) {
- tp += NS_INADDRSZ;
- saw_xdigit = 0;
- ipv4 = 1;
- break; /*%< '\\0' was seen by inet_pton4(). */
- }
- if (ch == '/' && getbits(src, &bits) > 0)
- break;
- goto enoent;
- }
- if (saw_xdigit) {
- if (tp + NS_INT16SZ > endp)
- goto enoent;
- *tp++ = (u_char) (val >> 8) & 0xff;
- *tp++ = (u_char) val & 0xff;
- }
- if (bits == -1)
+ if (sep == NULL)
bits = 128;
-
- words = (bits + 15) / 16;
- if (words < 2)
- words = 2;
- if (ipv4)
- words = 8;
- endp = tmp + 2 * words;
-
- if (colonp != NULL) {
- /*
- * Since some memmove()'s erroneously fail to handle
- * overlapping regions, we'll do the shift by hand.
- */
- const int n = tp - colonp;
- int i;
-
- if (tp == endp)
- goto enoent;
- for (i = 1; i <= n; i++) {
- endp[- i] = colonp[n - i];
- colonp[n - i] = 0;
+ else {
+ bits = strtonum(sep, 0, 128, &errstr);
+ if (errstr) {
+ errno = EINVAL;
+ return (-1);
}
- tp = endp;
}
- if (tp != endp)
- goto enoent;
bytes = (bits + 7) / 8;
- if (bytes > size)
- goto emsgsize;
- memcpy(dst, tmp, bytes);
- return (bits);
-
- enoent:
- errno = ENOENT;
- return (-1);
-
- emsgsize:
- errno = EMSGSIZE;
- return (-1);
-}
-
-/*%
- * int
- * inet_net_pton(af, src, dst, size)
- * convert network number from presentation to network format.
- * accepts hex octets, hex strings, decimal octets, and /CIDR.
- * "size" is in bytes and describes "dst".
- * return:
- * number of bits, either imputed classfully or specified with /CIDR,
- * or -1 if some failure occurred (check errno). ENOENT means it was
- * not a valid network specification.
- * author:
- * Paul Vixie (ISC), June 1996
- */
-int
-inet_net_pton(int af, const char *src, void *dst, size_t size) {
- switch (af) {
- case AF_INET:
- return (inet_net_pton_ipv4(src, dst, size));
- case AF_INET6:
- return (inet_net_pton_ipv6(src, dst, size));
- default:
- errno = EAFNOSUPPORT;
+ if (bytes > size) {
+ errno = EMSGSIZE;
return (-1);
}
+ memcpy(dst, &in6.s6_addr, bytes);
+ return (bits);
}
/*
@@ -408,5 +257,3 @@ inet_net_pton(int af, const char *src, void *dst, size_t size) {
*/
#undef inet_net_pton
__weak_reference(__inet_net_pton, inet_net_pton);
-
-/*! \file */
diff --git a/lib/libc/md/Makefile.inc b/lib/libc/md/Makefile.inc
deleted file mode 100644
index 82c5f0670485..000000000000
--- a/lib/libc/md/Makefile.inc
+++ /dev/null
@@ -1,3 +0,0 @@
-.PATH: ${SRCTOP}/sys/kern
-
-SRCS+= md5c.c
diff --git a/lib/libc/net/gai_strerror.c b/lib/libc/net/gai_strerror.c
index 0d4303e76a73..23f58b763573 100644
--- a/lib/libc/net/gai_strerror.c
+++ b/lib/libc/net/gai_strerror.c
@@ -45,22 +45,22 @@
* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) were omitted from RFC 3493,
* but are or may be used as extensions or in old code.
*/
-static const char *ai_errlist[] = {
- "Success", /* 0 */
- "Address family for hostname not supported", /* EAI_ADDRFAMILY */
- "Name could not be resolved at this time", /* EAI_AGAIN */
- "Flags parameter had an invalid value", /* EAI_BADFLAGS */
- "Non-recoverable failure in name resolution", /* EAI_FAIL */
- "Address family not recognized", /* EAI_FAMILY */
- "Memory allocation failure", /* EAI_MEMORY */
- "No address associated with hostname", /* EAI_NODATA*/
- "Name does not resolve", /* EAI_NONAME */
- "Service was not recognized for socket type", /* EAI_SERVICE */
- "Intended socket type was not recognized", /* EAI_SOCKTYPE */
- "System error returned in errno", /* EAI_SYSTEM */
- "Invalid value for hints", /* EAI_BADHINTS */
- "Resolved protocol is unknown", /* EAI_PROTOCOL */
- "Argument buffer overflow" /* EAI_OVERFLOW */
+static const char *const ai_errlist[] = {
+ [0] = "Success",
+ [EAI_ADDRFAMILY] = "Address family for hostname not supported",
+ [EAI_AGAIN] = "Name could not be resolved at this time",
+ [EAI_BADFLAGS] = "Flags parameter had an invalid value",
+ [EAI_FAIL] = "Non-recoverable failure in name resolution",
+ [EAI_FAMILY] = "Address family not recognized",
+ [EAI_MEMORY] = "Memory allocation failure",
+ [EAI_NODATA] = "No address associated with hostname",
+ [EAI_NONAME] = "Name does not resolve",
+ [EAI_SERVICE] = "Service was not recognized for socket type",
+ [EAI_SOCKTYPE] = "Intended socket type was not recognized",
+ [EAI_SYSTEM] = "System error returned in errno",
+ [EAI_BADHINTS] = "Invalid value for hints",
+ [EAI_PROTOCOL] = "Resolved protocol is unknown",
+ [EAI_OVERFLOW] = "Argument buffer overflow",
};
#if defined(NLS)
@@ -72,7 +72,7 @@ static int gai_keycreated = 0;
static void
gai_keycreate(void)
{
- gai_keycreated = (thr_keycreate(&gai_key, free) == 0);
+ gai_keycreated = thr_keycreate(&gai_key, free) == 0;
}
#endif
@@ -82,7 +82,9 @@ gai_strerror(int ecode)
#if defined(NLS)
nl_catd catd;
char *buf;
+ int saved_errno;
+ saved_errno = errno;
if (thr_main() != 0)
buf = gai_buf;
else {
@@ -110,11 +112,13 @@ gai_strerror(int ecode)
strlcpy(buf, catgets(catd, 3, NL_MSGMAX, "Unknown error"),
sizeof(gai_buf));
catclose(catd);
- return buf;
+ errno = saved_errno;
+ return (buf);
thr_err:
+ errno = saved_errno;
#endif
if (ecode >= 0 && ecode < EAI_MAX)
- return ai_errlist[ecode];
- return "Unknown error";
+ return (ai_errlist[ecode]);
+ return ("Unknown error");
}
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c
index b29fa1cdd845..216fc9bcf9a4 100644
--- a/lib/libc/net/gethostbydns.c
+++ b/lib/libc/net/gethostbydns.c
@@ -74,8 +74,10 @@
#define SPRINTF(x) ((size_t)sprintf x)
+#ifdef DEBUG
static const char AskedForGot[] =
"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
+#endif
#ifdef RESOLVSORT
static void addrsort(char **, int, res_state);
@@ -299,8 +301,10 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
switch (type) {
case T_PTR:
if (strcasecmp(tname, bp) != 0) {
+#ifdef DEBUG
syslog(LOG_NOTICE|LOG_AUTH,
AskedForGot, qname, bp);
+#endif
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -347,8 +351,10 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
case T_A:
case T_AAAA:
if (strcasecmp(he->h_name, bp) != 0) {
+#ifdef DEBUG
syslog(LOG_NOTICE|LOG_AUTH,
AskedForGot, he->h_name, bp);
+#endif
cp += n;
continue; /* XXX - had_error++ ? */
}
diff --git a/lib/libc/net/res_config.h b/lib/libc/net/res_config.h
index f049d6817b7a..39a1b5f1486f 100644
--- a/lib/libc/net/res_config.h
+++ b/lib/libc/net/res_config.h
@@ -1,5 +1,5 @@
-#define DEBUG 1 /* enable debugging code (needed for dig) */
+//#define DEBUG /* enable debugging code */
#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
-#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DON'T NEED IT */
+//#define SUNSECURITY /* verify gethostbyaddr() calls */
#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
diff --git a/lib/libc/nls/Makefile.inc b/lib/libc/nls/Makefile.inc
index f26e04c187a5..c211026aba72 100644
--- a/lib/libc/nls/Makefile.inc
+++ b/lib/libc/nls/Makefile.inc
@@ -12,6 +12,11 @@ MAN+= catclose.3 catgets.3 catopen.3
# for translators.
NLSNAME= libc
+# We don't want libc's NLS catalogues to be installed in the clibs package.
+# Put them in locales instead, since anyone interested in NLS will have
+# that installed.
+NLSPACKAGE= locales
+
NLS+= be_BY.UTF-8
NLS+= ca_ES.ISO8859-1
NLS+= de_DE.ISO8859-1
diff --git a/lib/libc/powerpc64/gen/_ctx_start.S b/lib/libc/powerpc64/gen/_ctx_start.S
index c2f8abfd6486..98225f9c1138 100644
--- a/lib/libc/powerpc64/gen/_ctx_start.S
+++ b/lib/libc/powerpc64/gen/_ctx_start.S
@@ -34,6 +34,16 @@
ld %r2,8(%r14)
ld %r14,0(%r14)
#else
+ /*
+ * The stack frame was already set up in makecontext(),
+ * so we can safely use the guaranteed fields here.
+ *
+ * Note we do step on the allocated stack frame's TOC,
+ * but since we never return from this function (i.e.
+ * never restore the stack frame) this should be safe.
+ */
+ std %r2,24(%r1) /* save TOC */
+
/* Load global entry point */
mr %r12,%r14
#endif
@@ -41,6 +51,10 @@
blrl /* branch to start function */
mr %r3,%r15 /* pass pointer to ucontext as argument */
nop
+#if defined(_CALL_ELF) && _CALL_ELF != 1
+ /* Restore TOC */
+ ld %r2,24(%r1)
+#endif
bl CNAME(_ctx_done) /* branch to ctxt completion func */
/*
* we should never return from the
diff --git a/lib/libc/powerpc64/gen/makecontext.c b/lib/libc/powerpc64/gen/makecontext.c
index 75c2d40bdd60..9e3a976fa1bd 100644
--- a/lib/libc/powerpc64/gen/makecontext.c
+++ b/lib/libc/powerpc64/gen/makecontext.c
@@ -78,7 +78,7 @@ __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
*/
stackargs = (argc > 8) ? argc - 8 : 0;
sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size
- - sizeof(uintptr_t)*(stackargs + 2);
+ - sizeof(uintptr_t)*(stackargs + 6);
sp = (char *)((uintptr_t)sp & ~0x1f);
mc = &ucp->uc_mcontext;
@@ -119,6 +119,7 @@ __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
mc->mc_srr0 = *(uintptr_t *)_ctx_start;
#else
mc->mc_srr0 = (uintptr_t) _ctx_start;
+ mc->mc_gpr[12] = (uintptr_t) _ctx_start;/* required for prologue */
#endif
mc->mc_gpr[1] = (uintptr_t) sp; /* new stack pointer */
mc->mc_gpr[14] = (uintptr_t) start; /* r14 <- start */
diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c
index f34dc322d0bb..aebea2b02435 100644
--- a/lib/libc/regex/regcomp.c
+++ b/lib/libc/regex/regcomp.c
@@ -1183,6 +1183,7 @@ p_b_pseudoclass(struct parse *p, char c) {
/* PASSTHROUGH */
case 'w':
p_b_cclass_named(p, cs, "alnum");
+ CHadd(p, cs, '_');
break;
case 'S':
cs->invert = 1;
diff --git a/lib/libc/resolv/Symbol.map b/lib/libc/resolv/Symbol.map
index 6b9c43298fb5..26daecbe2eff 100644
--- a/lib/libc/resolv/Symbol.map
+++ b/lib/libc/resolv/Symbol.map
@@ -103,6 +103,5 @@ FBSD_1.0 {
};
FBSD_1.4 {
- __res_rndinit;
__res_nrandomid;
};
diff --git a/lib/libc/resolv/res_debug.h b/lib/libc/resolv/res_debug.h
index dd048116fb49..ccae03e625aa 100644
--- a/lib/libc/resolv/res_debug.h
+++ b/lib/libc/resolv/res_debug.h
@@ -23,7 +23,7 @@
#ifndef DEBUG
# define Dprint(cond, args) /*empty*/
# define DprintQ(cond, args, query, size) /*empty*/
-# define Aerror(statp, file, string, error, address) /*empty*/
+# define Aerror(statp, file, string, error, address, alen) /*empty*/
# define Perror(statp, file, string, error) /*empty*/
#else
# define Dprint(cond, args) if (cond) {fprintf args;} else {}
diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c
index 70d6bc6d3bf2..5a2fce013c8c 100644
--- a/lib/libc/resolv/res_init.c
+++ b/lib/libc/resolv/res_init.c
@@ -86,19 +86,6 @@
#include <unistd.h>
#include <netdb.h>
-#ifndef HAVE_MD5
-# include "../dst/md5.h"
-#else
-# ifdef SOLARIS2
-# include <sys/md5.h>
-# elif _LIBC
-# include <md5.h>
-# endif
-#endif
-#ifndef _MD5_H_
-# define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */
-#endif
-
#include "un-namespace.h"
#include "port_after.h"
@@ -108,12 +95,6 @@
#include "res_private.h"
-/*% Options. Should all be left alone. */
-#define RESOLVSORT
-#ifndef DEBUG
-#define DEBUG
-#endif
-
#ifdef SOLARIS2
#include <sys/systeminfo.h>
#endif
@@ -190,8 +171,6 @@ __res_vinit(res_state statp, int preinit) {
statp->options = RES_DEFAULT;
}
- statp->_rnd = malloc(16);
- res_rndinit(statp);
statp->id = res_nrandomid(statp);
memset(u, 0, sizeof(u));
@@ -739,48 +718,18 @@ net_mask(struct in_addr in) /*!< XXX - should really use system's version of th
}
#endif
-static u_char srnd[16];
-
void
-res_rndinit(res_state statp)
+freebsd15_res_rndinit(res_state statp)
{
- struct timeval now;
- u_int32_t u32;
- u_int16_t u16;
- u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd;
-
- gettimeofday(&now, NULL);
- u32 = now.tv_sec;
- memcpy(rnd, &u32, 4);
- u32 = now.tv_usec;
- memcpy(rnd + 4, &u32, 4);
- u32 += now.tv_sec;
- memcpy(rnd + 8, &u32, 4);
- u16 = getpid();
- memcpy(rnd + 12, &u16, 2);
+ (void)statp;
}
+__sym_compat(__res_rndinit, freebsd15_res_rndinit, FBSD_1.4);
u_int
res_nrandomid(res_state statp) {
- struct timeval now;
- u_int16_t u16;
- MD5_CTX ctx;
- u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd;
-
- gettimeofday(&now, NULL);
- u16 = (u_int16_t) (now.tv_sec ^ now.tv_usec);
- memcpy(rnd + 14, &u16, 2);
-#ifndef HAVE_MD5
- MD5_Init(&ctx);
- MD5_Update(&ctx, rnd, 16);
- MD5_Final(rnd, &ctx);
-#else
- MD5Init(&ctx);
- MD5Update(&ctx, rnd, 16);
- MD5Final(rnd, &ctx);
-#endif
- memcpy(&u16, rnd + 14, 2);
- return ((u_int) u16);
+ (void) statp;
+
+ return ((u_int)(arc4random() & 0xffff));
}
/*%
@@ -814,10 +763,6 @@ res_ndestroy(res_state statp) {
free(statp->_u._ext.ext);
statp->_u._ext.ext = NULL;
}
- if (statp->_rnd != NULL) {
- free(statp->_rnd);
- statp->_rnd = NULL;
- }
statp->options &= ~RES_INIT;
}
diff --git a/lib/libc/resolv/res_mkquery.c b/lib/libc/resolv/res_mkquery.c
index 0c15def5d117..f6767a92375c 100644
--- a/lib/libc/resolv/res_mkquery.c
+++ b/lib/libc/resolv/res_mkquery.c
@@ -76,11 +76,6 @@
#include <string.h>
#include "port_after.h"
-/* Options. Leave them on. */
-#ifndef DEBUG
-#define DEBUG
-#endif
-
extern const char *_res_opcodes[];
/*%
diff --git a/lib/libc/resolv/res_mkupdate.c b/lib/libc/resolv/res_mkupdate.c
index e5a3cb702cda..3f595dc4ec08 100644
--- a/lib/libc/resolv/res_mkupdate.c
+++ b/lib/libc/resolv/res_mkupdate.c
@@ -48,10 +48,6 @@
#include "port_after.h"
-/* Options. Leave them on. */
-#ifndef DEBUG
-#define DEBUG
-#endif
#define MAXPORT 1024
static int getnum_str(u_char **, u_char *);
diff --git a/lib/libc/resolv/res_query.c b/lib/libc/resolv/res_query.c
index e9c628ad8d47..f26d59e522b4 100644
--- a/lib/libc/resolv/res_query.c
+++ b/lib/libc/resolv/res_query.c
@@ -81,11 +81,6 @@
#include <unistd.h>
#include "port_after.h"
-/* Options. Leave them on. */
-#ifndef DEBUG
-#define DEBUG
-#endif
-
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
#else
diff --git a/lib/libc/resolv/res_send.c b/lib/libc/resolv/res_send.c
index 3fb627b83d55..08c3aed7f934 100644
--- a/lib/libc/resolv/res_send.c
+++ b/lib/libc/resolv/res_send.c
@@ -112,10 +112,6 @@
#include "un-namespace.h"
-/* Options. Leave them on. */
-#ifndef DEBUG
-#define DEBUG
-#endif
#include "res_debug.h"
#include "res_private.h"
@@ -138,15 +134,12 @@ static int send_dg(res_state,
const u_char *, int,
u_char *, int, int *, int, int,
int *, int *);
+#ifdef DEBUG
static void Aerror(const res_state, FILE *, const char *, int,
const struct sockaddr *, int);
static void Perror(const res_state, FILE *, const char *, int);
-static int sock_eq(struct sockaddr *, struct sockaddr *);
-#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
-static int pselect(int, void *, void *, void *,
- struct timespec *,
- const sigset_t *);
#endif
+static int sock_eq(struct sockaddr *, struct sockaddr *);
void res_pquery(const res_state, const u_char *, int, FILE *);
static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
@@ -302,7 +295,9 @@ res_nsend(res_state statp,
#ifdef USE_KQUEUE
int kq;
#endif
+#ifdef DEBUG
char abuf[NI_MAXHOST];
+#endif
/* No name servers or res_init() failure */
if (statp->nscount == 0 || EXT(statp).ext == NULL) {
@@ -418,10 +413,10 @@ res_nsend(res_state statp,
*/
for (tries = 0; tries < statp->retry; tries++) {
for (ns = 0; ns < statp->nscount; ns++) {
- struct sockaddr *nsap;
- int nsaplen;
- nsap = get_nsaddr(statp, ns);
- nsaplen = get_salen(nsap);
+ struct sockaddr *nsap = get_nsaddr(statp, ns);
+#ifdef DEBUG
+ int nsaplen = get_salen(nsap);
+#endif
statp->_flags &= ~RES_F_LASTMASK;
statp->_flags |= (ns << RES_F_LASTSHIFT);
same_ns:
@@ -1088,6 +1083,7 @@ send_dg(res_state statp,
return (resplen);
}
+#ifdef DEBUG
static void
Aerror(const res_state statp, FILE *file, const char *string, int error,
const struct sockaddr *address, int alen)
@@ -1119,6 +1115,7 @@ Perror(const res_state statp, FILE *file, const char *string, int error) {
string, strerror(error));
errno = save;
}
+#endif
static int
sock_eq(struct sockaddr *a, struct sockaddr *b) {
@@ -1145,29 +1142,3 @@ sock_eq(struct sockaddr *a, struct sockaddr *b) {
return 0;
}
}
-
-#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
-/* XXX needs to move to the porting library. */
-static int
-pselect(int nfds, void *rfds, void *wfds, void *efds,
- struct timespec *tsp, const sigset_t *sigmask)
-{
- struct timeval tv, *tvp;
- sigset_t sigs;
- int n;
-
- if (tsp) {
- tvp = &tv;
- tv = evTimeVal(*tsp);
- } else
- tvp = NULL;
- if (sigmask)
- sigprocmask(SIG_SETMASK, sigmask, &sigs);
- n = select(nfds, rfds, wfds, efds, tvp);
- if (sigmask)
- sigprocmask(SIG_SETMASK, &sigs, NULL);
- if (tsp)
- *tsp = evTimeSpec(tv);
- return (n);
-}
-#endif
diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c
index 0e563f6a5996..8019f2d8f236 100644
--- a/lib/libc/rpc/rpc_generic.c
+++ b/lib/libc/rpc/rpc_generic.c
@@ -610,6 +610,10 @@ __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
return NULL;
break;
#endif
+ case AF_NETLINK:
+ if (asprintf(&ret, "%s", (char *)nbuf->buf) < 0)
+ return NULL;
+ break;
case AF_LOCAL:
sun = nbuf->buf;
if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map
index d491b83c11fb..e44ea6554d46 100644
--- a/lib/libc/stdio/Symbol.map
+++ b/lib/libc/stdio/Symbol.map
@@ -44,7 +44,6 @@ FBSD_1.0 {
fwscanf;
getc;
getchar;
- gets;
getw;
getwc;
getwchar;
diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c
index a0d7b71df782..49ec97eda39d 100644
--- a/lib/libc/stdio/fdopen.c
+++ b/lib/libc/stdio/fdopen.c
@@ -46,7 +46,7 @@ FILE *
fdopen(int fd, const char *mode)
{
FILE *fp;
- int flags, oflags, fdflags, tmp;
+ int flags, oflags, fdflags, rc, tmp;
/*
* File descriptors are a full int, but _file is only a short.
@@ -76,9 +76,19 @@ fdopen(int fd, const char *mode)
if ((fp = __sfp()) == NULL)
return (NULL);
- if ((oflags & O_CLOEXEC) && _fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
- fp->_flags = 0;
- return (NULL);
+ if ((oflags & O_CLOEXEC) != 0) {
+ tmp = _fcntl(fd, F_GETFD, 0);
+ if (tmp == -1) {
+ fp->_flags = 0;
+ return (NULL);
+ }
+ if ((tmp & FD_CLOEXEC) == 0) {
+ rc = _fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
+ if (rc == -1) {
+ fp->_flags = 0;
+ return (NULL);
+ }
+ }
}
fp->_flags = flags;
diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c
index f0732b6d6741..048fd30b3193 100644
--- a/lib/libc/stdio/freopen.c
+++ b/lib/libc/stdio/freopen.c
@@ -55,7 +55,7 @@ freopen(const char * __restrict file, const char * __restrict mode,
FILE * __restrict fp)
{
int f;
- int dflags, flags, isopen, oflags, sverrno, wantfd;
+ int dflags, fdflags, flags, isopen, oflags, sverrno, wantfd;
if ((flags = __sflags(mode, &oflags)) == 0) {
sverrno = errno;
@@ -113,8 +113,12 @@ freopen(const char * __restrict file, const char * __restrict mode,
(void) ftruncate(fp->_file, (off_t)0);
if (!(oflags & O_APPEND))
(void) _sseek(fp, (fpos_t)0, SEEK_SET);
- if (oflags & O_CLOEXEC)
- (void) _fcntl(fp->_file, F_SETFD, FD_CLOEXEC);
+ if ((oflags & O_CLOEXEC) != 0) {
+ fdflags = _fcntl(fp->_file, F_GETFD, 0);
+ if (fdflags != -1 && (fdflags & FD_CLOEXEC) == 0)
+ (void) _fcntl(fp->_file, F_SETFD,
+ fdflags | FD_CLOEXEC);
+ }
f = fp->_file;
isopen = 0;
wantfd = -1;
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index a678710e1ecb..89e9e843969f 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -318,10 +318,9 @@ parseint_fsm(int c, enum parseint_state *state, int *base)
case '0':
if (*state == begin || *state == havesign) {
*state = havezero;
- } else {
- *state = any;
+ return 1;
}
- return 1;
+ /* FALL THROUGH */
case '1':
case '2':
case '3':
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
index 57206a8407d5..7ca64eb37811 100644
--- a/lib/libc/stdio/vfwscanf.c
+++ b/lib/libc/stdio/vfwscanf.c
@@ -298,10 +298,9 @@ parseint_fsm(wchar_t c, enum parseint_state *state, int *base)
case '0':
if (*state == begin || *state == havesign) {
*state = havezero;
- } else {
- *state = any;
+ return 1;
}
- return 1;
+ /* FALL THROUGH */
case '1':
case '2':
case '3':
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index ca199a669be1..e7b9955b9646 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -10,7 +10,7 @@ MISRCS+=C99_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \
merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c qsort_r_compat.c \
qsort_s.c quick_exit.c radixsort.c rand.c \
- random.c reallocarray.c reallocf.c realpath.c remque.c \
+ random.c reallocarray.c reallocf.c realpath.c recallocarray.c remque.c \
set_constraint_handler_s.c strfmon.c strtoimax.c \
strtol.c strtold.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \
strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
@@ -76,6 +76,7 @@ MLINKS+=random.3 initstate.3 \
random.3 srandom.3 \
random.3 srandomdev.3
MLINKS+=radixsort.3 sradixsort.3
+MLINKS+=reallocarray.3 recallocarray.3
MLINKS+=set_constraint_handler_s.3 abort_handler_s.3
MLINKS+=set_constraint_handler_s.3 ignore_handler_s.3
MLINKS+=strfmon.3 strfmon_l.3
diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map
index 2b79ca2ece8b..53d71bcafb7d 100644
--- a/lib/libc/stdlib/Symbol.map
+++ b/lib/libc/stdlib/Symbol.map
@@ -131,6 +131,10 @@ FBSD_1.8 {
getenv_r;
};
+FBSD_1.9 {
+ recallocarray;
+};
+
FBSDprivate_1.0 {
__system;
_system;
diff --git a/lib/libc/stdlib/malloc/jemalloc/Makefile.inc b/lib/libc/stdlib/malloc/jemalloc/Makefile.inc
index c10d79dbce6c..7722a7b755f3 100644
--- a/lib/libc/stdlib/malloc/jemalloc/Makefile.inc
+++ b/lib/libc/stdlib/malloc/jemalloc/Makefile.inc
@@ -1,15 +1,21 @@
.PATH: ${LIBC_SRCTOP}/stdlib/malloc/jemalloc
JEMALLOCSRCS:= jemalloc.c arena.c background_thread.c base.c bin.c bitmap.c \
- ckh.c ctl.c div.c extent.c extent_dss.c extent_mmap.c hash.c hook.c \
- large.c log.c malloc_io.c mutex.c mutex_pool.c nstime.c pages.c \
- prng.c prof.c rtree.c safety_check.c sc.c stats.c sz.c tcache.c \
- test_hooks.c ticker.c tsd.c witness.c
+ ckh.c ctl.c div.c extent.c extent_dss.c extent_mmap.c hook.c \
+ large.c log.c malloc_io.c mutex.c nstime.c pages.c \
+ prof.c rtree.c safety_check.c sc.c stats.c sz.c tcache.c \
+ test_hooks.c ticker.c tsd.c witness.c \
+ bin_info.c san.c san_bump.c counter.c prof_data.c prof_log.c prof_recent.c prof_stats.c prof_sys.c \
+ emap.c edata.c edata_cache.c pa.c pa_extra.c pac.c decay.c hpa.c hpa_hooks.c fxp.c hpdata.c pai.c \
+ ecache.c ehooks.c eset.c sec.c cache_bin.c peak_event.c psset.c inspect.c exp_grow.c thread_event.c \
+ buf_writer.c
CFLAGS+=-I${SRCTOP}/contrib/jemalloc/include -I${LIBC_SRCTOP}/stdlib/malloc/jemalloc/include
.if ${MK_JEMALLOC_LG_VADDR_WIDE} != no
CFLAGS+=-D_USE_LG_VADDR_WIDE
.endif
+CFLAGS.gcc+=-Wno-error=missing-braces
+
.for src in ${JEMALLOCSRCS}
MISRCS+=jemalloc_${src}
diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h
index 1aedb916976b..900ae867f321 100644
--- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h
+++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h
@@ -45,17 +45,17 @@
#define LG_VADDR 48
/* Defined if C11 atomics are available. */
-#define JEMALLOC_C11_ATOMICS 1
+#define JEMALLOC_C11_ATOMICS
/* Defined if GCC __atomic atomics are available. */
-#define JEMALLOC_GCC_ATOMIC_ATOMICS 1
+#define JEMALLOC_GCC_ATOMIC_ATOMICS
/* and the 8-bit variant support. */
-#define JEMALLOC_GCC_U8_ATOMIC_ATOMICS 1
+#define JEMALLOC_GCC_U8_ATOMIC_ATOMICS
/* Defined if GCC __sync atomics are available. */
-#define JEMALLOC_GCC_SYNC_ATOMICS 1
+#define JEMALLOC_GCC_SYNC_ATOMICS
/* and the 8-bit variant support. */
-#define JEMALLOC_GCC_U8_SYNC_ATOMICS 1
+#define JEMALLOC_GCC_U8_SYNC_ATOMICS
/*
* Defined if __builtin_clz() and __builtin_clzl() are available.
@@ -73,7 +73,7 @@
/*
* Defined if secure_getenv(3) is available.
*/
-/* #undef JEMALLOC_HAVE_SECURE_GETENV */
+#define JEMALLOC_HAVE_SECURE_GETENV
/*
* Defined if issetugid(2) is available.
@@ -84,17 +84,23 @@
#define JEMALLOC_HAVE_PTHREAD_ATFORK
/* Defined if pthread_setname_np(3) is available. */
-/* #undef JEMALLOC_HAVE_PTHREAD_SETNAME_NP */
+#define JEMALLOC_HAVE_PTHREAD_SETNAME_NP
+
+/* Defined if pthread_getname_np(3) is available. */
+#define JEMALLOC_HAVE_PTHREAD_GETNAME_NP
+
+/* Defined if pthread_get_name_np(3) is available. */
+#define JEMALLOC_HAVE_PTHREAD_GET_NAME_NP
/*
* Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available.
*/
-/* #undef JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE */
+#define JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE
/*
* Defined if clock_gettime(CLOCK_MONOTONIC, ...) is available.
*/
-#define JEMALLOC_HAVE_CLOCK_MONOTONIC 1
+#define JEMALLOC_HAVE_CLOCK_MONOTONIC
/*
* Defined if mach_absolute_time() is available.
@@ -102,6 +108,11 @@
/* #undef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME */
/*
+ * Defined if clock_gettime(CLOCK_REALTIME, ...) is available.
+ */
+#define JEMALLOC_HAVE_CLOCK_REALTIME
+
+/*
* Defined if _malloc_thread_cleanup() exists. At least in the case of
* FreeBSD, pthread_key_create() allocates, which if used during malloc
* bootstrapping will cause recursion into the pthreads library. Therefore, if
@@ -122,7 +133,7 @@
* _pthread_mutex_init_calloc_cb(), in which case the function is used in order
* to avoid recursive allocation during mutex initialization.
*/
-#define JEMALLOC_MUTEX_INIT_CB 1
+#define JEMALLOC_MUTEX_INIT_CB
/* Non-empty if the tls_model attribute is supported. */
#define JEMALLOC_TLS_MODEL __attribute__((tls_model("initial-exec")))
@@ -163,6 +174,9 @@
/* Support utrace(2)-based tracing. */
#define JEMALLOC_UTRACE
+/* Support utrace(2)-based tracing (label based signature). */
+/* #undef JEMALLOC_UTRACE_LABEL */
+
/* Support optional abort() on OOM. */
#define JEMALLOC_XMALLOC
@@ -178,6 +192,9 @@
/* One page is 2^LG_PAGE bytes. */
#define LG_PAGE 12
+/* Maximum number of regions in a slab. */
+/* #undef CONFIG_LG_SLAB_MAXREGS */
+
/*
* One huge page is 2^LG_HUGEPAGE bytes. Note that this is defined even if the
* system does not explicitly support huge pages; system calls that require
@@ -292,16 +309,45 @@
/* #undef JEMALLOC_MADVISE_DONTDUMP */
/*
+ * Defined if MADV_[NO]CORE is supported as an argument to madvise.
+ */
+#define JEMALLOC_MADVISE_NOCORE
+
+/* Defined if mprotect(2) is available. */
+#define JEMALLOC_HAVE_MPROTECT
+
+/*
* Defined if transparent huge pages (THPs) are supported via the
* MADV_[NO]HUGEPAGE arguments to madvise(2), and THP support is enabled.
*/
/* #undef JEMALLOC_THP */
+/* Defined if posix_madvise is available. */
+/* #undef JEMALLOC_HAVE_POSIX_MADVISE */
+
+/*
+ * Method for purging unused pages using posix_madvise.
+ *
+ * posix_madvise(..., POSIX_MADV_DONTNEED)
+ */
+/* #undef JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED */
+/* #undef JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED_ZEROS */
+
+/*
+ * Defined if memcntl page admin call is supported
+ */
+/* #undef JEMALLOC_HAVE_MEMCNTL */
+
+/*
+ * Defined if malloc_size is supported
+ */
+/* #undef JEMALLOC_HAVE_MALLOC_SIZE */
+
/* Define if operating system has alloca.h header. */
/* #undef JEMALLOC_HAS_ALLOCA_H */
/* C99 restrict keyword supported. */
-#define JEMALLOC_HAS_RESTRICT 1
+#define JEMALLOC_HAS_RESTRICT
/* For use by hash code. */
/* #undef JEMALLOC_BIG_ENDIAN */
@@ -334,15 +380,15 @@
#define JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
/* GNU specific sched_getcpu support */
-/* #undef JEMALLOC_HAVE_SCHED_GETCPU */
+#define JEMALLOC_HAVE_SCHED_GETCPU
/* GNU specific sched_setaffinity support */
-/* #undef JEMALLOC_HAVE_SCHED_SETAFFINITY */
+#define JEMALLOC_HAVE_SCHED_SETAFFINITY
/*
* If defined, all the features necessary for background threads are present.
*/
-#define JEMALLOC_BACKGROUND_THREAD 1
+#define JEMALLOC_BACKGROUND_THREAD
/*
* If defined, jemalloc symbols are not exported (doesn't work when
@@ -354,7 +400,7 @@
#define JEMALLOC_CONFIG_MALLOC_CONF "abort_conf:false"
/* If defined, jemalloc takes the malloc/free/etc. symbol names. */
-#define JEMALLOC_IS_MALLOC 1
+#define JEMALLOC_IS_MALLOC
/*
* Defined if strerror_r returns char * if _GNU_SOURCE is defined.
@@ -364,4 +410,19 @@
/* Performs additional safety checks when defined. */
/* #undef JEMALLOC_OPT_SAFETY_CHECKS */
+/* Is C++ support being built? */
+#define JEMALLOC_ENABLE_CXX
+
+/* Performs additional size checks when defined. */
+/* #undef JEMALLOC_OPT_SIZE_CHECKS */
+
+/* Allows sampled junk and stash for checking use-after-free when defined. */
+/* #undef JEMALLOC_UAF_DETECTION */
+
+/* Darwin VM_MAKE_TAG support */
+/* #undef JEMALLOC_HAVE_VM_MAKE_TAG */
+
+/* If defined, realloc(ptr, 0) defaults to "free" instead of "alloc". */
+/* #undef JEMALLOC_ZERO_REALLOC_DEFAULT_FREE */
+
#endif /* JEMALLOC_INTERNAL_DEFS_H_ */
diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h
index d1dcc50d5a3b..b6cf5864109d 100644
--- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h
+++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h
@@ -4,12 +4,20 @@
#include "jemalloc_internal_defs.h"
#include "jemalloc/internal/jemalloc_internal_decls.h"
-#ifdef JEMALLOC_UTRACE
+#if defined(JEMALLOC_UTRACE) || defined(JEMALLOC_UTRACE_LABEL)
#include <sys/ktrace.h>
+# if defined(JEMALLOC_UTRACE)
+# define UTRACE_CALL(p, l) utrace(p, l)
+# else
+# define UTRACE_CALL(p, l) utrace("jemalloc_process", p, l)
+# define JEMALLOC_UTRACE
+# endif
#endif
+#ifndef JEMALLOC_PRIVATE_NAMESPACE
#include "un-namespace.h"
#include "libc_private.h"
+#endif
#define JEMALLOC_NO_DEMANGLE
#ifdef JEMALLOC_JET
@@ -177,6 +185,35 @@ static const bool config_opt_safety_checks =
#endif
;
+/*
+ * Extra debugging of sized deallocations too onerous to be included in the
+ * general safety checks.
+ */
+static const bool config_opt_size_checks =
+#if defined(JEMALLOC_OPT_SIZE_CHECKS) || defined(JEMALLOC_DEBUG)
+ true
+#else
+ false
+#endif
+ ;
+
+static const bool config_uaf_detection =
+#if defined(JEMALLOC_UAF_DETECTION) || defined(JEMALLOC_DEBUG)
+ true
+#else
+ false
+#endif
+ ;
+
+/* Whether or not the C++ extensions are enabled. */
+static const bool config_enable_cxx =
+#ifdef JEMALLOC_ENABLE_CXX
+ true
+#else
+ false
+#endif
+;
+
#if defined(_WIN32) || defined(JEMALLOC_HAVE_SCHED_GETCPU)
/* Currently percpu_arena depends on sched_getcpu. */
#define JEMALLOC_PERCPU_ARENA
@@ -206,5 +243,20 @@ static const bool have_background_thread =
false
#endif
;
+static const bool config_high_res_timer =
+#ifdef JEMALLOC_HAVE_CLOCK_REALTIME
+ true
+#else
+ false
+#endif
+ ;
+
+static const bool have_memcntl =
+#ifdef JEMALLOC_HAVE_MEMCNTL
+ true
+#else
+ false
+#endif
+ ;
#endif /* JEMALLOC_PREAMBLE_H */
diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h
index a448ad63fa54..08ce9219cbf8 100644
--- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h
+++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h
@@ -5,10 +5,9 @@
#define arena_init JEMALLOC_N(arena_init)
#define arena_migrate JEMALLOC_N(arena_migrate)
#define arena_set JEMALLOC_N(arena_set)
-#define arena_tdata_get_hard JEMALLOC_N(arena_tdata_get_hard)
#define arenas JEMALLOC_N(arenas)
#define arenas_lock JEMALLOC_N(arenas_lock)
-#define arenas_tdata_cleanup JEMALLOC_N(arenas_tdata_cleanup)
+#define batch_alloc JEMALLOC_N(batch_alloc)
#define bootstrap_calloc JEMALLOC_N(bootstrap_calloc)
#define bootstrap_free JEMALLOC_N(bootstrap_free)
#define bootstrap_malloc JEMALLOC_N(bootstrap_malloc)
@@ -16,8 +15,10 @@
#define iarena_cleanup JEMALLOC_N(iarena_cleanup)
#define je_sdallocx_noflags JEMALLOC_N(je_sdallocx_noflags)
#define jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child)
+#define junk_alloc_callback JEMALLOC_N(junk_alloc_callback)
+#define junk_free_callback JEMALLOC_N(junk_free_callback)
#define malloc_default JEMALLOC_N(malloc_default)
-#define malloc_initialized JEMALLOC_N(malloc_initialized)
+#define malloc_init_state JEMALLOC_N(malloc_init_state)
#define malloc_slow JEMALLOC_N(malloc_slow)
#define manual_arena_base JEMALLOC_N(manual_arena_base)
#define narenas_auto JEMALLOC_N(narenas_auto)
@@ -25,49 +26,64 @@
#define ncpus JEMALLOC_N(ncpus)
#define opt_abort JEMALLOC_N(opt_abort)
#define opt_abort_conf JEMALLOC_N(opt_abort_conf)
+#define opt_cache_oblivious JEMALLOC_N(opt_cache_oblivious)
#define opt_confirm_conf JEMALLOC_N(opt_confirm_conf)
+#define opt_experimental_infallible_new JEMALLOC_N(opt_experimental_infallible_new)
+#define opt_hpa JEMALLOC_N(opt_hpa)
+#define opt_hpa_opts JEMALLOC_N(opt_hpa_opts)
+#define opt_hpa_sec_opts JEMALLOC_N(opt_hpa_sec_opts)
#define opt_junk JEMALLOC_N(opt_junk)
#define opt_junk_alloc JEMALLOC_N(opt_junk_alloc)
#define opt_junk_free JEMALLOC_N(opt_junk_free)
#define opt_narenas JEMALLOC_N(opt_narenas)
+#define opt_narenas_ratio JEMALLOC_N(opt_narenas_ratio)
+#define opt_trust_madvise JEMALLOC_N(opt_trust_madvise)
#define opt_utrace JEMALLOC_N(opt_utrace)
#define opt_xmalloc JEMALLOC_N(opt_xmalloc)
#define opt_zero JEMALLOC_N(opt_zero)
+#define opt_zero_realloc_action JEMALLOC_N(opt_zero_realloc_action)
#define sdallocx_default JEMALLOC_N(sdallocx_default)
-#define arena_alloc_junk_small JEMALLOC_N(arena_alloc_junk_small)
+#define zero_realloc_count JEMALLOC_N(zero_realloc_count)
+#define zero_realloc_mode_names JEMALLOC_N(zero_realloc_mode_names)
#define arena_basic_stats_merge JEMALLOC_N(arena_basic_stats_merge)
-#define arena_bin_choose_lock JEMALLOC_N(arena_bin_choose_lock)
+#define arena_bin_choose JEMALLOC_N(arena_bin_choose)
+#define arena_bin_offsets JEMALLOC_N(arena_bin_offsets)
+#define arena_binind_div_info JEMALLOC_N(arena_binind_div_info)
#define arena_boot JEMALLOC_N(arena_boot)
+#define arena_cache_bin_fill_small JEMALLOC_N(arena_cache_bin_fill_small)
#define arena_choose_huge JEMALLOC_N(arena_choose_huge)
-#define arena_dalloc_bin_junked_locked JEMALLOC_N(arena_dalloc_bin_junked_locked)
-#define arena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small)
+#define arena_config_default JEMALLOC_N(arena_config_default)
+#define arena_dalloc_bin_locked_handle_newly_empty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_empty)
+#define arena_dalloc_bin_locked_handle_newly_nonempty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_nonempty)
#define arena_dalloc_promoted JEMALLOC_N(arena_dalloc_promoted)
#define arena_dalloc_small JEMALLOC_N(arena_dalloc_small)
#define arena_decay JEMALLOC_N(arena_decay)
+#define arena_decay_ms_get JEMALLOC_N(arena_decay_ms_get)
+#define arena_decay_ms_set JEMALLOC_N(arena_decay_ms_set)
#define arena_destroy JEMALLOC_N(arena_destroy)
#define arena_dirty_decay_ms_default_get JEMALLOC_N(arena_dirty_decay_ms_default_get)
#define arena_dirty_decay_ms_default_set JEMALLOC_N(arena_dirty_decay_ms_default_set)
-#define arena_dirty_decay_ms_get JEMALLOC_N(arena_dirty_decay_ms_get)
-#define arena_dirty_decay_ms_set JEMALLOC_N(arena_dirty_decay_ms_set)
+#define arena_do_deferred_work JEMALLOC_N(arena_do_deferred_work)
#define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get)
#define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set)
+#define arena_emap_global JEMALLOC_N(arena_emap_global)
#define arena_extent_alloc_large JEMALLOC_N(arena_extent_alloc_large)
#define arena_extent_dalloc_large_prep JEMALLOC_N(arena_extent_dalloc_large_prep)
#define arena_extent_ralloc_large_expand JEMALLOC_N(arena_extent_ralloc_large_expand)
#define arena_extent_ralloc_large_shrink JEMALLOC_N(arena_extent_ralloc_large_shrink)
-#define arena_extent_sn_next JEMALLOC_N(arena_extent_sn_next)
-#define arena_extents_dirty_dalloc JEMALLOC_N(arena_extents_dirty_dalloc)
+#define arena_fill_small_fresh JEMALLOC_N(arena_fill_small_fresh)
+#define arena_get_ehooks JEMALLOC_N(arena_get_ehooks)
+#define arena_handle_deferred_work JEMALLOC_N(arena_handle_deferred_work)
#define arena_init_huge JEMALLOC_N(arena_init_huge)
#define arena_is_huge JEMALLOC_N(arena_is_huge)
#define arena_malloc_hard JEMALLOC_N(arena_malloc_hard)
#define arena_muzzy_decay_ms_default_get JEMALLOC_N(arena_muzzy_decay_ms_default_get)
#define arena_muzzy_decay_ms_default_set JEMALLOC_N(arena_muzzy_decay_ms_default_set)
-#define arena_muzzy_decay_ms_get JEMALLOC_N(arena_muzzy_decay_ms_get)
-#define arena_muzzy_decay_ms_set JEMALLOC_N(arena_muzzy_decay_ms_set)
#define arena_new JEMALLOC_N(arena_new)
#define arena_nthreads_dec JEMALLOC_N(arena_nthreads_dec)
#define arena_nthreads_get JEMALLOC_N(arena_nthreads_get)
#define arena_nthreads_inc JEMALLOC_N(arena_nthreads_inc)
+#define arena_pa_central_global JEMALLOC_N(arena_pa_central_global)
#define arena_palloc JEMALLOC_N(arena_palloc)
#define arena_postfork_child JEMALLOC_N(arena_postfork_child)
#define arena_postfork_parent JEMALLOC_N(arena_postfork_parent)
@@ -79,14 +95,15 @@
#define arena_prefork5 JEMALLOC_N(arena_prefork5)
#define arena_prefork6 JEMALLOC_N(arena_prefork6)
#define arena_prefork7 JEMALLOC_N(arena_prefork7)
+#define arena_prefork8 JEMALLOC_N(arena_prefork8)
#define arena_prof_promote JEMALLOC_N(arena_prof_promote)
#define arena_ralloc JEMALLOC_N(arena_ralloc)
#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move)
#define arena_reset JEMALLOC_N(arena_reset)
#define arena_retain_grow_limit_get_set JEMALLOC_N(arena_retain_grow_limit_get_set)
+#define arena_set_extent_hooks JEMALLOC_N(arena_set_extent_hooks)
+#define arena_slab_dalloc JEMALLOC_N(arena_slab_dalloc)
#define arena_stats_merge JEMALLOC_N(arena_stats_merge)
-#define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small)
-#define h_steps JEMALLOC_N(h_steps)
#define opt_dirty_decay_ms JEMALLOC_N(opt_dirty_decay_ms)
#define opt_muzzy_decay_ms JEMALLOC_N(opt_muzzy_decay_ms)
#define opt_oversize_threshold JEMALLOC_N(opt_oversize_threshold)
@@ -99,13 +116,14 @@
#define background_thread_ctl_init JEMALLOC_N(background_thread_ctl_init)
#define background_thread_enabled_state JEMALLOC_N(background_thread_enabled_state)
#define background_thread_info JEMALLOC_N(background_thread_info)
-#define background_thread_interval_check JEMALLOC_N(background_thread_interval_check)
+#define background_thread_is_started JEMALLOC_N(background_thread_is_started)
#define background_thread_lock JEMALLOC_N(background_thread_lock)
#define background_thread_postfork_child JEMALLOC_N(background_thread_postfork_child)
#define background_thread_postfork_parent JEMALLOC_N(background_thread_postfork_parent)
#define background_thread_prefork0 JEMALLOC_N(background_thread_prefork0)
#define background_thread_prefork1 JEMALLOC_N(background_thread_prefork1)
#define background_thread_stats_read JEMALLOC_N(background_thread_stats_read)
+#define background_thread_wakeup_early JEMALLOC_N(background_thread_wakeup_early)
#define background_threads_disable JEMALLOC_N(background_threads_disable)
#define background_threads_enable JEMALLOC_N(background_threads_enable)
#define max_background_threads JEMALLOC_N(max_background_threads)
@@ -115,10 +133,11 @@
#define pthread_create_wrapper JEMALLOC_N(pthread_create_wrapper)
#define b0get JEMALLOC_N(b0get)
#define base_alloc JEMALLOC_N(base_alloc)
-#define base_alloc_extent JEMALLOC_N(base_alloc_extent)
+#define base_alloc_edata JEMALLOC_N(base_alloc_edata)
#define base_boot JEMALLOC_N(base_boot)
#define base_delete JEMALLOC_N(base_delete)
-#define base_extent_hooks_get JEMALLOC_N(base_extent_hooks_get)
+#define base_ehooks_get JEMALLOC_N(base_ehooks_get)
+#define base_ehooks_get_for_metadata JEMALLOC_N(base_ehooks_get_for_metadata)
#define base_extent_hooks_set JEMALLOC_N(base_extent_hooks_set)
#define base_new JEMALLOC_N(base_new)
#define base_postfork_child JEMALLOC_N(base_postfork_child)
@@ -127,17 +146,28 @@
#define base_stats_get JEMALLOC_N(base_stats_get)
#define metadata_thp_mode_names JEMALLOC_N(metadata_thp_mode_names)
#define opt_metadata_thp JEMALLOC_N(opt_metadata_thp)
-#define bin_boot JEMALLOC_N(bin_boot)
-#define bin_infos JEMALLOC_N(bin_infos)
#define bin_init JEMALLOC_N(bin_init)
#define bin_postfork_child JEMALLOC_N(bin_postfork_child)
#define bin_postfork_parent JEMALLOC_N(bin_postfork_parent)
#define bin_prefork JEMALLOC_N(bin_prefork)
#define bin_shard_sizes_boot JEMALLOC_N(bin_shard_sizes_boot)
#define bin_update_shard_size JEMALLOC_N(bin_update_shard_size)
+#define bin_info_boot JEMALLOC_N(bin_info_boot)
+#define bin_infos JEMALLOC_N(bin_infos)
#define bitmap_info_init JEMALLOC_N(bitmap_info_init)
#define bitmap_init JEMALLOC_N(bitmap_init)
#define bitmap_size JEMALLOC_N(bitmap_size)
+#define buf_writer_cb JEMALLOC_N(buf_writer_cb)
+#define buf_writer_flush JEMALLOC_N(buf_writer_flush)
+#define buf_writer_init JEMALLOC_N(buf_writer_init)
+#define buf_writer_pipe JEMALLOC_N(buf_writer_pipe)
+#define buf_writer_terminate JEMALLOC_N(buf_writer_terminate)
+#define cache_bin_info_compute_alloc JEMALLOC_N(cache_bin_info_compute_alloc)
+#define cache_bin_info_init JEMALLOC_N(cache_bin_info_init)
+#define cache_bin_init JEMALLOC_N(cache_bin_init)
+#define cache_bin_postincrement JEMALLOC_N(cache_bin_postincrement)
+#define cache_bin_preincrement JEMALLOC_N(cache_bin_preincrement)
+#define cache_bin_still_zero_initialized JEMALLOC_N(cache_bin_still_zero_initialized)
#define ckh_count JEMALLOC_N(ckh_count)
#define ckh_delete JEMALLOC_N(ckh_delete)
#define ckh_insert JEMALLOC_N(ckh_insert)
@@ -149,61 +179,116 @@
#define ckh_search JEMALLOC_N(ckh_search)
#define ckh_string_hash JEMALLOC_N(ckh_string_hash)
#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp)
+#define counter_accum_init JEMALLOC_N(counter_accum_init)
+#define counter_postfork_child JEMALLOC_N(counter_postfork_child)
+#define counter_postfork_parent JEMALLOC_N(counter_postfork_parent)
+#define counter_prefork JEMALLOC_N(counter_prefork)
#define ctl_boot JEMALLOC_N(ctl_boot)
#define ctl_bymib JEMALLOC_N(ctl_bymib)
+#define ctl_bymibname JEMALLOC_N(ctl_bymibname)
#define ctl_byname JEMALLOC_N(ctl_byname)
+#define ctl_mibnametomib JEMALLOC_N(ctl_mibnametomib)
+#define ctl_mtx_assert_held JEMALLOC_N(ctl_mtx_assert_held)
#define ctl_nametomib JEMALLOC_N(ctl_nametomib)
#define ctl_postfork_child JEMALLOC_N(ctl_postfork_child)
#define ctl_postfork_parent JEMALLOC_N(ctl_postfork_parent)
#define ctl_prefork JEMALLOC_N(ctl_prefork)
+#define decay_deadline_init JEMALLOC_N(decay_deadline_init)
+#define decay_init JEMALLOC_N(decay_init)
+#define decay_maybe_advance_epoch JEMALLOC_N(decay_maybe_advance_epoch)
+#define decay_ms_valid JEMALLOC_N(decay_ms_valid)
+#define decay_npages_purge_in JEMALLOC_N(decay_npages_purge_in)
+#define decay_ns_until_purge JEMALLOC_N(decay_ns_until_purge)
+#define decay_reinit JEMALLOC_N(decay_reinit)
#define div_init JEMALLOC_N(div_init)
-#define extent_alloc JEMALLOC_N(extent_alloc)
+#define ecache_init JEMALLOC_N(ecache_init)
+#define ecache_postfork_child JEMALLOC_N(ecache_postfork_child)
+#define ecache_postfork_parent JEMALLOC_N(ecache_postfork_parent)
+#define ecache_prefork JEMALLOC_N(ecache_prefork)
+#define edata_avail_any JEMALLOC_N(edata_avail_any)
+#define edata_avail_empty JEMALLOC_N(edata_avail_empty)
+#define edata_avail_first JEMALLOC_N(edata_avail_first)
+#define edata_avail_insert JEMALLOC_N(edata_avail_insert)
+#define edata_avail_new JEMALLOC_N(edata_avail_new)
+#define edata_avail_remove JEMALLOC_N(edata_avail_remove)
+#define edata_avail_remove_any JEMALLOC_N(edata_avail_remove_any)
+#define edata_avail_remove_first JEMALLOC_N(edata_avail_remove_first)
+#define edata_heap_any JEMALLOC_N(edata_heap_any)
+#define edata_heap_empty JEMALLOC_N(edata_heap_empty)
+#define edata_heap_first JEMALLOC_N(edata_heap_first)
+#define edata_heap_insert JEMALLOC_N(edata_heap_insert)
+#define edata_heap_new JEMALLOC_N(edata_heap_new)
+#define edata_heap_remove JEMALLOC_N(edata_heap_remove)
+#define edata_heap_remove_any JEMALLOC_N(edata_heap_remove_any)
+#define edata_heap_remove_first JEMALLOC_N(edata_heap_remove_first)
+#define edata_cache_fast_disable JEMALLOC_N(edata_cache_fast_disable)
+#define edata_cache_fast_get JEMALLOC_N(edata_cache_fast_get)
+#define edata_cache_fast_init JEMALLOC_N(edata_cache_fast_init)
+#define edata_cache_fast_put JEMALLOC_N(edata_cache_fast_put)
+#define edata_cache_get JEMALLOC_N(edata_cache_get)
+#define edata_cache_init JEMALLOC_N(edata_cache_init)
+#define edata_cache_postfork_child JEMALLOC_N(edata_cache_postfork_child)
+#define edata_cache_postfork_parent JEMALLOC_N(edata_cache_postfork_parent)
+#define edata_cache_prefork JEMALLOC_N(edata_cache_prefork)
+#define edata_cache_put JEMALLOC_N(edata_cache_put)
+#define ehooks_default_alloc_impl JEMALLOC_N(ehooks_default_alloc_impl)
+#define ehooks_default_commit_impl JEMALLOC_N(ehooks_default_commit_impl)
+#define ehooks_default_dalloc_impl JEMALLOC_N(ehooks_default_dalloc_impl)
+#define ehooks_default_decommit_impl JEMALLOC_N(ehooks_default_decommit_impl)
+#define ehooks_default_destroy_impl JEMALLOC_N(ehooks_default_destroy_impl)
+#define ehooks_default_extent_hooks JEMALLOC_N(ehooks_default_extent_hooks)
+#define ehooks_default_guard_impl JEMALLOC_N(ehooks_default_guard_impl)
+#define ehooks_default_merge JEMALLOC_N(ehooks_default_merge)
+#define ehooks_default_merge_impl JEMALLOC_N(ehooks_default_merge_impl)
+#define ehooks_default_purge_forced_impl JEMALLOC_N(ehooks_default_purge_forced_impl)
+#define ehooks_default_purge_lazy_impl JEMALLOC_N(ehooks_default_purge_lazy_impl)
+#define ehooks_default_split_impl JEMALLOC_N(ehooks_default_split_impl)
+#define ehooks_default_unguard_impl JEMALLOC_N(ehooks_default_unguard_impl)
+#define ehooks_default_zero_impl JEMALLOC_N(ehooks_default_zero_impl)
+#define ehooks_init JEMALLOC_N(ehooks_init)
+#define emap_deregister_boundary JEMALLOC_N(emap_deregister_boundary)
+#define emap_deregister_interior JEMALLOC_N(emap_deregister_interior)
+#define emap_do_assert_mapped JEMALLOC_N(emap_do_assert_mapped)
+#define emap_do_assert_not_mapped JEMALLOC_N(emap_do_assert_not_mapped)
+#define emap_init JEMALLOC_N(emap_init)
+#define emap_merge_commit JEMALLOC_N(emap_merge_commit)
+#define emap_merge_prepare JEMALLOC_N(emap_merge_prepare)
+#define emap_register_boundary JEMALLOC_N(emap_register_boundary)
+#define emap_register_interior JEMALLOC_N(emap_register_interior)
+#define emap_release_edata JEMALLOC_N(emap_release_edata)
+#define emap_remap JEMALLOC_N(emap_remap)
+#define emap_split_commit JEMALLOC_N(emap_split_commit)
+#define emap_split_prepare JEMALLOC_N(emap_split_prepare)
+#define emap_try_acquire_edata_neighbor JEMALLOC_N(emap_try_acquire_edata_neighbor)
+#define emap_try_acquire_edata_neighbor_expand JEMALLOC_N(emap_try_acquire_edata_neighbor_expand)
+#define emap_update_edata_state JEMALLOC_N(emap_update_edata_state)
+#define eset_fit JEMALLOC_N(eset_fit)
+#define eset_init JEMALLOC_N(eset_init)
+#define eset_insert JEMALLOC_N(eset_insert)
+#define eset_nbytes_get JEMALLOC_N(eset_nbytes_get)
+#define eset_nextents_get JEMALLOC_N(eset_nextents_get)
+#define eset_npages_get JEMALLOC_N(eset_npages_get)
+#define eset_remove JEMALLOC_N(eset_remove)
+#define exp_grow_init JEMALLOC_N(exp_grow_init)
+#define ecache_alloc JEMALLOC_N(ecache_alloc)
+#define ecache_alloc_grow JEMALLOC_N(ecache_alloc_grow)
+#define ecache_dalloc JEMALLOC_N(ecache_dalloc)
+#define ecache_evict JEMALLOC_N(ecache_evict)
#define extent_alloc_wrapper JEMALLOC_N(extent_alloc_wrapper)
-#define extent_avail_any JEMALLOC_N(extent_avail_any)
-#define extent_avail_empty JEMALLOC_N(extent_avail_empty)
-#define extent_avail_first JEMALLOC_N(extent_avail_first)
-#define extent_avail_insert JEMALLOC_N(extent_avail_insert)
-#define extent_avail_new JEMALLOC_N(extent_avail_new)
-#define extent_avail_remove JEMALLOC_N(extent_avail_remove)
-#define extent_avail_remove_any JEMALLOC_N(extent_avail_remove_any)
-#define extent_avail_remove_first JEMALLOC_N(extent_avail_remove_first)
#define extent_boot JEMALLOC_N(extent_boot)
#define extent_commit_wrapper JEMALLOC_N(extent_commit_wrapper)
-#define extent_dalloc JEMALLOC_N(extent_dalloc)
+#define extent_commit_zero JEMALLOC_N(extent_commit_zero)
#define extent_dalloc_gap JEMALLOC_N(extent_dalloc_gap)
#define extent_dalloc_wrapper JEMALLOC_N(extent_dalloc_wrapper)
#define extent_decommit_wrapper JEMALLOC_N(extent_decommit_wrapper)
#define extent_destroy_wrapper JEMALLOC_N(extent_destroy_wrapper)
-#define extent_heap_any JEMALLOC_N(extent_heap_any)
-#define extent_heap_empty JEMALLOC_N(extent_heap_empty)
-#define extent_heap_first JEMALLOC_N(extent_heap_first)
-#define extent_heap_insert JEMALLOC_N(extent_heap_insert)
-#define extent_heap_new JEMALLOC_N(extent_heap_new)
-#define extent_heap_remove JEMALLOC_N(extent_heap_remove)
-#define extent_heap_remove_any JEMALLOC_N(extent_heap_remove_any)
-#define extent_heap_remove_first JEMALLOC_N(extent_heap_remove_first)
-#define extent_hooks_default JEMALLOC_N(extent_hooks_default)
-#define extent_hooks_get JEMALLOC_N(extent_hooks_get)
-#define extent_hooks_set JEMALLOC_N(extent_hooks_set)
+#define extent_gdump_add JEMALLOC_N(extent_gdump_add)
#define extent_merge_wrapper JEMALLOC_N(extent_merge_wrapper)
-#define extent_mutex_pool JEMALLOC_N(extent_mutex_pool)
#define extent_purge_forced_wrapper JEMALLOC_N(extent_purge_forced_wrapper)
#define extent_purge_lazy_wrapper JEMALLOC_N(extent_purge_lazy_wrapper)
+#define extent_record JEMALLOC_N(extent_record)
+#define extent_sn_next JEMALLOC_N(extent_sn_next)
#define extent_split_wrapper JEMALLOC_N(extent_split_wrapper)
-#define extent_util_stats_get JEMALLOC_N(extent_util_stats_get)
-#define extent_util_stats_verbose_get JEMALLOC_N(extent_util_stats_verbose_get)
-#define extents_alloc JEMALLOC_N(extents_alloc)
-#define extents_dalloc JEMALLOC_N(extents_dalloc)
-#define extents_evict JEMALLOC_N(extents_evict)
-#define extents_init JEMALLOC_N(extents_init)
-#define extents_nbytes_get JEMALLOC_N(extents_nbytes_get)
-#define extents_nextents_get JEMALLOC_N(extents_nextents_get)
-#define extents_npages_get JEMALLOC_N(extents_npages_get)
-#define extents_postfork_child JEMALLOC_N(extents_postfork_child)
-#define extents_postfork_parent JEMALLOC_N(extents_postfork_parent)
-#define extents_prefork JEMALLOC_N(extents_prefork)
-#define extents_rtree JEMALLOC_N(extents_rtree)
-#define extents_state_get JEMALLOC_N(extents_state_get)
#define opt_lg_extent_max_active_fit JEMALLOC_N(opt_lg_extent_max_active_fit)
#define dss_prec_names JEMALLOC_N(dss_prec_names)
#define extent_alloc_dss JEMALLOC_N(extent_alloc_dss)
@@ -216,24 +301,66 @@
#define extent_alloc_mmap JEMALLOC_N(extent_alloc_mmap)
#define extent_dalloc_mmap JEMALLOC_N(extent_dalloc_mmap)
#define opt_retain JEMALLOC_N(opt_retain)
+#define fxp_parse JEMALLOC_N(fxp_parse)
+#define fxp_print JEMALLOC_N(fxp_print)
+#define opt_lg_san_uaf_align JEMALLOC_N(opt_lg_san_uaf_align)
+#define opt_san_guard_large JEMALLOC_N(opt_san_guard_large)
+#define opt_san_guard_small JEMALLOC_N(opt_san_guard_small)
+#define san_cache_bin_nonfast_mask JEMALLOC_N(san_cache_bin_nonfast_mask)
+#define san_check_stashed_ptrs JEMALLOC_N(san_check_stashed_ptrs)
+#define san_guard_pages JEMALLOC_N(san_guard_pages)
+#define san_init JEMALLOC_N(san_init)
+#define san_unguard_pages JEMALLOC_N(san_unguard_pages)
+#define san_unguard_pages_pre_destroy JEMALLOC_N(san_unguard_pages_pre_destroy)
+#define tsd_san_init JEMALLOC_N(tsd_san_init)
+#define san_bump_alloc JEMALLOC_N(san_bump_alloc)
#define hook_boot JEMALLOC_N(hook_boot)
#define hook_install JEMALLOC_N(hook_install)
#define hook_invoke_alloc JEMALLOC_N(hook_invoke_alloc)
#define hook_invoke_dalloc JEMALLOC_N(hook_invoke_dalloc)
#define hook_invoke_expand JEMALLOC_N(hook_invoke_expand)
#define hook_remove JEMALLOC_N(hook_remove)
+#define hpa_central_extract JEMALLOC_N(hpa_central_extract)
+#define hpa_central_init JEMALLOC_N(hpa_central_init)
+#define hpa_shard_destroy JEMALLOC_N(hpa_shard_destroy)
+#define hpa_shard_disable JEMALLOC_N(hpa_shard_disable)
+#define hpa_shard_do_deferred_work JEMALLOC_N(hpa_shard_do_deferred_work)
+#define hpa_shard_init JEMALLOC_N(hpa_shard_init)
+#define hpa_shard_postfork_child JEMALLOC_N(hpa_shard_postfork_child)
+#define hpa_shard_postfork_parent JEMALLOC_N(hpa_shard_postfork_parent)
+#define hpa_shard_prefork3 JEMALLOC_N(hpa_shard_prefork3)
+#define hpa_shard_prefork4 JEMALLOC_N(hpa_shard_prefork4)
+#define hpa_shard_set_deferral_allowed JEMALLOC_N(hpa_shard_set_deferral_allowed)
+#define hpa_shard_stats_accum JEMALLOC_N(hpa_shard_stats_accum)
+#define hpa_shard_stats_merge JEMALLOC_N(hpa_shard_stats_merge)
+#define hpa_supported JEMALLOC_N(hpa_supported)
+#define hpa_hooks_default JEMALLOC_N(hpa_hooks_default)
+#define hpdata_age_heap_any JEMALLOC_N(hpdata_age_heap_any)
+#define hpdata_age_heap_empty JEMALLOC_N(hpdata_age_heap_empty)
+#define hpdata_age_heap_first JEMALLOC_N(hpdata_age_heap_first)
+#define hpdata_age_heap_insert JEMALLOC_N(hpdata_age_heap_insert)
+#define hpdata_age_heap_new JEMALLOC_N(hpdata_age_heap_new)
+#define hpdata_age_heap_remove JEMALLOC_N(hpdata_age_heap_remove)
+#define hpdata_age_heap_remove_any JEMALLOC_N(hpdata_age_heap_remove_any)
+#define hpdata_age_heap_remove_first JEMALLOC_N(hpdata_age_heap_remove_first)
+#define hpdata_dehugify JEMALLOC_N(hpdata_dehugify)
+#define hpdata_hugify JEMALLOC_N(hpdata_hugify)
+#define hpdata_init JEMALLOC_N(hpdata_init)
+#define hpdata_purge_begin JEMALLOC_N(hpdata_purge_begin)
+#define hpdata_purge_end JEMALLOC_N(hpdata_purge_end)
+#define hpdata_purge_next JEMALLOC_N(hpdata_purge_next)
+#define hpdata_reserve_alloc JEMALLOC_N(hpdata_reserve_alloc)
+#define hpdata_unreserve JEMALLOC_N(hpdata_unreserve)
+#define inspect_extent_util_stats_get JEMALLOC_N(inspect_extent_util_stats_get)
+#define inspect_extent_util_stats_verbose_get JEMALLOC_N(inspect_extent_util_stats_verbose_get)
#define large_dalloc JEMALLOC_N(large_dalloc)
#define large_dalloc_finish JEMALLOC_N(large_dalloc_finish)
-#define large_dalloc_junk JEMALLOC_N(large_dalloc_junk)
-#define large_dalloc_maybe_junk JEMALLOC_N(large_dalloc_maybe_junk)
-#define large_dalloc_prep_junked_locked JEMALLOC_N(large_dalloc_prep_junked_locked)
+#define large_dalloc_prep_locked JEMALLOC_N(large_dalloc_prep_locked)
#define large_malloc JEMALLOC_N(large_malloc)
#define large_palloc JEMALLOC_N(large_palloc)
-#define large_prof_alloc_time_get JEMALLOC_N(large_prof_alloc_time_get)
-#define large_prof_alloc_time_set JEMALLOC_N(large_prof_alloc_time_set)
-#define large_prof_tctx_get JEMALLOC_N(large_prof_tctx_get)
+#define large_prof_info_get JEMALLOC_N(large_prof_info_get)
+#define large_prof_info_set JEMALLOC_N(large_prof_info_set)
#define large_prof_tctx_reset JEMALLOC_N(large_prof_tctx_reset)
-#define large_prof_tctx_set JEMALLOC_N(large_prof_tctx_set)
#define large_ralloc JEMALLOC_N(large_ralloc)
#define large_ralloc_no_move JEMALLOC_N(large_ralloc_no_move)
#define large_salloc JEMALLOC_N(large_salloc)
@@ -248,14 +375,17 @@
#define malloc_vcprintf JEMALLOC_N(malloc_vcprintf)
#define malloc_vsnprintf JEMALLOC_N(malloc_vsnprintf)
#define malloc_write JEMALLOC_N(malloc_write)
+#define wrtmessage JEMALLOC_N(wrtmessage)
+#define wrtmessage_1_0 JEMALLOC_N(wrtmessage_1_0)
#define malloc_mutex_boot JEMALLOC_N(malloc_mutex_boot)
+#define malloc_mutex_first_thread JEMALLOC_N(malloc_mutex_first_thread)
#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init)
#define malloc_mutex_lock_slow JEMALLOC_N(malloc_mutex_lock_slow)
#define malloc_mutex_postfork_child JEMALLOC_N(malloc_mutex_postfork_child)
#define malloc_mutex_postfork_parent JEMALLOC_N(malloc_mutex_postfork_parent)
#define malloc_mutex_prefork JEMALLOC_N(malloc_mutex_prefork)
#define malloc_mutex_prof_data_reset JEMALLOC_N(malloc_mutex_prof_data_reset)
-#define mutex_pool_init JEMALLOC_N(mutex_pool_init)
+#define opt_mutex_max_spin JEMALLOC_N(opt_mutex_max_spin)
#define nstime_add JEMALLOC_N(nstime_add)
#define nstime_compare JEMALLOC_N(nstime_compare)
#define nstime_copy JEMALLOC_N(nstime_copy)
@@ -265,14 +395,56 @@
#define nstime_imultiply JEMALLOC_N(nstime_imultiply)
#define nstime_init JEMALLOC_N(nstime_init)
#define nstime_init2 JEMALLOC_N(nstime_init2)
+#define nstime_init_update JEMALLOC_N(nstime_init_update)
#define nstime_isubtract JEMALLOC_N(nstime_isubtract)
#define nstime_monotonic JEMALLOC_N(nstime_monotonic)
#define nstime_msec JEMALLOC_N(nstime_msec)
#define nstime_ns JEMALLOC_N(nstime_ns)
+#define nstime_ns_since JEMALLOC_N(nstime_ns_since)
#define nstime_nsec JEMALLOC_N(nstime_nsec)
+#define nstime_prof_init_update JEMALLOC_N(nstime_prof_init_update)
+#define nstime_prof_update JEMALLOC_N(nstime_prof_update)
#define nstime_sec JEMALLOC_N(nstime_sec)
#define nstime_subtract JEMALLOC_N(nstime_subtract)
#define nstime_update JEMALLOC_N(nstime_update)
+#define opt_prof_time_res JEMALLOC_N(opt_prof_time_res)
+#define prof_time_res_mode_names JEMALLOC_N(prof_time_res_mode_names)
+#define pa_alloc JEMALLOC_N(pa_alloc)
+#define pa_central_init JEMALLOC_N(pa_central_init)
+#define pa_dalloc JEMALLOC_N(pa_dalloc)
+#define pa_decay_ms_get JEMALLOC_N(pa_decay_ms_get)
+#define pa_decay_ms_set JEMALLOC_N(pa_decay_ms_set)
+#define pa_expand JEMALLOC_N(pa_expand)
+#define pa_shard_destroy JEMALLOC_N(pa_shard_destroy)
+#define pa_shard_disable_hpa JEMALLOC_N(pa_shard_disable_hpa)
+#define pa_shard_do_deferred_work JEMALLOC_N(pa_shard_do_deferred_work)
+#define pa_shard_enable_hpa JEMALLOC_N(pa_shard_enable_hpa)
+#define pa_shard_init JEMALLOC_N(pa_shard_init)
+#define pa_shard_reset JEMALLOC_N(pa_shard_reset)
+#define pa_shard_retain_grow_limit_get_set JEMALLOC_N(pa_shard_retain_grow_limit_get_set)
+#define pa_shard_set_deferral_allowed JEMALLOC_N(pa_shard_set_deferral_allowed)
+#define pa_shard_time_until_deferred_work JEMALLOC_N(pa_shard_time_until_deferred_work)
+#define pa_shrink JEMALLOC_N(pa_shrink)
+#define pa_shard_basic_stats_merge JEMALLOC_N(pa_shard_basic_stats_merge)
+#define pa_shard_mtx_stats_read JEMALLOC_N(pa_shard_mtx_stats_read)
+#define pa_shard_postfork_child JEMALLOC_N(pa_shard_postfork_child)
+#define pa_shard_postfork_parent JEMALLOC_N(pa_shard_postfork_parent)
+#define pa_shard_prefork0 JEMALLOC_N(pa_shard_prefork0)
+#define pa_shard_prefork2 JEMALLOC_N(pa_shard_prefork2)
+#define pa_shard_prefork3 JEMALLOC_N(pa_shard_prefork3)
+#define pa_shard_prefork4 JEMALLOC_N(pa_shard_prefork4)
+#define pa_shard_prefork5 JEMALLOC_N(pa_shard_prefork5)
+#define pa_shard_stats_merge JEMALLOC_N(pa_shard_stats_merge)
+#define pai_alloc_batch_default JEMALLOC_N(pai_alloc_batch_default)
+#define pai_dalloc_batch_default JEMALLOC_N(pai_dalloc_batch_default)
+#define pac_decay_all JEMALLOC_N(pac_decay_all)
+#define pac_decay_ms_get JEMALLOC_N(pac_decay_ms_get)
+#define pac_decay_ms_set JEMALLOC_N(pac_decay_ms_set)
+#define pac_destroy JEMALLOC_N(pac_destroy)
+#define pac_init JEMALLOC_N(pac_init)
+#define pac_maybe_decay_purge JEMALLOC_N(pac_maybe_decay_purge)
+#define pac_reset JEMALLOC_N(pac_reset)
+#define pac_retain_grow_limit_get_set JEMALLOC_N(pac_retain_grow_limit_get_set)
#define init_system_thp_mode JEMALLOC_N(init_system_thp_mode)
#define opt_thp JEMALLOC_N(opt_thp)
#define pages_boot JEMALLOC_N(pages_boot)
@@ -282,14 +454,23 @@
#define pages_dontdump JEMALLOC_N(pages_dontdump)
#define pages_huge JEMALLOC_N(pages_huge)
#define pages_map JEMALLOC_N(pages_map)
+#define pages_mark_guards JEMALLOC_N(pages_mark_guards)
#define pages_nohuge JEMALLOC_N(pages_nohuge)
#define pages_purge_forced JEMALLOC_N(pages_purge_forced)
#define pages_purge_lazy JEMALLOC_N(pages_purge_lazy)
#define pages_set_thp_state JEMALLOC_N(pages_set_thp_state)
#define pages_unmap JEMALLOC_N(pages_unmap)
+#define pages_unmark_guards JEMALLOC_N(pages_unmark_guards)
#define thp_mode_names JEMALLOC_N(thp_mode_names)
-#define bt2gctx_mtx JEMALLOC_N(bt2gctx_mtx)
-#define bt_init JEMALLOC_N(bt_init)
+#define peak_alloc_event_handler JEMALLOC_N(peak_alloc_event_handler)
+#define peak_alloc_new_event_wait JEMALLOC_N(peak_alloc_new_event_wait)
+#define peak_alloc_postponed_event_wait JEMALLOC_N(peak_alloc_postponed_event_wait)
+#define peak_dalloc_event_handler JEMALLOC_N(peak_dalloc_event_handler)
+#define peak_dalloc_new_event_wait JEMALLOC_N(peak_dalloc_new_event_wait)
+#define peak_dalloc_postponed_event_wait JEMALLOC_N(peak_dalloc_postponed_event_wait)
+#define peak_event_max JEMALLOC_N(peak_event_max)
+#define peak_event_update JEMALLOC_N(peak_event_update)
+#define peak_event_zero JEMALLOC_N(peak_event_zero)
#define lg_prof_sample JEMALLOC_N(lg_prof_sample)
#define opt_lg_prof_interval JEMALLOC_N(opt_lg_prof_interval)
#define opt_lg_prof_sample JEMALLOC_N(opt_lg_prof_sample)
@@ -299,20 +480,25 @@
#define opt_prof_final JEMALLOC_N(opt_prof_final)
#define opt_prof_gdump JEMALLOC_N(opt_prof_gdump)
#define opt_prof_leak JEMALLOC_N(opt_prof_leak)
-#define opt_prof_log JEMALLOC_N(opt_prof_log)
+#define opt_prof_leak_error JEMALLOC_N(opt_prof_leak_error)
#define opt_prof_prefix JEMALLOC_N(opt_prof_prefix)
+#define opt_prof_sys_thread_name JEMALLOC_N(opt_prof_sys_thread_name)
#define opt_prof_thread_active_init JEMALLOC_N(opt_prof_thread_active_init)
-#define prof_accum_init JEMALLOC_N(prof_accum_init)
-#define prof_active JEMALLOC_N(prof_active)
+#define opt_prof_unbias JEMALLOC_N(opt_prof_unbias)
#define prof_active_get JEMALLOC_N(prof_active_get)
#define prof_active_set JEMALLOC_N(prof_active_set)
+#define prof_active_state JEMALLOC_N(prof_active_state)
#define prof_alloc_rollback JEMALLOC_N(prof_alloc_rollback)
-#define prof_backtrace JEMALLOC_N(prof_backtrace)
+#define prof_backtrace_hook JEMALLOC_N(prof_backtrace_hook)
+#define prof_backtrace_hook_get JEMALLOC_N(prof_backtrace_hook_get)
+#define prof_backtrace_hook_set JEMALLOC_N(prof_backtrace_hook_set)
#define prof_boot0 JEMALLOC_N(prof_boot0)
#define prof_boot1 JEMALLOC_N(prof_boot1)
#define prof_boot2 JEMALLOC_N(prof_boot2)
-#define prof_dump_header JEMALLOC_N(prof_dump_header)
-#define prof_dump_open JEMALLOC_N(prof_dump_open)
+#define prof_booted JEMALLOC_N(prof_booted)
+#define prof_dump_hook JEMALLOC_N(prof_dump_hook)
+#define prof_dump_hook_get JEMALLOC_N(prof_dump_hook_get)
+#define prof_dump_hook_set JEMALLOC_N(prof_dump_hook_set)
#define prof_free_sampled_object JEMALLOC_N(prof_free_sampled_object)
#define prof_gdump JEMALLOC_N(prof_gdump)
#define prof_gdump_get JEMALLOC_N(prof_gdump_get)
@@ -320,18 +506,16 @@
#define prof_gdump_val JEMALLOC_N(prof_gdump_val)
#define prof_idump JEMALLOC_N(prof_idump)
#define prof_interval JEMALLOC_N(prof_interval)
-#define prof_log_start JEMALLOC_N(prof_log_start)
-#define prof_log_stop JEMALLOC_N(prof_log_stop)
-#define prof_logging_state JEMALLOC_N(prof_logging_state)
-#define prof_lookup JEMALLOC_N(prof_lookup)
#define prof_malloc_sample_object JEMALLOC_N(prof_malloc_sample_object)
#define prof_mdump JEMALLOC_N(prof_mdump)
#define prof_postfork_child JEMALLOC_N(prof_postfork_child)
#define prof_postfork_parent JEMALLOC_N(prof_postfork_parent)
#define prof_prefork0 JEMALLOC_N(prof_prefork0)
#define prof_prefork1 JEMALLOC_N(prof_prefork1)
-#define prof_reset JEMALLOC_N(prof_reset)
-#define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update)
+#define prof_sample_event_handler JEMALLOC_N(prof_sample_event_handler)
+#define prof_sample_new_event_wait JEMALLOC_N(prof_sample_new_event_wait)
+#define prof_sample_postponed_event_wait JEMALLOC_N(prof_sample_postponed_event_wait)
+#define prof_tctx_create JEMALLOC_N(prof_tctx_create)
#define prof_tdata_cleanup JEMALLOC_N(prof_tdata_cleanup)
#define prof_tdata_init JEMALLOC_N(prof_tdata_init)
#define prof_tdata_reinit JEMALLOC_N(prof_tdata_reinit)
@@ -341,42 +525,157 @@
#define prof_thread_active_set JEMALLOC_N(prof_thread_active_set)
#define prof_thread_name_get JEMALLOC_N(prof_thread_name_get)
#define prof_thread_name_set JEMALLOC_N(prof_thread_name_set)
+#define bt2gctx_mtx JEMALLOC_N(bt2gctx_mtx)
+#define gctx_locks JEMALLOC_N(gctx_locks)
+#define prof_bt_count JEMALLOC_N(prof_bt_count)
+#define prof_bt_hash JEMALLOC_N(prof_bt_hash)
+#define prof_bt_keycomp JEMALLOC_N(prof_bt_keycomp)
+#define prof_cnt_all JEMALLOC_N(prof_cnt_all)
+#define prof_data_init JEMALLOC_N(prof_data_init)
+#define prof_dump_impl JEMALLOC_N(prof_dump_impl)
+#define prof_dump_mtx JEMALLOC_N(prof_dump_mtx)
+#define prof_lookup JEMALLOC_N(prof_lookup)
+#define prof_reset JEMALLOC_N(prof_reset)
+#define prof_shifted_unbiased_cnt JEMALLOC_N(prof_shifted_unbiased_cnt)
+#define prof_tctx_try_destroy JEMALLOC_N(prof_tctx_try_destroy)
+#define prof_tdata_count JEMALLOC_N(prof_tdata_count)
+#define prof_tdata_detach JEMALLOC_N(prof_tdata_detach)
+#define prof_tdata_init_impl JEMALLOC_N(prof_tdata_init_impl)
+#define prof_thread_name_alloc JEMALLOC_N(prof_thread_name_alloc)
+#define prof_thread_name_set_impl JEMALLOC_N(prof_thread_name_set_impl)
+#define prof_unbias_map_init JEMALLOC_N(prof_unbias_map_init)
+#define prof_unbiased_sz JEMALLOC_N(prof_unbiased_sz)
+#define tdata_locks JEMALLOC_N(tdata_locks)
+#define tdatas_mtx JEMALLOC_N(tdatas_mtx)
+#define log_mtx JEMALLOC_N(log_mtx)
+#define opt_prof_log JEMALLOC_N(opt_prof_log)
+#define prof_log_alloc_count JEMALLOC_N(prof_log_alloc_count)
+#define prof_log_bt_count JEMALLOC_N(prof_log_bt_count)
+#define prof_log_dummy_set JEMALLOC_N(prof_log_dummy_set)
+#define prof_log_init JEMALLOC_N(prof_log_init)
+#define prof_log_is_logging JEMALLOC_N(prof_log_is_logging)
+#define prof_log_rep_check JEMALLOC_N(prof_log_rep_check)
+#define prof_log_start JEMALLOC_N(prof_log_start)
+#define prof_log_stop JEMALLOC_N(prof_log_stop)
+#define prof_log_thr_count JEMALLOC_N(prof_log_thr_count)
+#define prof_logging_state JEMALLOC_N(prof_logging_state)
+#define prof_try_log JEMALLOC_N(prof_try_log)
+#define edata_prof_recent_alloc_get_no_lock_test JEMALLOC_N(edata_prof_recent_alloc_get_no_lock_test)
+#define edata_prof_recent_alloc_init JEMALLOC_N(edata_prof_recent_alloc_init)
+#define opt_prof_recent_alloc_max JEMALLOC_N(opt_prof_recent_alloc_max)
+#define prof_recent_alloc JEMALLOC_N(prof_recent_alloc)
+#define prof_recent_alloc_dump JEMALLOC_N(prof_recent_alloc_dump)
+#define prof_recent_alloc_edata_get_no_lock_test JEMALLOC_N(prof_recent_alloc_edata_get_no_lock_test)
+#define prof_recent_alloc_list JEMALLOC_N(prof_recent_alloc_list)
+#define prof_recent_alloc_max_ctl_read JEMALLOC_N(prof_recent_alloc_max_ctl_read)
+#define prof_recent_alloc_max_ctl_write JEMALLOC_N(prof_recent_alloc_max_ctl_write)
+#define prof_recent_alloc_mtx JEMALLOC_N(prof_recent_alloc_mtx)
+#define prof_recent_alloc_prepare JEMALLOC_N(prof_recent_alloc_prepare)
+#define prof_recent_alloc_reset JEMALLOC_N(prof_recent_alloc_reset)
+#define prof_recent_dump_mtx JEMALLOC_N(prof_recent_dump_mtx)
+#define prof_recent_init JEMALLOC_N(prof_recent_init)
+#define opt_prof_stats JEMALLOC_N(opt_prof_stats)
+#define prof_stats_dec JEMALLOC_N(prof_stats_dec)
+#define prof_stats_get_accum JEMALLOC_N(prof_stats_get_accum)
+#define prof_stats_get_live JEMALLOC_N(prof_stats_get_live)
+#define prof_stats_inc JEMALLOC_N(prof_stats_inc)
+#define prof_stats_mtx JEMALLOC_N(prof_stats_mtx)
+#define bt_init JEMALLOC_N(bt_init)
+#define prof_backtrace JEMALLOC_N(prof_backtrace)
+#define prof_base JEMALLOC_N(prof_base)
+#define prof_do_mock JEMALLOC_N(prof_do_mock)
+#define prof_dump_filename_mtx JEMALLOC_N(prof_dump_filename_mtx)
+#define prof_dump_open_file JEMALLOC_N(prof_dump_open_file)
+#define prof_dump_open_maps JEMALLOC_N(prof_dump_open_maps)
+#define prof_dump_write_file JEMALLOC_N(prof_dump_write_file)
+#define prof_fdump_impl JEMALLOC_N(prof_fdump_impl)
+#define prof_gdump_impl JEMALLOC_N(prof_gdump_impl)
+#define prof_get_default_filename JEMALLOC_N(prof_get_default_filename)
+#define prof_getpid JEMALLOC_N(prof_getpid)
+#define prof_hooks_init JEMALLOC_N(prof_hooks_init)
+#define prof_idump_impl JEMALLOC_N(prof_idump_impl)
+#define prof_mdump_impl JEMALLOC_N(prof_mdump_impl)
+#define prof_prefix_set JEMALLOC_N(prof_prefix_set)
+#define prof_sys_thread_name_fetch JEMALLOC_N(prof_sys_thread_name_fetch)
+#define prof_sys_thread_name_read JEMALLOC_N(prof_sys_thread_name_read)
+#define prof_unwind_init JEMALLOC_N(prof_unwind_init)
+#define psset_init JEMALLOC_N(psset_init)
+#define psset_insert JEMALLOC_N(psset_insert)
+#define psset_pick_alloc JEMALLOC_N(psset_pick_alloc)
+#define psset_pick_hugify JEMALLOC_N(psset_pick_hugify)
+#define psset_pick_purge JEMALLOC_N(psset_pick_purge)
+#define psset_remove JEMALLOC_N(psset_remove)
+#define psset_stats_accum JEMALLOC_N(psset_stats_accum)
+#define psset_update_begin JEMALLOC_N(psset_update_begin)
+#define psset_update_end JEMALLOC_N(psset_update_end)
#define rtree_ctx_data_init JEMALLOC_N(rtree_ctx_data_init)
-#define rtree_leaf_alloc JEMALLOC_N(rtree_leaf_alloc)
-#define rtree_leaf_dalloc JEMALLOC_N(rtree_leaf_dalloc)
#define rtree_leaf_elm_lookup_hard JEMALLOC_N(rtree_leaf_elm_lookup_hard)
#define rtree_new JEMALLOC_N(rtree_new)
-#define rtree_node_alloc JEMALLOC_N(rtree_node_alloc)
-#define rtree_node_dalloc JEMALLOC_N(rtree_node_dalloc)
#define safety_check_fail JEMALLOC_N(safety_check_fail)
+#define safety_check_fail_sized_dealloc JEMALLOC_N(safety_check_fail_sized_dealloc)
#define safety_check_set_abort JEMALLOC_N(safety_check_set_abort)
+#define reg_size_compute JEMALLOC_N(reg_size_compute)
+#define sc_boot JEMALLOC_N(sc_boot)
+#define sc_data_init JEMALLOC_N(sc_data_init)
+#define sc_data_update_slab_size JEMALLOC_N(sc_data_update_slab_size)
+#define sec_disable JEMALLOC_N(sec_disable)
+#define sec_flush JEMALLOC_N(sec_flush)
+#define sec_init JEMALLOC_N(sec_init)
+#define sec_mutex_stats_read JEMALLOC_N(sec_mutex_stats_read)
+#define sec_postfork_child JEMALLOC_N(sec_postfork_child)
+#define sec_postfork_parent JEMALLOC_N(sec_postfork_parent)
+#define sec_prefork2 JEMALLOC_N(sec_prefork2)
+#define sec_stats_merge JEMALLOC_N(sec_stats_merge)
#define arena_mutex_names JEMALLOC_N(arena_mutex_names)
#define global_mutex_names JEMALLOC_N(global_mutex_names)
+#define opt_stats_interval JEMALLOC_N(opt_stats_interval)
+#define opt_stats_interval_opts JEMALLOC_N(opt_stats_interval_opts)
#define opt_stats_print JEMALLOC_N(opt_stats_print)
#define opt_stats_print_opts JEMALLOC_N(opt_stats_print_opts)
+#define stats_boot JEMALLOC_N(stats_boot)
+#define stats_interval_event_handler JEMALLOC_N(stats_interval_event_handler)
+#define stats_interval_new_event_wait JEMALLOC_N(stats_interval_new_event_wait)
+#define stats_interval_postponed_event_wait JEMALLOC_N(stats_interval_postponed_event_wait)
+#define stats_postfork_child JEMALLOC_N(stats_postfork_child)
+#define stats_postfork_parent JEMALLOC_N(stats_postfork_parent)
+#define stats_prefork JEMALLOC_N(stats_prefork)
#define stats_print JEMALLOC_N(stats_print)
-#define sc_boot JEMALLOC_N(sc_boot)
-#define sc_data_global JEMALLOC_N(sc_data_global)
-#define sc_data_init JEMALLOC_N(sc_data_init)
-#define sc_data_update_slab_size JEMALLOC_N(sc_data_update_slab_size)
#define sz_boot JEMALLOC_N(sz_boot)
#define sz_index2size_tab JEMALLOC_N(sz_index2size_tab)
+#define sz_large_pad JEMALLOC_N(sz_large_pad)
#define sz_pind2sz_tab JEMALLOC_N(sz_pind2sz_tab)
+#define sz_psz_quantize_ceil JEMALLOC_N(sz_psz_quantize_ceil)
+#define sz_psz_quantize_floor JEMALLOC_N(sz_psz_quantize_floor)
#define sz_size2index_tab JEMALLOC_N(sz_size2index_tab)
#define nhbins JEMALLOC_N(nhbins)
-#define opt_lg_tcache_max JEMALLOC_N(opt_lg_tcache_max)
+#define opt_lg_tcache_flush_large_div JEMALLOC_N(opt_lg_tcache_flush_large_div)
+#define opt_lg_tcache_flush_small_div JEMALLOC_N(opt_lg_tcache_flush_small_div)
+#define opt_lg_tcache_nslots_mul JEMALLOC_N(opt_lg_tcache_nslots_mul)
#define opt_tcache JEMALLOC_N(opt_tcache)
+#define opt_tcache_gc_delay_bytes JEMALLOC_N(opt_tcache_gc_delay_bytes)
+#define opt_tcache_gc_incr_bytes JEMALLOC_N(opt_tcache_gc_incr_bytes)
+#define opt_tcache_max JEMALLOC_N(opt_tcache_max)
+#define opt_tcache_nslots_large JEMALLOC_N(opt_tcache_nslots_large)
+#define opt_tcache_nslots_small_max JEMALLOC_N(opt_tcache_nslots_small_max)
+#define opt_tcache_nslots_small_min JEMALLOC_N(opt_tcache_nslots_small_min)
#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard)
#define tcache_arena_associate JEMALLOC_N(tcache_arena_associate)
#define tcache_arena_reassociate JEMALLOC_N(tcache_arena_reassociate)
+#define tcache_assert_initialized JEMALLOC_N(tcache_assert_initialized)
#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large)
#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small)
+#define tcache_bin_flush_stashed JEMALLOC_N(tcache_bin_flush_stashed)
#define tcache_bin_info JEMALLOC_N(tcache_bin_info)
#define tcache_boot JEMALLOC_N(tcache_boot)
#define tcache_cleanup JEMALLOC_N(tcache_cleanup)
#define tcache_create_explicit JEMALLOC_N(tcache_create_explicit)
-#define tcache_event_hard JEMALLOC_N(tcache_event_hard)
#define tcache_flush JEMALLOC_N(tcache_flush)
+#define tcache_gc_dalloc_event_handler JEMALLOC_N(tcache_gc_dalloc_event_handler)
+#define tcache_gc_dalloc_new_event_wait JEMALLOC_N(tcache_gc_dalloc_new_event_wait)
+#define tcache_gc_dalloc_postponed_event_wait JEMALLOC_N(tcache_gc_dalloc_postponed_event_wait)
+#define tcache_gc_event_handler JEMALLOC_N(tcache_gc_event_handler)
+#define tcache_gc_new_event_wait JEMALLOC_N(tcache_gc_new_event_wait)
+#define tcache_gc_postponed_event_wait JEMALLOC_N(tcache_gc_postponed_event_wait)
#define tcache_maxclass JEMALLOC_N(tcache_maxclass)
#define tcache_postfork_child JEMALLOC_N(tcache_postfork_child)
#define tcache_postfork_parent JEMALLOC_N(tcache_postfork_parent)
@@ -391,9 +690,13 @@
#define tsd_tcache_enabled_data_init JEMALLOC_N(tsd_tcache_enabled_data_init)
#define test_hooks_arena_new_hook JEMALLOC_N(test_hooks_arena_new_hook)
#define test_hooks_libc_hook JEMALLOC_N(test_hooks_libc_hook)
+#define te_assert_invariants_debug JEMALLOC_N(te_assert_invariants_debug)
+#define te_event_trigger JEMALLOC_N(te_event_trigger)
+#define te_recompute_fast_threshold JEMALLOC_N(te_recompute_fast_threshold)
+#define tsd_te_init JEMALLOC_N(tsd_te_init)
+#define ticker_geom_table JEMALLOC_N(ticker_geom_table)
#define malloc_tsd_boot0 JEMALLOC_N(malloc_tsd_boot0)
#define malloc_tsd_boot1 JEMALLOC_N(malloc_tsd_boot1)
-#define malloc_tsd_cleanup_register JEMALLOC_N(malloc_tsd_cleanup_register)
#define malloc_tsd_dalloc JEMALLOC_N(malloc_tsd_dalloc)
#define malloc_tsd_malloc JEMALLOC_N(malloc_tsd_malloc)
#define tsd_booted JEMALLOC_N(tsd_booted)
diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h
index 78d5c66377c3..6363f085f34b 100644
--- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h
+++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h
@@ -7,11 +7,12 @@
#define je_mallctlnametomib JEMALLOC_N(mallctlnametomib)
#define je_malloc JEMALLOC_N(malloc)
#define je_malloc_conf JEMALLOC_N(malloc_conf)
+#define je_malloc_conf_2_conf_harder JEMALLOC_N(malloc_conf_2_conf_harder)
#define je_malloc_message JEMALLOC_N(malloc_message)
#define je_malloc_stats_print JEMALLOC_N(malloc_stats_print)
#define je_malloc_usable_size JEMALLOC_N(malloc_usable_size)
#define je_mallocx JEMALLOC_N(mallocx)
-#define je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 JEMALLOC_N(smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756)
+#define je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c JEMALLOC_N(smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c)
#define je_nallocx JEMALLOC_N(nallocx)
#define je_posix_memalign JEMALLOC_N(posix_memalign)
#define je_rallocx JEMALLOC_N(rallocx)
@@ -19,4 +20,5 @@
#define je_sallocx JEMALLOC_N(sallocx)
#define je_sdallocx JEMALLOC_N(sdallocx)
#define je_xallocx JEMALLOC_N(xallocx)
+#define je_memalign JEMALLOC_N(memalign)
#define je_valloc JEMALLOC_N(valloc)
diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h
index c3fa08e83f22..f9ed38656a87 100644
--- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h
+++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h
@@ -19,6 +19,12 @@ extern "C" {
/* Defined if format(printf, ...) attribute is supported. */
#define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF
+/* Defined if fallthrough attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_FALLTHROUGH
+
+/* Defined if cold attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_COLD
+
/*
* Define overrides for non-standard allocator-related functions if they are
* present on the system.
@@ -68,11 +74,12 @@ extern "C" {
# define je_mallctlnametomib mallctlnametomib
# define je_malloc malloc
# define je_malloc_conf malloc_conf
+# define je_malloc_conf_2_conf_harder malloc_conf_2_conf_harder
# define je_malloc_message malloc_message
# define je_malloc_stats_print malloc_stats_print
# define je_malloc_usable_size malloc_usable_size
# define je_mallocx mallocx
-# define je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
+# define je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c
# define je_nallocx nallocx
# define je_posix_memalign posix_memalign
# define je_rallocx rallocx
@@ -80,6 +87,7 @@ extern "C" {
# define je_sallocx sallocx
# define je_sdallocx sdallocx
# define je_xallocx xallocx
+# define je_memalign memalign
# define je_valloc valloc
#endif
@@ -91,13 +99,13 @@ extern "C" {
#include <limits.h>
#include <strings.h>
-#define JEMALLOC_VERSION "5.2.1-0-gea6b3e973b477b8061e0076bb257dbd7f3faa756"
+#define JEMALLOC_VERSION "5.3.0-0-g54eaed1d8b56b1aa528be3bdd1877e59c56fa90c"
#define JEMALLOC_VERSION_MAJOR 5
-#define JEMALLOC_VERSION_MINOR 2
-#define JEMALLOC_VERSION_BUGFIX 1
+#define JEMALLOC_VERSION_MINOR 3
+#define JEMALLOC_VERSION_BUGFIX 0
#define JEMALLOC_VERSION_NREV 0
-#define JEMALLOC_VERSION_GID "ea6b3e973b477b8061e0076bb257dbd7f3faa756"
-#define JEMALLOC_VERSION_GID_IDENT ea6b3e973b477b8061e0076bb257dbd7f3faa756
+#define JEMALLOC_VERSION_GID "54eaed1d8b56b1aa528be3bdd1877e59c56fa90c"
+#define JEMALLOC_VERSION_GID_IDENT 54eaed1d8b56b1aa528be3bdd1877e59c56fa90c
#define MALLOCX_LG_ALIGN(la) ((int)(la))
#if LG_SIZEOF_PTR == 2
@@ -158,6 +166,7 @@ extern "C" {
# endif
# define JEMALLOC_FORMAT_ARG(i)
# define JEMALLOC_FORMAT_PRINTF(s, i)
+# define JEMALLOC_FALLTHROUGH
# define JEMALLOC_NOINLINE __declspec(noinline)
# ifdef __cplusplus
# define JEMALLOC_NOTHROW __declspec(nothrow)
@@ -171,6 +180,7 @@ extern "C" {
# else
# define JEMALLOC_ALLOCATOR
# endif
+# define JEMALLOC_COLD
#elif defined(JEMALLOC_HAVE_ATTR)
# define JEMALLOC_ATTR(s) __attribute__((s))
# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
@@ -196,11 +206,21 @@ extern "C" {
# else
# define JEMALLOC_FORMAT_PRINTF(s, i)
# endif
+# ifdef JEMALLOC_HAVE_ATTR_FALLTHROUGH
+# define JEMALLOC_FALLTHROUGH JEMALLOC_ATTR(fallthrough)
+# else
+# define JEMALLOC_FALLTHROUGH
+# endif
# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)
# define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow)
# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
# define JEMALLOC_RESTRICT_RETURN
# define JEMALLOC_ALLOCATOR
+# ifdef JEMALLOC_HAVE_ATTR_COLD
+# define JEMALLOC_COLD JEMALLOC_ATTR(__cold__)
+# else
+# define JEMALLOC_COLD
+# endif
#else
# define JEMALLOC_ATTR(s)
# define JEMALLOC_ALIGNED(s)
@@ -208,11 +228,19 @@ extern "C" {
# define JEMALLOC_ALLOC_SIZE2(s1, s2)
# define JEMALLOC_EXPORT
# define JEMALLOC_FORMAT_PRINTF(s, i)
+# define JEMALLOC_FALLTHROUGH
# define JEMALLOC_NOINLINE
# define JEMALLOC_NOTHROW
# define JEMALLOC_SECTION(s)
# define JEMALLOC_RESTRICT_RETURN
# define JEMALLOC_ALLOCATOR
+# define JEMALLOC_COLD
+#endif
+
+#if (defined(__APPLE__) || defined(__FreeBSD__)) && !defined(JEMALLOC_NO_RENAME)
+# define JEMALLOC_SYS_NOTHROW
+#else
+# define JEMALLOC_SYS_NOTHROW JEMALLOC_NOTHROW
#endif
/*
@@ -225,21 +253,22 @@ extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque,
const char *s);
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
- void JEMALLOC_NOTHROW *je_malloc(size_t size)
+ void JEMALLOC_SYS_NOTHROW *je_malloc(size_t size)
JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
- void JEMALLOC_NOTHROW *je_calloc(size_t num, size_t size)
+ void JEMALLOC_SYS_NOTHROW *je_calloc(size_t num, size_t size)
JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2);
-JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_posix_memalign(void **memptr,
- size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1));
+JEMALLOC_EXPORT int JEMALLOC_SYS_NOTHROW je_posix_memalign(
+ void **memptr, size_t alignment, size_t size) JEMALLOC_CXX_THROW
+ JEMALLOC_ATTR(nonnull(1));
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
- void JEMALLOC_NOTHROW *je_aligned_alloc(size_t alignment,
+ void JEMALLOC_SYS_NOTHROW *je_aligned_alloc(size_t alignment,
size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc)
JEMALLOC_ALLOC_SIZE(2);
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
- void JEMALLOC_NOTHROW *je_realloc(void *ptr, size_t size)
+ void JEMALLOC_SYS_NOTHROW *je_realloc(void *ptr, size_t size)
JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2);
-JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_free(void *ptr)
+JEMALLOC_EXPORT void JEMALLOC_SYS_NOTHROW je_free(void *ptr)
JEMALLOC_CXX_THROW;
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
@@ -269,16 +298,20 @@ JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_malloc_stats_print(
const char *opts);
JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_usable_size(
JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW;
+#ifdef JEMALLOC_HAVE_MALLOC_SIZE
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_size(
+ const void *ptr);
+#endif
#ifdef JEMALLOC_OVERRIDE_MEMALIGN
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
- void JEMALLOC_NOTHROW *je_memalign(size_t alignment, size_t size)
+ void JEMALLOC_SYS_NOTHROW *je_memalign(size_t alignment, size_t size)
JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc);
#endif
#ifdef JEMALLOC_OVERRIDE_VALLOC
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
- void JEMALLOC_NOTHROW *je_valloc(size_t size) JEMALLOC_CXX_THROW
+ void JEMALLOC_SYS_NOTHROW *je_valloc(size_t size) JEMALLOC_CXX_THROW
JEMALLOC_ATTR(malloc);
#endif
@@ -380,11 +413,12 @@ struct extent_hooks_s {
# define mallctlnametomib je_mallctlnametomib
# define malloc je_malloc
# define malloc_conf je_malloc_conf
+# define malloc_conf_2_conf_harder je_malloc_conf_2_conf_harder
# define malloc_message je_malloc_message
# define malloc_stats_print je_malloc_stats_print
# define malloc_usable_size je_malloc_usable_size
# define mallocx je_mallocx
-# define smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
+# define smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c
# define nallocx je_nallocx
# define posix_memalign je_posix_memalign
# define rallocx je_rallocx
@@ -412,11 +446,12 @@ struct extent_hooks_s {
# undef je_mallctlnametomib
# undef je_malloc
# undef je_malloc_conf
+# undef je_malloc_conf_2_conf_harder
# undef je_malloc_message
# undef je_malloc_stats_print
# undef je_malloc_usable_size
# undef je_mallocx
-# undef je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756
+# undef je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c
# undef je_nallocx
# undef je_posix_memalign
# undef je_rallocx
diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h
index e733906bc146..34c86271ab2e 100644
--- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h
+++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h
@@ -2,6 +2,8 @@
* Override settings that were generated in jemalloc_defs.h as necessary.
*/
+#ifndef JEMALLOC_NO_PRIVATE_NAMESPACE
+
#undef JEMALLOC_OVERRIDE_VALLOC
#ifndef MALLOC_PRODUCTION
@@ -96,8 +98,12 @@
#include <machine/cpufunc.h>
#define CPU_SPINWAIT cpu_spinwait()
-/* Disable lazy-lock machinery, mangle isthreaded, and adjust its type. */
+/*
+ * Disable lazy-lock machinery, redirect isthreaded to libc's flag, undo
+ * jemalloc's namespace stuff for it and adjust its type.
+ */
#undef JEMALLOC_LAZY_LOCK
+#undef isthreaded
extern int __isthreaded;
#define isthreaded ((bool)__isthreaded)
@@ -197,3 +203,5 @@ __sym_compat(sallocm, weak_sallocm, FBSD_1.3);
__sym_compat(dallocm, weak_dallocm, FBSD_1.3);
__sym_compat(nallocm, weak_nallocm, FBSD_1.3);
#endif
+
+#endif
diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_defs.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_defs.h
new file mode 100644
index 000000000000..fb104aaeec98
--- /dev/null
+++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_defs.h
@@ -0,0 +1,55 @@
+/* include/jemalloc/jemalloc_defs.h. Generated from jemalloc_defs.h.in by configure. */
+/* Defined if __attribute__((...)) syntax is supported. */
+#define JEMALLOC_HAVE_ATTR
+
+/* Defined if alloc_size attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_ALLOC_SIZE
+
+/* Defined if format_arg(...) attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_FORMAT_ARG
+
+/* Defined if format(gnu_printf, ...) attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF
+
+/* Defined if format(printf, ...) attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF
+
+/* Defined if fallthrough attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_FALLTHROUGH
+
+/* Defined if cold attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_COLD
+
+/*
+ * Define overrides for non-standard allocator-related functions if they are
+ * present on the system.
+ */
+#define JEMALLOC_OVERRIDE_MEMALIGN
+#define JEMALLOC_OVERRIDE_VALLOC
+
+/*
+ * At least Linux omits the "const" in:
+ *
+ * size_t malloc_usable_size(const void *ptr);
+ *
+ * Match the operating system's prototype.
+ */
+#define JEMALLOC_USABLE_SIZE_CONST const
+
+/*
+ * If defined, specify throw() for the public function prototypes when compiling
+ * with C++. The only justification for this is to match the prototypes that
+ * glibc defines.
+ */
+/* #undef JEMALLOC_USE_CXX_THROW */
+
+#ifdef _MSC_VER
+# ifdef _WIN64
+# define LG_SIZEOF_PTR_WIN 3
+# else
+# define LG_SIZEOF_PTR_WIN 2
+# endif
+#endif
+
+/* sizeof(void *) == 2^LG_SIZEOF_PTR. */
+#define LG_SIZEOF_PTR 3
diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c
index e0b06494cf98..400124593d07 100644
--- a/lib/libc/stdlib/qsort.c
+++ b/lib/libc/stdlib/qsort.c
@@ -106,13 +106,11 @@ local_qsort(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk)
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
size_t d1, d2;
int cmp_result;
- int swap_cnt;
/* if there are less than 2 elements, then sorting is not needed */
if (__predict_false(n < 2))
return;
loop:
- swap_cnt = 0;
if (n < 7) {
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
for (pl = pm;
@@ -141,7 +139,6 @@ loop:
for (;;) {
while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
if (cmp_result == 0) {
- swap_cnt = 1;
swapfunc(pa, pb, es);
pa += es;
}
@@ -149,7 +146,6 @@ loop:
}
while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
if (cmp_result == 0) {
- swap_cnt = 1;
swapfunc(pc, pd, es);
pd -= es;
}
@@ -158,18 +154,9 @@ loop:
if (pb > pc)
break;
swapfunc(pb, pc, es);
- swap_cnt = 1;
pb += es;
pc -= es;
}
- if (swap_cnt == 0) { /* Switch to insertion sort */
- for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
- for (pl = pm;
- pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
- pl -= es)
- swapfunc(pl, pl - es, es);
- return;
- }
pn = (char *)a + n * es;
d1 = MIN(pa - (char *)a, pb - pa);
diff --git a/lib/libc/stdlib/reallocarray.3 b/lib/libc/stdlib/reallocarray.3
index 80035c67a497..9a2ab5c7a840 100644
--- a/lib/libc/stdlib/reallocarray.3
+++ b/lib/libc/stdlib/reallocarray.3
@@ -26,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 1, 2015
+.Dd October 2, 2025
.Dt REALLOCARRAY 3
.Os
.Sh NAME
@@ -38,6 +38,8 @@
.In stdlib.h
.Ft void *
.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
+.Ft void *
+.Fn recallocarray "void *ptr" "size_t oldnmeb" "size_t nmemb" size_t size"
.Sh DESCRIPTION
The
.Fn reallocarray
@@ -52,6 +54,33 @@ and checks for integer overflow in the calculation
.Fa nmemb
*
.Fa size .
+.Pp
+The
+.Fn recallocarray
+function is similar to the
+.Fn reallocarray
+function
+except it ensures newly allocated memory is cleared similar to
+.Fn calloc .
+If
+.Fa ptr
+is
+.Dv NULL ,
+.Fa oldnmemb
+is ignored and the call is equivalent to
+.Fn calloc .
+If
+.Fa ptr
+is not
+.Dv NULL ,
+.Fa oldnmemb
+must be a value such that
+.Fa oldnmemb
+*
+.Fa size
+is the size of the earlier allocation that returned
+.Fa ptr ,
+otherwise the behaviour is undefined.
.Sh RETURN VALUES
The
.Fn reallocarray
@@ -142,3 +171,9 @@ function first appeared in
.Ox 5.6
and
.Fx 11.0 .
+The
+.Fn recallocarray
+function first appeared in
+.Ox 6.1
+and
+.Fx 16.0 .
diff --git a/lib/libc/stdlib/reallocarray.c b/lib/libc/stdlib/reallocarray.c
index 0868804486cc..3632734c84de 100644
--- a/lib/libc/stdlib/reallocarray.c
+++ b/lib/libc/stdlib/reallocarray.c
@@ -17,23 +17,19 @@
#include <sys/types.h>
#include <errno.h>
+#include <stdckdint.h>
#include <stdint.h>
#include <stdlib.h>
-/*
- * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
- * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
- */
-#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
-
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
+ size_t nbytes;
- if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
- nmemb > 0 && SIZE_MAX / nmemb < size) {
+ if (ckd_mul(&nbytes, nmemb, size)) {
errno = ENOMEM;
return (NULL);
}
- return (realloc(optr, size * nmemb));
+
+ return (realloc(optr, nbytes));
}
diff --git a/lib/libc/stdlib/realpath.3 b/lib/libc/stdlib/realpath.3
index 065ba312c2ef..76f40249963b 100644
--- a/lib/libc/stdlib/realpath.3
+++ b/lib/libc/stdlib/realpath.3
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 11, 2012
+.Dd October 10, 2025
.Dt REALPATH 3
.Os
.Sh NAME
@@ -108,11 +108,11 @@ and
.Xr getcwd 3 .
.Sh SEE ALSO
.Xr getcwd 3
-.\" .Sh STANDARDS
-.\" The
-.\" .Fn realpath
-.\" function conforms to
-.\" .St -p1003.1-2001 .
+.Sh STANDARDS
+The
+.Fn realpath
+function conforms to
+.St -p1003.1-2001 .
.Sh HISTORY
The
.Fn realpath
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
index 4c52b73319ab..18f29e95ee6b 100644
--- a/lib/libc/stdlib/realpath.c
+++ b/lib/libc/stdlib/realpath.c
@@ -49,7 +49,7 @@ realpath1(const char *path, char *resolved)
{
struct stat sb;
char *p, *q;
- size_t left_len, resolved_len, next_token_len;
+ size_t left_len, prev_len, resolved_len, next_token_len;
unsigned symlinks;
ssize_t slen;
char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
@@ -98,6 +98,7 @@ realpath1(const char *path, char *resolved)
left_len = 0;
}
+ prev_len = resolved_len;
if (resolved[resolved_len - 1] != '/') {
if (resolved_len + 1 >= PATH_MAX) {
errno = ENAMETOOLONG;
@@ -133,8 +134,17 @@ realpath1(const char *path, char *resolved)
errno = ENAMETOOLONG;
return (NULL);
}
- if (lstat(resolved, &sb) != 0)
+ if (lstat(resolved, &sb) != 0) {
+ /*
+ * EACCES means the parent directory is not
+ * readable, while ENOTDIR means the parent
+ * directory is not a directory. Rewind the path
+ * to correctly indicate where the error lies.
+ */
+ if (errno == EACCES || errno == ENOTDIR)
+ resolved[prev_len] = '\0';
return (NULL);
+ }
if (S_ISLNK(sb.st_mode)) {
if (symlinks++ > MAXSYMLINKS) {
errno = ELOOP;
diff --git a/lib/libopenbsd/recallocarray.c b/lib/libc/stdlib/recallocarray.c
index 11e1fda744c7..cbf1fb2470cf 100644
--- a/lib/libopenbsd/recallocarray.c
+++ b/lib/libc/stdlib/recallocarray.c
@@ -16,17 +16,12 @@
*/
#include <errno.h>
+#include <stdckdint.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
-/*
- * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
- * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
- */
-#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
-
void *recallocarray(void *, size_t, size_t, size_t);
void *
@@ -38,19 +33,15 @@ recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
if (ptr == NULL)
return calloc(newnmemb, size);
- if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
- newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+ if (ckd_mul(&newsize, newnmemb, size)) {
errno = ENOMEM;
return NULL;
}
- newsize = newnmemb * size;
- if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
- oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+ if (ckd_mul(&oldsize, oldnmemb, size)) {
errno = EINVAL;
return NULL;
}
- oldsize = oldnmemb * size;
/*
* Don't bother too much if we're shrinking just a bit,
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
index 5d0ce7765b63..1baa39a6c0a6 100644
--- a/lib/libc/stdtime/Makefile.inc
+++ b/lib/libc/stdtime/Makefile.inc
@@ -18,6 +18,7 @@ CFLAGS.${src}+= -I${LIBC_SRCTOP}/stdtime
CFLAGS.localtime.c+= -DALL_STATE -DTHREAD_SAFE
.if ${MK_DETECT_TZ_CHANGES} != "no"
CFLAGS.localtime.c+= -DDETECT_TZ_CHANGES
+CFLAGS.Version.map+= -DDETECT_TZ_CHANGES
.endif
MAN+= ctime.3 strftime.3 strptime.3 time2posix.3 tzset.3
@@ -31,4 +32,5 @@ MLINKS+=strftime.3 strftime_l.3
MLINKS+=strptime.3 strptime_l.3
MLINKS+=time2posix.3 posix2time.3
MLINKS+=tzset.3 daylight.3 \
- tzset.3 timezone.3
+ tzset.3 timezone.3 \
+ tzset.3 tzname.3
diff --git a/lib/libc/stdtime/Symbol.map b/lib/libc/stdtime/Symbol.map
index 669d4d47907b..6a34cd3ea590 100644
--- a/lib/libc/stdtime/Symbol.map
+++ b/lib/libc/stdtime/Symbol.map
@@ -35,3 +35,9 @@ FBSD_1.8 {
daylight;
timezone;
};
+
+FBSDprivate_1.0 {
+#ifdef DETECT_TZ_CHANGES
+ __tz_change_interval;
+#endif
+};
diff --git a/lib/libc/stdtime/ctime.3 b/lib/libc/stdtime/ctime.3
index 96b7f775535a..6384e8bd959b 100644
--- a/lib/libc/stdtime/ctime.3
+++ b/lib/libc/stdtime/ctime.3
@@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 26, 2024
+.Dd September 23, 2025
.Dt CTIME 3
.Os
.Sh NAME
@@ -41,6 +41,8 @@
.Nm localtime ,
.Nm localtime_r ,
.Nm mktime ,
+.Nm offtime ,
+.Nm offtime_r ,
.Nm timegm
.Nd transform binary date and time values
.Sh LIBRARY
@@ -68,14 +70,19 @@
.Fn localtime_r "const time_t *clock" "struct tm *result"
.Ft time_t
.Fn mktime "struct tm *tm"
+.Ft struct tm *
+.Fn offtime "const time_t *clock" "long offset"
+.Ft struct tm *
+.Fn offtime_r "const time_t *clock" "long offset" "struct tm *result"
.Ft time_t
.Fn timegm "struct tm *tm"
.Sh DESCRIPTION
The
.Fn ctime ,
.Fn gmtime ,
+.Fn localtime ,
and
-.Fn localtime
+.Fn offtime
functions all take as argument a pointer to a time value representing
the time in seconds since the Epoch (00:00:00 UTC on January 1, 1970;
see
@@ -123,6 +130,18 @@ adjustment, and returns a pointer to a
.Vt struct tm .
.Pp
The
+.Fn offtime
+function similarly converts the time value with a time zone adjustment
+corresponding to the provided
+.Fa offset ,
+which is expressed in seconds, with positive values indicating a time
+zone ahead of UTC (east of the Prime Meridian).
+It does not call
+.Xr tzset 3
+or modify
+.Va tzname .
+.Pp
+The
.Fn ctime
function
adjusts the time value for the current time zone in the same manner as
@@ -155,13 +174,15 @@ except the caller must provide the output buffer
.Fa buf ,
which must be at least 26 characters long, to store the result in.
The
-.Fn localtime_r
+.Fn localtime_r ,
+.Fn gmtime_r ,
and
-.Fn gmtime_r
+.Fn offtime_r
functions provide the same functionality as
-.Fn localtime
+.Fn localtime ,
+.Fn gmtime ,
and
-.Fn gmtime
+.Fn offtime
respectively, except the caller must provide the output buffer
.Fa result .
.Pp
@@ -368,6 +389,12 @@ and
.Fn localtime_r
functions have been available since
.Fx 8.0 .
+The
+.Fn offtime
+and
+.Fn offtime_r
+functions were added in
+.Fx 15.0 .
.Sh BUGS
Except for
.Fn difftime ,
diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3
index 7df73d2d080a..9456fa757b85 100644
--- a/lib/libc/stdtime/strptime.3
+++ b/lib/libc/stdtime/strptime.3
@@ -171,7 +171,7 @@ is taken as noon.
The
.Fa %Z
format specifier only accepts time zone abbreviations of the local time zone,
-or the value "GMT".
+and the values "GMT", "UTC", or "Z".
This limitation is because of ambiguity due to of the over loading of time
zone abbreviations.
One such example is
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index 5f1293c7a267..375e49146639 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -546,7 +546,8 @@ label:
zonestr[cp - buf] = '\0';
tzset();
if (0 == strcmp(zonestr, "GMT") ||
- 0 == strcmp(zonestr, "UTC")) {
+ 0 == strcmp(zonestr, "UTC") ||
+ 0 == strcmp(zonestr, "Z")) {
*GMTp = 1;
} else if (0 == strcmp(zonestr, tzname[0])) {
tm->tm_isdst = 0;
diff --git a/lib/libc/stdtime/tzset.3 b/lib/libc/stdtime/tzset.3
index 94ccbec9aba7..33e6a556306d 100644
--- a/lib/libc/stdtime/tzset.3
+++ b/lib/libc/stdtime/tzset.3
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 25, 2023
+.Dd September 30, 2025
.Dt TZSET 3
.Os
.Sh NAME
@@ -58,8 +58,8 @@ specifies how this is done.
.Pp
If
.Ev TZ
-does not appear in the environment, the best available approximation to
-local wall clock time, as specified by the
+does not appear in the environment, the best available approximation
+to local wall clock time, as specified by the
.Xr tzfile 5 Ns -format
file
.Pa /etc/localtime
@@ -68,9 +68,7 @@ is used.
If
.Ev TZ
appears in the environment but its value is a null string, Coordinated
-Universal Time
-.Pq Tn UTC
-is used (without leap second correction).
+Universal Time (UTC) is used (without leap second correction).
.Pp
If
.Ev TZ
@@ -81,13 +79,12 @@ the rest of its value is used as a pathname of a
file from which to read the time conversion information.
If the first character of the pathname is a slash
.Pq Ql /
-it is used as
-an absolute pathname; otherwise, it is used as a pathname relative to
-the system time conversion information directory.
+it is used as an absolute pathname; otherwise, it is used as a
+pathname relative to the system time conversion information directory.
.Pp
-If its value does not begin with a colon, it is first used as the pathname
-of a file (as described above) from which to read the time conversion
-information.
+If its value does not begin with a colon, it is first used as the
+pathname of a file (as described above) from which to read the time
+conversion information.
If that file cannot be read, the value is then interpreted as a direct
specification (the format is described below) of the time conversion
information.
@@ -96,24 +93,23 @@ If the
.Ev TZ
environment variable does not specify a
.Xr tzfile 5 Ns -format
-file and cannot be interpreted as a direct specification,
-.Tn UTC
-is used.
+file and cannot be interpreted as a direct specification, UTC is used.
.Pp
After the first call to
.Nm tzset ,
the
.Vt timezone
-variable is set to the difference, in seconds, between Coordinated Universal
-Time (UTC) and the local time.
+variable is set to the difference, in seconds, between Coordinated
+Universal Time (UTC) and the local time.
The
.Vt daylight
variable is set to 0 if the local timezone is observing standard time.
-It is set to 1 if the local timezone ever observes an alternate time, such as summer time.
+It is set to 1 if the local timezone ever observes an alternate time,
+such as summer time.
The first element of the
.Vt tzname
-array is the timezone name of standard time, while the second element is the
-name of the altnerative time zone.
+array is the timezone name of standard time, while the second element
+is the name of the altnerative time zone.
.Sh SPECIFICATION FORMAT
When
.Ev TZ
@@ -151,8 +147,7 @@ minus
.Pq Ql \- ,
plus
.Pq Ql + ,
-and
-.Tn ASCII
+and ASCII
.Dv NUL
are allowed.
.It Em offset
@@ -294,10 +289,8 @@ by the
file
.Em posixrules
in the system time conversion information directory are used, with the
-standard and summer time offsets from
-.Tn UTC
-replaced by those specified by
-the
+standard and summer time offsets from UTC replaced by those specified
+by the
.Em offset
values in
.Ev TZ .
@@ -315,20 +308,14 @@ local time zone file
.It Pa /usr/share/zoneinfo
time zone directory
.It Pa /usr/share/zoneinfo/posixrules
-rules for
-.Tn POSIX Ns -style
-.Tn TZ Ns 's
+rules for POSIX-style TZs
.It Pa /usr/share/zoneinfo/Etc/GMT
-for
-.Tn UTC
-leap seconds
+for UTC leap seconds
.El
.Pp
If the file
.Pa /usr/share/zoneinfo/UTC
-does not exist,
-.Tn UTC
-leap seconds are loaded from
+does not exist, UTC leap seconds are loaded from
.Pa /usr/share/zoneinfo/posixrules .
.Sh SEE ALSO
.Xr date 1 ,
diff --git a/lib/libc/string/memchr.3 b/lib/libc/string/memchr.3
index f5d1fe5d5c7f..c50e932d3382 100644
--- a/lib/libc/string/memchr.3
+++ b/lib/libc/string/memchr.3
@@ -34,7 +34,7 @@
.Os
.Sh NAME
.Nm memchr
-.Nd locate byte in byte string
+.Nd locate byte in memory object
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -51,8 +51,11 @@ locates the first occurrence of
.Fa c
(converted to an
.Vt "unsigned char" )
-in string
-.Fa b .
+in object
+.Fa b ,
+limited to at most
+.Fa len
+characters.
.Pp
The
.Fn memrchr
@@ -60,16 +63,19 @@ function behaves like
.Fn memchr ,
except that it locates the last occurrence of
.Fa c
-in string
-.Fa b .
+in object
+.Fa b ,
+limited to the first
+.Fa len
+characters.
.Sh RETURN VALUES
The
.Fn memchr
and
.Fn memrchr
-functions
-return a pointer to the byte located,
-or NULL if no such byte exists within
+functions return a pointer to the byte located, or
+.Dv NULL
+if no such byte exists within
.Fa len
bytes.
.Sh SEE ALSO
diff --git a/lib/libc/sys/accept.c b/lib/libc/sys/accept.c
index 95c8b4a58c74..c6fb040ab6d6 100644
--- a/lib/libc/sys/accept.c
+++ b/lib/libc/sys/accept.c
@@ -34,8 +34,6 @@
#include <sys/socket.h>
#include "libc_private.h"
-__weak_reference(__sys_accept, __accept);
-
#pragma weak accept
int
accept(int s, struct sockaddr *addr, socklen_t *addrlen)
diff --git a/lib/libc/sys/accept4.c b/lib/libc/sys/accept4.c
index 1a1f75c9f528..146dde9ae6fa 100644
--- a/lib/libc/sys/accept4.c
+++ b/lib/libc/sys/accept4.c
@@ -34,8 +34,6 @@
#include <sys/socket.h>
#include "libc_private.h"
-__weak_reference(__sys_accept4, __accept4);
-
#pragma weak accept4
int
accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
diff --git a/lib/libc/sys/aio_suspend.c b/lib/libc/sys/aio_suspend.c
index 592cb5b0e1d7..5a7774705ac2 100644
--- a/lib/libc/sys/aio_suspend.c
+++ b/lib/libc/sys/aio_suspend.c
@@ -33,8 +33,6 @@
#include <sys/aio.h>
#include "libc_private.h"
-__weak_reference(__sys_aio_suspend, __aio_suspend);
-
#pragma weak aio_suspend
int
aio_suspend(const struct aiocb * const iocbs[], int niocb,
diff --git a/lib/libc/sys/clock_nanosleep.c b/lib/libc/sys/clock_nanosleep.c
index a50af30e1fb3..db14bd46f85e 100644
--- a/lib/libc/sys/clock_nanosleep.c
+++ b/lib/libc/sys/clock_nanosleep.c
@@ -34,8 +34,6 @@
#include <time.h>
#include "libc_private.h"
-__weak_reference(__sys_clock_nanosleep, __clock_nanosleep);
-
#pragma weak clock_nanosleep
int
clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
diff --git a/lib/libc/sys/close.c b/lib/libc/sys/close.c
index 08a5419361a9..8aa2b9b6ad13 100644
--- a/lib/libc/sys/close.c
+++ b/lib/libc/sys/close.c
@@ -34,8 +34,6 @@
#include <unistd.h>
#include "libc_private.h"
-__weak_reference(__sys_close, __close);
-
#pragma weak close
int
close(int fd)
diff --git a/lib/libc/sys/connect.c b/lib/libc/sys/connect.c
index e64451683abc..f27813b63df0 100644
--- a/lib/libc/sys/connect.c
+++ b/lib/libc/sys/connect.c
@@ -34,8 +34,6 @@
#include <sys/socket.h>
#include "libc_private.h"
-__weak_reference(__sys_connect, __connect);
-
#pragma weak connect
int
connect(int s, const struct sockaddr *addr, socklen_t addrlen)
diff --git a/lib/libc/sys/fork.c b/lib/libc/sys/fork.c
index e907c51b5cee..3af81c14ffb3 100644
--- a/lib/libc/sys/fork.c
+++ b/lib/libc/sys/fork.c
@@ -33,8 +33,6 @@
#include <unistd.h>
#include "libc_private.h"
-__weak_reference(__sys_fork, __fork);
-
#pragma weak fork
pid_t
fork(void)
diff --git a/lib/libc/sys/fsync.c b/lib/libc/sys/fsync.c
index e542c8cdea48..c58b29ca6a77 100644
--- a/lib/libc/sys/fsync.c
+++ b/lib/libc/sys/fsync.c
@@ -34,8 +34,6 @@
#include <unistd.h>
#include "libc_private.h"
-__weak_reference(__sys_fsync, __fsync);
-
int
fsync(int fd)
{
diff --git a/lib/libc/sys/kevent.c b/lib/libc/sys/kevent.c
index f16ac89a36c6..e395e16c67f5 100644
--- a/lib/libc/sys/kevent.c
+++ b/lib/libc/sys/kevent.c
@@ -34,8 +34,6 @@
#include <sys/time.h>
#include "libc_private.h"
-__weak_reference(__sys_kevent, __kevent);
-
#pragma weak kevent
int
kevent(int kq, const struct kevent *changelist, int nchanges,
diff --git a/lib/libc/sys/msync.c b/lib/libc/sys/msync.c
index f825db97b947..11dd988300eb 100644
--- a/lib/libc/sys/msync.c
+++ b/lib/libc/sys/msync.c
@@ -34,8 +34,6 @@
#include <sys/mman.h>
#include "libc_private.h"
-__weak_reference(__sys_msync, __msync);
-
#pragma weak msync
int
msync(void *addr, size_t len, int flags)
diff --git a/lib/libc/sys/nanosleep.c b/lib/libc/sys/nanosleep.c
index bd0794c3af8e..23c07e3bf5fc 100644
--- a/lib/libc/sys/nanosleep.c
+++ b/lib/libc/sys/nanosleep.c
@@ -33,8 +33,6 @@
#include <time.h>
#include "libc_private.h"
-__weak_reference(__sys_nanosleep, __nanosleep);
-
#pragma weak nanosleep
int
nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
diff --git a/lib/libc/sys/open.c b/lib/libc/sys/open.c
index 57c07637d2aa..dd7bedebf141 100644
--- a/lib/libc/sys/open.c
+++ b/lib/libc/sys/open.c
@@ -34,8 +34,6 @@
#include <stdarg.h>
#include "libc_private.h"
-__weak_reference(__sys_open, __open);
-
#pragma weak open
int
open(const char *path, int flags, ...)
diff --git a/lib/libc/sys/openat.c b/lib/libc/sys/openat.c
index 1cd8e7d90745..ba937cae3a3e 100644
--- a/lib/libc/sys/openat.c
+++ b/lib/libc/sys/openat.c
@@ -34,7 +34,6 @@
#include <stdarg.h>
#include "libc_private.h"
-__weak_reference(__sys_openat, __openat);
__sym_compat(openat, __impl_openat, FBSD_1.1);
__weak_reference(openat, __impl_openat);
__sym_default(openat, openat, FBSD_1.2);
diff --git a/lib/libc/sys/poll.c b/lib/libc/sys/poll.c
index 5e000f7e728f..8c6a89adb2cb 100644
--- a/lib/libc/sys/poll.c
+++ b/lib/libc/sys/poll.c
@@ -34,8 +34,6 @@
#include <ssp/ssp.h>
#include "libc_private.h"
-__weak_reference(__sys_poll, __poll);
-
int __weak_symbol
__ssp_real(poll)(struct pollfd pfd[], nfds_t nfds, int timeout)
{
diff --git a/lib/libc/sys/ppoll.c b/lib/libc/sys/ppoll.c
index 72c0b5d5e421..5ffc35a8cbb0 100644
--- a/lib/libc/sys/ppoll.c
+++ b/lib/libc/sys/ppoll.c
@@ -34,8 +34,6 @@
#include <ssp/ssp.h>
#include "libc_private.h"
-__weak_reference(__sys_ppoll, __ppoll);
-
int __weak_symbol
__ssp_real(ppoll)(struct pollfd pfd[], nfds_t nfds,
const struct timespec *__restrict timeout,
diff --git a/lib/libc/sys/pselect.c b/lib/libc/sys/pselect.c
index 38477e39af44..2c1c9896d6b9 100644
--- a/lib/libc/sys/pselect.c
+++ b/lib/libc/sys/pselect.c
@@ -33,8 +33,6 @@
#include <sys/select.h>
#include "libc_private.h"
-__weak_reference(__sys_pselect, __pselect);
-
#pragma weak pselect
int
pselect(int n, fd_set *rs, fd_set *ws, fd_set *es, const struct timespec *t,
diff --git a/lib/libc/sys/read.c b/lib/libc/sys/read.c
index b4610e0c38c3..75cc7e42b013 100644
--- a/lib/libc/sys/read.c
+++ b/lib/libc/sys/read.c
@@ -34,8 +34,6 @@
#include <unistd.h>
#include "libc_private.h"
-__weak_reference(__sys_read, __read);
-
#pragma weak read
ssize_t
read(int fd, void *buf, size_t nbytes)
diff --git a/lib/libc/sys/readv.c b/lib/libc/sys/readv.c
index 2729f6ed99da..83b4bf9ba3e6 100644
--- a/lib/libc/sys/readv.c
+++ b/lib/libc/sys/readv.c
@@ -36,8 +36,6 @@
#include <ssp/ssp.h>
#include "libc_private.h"
-__weak_reference(__sys_readv, __readv);
-
ssize_t __weak_symbol
__ssp_real(readv)(int fd, const struct iovec *iov, int iovcnt)
{
diff --git a/lib/libc/sys/recvfrom.c b/lib/libc/sys/recvfrom.c
index 0cdbd8a4ccaa..f7e2dd2ca6c8 100644
--- a/lib/libc/sys/recvfrom.c
+++ b/lib/libc/sys/recvfrom.c
@@ -35,8 +35,6 @@
#include <ssp/ssp.h>
#include "libc_private.h"
-__weak_reference(__sys_recvfrom, __recvfrom);
-
ssize_t __weak_symbol
__ssp_real(recvfrom)(int s, void *buf, size_t len, int flags,
struct sockaddr * __restrict from, socklen_t * __restrict fromlen)
diff --git a/lib/libc/sys/recvmsg.c b/lib/libc/sys/recvmsg.c
index ce0f5e0478cd..7c820c47b325 100644
--- a/lib/libc/sys/recvmsg.c
+++ b/lib/libc/sys/recvmsg.c
@@ -35,8 +35,6 @@
#include <ssp/ssp.h>
#include "libc_private.h"
-__weak_reference(__sys_recvmsg, __recvmsg);
-
ssize_t __weak_symbol
__ssp_real(recvmsg)(int s, struct msghdr *msg, int flags)
{
diff --git a/lib/libc/sys/select.c b/lib/libc/sys/select.c
index bbbcfc8bf1e0..909449f17da8 100644
--- a/lib/libc/sys/select.c
+++ b/lib/libc/sys/select.c
@@ -33,8 +33,6 @@
#include <sys/select.h>
#include "libc_private.h"
-__weak_reference(__sys_select, __select);
-
#pragma weak select
int
select(int n, fd_set *rs, fd_set *ws, fd_set *es, struct timeval *t)
diff --git a/lib/libc/sys/sendmsg.c b/lib/libc/sys/sendmsg.c
index fd4e41837c48..6c5fb4021ce3 100644
--- a/lib/libc/sys/sendmsg.c
+++ b/lib/libc/sys/sendmsg.c
@@ -34,8 +34,6 @@
#include <sys/socket.h>
#include "libc_private.h"
-__weak_reference(__sys_sendmsg, __sendmsg);
-
#pragma weak sendmsg
ssize_t
sendmsg(int s, const struct msghdr *msg, int flags)
diff --git a/lib/libc/sys/sendto.c b/lib/libc/sys/sendto.c
index 708fc6ec9368..b8a173f434a9 100644
--- a/lib/libc/sys/sendto.c
+++ b/lib/libc/sys/sendto.c
@@ -34,8 +34,6 @@
#include <sys/socket.h>
#include "libc_private.h"
-__weak_reference(__sys_sendto, __sendto);
-
#pragma weak sendto
ssize_t
sendto(int s, const void *msg, size_t len, int flags,
diff --git a/lib/libc/sys/setcontext.c b/lib/libc/sys/setcontext.c
index 96b5dc115067..a750c4dfea30 100644
--- a/lib/libc/sys/setcontext.c
+++ b/lib/libc/sys/setcontext.c
@@ -33,7 +33,6 @@
#include <ucontext.h>
#include "libc_private.h"
-__weak_reference(__sys_setcontext, __setcontext);
__sym_compat(setcontext, __impl_setcontext, FBSD_1.0);
__weak_reference(setcontext, __impl_setcontext);
__sym_default(setcontext, setcontext, FBSD_1.2);
diff --git a/lib/libc/sys/sigaction.c b/lib/libc/sys/sigaction.c
index 809881ca4d3f..7ce177895c81 100644
--- a/lib/libc/sys/sigaction.c
+++ b/lib/libc/sys/sigaction.c
@@ -33,7 +33,6 @@
#include <signal.h>
#include "libc_private.h"
-__weak_reference(__sys_sigaction, __sigaction);
__weak_reference(sigaction, __libc_sigaction);
#pragma weak sigaction
diff --git a/lib/libc/sys/sigprocmask.c b/lib/libc/sys/sigprocmask.c
index 96cb9586509b..8b7fb6fb8e74 100644
--- a/lib/libc/sys/sigprocmask.c
+++ b/lib/libc/sys/sigprocmask.c
@@ -33,7 +33,6 @@
#include <signal.h>
#include "libc_private.h"
-__weak_reference(__sys_sigprocmask, __sigprocmask);
__weak_reference(sigprocmask, __libc_sigprocmask);
#pragma weak sigprocmask
diff --git a/lib/libc/sys/sigsuspend.c b/lib/libc/sys/sigsuspend.c
index e5a9495f9f39..ac117650ed1b 100644
--- a/lib/libc/sys/sigsuspend.c
+++ b/lib/libc/sys/sigsuspend.c
@@ -33,7 +33,6 @@
#include <signal.h>
#include "libc_private.h"
-__weak_reference(__sys_sigsuspend, __sigsuspend);
__weak_reference(sigsuspend, __libc_sigsuspend);
#pragma weak sigsuspend
diff --git a/lib/libc/sys/sigtimedwait.c b/lib/libc/sys/sigtimedwait.c
index 839e5fe4d992..4efa69555f39 100644
--- a/lib/libc/sys/sigtimedwait.c
+++ b/lib/libc/sys/sigtimedwait.c
@@ -33,8 +33,6 @@
#include <signal.h>
#include "libc_private.h"
-__weak_reference(__sys_sigtimedwait, __sigtimedwait);
-
#pragma weak sigtimedwait
int
sigtimedwait(const sigset_t * __restrict set, siginfo_t * __restrict info,
diff --git a/lib/libc/sys/sigwaitinfo.c b/lib/libc/sys/sigwaitinfo.c
index 611d09c3c221..e94777b731e6 100644
--- a/lib/libc/sys/sigwaitinfo.c
+++ b/lib/libc/sys/sigwaitinfo.c
@@ -33,8 +33,6 @@
#include <signal.h>
#include "libc_private.h"
-__weak_reference(__sys_sigwaitinfo, __sigwaitinfo);
-
#pragma weak sigwaitinfo
int
sigwaitinfo(const sigset_t * __restrict set, siginfo_t * __restrict info)
diff --git a/lib/libc/sys/swapcontext.c b/lib/libc/sys/swapcontext.c
index b69a5b19e698..69d4dfea16b5 100644
--- a/lib/libc/sys/swapcontext.c
+++ b/lib/libc/sys/swapcontext.c
@@ -35,7 +35,6 @@
#include <stddef.h>
#include "libc_private.h"
-__weak_reference(__sys_swapcontext, __swapcontext);
__sym_compat(swapcontext, __impl_swapcontext, FBSD_1.0);
__weak_reference(swapcontext, __impl_swapcontext);
__sym_default(swapcontext, swapcontext, FBSD_1.2);
diff --git a/lib/libc/sys/wait4.c b/lib/libc/sys/wait4.c
index 57b0071ef87f..1d30c2d44c19 100644
--- a/lib/libc/sys/wait4.c
+++ b/lib/libc/sys/wait4.c
@@ -33,8 +33,6 @@
#include <sys/wait.h>
#include "libc_private.h"
-__weak_reference(__sys_wait4, __wait4);
-
#pragma weak wait4
pid_t
wait4(pid_t pid, int *status, int options, struct rusage *ru)
diff --git a/lib/libc/sys/wait6.c b/lib/libc/sys/wait6.c
index 118a7ef6b99e..70817bdb441c 100644
--- a/lib/libc/sys/wait6.c
+++ b/lib/libc/sys/wait6.c
@@ -34,8 +34,6 @@
#include <signal.h>
#include "libc_private.h"
-__weak_reference(__sys_wait6, __wait6);
-
#pragma weak wait6
pid_t
wait6(idtype_t idtype, id_t id, int *status, int options, struct __wrusage *ru,
diff --git a/lib/libc/sys/write.c b/lib/libc/sys/write.c
index 5880856b8af8..15e2d22fdbc5 100644
--- a/lib/libc/sys/write.c
+++ b/lib/libc/sys/write.c
@@ -34,8 +34,6 @@
#include <unistd.h>
#include "libc_private.h"
-__weak_reference(__sys_write, __write);
-
#pragma weak write
ssize_t
write(int fd, const void *buf, size_t nbytes)
diff --git a/lib/libc/sys/writev.c b/lib/libc/sys/writev.c
index 9a32cb603ab8..b642c6af9a89 100644
--- a/lib/libc/sys/writev.c
+++ b/lib/libc/sys/writev.c
@@ -35,8 +35,6 @@
#include <unistd.h>
#include "libc_private.h"
-__weak_reference(__sys_writev, __writev);
-
#pragma weak writev
ssize_t
writev(int fd, const struct iovec *iov, int iovcnt)
diff --git a/lib/libc/tests/db/Makefile b/lib/libc/tests/db/Makefile
index f1f33bd2bafc..771569183584 100644
--- a/lib/libc/tests/db/Makefile
+++ b/lib/libc/tests/db/Makefile
@@ -7,6 +7,10 @@ PROGS+= h_lfsr
${PACKAGE}FILES+= README
+ATF_TESTS_C+= dbm_open_test
+ATF_TESTS_C+= dbm_perm_test
+ATF_TESTS_C+= dbm_nextkey_test
+
NETBSD_ATF_TESTS_C+= db_hash_seq_test
NETBSD_ATF_TESTS_SH+= db_test
ATF_TESTS_SH_SED_db_test= -e 's,/bin/csh,/bin/cat,g'
diff --git a/lib/libc/tests/db/dbm_nextkey_test.c b/lib/libc/tests/db/dbm_nextkey_test.c
new file mode 100644
index 000000000000..67b745efb196
--- /dev/null
+++ b/lib/libc/tests/db/dbm_nextkey_test.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2025 Klara, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <fcntl.h>
+#include <ndbm.h>
+#include <stdio.h>
+
+#include <atf-c.h>
+
+static const char *path = "tmp";
+static const char *dbname = "tmp.db";
+
+ATF_TC(dbm_nextkey_test);
+ATF_TC_HEAD(dbm_nextkey_test, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Check that dbm_nextkey always returns NULL after reaching the end of the database");
+}
+
+ATF_TC_BODY(dbm_nextkey_test, tc)
+{
+ DBM *db;
+ datum key, data;
+
+ data.dptr = "bar";
+ data.dsize = strlen("bar");
+ key.dptr = "foo";
+ key.dsize = strlen("foo");
+
+ db = dbm_open(path, O_RDWR | O_CREAT, 0755);
+ ATF_CHECK(db != NULL);
+ ATF_REQUIRE(atf_utils_file_exists(dbname));
+ ATF_REQUIRE(dbm_store(db, key, data, DBM_INSERT) != -1);
+
+ key = dbm_firstkey(db);
+ ATF_REQUIRE(key.dptr != NULL);
+ key = dbm_nextkey(db);
+ ATF_REQUIRE(key.dptr == NULL);
+ key = dbm_nextkey(db);
+ ATF_REQUIRE(key.dptr == NULL);
+
+ dbm_close(db);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, dbm_nextkey_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/db/dbm_open_test.c b/lib/libc/tests/db/dbm_open_test.c
new file mode 100644
index 000000000000..8a3e888bf72c
--- /dev/null
+++ b/lib/libc/tests/db/dbm_open_test.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2025 Klara, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <fcntl.h>
+#include <ndbm.h>
+#include <stdio.h>
+
+#include <atf-c.h>
+
+static const char *path = "tmp";
+static const char *dbname = "tmp.db";
+
+ATF_TC(dbm_open_missing_test);
+ATF_TC_HEAD(dbm_open_missing_test, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test dbm_open when creating a new database");
+}
+
+ATF_TC_BODY(dbm_open_missing_test, tc)
+{
+
+ /*
+ * POSIX.1 specifies that a missing database file should
+ * always get created if O_CREAT is present, except when
+ * O_EXCL is specified as well.
+ */
+ ATF_CHECK(dbm_open(path, O_RDONLY, 0755) == NULL);
+ ATF_REQUIRE(!atf_utils_file_exists(dbname));
+ ATF_CHECK(dbm_open(path, O_RDONLY | O_CREAT, 0755) != NULL);
+ ATF_REQUIRE(atf_utils_file_exists(dbname));
+ ATF_CHECK(dbm_open(path, O_RDONLY | O_CREAT | O_EXCL, 0755) == NULL);
+}
+
+ATF_TC_WITHOUT_HEAD(dbm_open_wronly_test);
+ATF_TC_BODY(dbm_open_wronly_test, tc)
+{
+ ATF_CHECK(dbm_open(path, O_WRONLY, 0755) == NULL);
+ ATF_REQUIRE(!atf_utils_file_exists(dbname));
+ ATF_CHECK(dbm_open(path, O_WRONLY | O_CREAT, 0755) != NULL);
+ ATF_REQUIRE(atf_utils_file_exists(dbname));
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, dbm_open_missing_test);
+ ATF_TP_ADD_TC(tp, dbm_open_wronly_test);
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/db/dbm_perm_test.c b/lib/libc/tests/db/dbm_perm_test.c
new file mode 100644
index 000000000000..c07210292014
--- /dev/null
+++ b/lib/libc/tests/db/dbm_perm_test.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2025 Klara, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <ndbm.h>
+#include <stdio.h>
+
+#include <atf-c.h>
+
+static const char *path = "tmp";
+static const char *dbname = "tmp.db";
+
+static void
+create_db(void)
+{
+ DB *db;
+ datum data, key;
+
+ data.dptr = "bar";
+ data.dsize = strlen("bar");
+ key.dptr = "foo";
+ key.dsize = strlen("foo");
+
+ db = dbm_open(path, O_RDWR | O_CREAT, 0755);
+ ATF_CHECK(db != NULL);
+ ATF_REQUIRE(atf_utils_file_exists(dbname));
+ ATF_REQUIRE(dbm_store(db, key, data, DBM_INSERT) != -1);
+ dbm_close(db);
+}
+
+ATF_TC_WITHOUT_HEAD(dbm_rdonly_test);
+ATF_TC_BODY(dbm_rdonly_test, tc)
+{
+ DB *db;
+ datum data, key;
+
+ bzero(&data, sizeof(data));
+ key.dptr = "foo";
+ key.dsize = strlen("foo");
+ create_db();
+
+ db = dbm_open(path, O_RDONLY, 0755);
+ data = dbm_fetch(db, key);
+ ATF_REQUIRE(data.dptr != NULL);
+ ATF_REQUIRE(strncmp((const char*)data.dptr, "bar", data.dsize) == 0);
+ ATF_REQUIRE(dbm_store(db, key, data, DBM_REPLACE) == -1);
+ ATF_REQUIRE(errno == EPERM);
+}
+
+ATF_TC_WITHOUT_HEAD(dbm_wronly_test);
+ATF_TC_BODY(dbm_wronly_test, tc)
+{
+ DB *db;
+ datum data, key;
+
+ key.dptr = "foo";
+ key.dsize = strlen("foo");
+ data.dptr = "baz";
+ data.dsize = strlen("baz");
+ create_db();
+
+ db = dbm_open(path, O_WRONLY, 0755);
+ data = dbm_fetch(db, key);
+ ATF_REQUIRE(data.dptr == NULL);
+ ATF_REQUIRE(errno == EPERM);
+ ATF_REQUIRE(dbm_store(db, key, data, DBM_REPLACE) != -1);
+}
+
+ATF_TC_WITHOUT_HEAD(dbm_rdwr_test);
+ATF_TC_BODY(dbm_rdwr_test, tc)
+{
+ DB *db;
+ datum data, key;
+
+ key.dptr = "foo";
+ key.dsize = strlen("foo");
+ create_db();
+
+ db = dbm_open(path, O_RDWR, 0755);
+ data = dbm_fetch(db, key);
+ ATF_REQUIRE(data.dptr != NULL);
+ data.dptr = "baz";
+ data.dsize = strlen("baz");
+ ATF_REQUIRE(dbm_store(db, key, data, DBM_REPLACE) != -1);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, dbm_rdonly_test);
+ ATF_TP_ADD_TC(tp, dbm_wronly_test);
+ ATF_TP_ADD_TC(tp, dbm_rdwr_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/gen/posix_spawn_test.c b/lib/libc/tests/gen/posix_spawn_test.c
index 77c3b5a569d9..22133cf1d59a 100644
--- a/lib/libc/tests/gen/posix_spawn_test.c
+++ b/lib/libc/tests/gen/posix_spawn_test.c
@@ -29,8 +29,11 @@
* IEEE Std. 1003.1-2008.
*/
+#include <sys/param.h>
+#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -38,6 +41,10 @@
#include <atf-c.h>
+static const char true_script[] =
+ "#!/usr/bin/env\n"
+ "/usr/bin/true\n";
+
char *myenv[2] = { "answer=42", NULL };
ATF_TC_WITHOUT_HEAD(posix_spawn_simple_test);
@@ -124,6 +131,48 @@ ATF_TC_BODY(posix_spawnp_enoexec_fallback_null_argv0, tc)
ATF_REQUIRE(error == EINVAL);
}
+ATF_TC(posix_spawnp_eacces);
+ATF_TC_HEAD(posix_spawnp_eacces, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Verify EACCES behavior in posix_spawnp");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+ATF_TC_BODY(posix_spawnp_eacces, tc)
+{
+ const struct spawnp_eacces_tc {
+ const char *pathvar;
+ int error_expected;
+ } spawnp_eacces_tests[] = {
+ { ".", EACCES }, /* File exists, but not +x */
+ { "unsearchable", ENOENT }, /* File exists, dir not +x */
+ };
+ char *myargs[2] = { "eacces", NULL };
+ int error;
+
+ error = mkdir("unsearchable", 0755);
+ ATF_REQUIRE(error == 0);
+ error = symlink("/usr/bin/true", "unsearchable/eacces");
+ ATF_REQUIRE(error == 0);
+
+ (void)chmod("unsearchable", 0444);
+
+ /* this will create a non-executable file */
+ atf_utils_create_file("eacces", true_script);
+
+ for (size_t i = 0; i < nitems(spawnp_eacces_tests); i++) {
+ const struct spawnp_eacces_tc *tc = &spawnp_eacces_tests[i];
+ pid_t pid;
+
+ error = setenv("PATH", tc->pathvar, 1);
+ ATF_REQUIRE_EQ(0, error);
+
+ error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs,
+ myenv);
+ ATF_CHECK_INTEQ_MSG(tc->error_expected, error,
+ "path '%s'", tc->pathvar);
+ }
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -131,6 +180,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, posix_spawn_no_such_command_negative_test);
ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback);
ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback_null_argv0);
+ ATF_TP_ADD_TC(tp, posix_spawnp_eacces);
return (atf_no_error());
}
diff --git a/lib/libc/tests/gen/realpath2_test.c b/lib/libc/tests/gen/realpath2_test.c
index f89dd99cbb72..431df8721ae0 100644
--- a/lib/libc/tests/gen/realpath2_test.c
+++ b/lib/libc/tests/gen/realpath2_test.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2017 Jan Kokemüller
* All rights reserved.
+ * Copyright (c) 2025 Klara, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,6 +26,8 @@
*/
#include <sys/param.h>
+#include <sys/stat.h>
+
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -34,6 +37,31 @@
#include <atf-c.h>
+ATF_TC(realpath_null);
+ATF_TC_HEAD(realpath_null, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test null input");
+}
+ATF_TC_BODY(realpath_null, tc)
+{
+ ATF_REQUIRE_ERRNO(EINVAL, realpath(NULL, NULL) == NULL);
+}
+
+ATF_TC(realpath_empty);
+ATF_TC_HEAD(realpath_empty, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test empty input");
+}
+ATF_TC_BODY(realpath_empty, tc)
+{
+ char resb[PATH_MAX] = "";
+
+ ATF_REQUIRE_EQ(0, mkdir("foo", 0755));
+ ATF_REQUIRE_EQ(0, chdir("foo"));
+ ATF_REQUIRE_ERRNO(ENOENT, realpath("", resb) == NULL);
+ ATF_REQUIRE_STREQ("", resb);
+}
+
ATF_TC(realpath_buffer_overflow);
ATF_TC_HEAD(realpath_buffer_overflow, tc)
{
@@ -44,16 +72,11 @@ ATF_TC_HEAD(realpath_buffer_overflow, tc)
ATF_TC_BODY(realpath_buffer_overflow, tc)
{
- char path[MAXPATHLEN] = { 0 };
- char resb[MAXPATHLEN] = { 0 };
- size_t i;
+ char path[PATH_MAX] = "";
+ char resb[PATH_MAX] = "";
- path[0] = 'a';
+ memset(path, 'a', sizeof(path) - 1);
path[1] = '/';
- for (i = 2; i < sizeof(path) - 1; ++i) {
- path[i] = 'a';
- }
-
ATF_REQUIRE(realpath(path, resb) == NULL);
}
@@ -66,9 +89,9 @@ ATF_TC_HEAD(realpath_empty_symlink, tc)
ATF_TC_BODY(realpath_empty_symlink, tc)
{
- char path[MAXPATHLEN] = { 0 };
- char slnk[MAXPATHLEN] = { 0 };
- char resb[MAXPATHLEN] = { 0 };
+ char path[PATH_MAX] = "";
+ char slnk[PATH_MAX] = "";
+ char resb[PATH_MAX] = "";
int fd;
(void)strlcat(slnk, "empty_symlink", sizeof(slnk));
@@ -89,11 +112,70 @@ ATF_TC_BODY(realpath_empty_symlink, tc)
ATF_REQUIRE(unlink(slnk) == 0);
}
-ATF_TP_ADD_TCS(tp)
+ATF_TC(realpath_partial);
+ATF_TC_HEAD(realpath_partial, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that failure leaves a partial result");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(realpath_partial, tc)
{
+ char resb[PATH_MAX] = "";
+ size_t len;
+
+ /* scenario 1: missing directory */
+ ATF_REQUIRE_EQ(0, mkdir("foo", 0755));
+ ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL);
+ len = strnlen(resb, sizeof(resb));
+ ATF_REQUIRE(len > 8 && len < sizeof(resb));
+ ATF_REQUIRE_STREQ("/foo/bar", resb + len - 8);
+
+ /* scenario 2: dead link 1 */
+ ATF_REQUIRE_EQ(0, symlink("nix", "foo/bar"));
+ ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL);
+ len = strnlen(resb, sizeof(resb));
+ ATF_REQUIRE(len > 8 && len < sizeof(resb));
+ ATF_REQUIRE_STREQ("/foo/nix", resb + len - 8);
+
+ /* scenario 3: missing file */
+ ATF_REQUIRE_EQ(0, unlink("foo/bar"));
+ ATF_REQUIRE_EQ(0, mkdir("foo/bar", 0755));
+ ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL);
+ len = strnlen(resb, sizeof(resb));
+ ATF_REQUIRE(len > 12 && len < sizeof(resb));
+ ATF_REQUIRE_STREQ("/foo/bar/baz", resb + len - 12);
+
+ /* scenario 4: dead link 2 */
+ ATF_REQUIRE_EQ(0, symlink("nix", "foo/bar/baz"));
+ ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL);
+ len = strnlen(resb, sizeof(resb));
+ ATF_REQUIRE(len > 12 && len < sizeof(resb));
+ ATF_REQUIRE_STREQ("/foo/bar/nix", resb + len - 12);
+
+ /* scenario 5: unreadable directory */
+ ATF_REQUIRE_EQ(0, chmod("foo", 000));
+ ATF_REQUIRE_ERRNO(EACCES, realpath("foo/bar/baz", resb) == NULL);
+ len = strnlen(resb, sizeof(resb));
+ ATF_REQUIRE(len > 4 && len < sizeof(resb));
+ ATF_REQUIRE_STREQ("/foo", resb + len - 4);
+
+ /* scenario 6: not a directory */
+ ATF_REQUIRE_EQ(0, close(creat("bar", 0644)));
+ ATF_REQUIRE_ERRNO(ENOTDIR, realpath("bar/baz", resb) == NULL);
+ len = strnlen(resb, sizeof(resb));
+ ATF_REQUIRE(len > 4 && len < sizeof(resb));
+ ATF_REQUIRE_STREQ("/bar", resb + len - 4);
+}
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, realpath_null);
+ ATF_TP_ADD_TC(tp, realpath_empty);
ATF_TP_ADD_TC(tp, realpath_buffer_overflow);
ATF_TP_ADD_TC(tp, realpath_empty_symlink);
+ ATF_TP_ADD_TC(tp, realpath_partial);
return atf_no_error();
}
diff --git a/lib/libc/tests/net/Makefile b/lib/libc/tests/net/Makefile
index 24cff61e8d24..ec0668633508 100644
--- a/lib/libc/tests/net/Makefile
+++ b/lib/libc/tests/net/Makefile
@@ -4,8 +4,10 @@ ATF_TESTS_C+= ether_test
ATF_TESTS_C+= eui64_aton_test
ATF_TESTS_C+= eui64_ntoa_test
ATF_TESTS_CXX+= link_addr_test
+ATF_TESTS_CXX+= inet_net_test
CXXSTD.link_addr_test= c++20
+CXXSTD.inet_net_test= c++20
CFLAGS+= -I${.CURDIR}
diff --git a/lib/libc/tests/net/inet_net_test.cc b/lib/libc/tests/net/inet_net_test.cc
new file mode 100644
index 000000000000..60b60b152eca
--- /dev/null
+++ b/lib/libc/tests/net/inet_net_test.cc
@@ -0,0 +1,333 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2025 Lexi Winter <ivy@FreeBSD.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Tests for inet_net_pton() and inet_net_ntop().
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ranges>
+#include <string>
+#include <vector>
+
+#include <atf-c++.hpp>
+
+using namespace std::literals;
+
+/*
+ * inet_net_ntop() and inet_net_pton() for IPv4.
+ */
+ATF_TEST_CASE_WITHOUT_HEAD(inet_net_inet4)
+ATF_TEST_CASE_BODY(inet_net_inet4)
+{
+ /*
+ * Define a list of addresses we want to check. Each address is passed
+ * to inet_net_pton() to convert it to an in_addr, then we convert the
+ * in_addr back to a string and compare it with the expected value. We
+ * want to test over-long prefixes here (such as 10.0.0.1/8), so we also
+ * specify what the result is expected to be.
+ */
+
+ struct test_addr {
+ std::string input;
+ int bits;
+ std::string output;
+ };
+
+ auto test_addrs = std::vector<test_addr>{
+ // Simple prefixes that fall on octet boundaries.
+ { "10.0.0.0/8", 8, "10/8" },
+ { "10.1.0.0/16", 16, "10.1/16" },
+ { "10.1.2.0/24", 24, "10.1.2/24" },
+ { "10.1.2.3/32", 32, "10.1.2.3/32" },
+
+ // Simple prefixes with the short-form address.
+ { "10/8", 8, "10/8" },
+ { "10.1/16", 16, "10.1/16" },
+ { "10.1.2/24", 24, "10.1.2/24" },
+
+ // A prefix that doesn't fall on an octet boundary.
+ { "10.1.64/18", 18, "10.1.64/18" },
+
+ // An overlong prefix with bits that aren't part of the prefix.
+ { "10.0.0.1/8", 8, "10/8" },
+ };
+
+ for (auto const &addr: test_addrs) {
+ /*
+ * Convert the input string to an in_addr + bits, and make
+ * sure the result produces the number of bits we expected.
+ */
+
+ auto in = in_addr{};
+ auto bits = inet_net_pton(AF_INET, addr.input.c_str(),
+ &in, sizeof(in));
+ ATF_REQUIRE(bits != -1);
+ ATF_REQUIRE_EQ(bits, addr.bits);
+
+ /*
+ * Convert the in_addr back to a string
+ */
+
+ /*
+ * XXX: Should there be a constant for the size of the result
+ * buffer? For now, use ADDRSTRLEN + 3 ("/32") + 1 (NUL).
+ *
+ * Fill the buffer with 'Z', so we can check the result was
+ * properly terminated.
+ */
+ auto strbuf = std::vector<char>(INET_ADDRSTRLEN + 3 + 1, 'Z');
+ auto ret = inet_net_ntop(AF_INET, &in, bits,
+ strbuf.data(), strbuf.size());
+ ATF_REQUIRE(ret != NULL);
+ ATF_REQUIRE_EQ(ret, strbuf.data());
+
+ /* Make sure the result was NUL-terminated and find the NUL */
+ ATF_REQUIRE(strbuf.size() >= 1);
+ auto end = std::ranges::find(strbuf, '\0');
+ ATF_REQUIRE(end != strbuf.end());
+
+ /*
+ * Check the result matches what we expect. Use a temporary
+ * string here instead of std::ranges::equal because this
+ * means ATF can print the mismatch.
+ */
+ auto str = std::string(std::ranges::begin(strbuf), end);
+ ATF_REQUIRE_EQ(str, addr.output);
+ }
+}
+
+/*
+ * inet_net_ntop() and inet_net_pton() for IPv6.
+ */
+ATF_TEST_CASE_WITHOUT_HEAD(inet_net_inet6)
+ATF_TEST_CASE_BODY(inet_net_inet6)
+{
+ /*
+ * Define a list of addresses we want to check. Each address is
+ * passed to inet_net_pton() to convert it to an in6_addr, then we
+ * convert the in6_addr back to a string and compare it with the
+ * expected value. We want to test over-long prefixes here (such
+ * as 2001:db8::1/32), so we also specify what the result is
+ * expected to be.
+ */
+
+ struct test_addr {
+ std::string input;
+ int bits;
+ std::string output;
+ };
+
+ auto test_addrs = std::vector<test_addr>{
+ // A prefix with a trailing ::
+ { "2001:db8::/32", 32, "2001:db8::/32" },
+
+ // A prefix with a leading ::. Note that the output is
+ // different from the input because inet_ntop() renders
+ // this prefix with an IPv4 suffix for legacy reasons.
+ { "::ffff:0:0/96", 96, "::ffff:0.0.0.0/96" },
+
+ // The same prefix but with the IPv4 legacy form as input.
+ { "::ffff:0.0.0.0/96", 96, "::ffff:0.0.0.0/96" },
+
+ // A prefix with an infix ::.
+ { "2001:db8::1/128", 128, "2001:db8::1/128" },
+
+ // A prefix with bits set which are outside the prefix;
+ // these should be silently ignored.
+ { "2001:db8:1:1:1:1:1:1/32", 32, "2001:db8::/32" },
+
+ // As above but with infix ::.
+ { "2001:db8::1/32", 32, "2001:db8::/32" },
+
+ // A prefix with only ::, commonly used to represent the
+ // entire address space.
+ { "::/0", 0, "::/0" },
+
+ // A single address with no ::.
+ { "2001:db8:1:1:1:1:1:1/128", 128, "2001:db8:1:1:1:1:1:1/128" },
+
+ // A prefix with no ::.
+ { "2001:db8:1:1:0:0:0:0/64", 64, "2001:db8:1:1::/64" },
+
+ // A prefix which isn't on a 16-bit boundary.
+ { "2001:db8:c000::/56", 56, "2001:db8:c000::/56" },
+
+ // A prefix which isn't on a nibble boundary.
+ { "2001:db8:c100::/57", 57, "2001:db8:c100::/57" },
+
+ // An address without a prefix length, which should be treated
+ // as a /128.
+ { "2001:db8::", 128, "2001:db8::/128" },
+ { "2001:db8::1", 128, "2001:db8::1/128" },
+
+ // Test vectors provided in PR bin/289198.
+ { "fe80::1/64", 64, "fe80::/64" },
+ { "fe80::f000:74ff:fe54:bed2/64",
+ 64, "fe80::/64" },
+ { "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/64",
+ 64, "ffff:ffff:ffff:ffff::/64" },
+ { "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128,
+ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" },
+ };
+
+ for (auto const &addr: test_addrs) {
+ /*
+ * Convert the input string to an in6_addr + bits, and make
+ * sure the result produces the number of bits we expected.
+ */
+
+ auto in6 = in6_addr{};
+ errno = 0;
+ auto bits = inet_net_pton(AF_INET6, addr.input.c_str(),
+ &in6, sizeof(in6));
+ ATF_REQUIRE(bits != -1);
+ ATF_REQUIRE_EQ(bits, addr.bits);
+
+ /*
+ * Convert the in6_addr back to a string
+ */
+
+ /*
+ * XXX: Should there be a constant for the size of the result
+ * buffer? For now, use ADDRSTRLEN + 4 ("/128") + 1 (NUL).
+ *
+ * Fill the buffer with 'Z', so we can check the result was
+ * properly terminated.
+ */
+ auto strbuf = std::vector<char>(INET6_ADDRSTRLEN + 4 + 1, 'Z');
+ auto ret = inet_net_ntop(AF_INET6, &in6, bits,
+ strbuf.data(), strbuf.size());
+ ATF_REQUIRE(ret != NULL);
+ ATF_REQUIRE_EQ(ret, strbuf.data());
+
+ /* Make sure the result was NUL-terminated and find the NUL */
+ ATF_REQUIRE(strbuf.size() >= 1);
+ auto end = std::ranges::find(strbuf, '\0');
+ ATF_REQUIRE(end != strbuf.end());
+
+ /*
+ * Check the result matches what we expect. Use a temporary
+ * string here instead of std::ranges::equal because this
+ * means ATF can print the mismatch.
+ */
+ auto str = std::string(std::ranges::begin(strbuf), end);
+ ATF_REQUIRE_EQ(str, addr.output);
+ }
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(inet_net_pton_invalid)
+ATF_TEST_CASE_BODY(inet_net_pton_invalid)
+{
+ auto ret = int{};
+ auto addr4 = in_addr{};
+ auto str4 = "10.0.0.0"s;
+ auto addr6 = in6_addr{};
+ auto str6 = "2001:db8::"s;
+
+ /* Passing an address which is too short should be an error */
+ ret = inet_net_pton(AF_INET6, str6.c_str(), &addr6, sizeof(addr6) - 1);
+ ATF_REQUIRE_EQ(ret, -1);
+
+ ret = inet_net_pton(AF_INET, str4.c_str(), &addr4, sizeof(addr4) - 1);
+ ATF_REQUIRE_EQ(ret, -1);
+
+ /* Test some generally invalid addresses. */
+ auto invalid4 = std::vector<std::string>{
+ // Prefix length too big
+ "10.0.0.0/33",
+ // Prefix length is negative
+ "10.0.0.0/-1",
+ // Prefix length is not a number
+ "10.0.0.0/foo",
+ // Input is not a network prefix
+ "this is not an IP address",
+ };
+
+ for (auto const &addr: invalid4) {
+ auto ret = inet_net_pton(AF_INET, addr.c_str(), &addr4,
+ sizeof(addr4));
+ ATF_REQUIRE_EQ(ret, -1);
+ }
+
+ auto invalid6 = std::vector<std::string>{
+ // Prefix length too big
+ "2001:db8::/129",
+ // Prefix length is negative
+ "2001:db8::/-1",
+ // Prefix length is not a number
+ "2001:db8::/foo",
+ // Input is not a network prefix
+ "this is not an IP address",
+ };
+
+ for (auto const &addr: invalid6) {
+ auto ret = inet_net_pton(AF_INET6, addr.c_str(), &addr6,
+ sizeof(addr6));
+ ATF_REQUIRE_EQ(ret, -1);
+ }
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(inet_net_ntop_invalid)
+ATF_TEST_CASE_BODY(inet_net_ntop_invalid)
+{
+ auto addr4 = in_addr{};
+ auto addr6 = in6_addr{};
+ auto strbuf = std::vector<char>(INET6_ADDRSTRLEN + 4 + 1);
+
+ /*
+ * Passing a buffer which is too small should not overrun the buffer.
+ * Test this by initialising the buffer to 'Z', and only providing
+ * part of it to the function.
+ */
+
+ std::ranges::fill(strbuf, 'Z');
+ auto ret = inet_net_ntop(AF_INET6, &addr6, 128, strbuf.data(), 1);
+ ATF_REQUIRE_EQ(ret, nullptr);
+ ATF_REQUIRE_EQ(strbuf[1], 'Z');
+
+ std::ranges::fill(strbuf, 'Z');
+ ret = inet_net_ntop(AF_INET, &addr4, 32, strbuf.data(), 1);
+ ATF_REQUIRE_EQ(ret, nullptr);
+ ATF_REQUIRE_EQ(strbuf[1], 'Z');
+
+ /* Check that invalid prefix lengths return an error */
+
+ ret = inet_net_ntop(AF_INET6, &addr6, 129, strbuf.data(), strbuf.size());
+ ATF_REQUIRE_EQ(ret, nullptr);
+ ret = inet_net_ntop(AF_INET6, &addr6, -1, strbuf.data(), strbuf.size());
+ ATF_REQUIRE_EQ(ret, nullptr);
+
+ ret = inet_net_ntop(AF_INET, &addr4, 33, strbuf.data(), strbuf.size());
+ ATF_REQUIRE_EQ(ret, nullptr);
+ ret = inet_net_ntop(AF_INET, &addr4, -1, strbuf.data(), strbuf.size());
+ ATF_REQUIRE_EQ(ret, nullptr);
+}
+
+ATF_INIT_TEST_CASES(tcs)
+{
+ ATF_ADD_TEST_CASE(tcs, inet_net_inet4);
+ ATF_ADD_TEST_CASE(tcs, inet_net_inet6);
+ ATF_ADD_TEST_CASE(tcs, inet_net_pton_invalid);
+ ATF_ADD_TEST_CASE(tcs, inet_net_ntop_invalid);
+}
diff --git a/lib/libc/tests/stdio/flushlbuf_test.c b/lib/libc/tests/stdio/flushlbuf_test.c
index 11d9ea4ecc6c..3f8a6378f933 100644
--- a/lib/libc/tests/stdio/flushlbuf_test.c
+++ b/lib/libc/tests/stdio/flushlbuf_test.c
@@ -22,22 +22,23 @@ struct stream {
unsigned int pos;
};
-static int writefn(void *cookie, const char *buf, int len)
+static int
+writefn(void *cookie, const char *buf, int len)
{
struct stream *s = cookie;
int written = 0;
if (len <= 0)
- return 0;
+ return (0);
while (len > 0 && s->pos < s->len) {
s->buf[s->pos++] = *buf++;
written++;
len--;
}
if (written > 0)
- return written;
+ return (written);
errno = EAGAIN;
- return -1;
+ return (-1);
}
ATF_TC_WITHOUT_HEAD(flushlbuf_partial);
@@ -147,7 +148,6 @@ ATF_TC_BODY(flushlbuf_full, tc)
ATF_TP_ADD_TCS(tp)
{
-
ATF_TP_ADD_TC(tp, flushlbuf_partial);
ATF_TP_ADD_TC(tp, flushlbuf_full);
diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c
index 031859124163..4493fe1c15d3 100644
--- a/lib/libc/tests/stdio/printfloat_test.c
+++ b/lib/libc/tests/stdio/printfloat_test.c
@@ -398,6 +398,18 @@ ATF_TC_BODY(subnormal_float, tc)
testfmt("-0X1P-149", "%A", negative);
}
+ATF_TC_WITHOUT_HEAD(hexadecimal_rounding_fullprec);
+ATF_TC_BODY(hexadecimal_rounding_fullprec, tc)
+{
+ /* Double: %.13a with binary64 mantissa=53 */
+ testfmt("0x1.1234567890bbbp+0", "%.13a", 0x1.1234567890bbbp+0);
+
+#if defined(__aarch64__)
+ /* On arm64, long double is IEEE binary128 (mantissa=113) */
+ testfmt("0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0", "%.28La", 0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0L);
+#endif
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -414,6 +426,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, hexadecimal_rounding);
ATF_TP_ADD_TC(tp, subnormal_double);
ATF_TP_ADD_TC(tp, subnormal_float);
+ ATF_TP_ADD_TC(tp, hexadecimal_rounding_fullprec);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/sscanf_test.c b/lib/libc/tests/stdio/sscanf_test.c
index e916873d38c3..e43292820eeb 100644
--- a/lib/libc/tests/stdio/sscanf_test.c
+++ b/lib/libc/tests/stdio/sscanf_test.c
@@ -68,6 +68,31 @@ static const struct sscanf_test_case {
{ "0e", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
{ "0f", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
{ "0x", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
+ // all digits with two leading zeroes
+ { "000", { 1, 0, 3 }, { 1, 0, 3 }, { 1, 0, 3 }, { 1, 0, 3 }, { 1, 0, 3 }, },
+ { "001", { 1, 1, 3 }, { 1, 1, 3 }, { 1, 1, 3 }, { 1, 1, 3 }, { 1, 1, 3 }, },
+ { "002", { 1, 0, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, },
+ { "003", { 1, 0, 2 }, { 1, 3, 3 }, { 1, 3, 3 }, { 1, 3, 3 }, { 1, 3, 3 }, },
+ { "004", { 1, 0, 2 }, { 1, 4, 3 }, { 1, 4, 3 }, { 1, 4, 3 }, { 1, 4, 3 }, },
+ { "005", { 1, 0, 2 }, { 1, 5, 3 }, { 1, 5, 3 }, { 1, 5, 3 }, { 1, 5, 3 }, },
+ { "006", { 1, 0, 2 }, { 1, 6, 3 }, { 1, 6, 3 }, { 1, 6, 3 }, { 1, 6, 3 }, },
+ { "007", { 1, 0, 2 }, { 1, 7, 3 }, { 1, 7, 3 }, { 1, 7, 3 }, { 1, 7, 3 }, },
+ { "008", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 8, 3 }, { 1, 8, 3 }, { 1, 0, 2 }, },
+ { "009", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 9, 3 }, { 1, 9, 3 }, { 1, 0, 2 }, },
+ { "00A", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 10, 3 }, { 1, 0, 2 }, },
+ { "00B", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 11, 3 }, { 1, 0, 2 }, },
+ { "00C", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 12, 3 }, { 1, 0, 2 }, },
+ { "00D", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 13, 3 }, { 1, 0, 2 }, },
+ { "00E", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 14, 3 }, { 1, 0, 2 }, },
+ { "00F", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 15, 3 }, { 1, 0, 2 }, },
+ { "00X", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, },
+ { "00a", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 10, 3 }, { 1, 0, 2 }, },
+ { "00b", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 11, 3 }, { 1, 0, 2 }, },
+ { "00c", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 12, 3 }, { 1, 0, 2 }, },
+ { "00d", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 13, 3 }, { 1, 0, 2 }, },
+ { "00e", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 14, 3 }, { 1, 0, 2 }, },
+ { "00f", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 15, 3 }, { 1, 0, 2 }, },
+ { "00x", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, },
// all digits with leading one
{ "10", { 1, 2, 2 }, { 1, 8, 2 }, { 1, 10, 2 }, { 1, 16, 2 }, { 1, 10, 2 }, },
{ "11", { 1, 3, 2 }, { 1, 9, 2 }, { 1, 11, 2 }, { 1, 17, 2 }, { 1, 11, 2 }, },
diff --git a/lib/libc/tests/stdio/swscanf_test.c b/lib/libc/tests/stdio/swscanf_test.c
index f7ad30b963a7..f0638081e16f 100644
--- a/lib/libc/tests/stdio/swscanf_test.c
+++ b/lib/libc/tests/stdio/swscanf_test.c
@@ -71,6 +71,31 @@ static const struct swscanf_test_case {
{ L"0e", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
{ L"0f", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
{ L"0x", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
+ // all digits with two leading zeroes
+ { L"000", { 1, 0, 3 }, { 1, 0, 3 }, { 1, 0, 3 }, { 1, 0, 3 }, { 1, 0, 3 }, },
+ { L"001", { 1, 1, 3 }, { 1, 1, 3 }, { 1, 1, 3 }, { 1, 1, 3 }, { 1, 1, 3 }, },
+ { L"002", { 1, 0, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, },
+ { L"003", { 1, 0, 2 }, { 1, 3, 3 }, { 1, 3, 3 }, { 1, 3, 3 }, { 1, 3, 3 }, },
+ { L"004", { 1, 0, 2 }, { 1, 4, 3 }, { 1, 4, 3 }, { 1, 4, 3 }, { 1, 4, 3 }, },
+ { L"005", { 1, 0, 2 }, { 1, 5, 3 }, { 1, 5, 3 }, { 1, 5, 3 }, { 1, 5, 3 }, },
+ { L"006", { 1, 0, 2 }, { 1, 6, 3 }, { 1, 6, 3 }, { 1, 6, 3 }, { 1, 6, 3 }, },
+ { L"007", { 1, 0, 2 }, { 1, 7, 3 }, { 1, 7, 3 }, { 1, 7, 3 }, { 1, 7, 3 }, },
+ { L"008", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 8, 3 }, { 1, 8, 3 }, { 1, 0, 2 }, },
+ { L"009", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 9, 3 }, { 1, 9, 3 }, { 1, 0, 2 }, },
+ { L"00A", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 10, 3 }, { 1, 0, 2 }, },
+ { L"00B", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 11, 3 }, { 1, 0, 2 }, },
+ { L"00C", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 12, 3 }, { 1, 0, 2 }, },
+ { L"00D", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 13, 3 }, { 1, 0, 2 }, },
+ { L"00E", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 14, 3 }, { 1, 0, 2 }, },
+ { L"00F", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 15, 3 }, { 1, 0, 2 }, },
+ { L"00X", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, },
+ { L"00a", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 10, 3 }, { 1, 0, 2 }, },
+ { L"00b", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 11, 3 }, { 1, 0, 2 }, },
+ { L"00c", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 12, 3 }, { 1, 0, 2 }, },
+ { L"00d", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 13, 3 }, { 1, 0, 2 }, },
+ { L"00e", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 14, 3 }, { 1, 0, 2 }, },
+ { L"00f", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 15, 3 }, { 1, 0, 2 }, },
+ { L"00x", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, },
// all digits with leading one
{ L"10", { 1, 2, 2 }, { 1, 8, 2 }, { 1, 10, 2 }, { 1, 16, 2 }, { 1, 10, 2 }, },
{ L"11", { 1, 3, 2 }, { 1, 9, 2 }, { 1, 11, 2 }, { 1, 17, 2 }, { 1, 11, 2 }, },
diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile
index 50726a5d8af6..9d84becfbd1f 100644
--- a/lib/libc/tests/stdlib/Makefile
+++ b/lib/libc/tests/stdlib/Makefile
@@ -14,6 +14,7 @@ ATF_TESTS_C+= qsort_b_test
ATF_TESTS_C+= qsort_r_compat_test
ATF_TESTS_C+= qsort_r_test
ATF_TESTS_C+= qsort_s_test
+ATF_TESTS_C+= qsort_bench
ATF_TESTS_C+= set_constraint_handler_s_test
ATF_TESTS_C+= strfmon_test
ATF_TESTS_C+= tsearch_test
diff --git a/lib/libc/tests/stdlib/qsort_bench.c b/lib/libc/tests/stdlib/qsort_bench.c
new file mode 100644
index 000000000000..5f2cfae40140
--- /dev/null
+++ b/lib/libc/tests/stdlib/qsort_bench.c
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <atf-c.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+/*-
+ * Measures qsort(3) runtime with pathological input and verify that it
+ * stays close to N * log2(N).
+ *
+ * Thanks to Vivian Hussey for the proof of concept.
+ *
+ * The input we construct is similar to a sweep from 0 to N where each
+ * half, except for the first element, has been reversed; for instance,
+ * with N = 8, we get { 0, 3, 2, 1, 4, 8, 7, 6 }. This triggers a bug in
+ * the BSD qsort(3) where it will switch to insertion sort if the pivots
+ * are sorted.
+ *
+ * This article goes into more detail about the bug and its origin:
+ *
+ * https://www.raygard.net/2022/02/26/Re-engineering-a-qsort-part-3
+ *
+ * With this optimization (the `if (swap_cnt == 0)` block), qsort(3) needs
+ * roughly N * N / 4 comparisons to sort our pathological input. Without
+ * it, it needs only a little more than N * log2(N) comparisons.
+ */
+
+/* we stop testing once a single takes longer than this */
+#define MAXRUNSECS 10
+
+static bool debugging;
+
+static uintmax_t ncmp;
+
+static int
+intcmp(const void *a, const void *b)
+{
+ ncmp++;
+ return ((*(int *)a > *(int *)b) - (*(int *)a < *(int *)b));
+}
+
+static void
+qsort_bench(int log2n)
+{
+ uintmax_t n = 1LLU << log2n;
+ int *buf;
+
+ /* fill an array with a pathological pattern */
+ ATF_REQUIRE(buf = malloc(n * sizeof(*buf)));
+ buf[0] = 0;
+ buf[n / 2] = n / 2;
+ for (unsigned int i = 1; i < n / 2; i++) {
+ buf[i] = n / 2 - i;
+ buf[n / 2 + i] = n - i;
+ }
+
+ ncmp = 0;
+ qsort(buf, n, sizeof(*buf), intcmp);
+
+ /* check result and free array */
+ if (debugging) {
+ for (unsigned int i = 1; i < n; i++) {
+ ATF_REQUIRE_MSG(buf[i] > buf[i - 1],
+ "array is not sorted");
+ }
+ }
+ free(buf);
+
+ /* check that runtime does not exceed N² */
+ ATF_CHECK_MSG(ncmp / n < n,
+ "runtime %ju exceeds N² for N = %ju", ncmp, n);
+
+ /* check that runtime does not exceed N log N by much */
+ ATF_CHECK_MSG(ncmp / n <= log2n + 1,
+ "runtime %ju exceeds N log N for N = %ju", ncmp, n);
+}
+
+ATF_TC_WITHOUT_HEAD(qsort_bench);
+ATF_TC_BODY(qsort_bench, tc)
+{
+ struct timespec t0, t1;
+ uintmax_t tus;
+
+ for (int i = 10; i <= 30; i++) {
+ clock_gettime(CLOCK_UPTIME, &t0);
+ qsort_bench(i);
+ clock_gettime(CLOCK_UPTIME, &t1);
+ tus = t1.tv_sec * 1000000 + t1.tv_nsec / 1000;
+ tus -= t0.tv_sec * 1000000 + t0.tv_nsec / 1000;
+ if (debugging) {
+ fprintf(stderr, "N = 2^%d in %ju.%06jus\n",
+ i, tus / 1000000, tus % 1000000);
+ }
+ /* stop once an individual run exceeds our limit */
+ if (tus / 1000000 >= MAXRUNSECS)
+ break;
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") &&
+ isatty(STDERR_FILENO);
+ ATF_TP_ADD_TC(tp, qsort_bench);
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdtime/Makefile b/lib/libc/tests/stdtime/Makefile
index c7a7f5b9436f..590dea22da31 100644
--- a/lib/libc/tests/stdtime/Makefile
+++ b/lib/libc/tests/stdtime/Makefile
@@ -1,6 +1,12 @@
-.include <bsd.own.mk>
+.include <src.opts.mk>
ATF_TESTS_C+= strptime_test
+ATF_TESTS_C+= detect_tz_changes_test
+
+CFLAGS.detect_tz_changes_test+= -I${SRCTOP}/contrib/tzcode
+.if ${MK_DETECT_TZ_CHANGES} != "no"
+CFLAGS.detect_tz_changes_test+= -DDETECT_TZ_CHANGES
+.endif
TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/}
diff --git a/lib/libc/tests/stdtime/detect_tz_changes_test.c b/lib/libc/tests/stdtime/detect_tz_changes_test.c
new file mode 100644
index 000000000000..06c31c9fbc3d
--- /dev/null
+++ b/lib/libc/tests/stdtime/detect_tz_changes_test.c
@@ -0,0 +1,477 @@
+/*-
+ * Copyright (c) 2025 Klara, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "tzdir.h"
+
+#include <atf-c.h>
+
+struct tzcase {
+ const char *tzfn;
+ const char *expect;
+};
+
+static const struct tzcase tzcases[] = {
+ /*
+ * A handful of time zones and the expected result of
+ * strftime("%z (%Z)", tm) when that time zone is active
+ * and tm represents a date in the summer of 2025.
+ */
+ { "America/Vancouver", "-0700 (PDT)" },
+ { "America/New_York", "-0400 (EDT)" },
+ { "Europe/London", "+0100 (BST)" },
+ { "Europe/Paris", "+0200 (CEST)" },
+ { "Asia/Kolkata", "+0530 (IST)" },
+ { "Asia/Tokyo", "+0900 (JST)" },
+ { "Australia/Canberra", "+1000 (AEST)" },
+ { "UTC", "+0000 (UTC)" },
+ { 0 },
+};
+static const struct tzcase utc = { "UTC", "+0000 (UTC)" };
+static const struct tzcase invalid = { "invalid", "+0000 (-00)" };
+static const time_t then = 1751328000; /* 2025-07-01 00:00:00 UTC */
+
+static bool debugging;
+
+static void
+debug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (debugging) {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ }
+}
+
+static void
+change_tz(const char *tzn)
+{
+ static const char *zfn = TZDIR;
+ static const char *tfn = "root" TZDEFAULT ".tmp";
+ static const char *dfn = "root" TZDEFAULT;
+ ssize_t clen;
+ int zfd, sfd, dfd;
+
+ ATF_REQUIRE((zfd = open(zfn, O_DIRECTORY | O_SEARCH)) >= 0);
+ ATF_REQUIRE((sfd = openat(zfd, tzn, O_RDONLY)) >= 0);
+ ATF_REQUIRE((dfd = open(tfn, O_CREAT | O_TRUNC | O_WRONLY, 0644)) >= 0);
+ do {
+ clen = copy_file_range(sfd, NULL, dfd, NULL, SSIZE_MAX, 0);
+ ATF_REQUIRE_MSG(clen != -1, "failed to copy %s/%s: %m",
+ zfn, tzn);
+ } while (clen > 0);
+ ATF_CHECK_EQ(0, close(dfd));
+ ATF_CHECK_EQ(0, close(sfd));
+ ATF_CHECK_EQ(0, close(zfd));
+ ATF_REQUIRE_EQ(0, rename(tfn, dfn));
+ debug("time zone %s installed", tzn);
+}
+
+static void
+test_tz(const char *expect)
+{
+ char buf[128];
+ struct tm *tm;
+ size_t len;
+
+ ATF_REQUIRE((tm = localtime(&then)) != NULL);
+ len = strftime(buf, sizeof(buf), "%z (%Z)", tm);
+ ATF_REQUIRE(len > 0);
+ ATF_CHECK_STREQ(expect, buf);
+}
+
+ATF_TC(tz_default);
+ATF_TC_HEAD(tz_default, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test default zone");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_default, tc)
+{
+ /* prepare chroot with no /etc/localtime */
+ ATF_REQUIRE_EQ(0, mkdir("root", 0755));
+ ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755));
+ /* enter chroot */
+ ATF_REQUIRE_EQ(0, chroot("root"));
+ ATF_REQUIRE_EQ(0, chdir("/"));
+ /* check timezone */
+ unsetenv("TZ");
+ test_tz("+0000 (UTC)");
+}
+
+ATF_TC(tz_invalid_file);
+ATF_TC_HEAD(tz_invalid_file, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test invalid zone file");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_invalid_file, tc)
+{
+ static const char *dfn = "root/etc/localtime";
+ int fd;
+
+ /* prepare chroot with bogus /etc/localtime */
+ ATF_REQUIRE_EQ(0, mkdir("root", 0755));
+ ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755));
+ ATF_REQUIRE((fd = open(dfn, O_RDWR | O_CREAT, 0644)) >= 0);
+ ATF_REQUIRE_EQ(8, write(fd, "invalid\n", 8));
+ ATF_REQUIRE_EQ(0, close(fd));
+ /* enter chroot */
+ ATF_REQUIRE_EQ(0, chroot("root"));
+ ATF_REQUIRE_EQ(0, chdir("/"));
+ /* check timezone */
+ unsetenv("TZ");
+ test_tz(invalid.expect);
+}
+
+ATF_TC(thin_jail);
+ATF_TC_HEAD(thin_jail, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test typical thin jail scenario");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(thin_jail, tc)
+{
+ const struct tzcase *tzcase = tzcases;
+
+ /* prepare chroot */
+ ATF_REQUIRE_EQ(0, mkdir("root", 0755));
+ ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755));
+ change_tz(tzcase->tzfn);
+ /* enter chroot */
+ ATF_REQUIRE_EQ(0, chroot("root"));
+ ATF_REQUIRE_EQ(0, chdir("/"));
+ /* check timezone */
+ unsetenv("TZ");
+ test_tz(tzcase->expect);
+}
+
+#ifdef DETECT_TZ_CHANGES
+/*
+ * Test time zone change detection.
+ *
+ * The parent creates a chroot containing only /etc/localtime, initially
+ * set to UTC. It then forks a child which enters the chroot, repeatedly
+ * checks the current time zone, and prints it to stdout if it changes
+ * (including once on startup). Meanwhile, the parent waits for output
+ * from the child. Every time it receives a line of text from the child,
+ * it checks that it is as expected, then changes /etc/localtime within
+ * the chroot to the next case in the list. Once it reaches the end of
+ * the list, it closes a pipe to notify the child, which terminates.
+ *
+ * Note that ATF and / or Kyua may have set the timezone before the test
+ * case starts (even unintentionally). Therefore, we start the test only
+ * after we've received and discarded the first report from the child,
+ * which should come almost immediately on startup.
+ */
+static const char *tz_change_interval_sym = "__tz_change_interval";
+static int *tz_change_interval_p;
+static const int tz_change_interval = 3;
+static int tz_change_timeout = 90;
+
+ATF_TC(detect_tz_changes);
+ATF_TC_HEAD(detect_tz_changes, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test timezone change detection");
+ atf_tc_set_md_var(tc, "require.user", "root");
+ atf_tc_set_md_var(tc, "timeout", "600");
+}
+ATF_TC_BODY(detect_tz_changes, tc)
+{
+ char obuf[1024] = "";
+ char ebuf[1024] = "";
+ struct pollfd fds[3];
+ int opd[2], epd[2], spd[2];
+ time_t changed, now;
+ const struct tzcase *tzcase = NULL;
+ struct tm *tm;
+ size_t olen = 0, elen = 0;
+ ssize_t rlen;
+ long curoff = LONG_MIN;
+ pid_t pid;
+ int nfds, status;
+
+ /* speed up the test if possible */
+ tz_change_interval_p = dlsym(RTLD_SELF, tz_change_interval_sym);
+ if (tz_change_interval_p != NULL &&
+ *tz_change_interval_p > tz_change_interval) {
+ debug("reducing detection interval from %d to %d",
+ *tz_change_interval_p, tz_change_interval);
+ *tz_change_interval_p = tz_change_interval;
+ tz_change_timeout = tz_change_interval * 3;
+ }
+ /* prepare chroot */
+ ATF_REQUIRE_EQ(0, mkdir("root", 0755));
+ ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755));
+ change_tz("UTC");
+ time(&changed);
+ /* output, error, sync pipes */
+ if (pipe(opd) != 0 || pipe(epd) != 0 || pipe(spd) != 0)
+ atf_tc_fail("failed to pipe");
+ /* fork child */
+ if ((pid = fork()) < 0)
+ atf_tc_fail("failed to fork");
+ if (pid == 0) {
+ /* child */
+ dup2(opd[1], STDOUT_FILENO);
+ close(opd[0]);
+ close(opd[1]);
+ dup2(epd[1], STDERR_FILENO);
+ close(epd[0]);
+ close(epd[1]);
+ close(spd[0]);
+ unsetenv("TZ");
+ ATF_REQUIRE_EQ(0, chroot("root"));
+ ATF_REQUIRE_EQ(0, chdir("/"));
+ fds[0].fd = spd[1];
+ fds[0].events = POLLIN;
+ for (;;) {
+ ATF_REQUIRE(poll(fds, 1, 100) >= 0);
+ if (fds[0].revents & POLLHUP) {
+ /* parent closed sync pipe */
+ _exit(0);
+ }
+ ATF_REQUIRE((tm = localtime(&then)) != NULL);
+ if (tm->tm_gmtoff == curoff)
+ continue;
+ olen = strftime(obuf, sizeof(obuf), "%z (%Z)", tm);
+ ATF_REQUIRE(olen > 0);
+ fprintf(stdout, "%s\n", obuf);
+ fflush(stdout);
+ curoff = tm->tm_gmtoff;
+ }
+ _exit(2);
+ }
+ /* parent */
+ close(opd[1]);
+ close(epd[1]);
+ close(spd[1]);
+ /* receive output until child terminates */
+ fds[0].fd = opd[0];
+ fds[0].events = POLLIN;
+ fds[1].fd = epd[0];
+ fds[1].events = POLLIN;
+ fds[2].fd = spd[0];
+ fds[2].events = POLLIN;
+ nfds = 3;
+ for (;;) {
+ ATF_REQUIRE(poll(fds, 3, 1000) >= 0);
+ time(&now);
+ if (fds[0].revents & POLLIN && olen < sizeof(obuf)) {
+ rlen = read(opd[0], obuf + olen, sizeof(obuf) - olen);
+ ATF_REQUIRE(rlen >= 0);
+ olen += rlen;
+ }
+ if (olen > 0) {
+ ATF_REQUIRE_EQ('\n', obuf[olen - 1]);
+ obuf[--olen] = '\0';
+ /* tzcase will be NULL at first */
+ if (tzcase != NULL) {
+ debug("%s", obuf);
+ ATF_REQUIRE_STREQ(tzcase->expect, obuf);
+ debug("change to %s detected after %d s",
+ tzcase->tzfn, (int)(now - changed));
+ if (tz_change_interval_p != NULL) {
+ ATF_CHECK((int)(now - changed) >=
+ *tz_change_interval_p - 1);
+ ATF_CHECK((int)(now - changed) <=
+ *tz_change_interval_p + 1);
+ }
+ }
+ olen = 0;
+ /* first / next test case */
+ if (tzcase == NULL)
+ tzcase = tzcases;
+ else
+ tzcase++;
+ if (tzcase->tzfn == NULL) {
+ /* test is over */
+ break;
+ }
+ change_tz(tzcase->tzfn);
+ changed = now;
+ }
+ if (fds[1].revents & POLLIN && elen < sizeof(ebuf)) {
+ rlen = read(epd[0], ebuf + elen, sizeof(ebuf) - elen);
+ ATF_REQUIRE(rlen >= 0);
+ elen += rlen;
+ }
+ if (elen > 0) {
+ ATF_REQUIRE_EQ(elen, fwrite(ebuf, 1, elen, stderr));
+ elen = 0;
+ }
+ if (nfds > 2 && fds[2].revents & POLLHUP) {
+ /* child closed sync pipe */
+ break;
+ }
+ /*
+ * The timeout for this test case is set to 10 minutes,
+ * because it can take that long to run with the default
+ * 61-second interval. However, each individual tzcase
+ * entry should not take much longer than the detection
+ * interval to test, so we can detect a problem long
+ * before Kyua terminates us.
+ */
+ if ((now - changed) > tz_change_timeout) {
+ close(spd[0]);
+ if (tz_change_interval_p == NULL &&
+ tzcase == tzcases) {
+ /*
+ * The most likely explanation in this
+ * case is that libc was built without
+ * time zone change detection.
+ */
+ atf_tc_skip("time zone change detection "
+ "does not appear to be enabled");
+ }
+ atf_tc_fail("timed out waiting for change to %s "
+ "to be detected", tzcase->tzfn);
+ }
+ }
+ close(opd[0]);
+ close(epd[0]);
+ close(spd[0]); /* this will wake up and terminate the child */
+ if (olen > 0)
+ ATF_REQUIRE_EQ(olen, fwrite(obuf, 1, olen, stdout));
+ if (elen > 0)
+ ATF_REQUIRE_EQ(elen, fwrite(ebuf, 1, elen, stderr));
+ ATF_REQUIRE_EQ(pid, waitpid(pid, &status, 0));
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(0, WEXITSTATUS(status));
+}
+#endif /* DETECT_TZ_CHANGES */
+
+static void
+test_tz_env(const char *tzval, const char *expect)
+{
+ setenv("TZ", tzval, 1);
+ test_tz(expect);
+}
+
+static void
+tz_env_common(void)
+{
+ char path[MAXPATHLEN];
+ const struct tzcase *tzcase = tzcases;
+ int len;
+
+ /* relative path */
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++)
+ test_tz_env(tzcase->tzfn, tzcase->expect);
+ /* absolute path */
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) {
+ len = snprintf(path, sizeof(path), "%s/%s", TZDIR, tzcase->tzfn);
+ ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path));
+ test_tz_env(path, tzcase->expect);
+ }
+ /* absolute path with additional slashes */
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) {
+ len = snprintf(path, sizeof(path), "%s/////%s", TZDIR, tzcase->tzfn);
+ ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path));
+ test_tz_env(path, tzcase->expect);
+ }
+}
+
+ATF_TC(tz_env);
+ATF_TC_HEAD(tz_env, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test TZ environment variable");
+}
+ATF_TC_BODY(tz_env, tc)
+{
+ tz_env_common();
+ /* escape from TZDIR is permitted when not setugid */
+ test_tz_env("../zoneinfo/UTC", utc.expect);
+}
+
+
+ATF_TC(tz_invalid_env);
+ATF_TC_HEAD(tz_invalid_env, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test invalid TZ value");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_invalid_env, tc)
+{
+ test_tz_env("invalid", invalid.expect);
+ test_tz_env(":invalid", invalid.expect);
+}
+
+ATF_TC(setugid);
+ATF_TC_HEAD(setugid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setugid process");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(setugid, tc)
+{
+ const struct tzcase *tzcase = tzcases;
+
+ /* prepare chroot */
+ ATF_REQUIRE_EQ(0, mkdir("root", 0755));
+ ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755));
+ change_tz(tzcase->tzfn);
+ /* enter chroot */
+ ATF_REQUIRE_EQ(0, chroot("root"));
+ ATF_REQUIRE_EQ(0, chdir("/"));
+ /* become setugid */
+ ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY));
+ ATF_REQUIRE(issetugid());
+ /* check timezone */
+ unsetenv("TZ");
+ test_tz(tzcases->expect);
+}
+
+ATF_TC(tz_env_setugid);
+ATF_TC_HEAD(tz_env_setugid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test TZ environment variable "
+ "in setugid process");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_env_setugid, tc)
+{
+ ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY));
+ ATF_REQUIRE(issetugid());
+ tz_env_common();
+ /* escape from TZDIR is not permitted when setugid */
+ test_tz_env("../zoneinfo/UTC", invalid.expect);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") &&
+ isatty(STDERR_FILENO);
+ ATF_TP_ADD_TC(tp, tz_default);
+ ATF_TP_ADD_TC(tp, tz_invalid_file);
+ ATF_TP_ADD_TC(tp, thin_jail);
+#ifdef DETECT_TZ_CHANGES
+ ATF_TP_ADD_TC(tp, detect_tz_changes);
+#endif /* DETECT_TZ_CHANGES */
+ ATF_TP_ADD_TC(tp, tz_env);
+ ATF_TP_ADD_TC(tp, tz_invalid_env);
+ ATF_TP_ADD_TC(tp, setugid);
+ ATF_TP_ADD_TC(tp, tz_env_setugid);
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/string/memcmp_test.c b/lib/libc/tests/string/memcmp_test.c
index 5286a0b994f3..fa2f498ccfaf 100644
--- a/lib/libc/tests/string/memcmp_test.c
+++ b/lib/libc/tests/string/memcmp_test.c
@@ -41,14 +41,14 @@
#endif
/*
- * On FreeBSD we demand that memcmp returns the difference between the
- * characters at the first site of mismatch. However, ISO/IEC 9899:1990
- * only specifies that a number greater than, equal to, or less than
- * zero shall be returned. If a unit test for this less strict
- * behaviour is desired, define RES(x) to be (((x) > 0) - ((x) < 0)).
+ * On FreeBSD we previously demanded that memcmp returns the difference
+ * between the characters at the first site of mismatch. However,
+ * ISO/IEC 9899:1990 only specifies that a number greater than, equal
+ * to, or less than zero shall be returned. If a unit test for the
+ * more strict behaviour is desired, define RES(x) to be (x).
*/
#ifndef RES
-#define RES(x) (x)
+#define RES(x) (((x) > 0) - ((x) < 0))
#endif
static int (*memcmp_fn)(const void *, const void *, size_t);
diff --git a/lib/libc/tests/sys/Makefile b/lib/libc/tests/sys/Makefile
index 89d341ff400a..88f8191a16eb 100644
--- a/lib/libc/tests/sys/Makefile
+++ b/lib/libc/tests/sys/Makefile
@@ -7,11 +7,11 @@ ATF_TESTS_C+= brk_test
.endif
ATF_TESTS_C+= cpuset_test
ATF_TESTS_C+= errno_test
+ATF_TESTS_C+= swapcontext_test
ATF_TESTS_C+= queue_test
ATF_TESTS_C+= sendfile_test
-# TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg,
-# swapcontext
+# TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg
NETBSD_ATF_TESTS_C+= access_test
NETBSD_ATF_TESTS_C+= bind_test
NETBSD_ATF_TESTS_C+= chroot_test
diff --git a/lib/libc/tests/sys/swapcontext_test.c b/lib/libc/tests/sys/swapcontext_test.c
new file mode 100644
index 000000000000..f341a746e515
--- /dev/null
+++ b/lib/libc/tests/sys/swapcontext_test.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2025 Raptor Computing Systems, LLC
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ucontext.h>
+#include <errno.h>
+
+#include <atf-c.h>
+
+#define STACK_SIZE (64ull << 10)
+
+static volatile int callback_reached = 0;
+
+static ucontext_t uctx_save, uctx_switch;
+
+static void swapcontext_callback()
+{
+ // Increment callback reached variable
+ // If this is called multiple times, we will fail the test
+ // If this is not called at all, we will fail the test
+ callback_reached++;
+}
+
+ATF_TC(swapcontext_basic);
+ATF_TC_HEAD(swapcontext_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Verify basic functionality of swapcontext");
+}
+
+ATF_TC_BODY(swapcontext_basic, tc)
+{
+ char *stack;
+ int res;
+
+ stack = malloc(STACK_SIZE);
+ ATF_REQUIRE_MSG(stack != NULL, "malloc failed: %s", strerror(errno));
+ res = getcontext(&uctx_switch);
+ ATF_REQUIRE_MSG(res == 0, "getcontext failed: %s", strerror(errno));
+
+ uctx_switch.uc_stack.ss_sp = stack;
+ uctx_switch.uc_stack.ss_size = STACK_SIZE;
+ uctx_switch.uc_link = &uctx_save;
+ makecontext(&uctx_switch, swapcontext_callback, 0);
+
+ res = swapcontext(&uctx_save, &uctx_switch);
+
+ ATF_REQUIRE_MSG(res == 0, "swapcontext failed: %s", strerror(errno));
+ ATF_REQUIRE_MSG(callback_reached == 1,
+ "callback failed, reached %d times", callback_reached);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, swapcontext_basic);
+
+ return (atf_no_error());
+}
+
diff --git a/lib/libc/tests/tls/dso/Makefile b/lib/libc/tests/tls/dso/Makefile
index 5efd8b29a6bd..783534ff7aae 100644
--- a/lib/libc/tests/tls/dso/Makefile
+++ b/lib/libc/tests/tls/dso/Makefile
@@ -6,6 +6,7 @@ SRCS= h_tls_dlopen.c
MAN=
PACKAGE= tests
+NO_DEV_PACKAGE=
LIBDIR= ${TESTSBASE}/lib/libc/tls
SHLIB_MAJOR= 1
diff --git a/lib/libc/tests/tls_dso/Makefile b/lib/libc/tests/tls_dso/Makefile
index 89296c643695..7cb8f98b431e 100644
--- a/lib/libc/tests/tls_dso/Makefile
+++ b/lib/libc/tests/tls_dso/Makefile
@@ -7,6 +7,7 @@ LIBDIR= ${TESTSBASE}/lib/libc/tls
SHLIBDIR= ${TESTSBASE}/lib/libc/tls
SHLIB_MAJOR= 1
PACKAGE= tests
+NO_DEV_PACKAGE=
WITHOUT_STATIC=
WITHOUT_PROFILE=
diff --git a/lib/libcasper/services/cap_fileargs/cap_fileargs.3 b/lib/libcasper/services/cap_fileargs/cap_fileargs.3
index c7ce45c518d1..6a69fe7e1f4a 100644
--- a/lib/libcasper/services/cap_fileargs/cap_fileargs.3
+++ b/lib/libcasper/services/cap_fileargs/cap_fileargs.3
@@ -22,10 +22,11 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 6, 2023
+.Dd August 8, 2025
.Dt CAP_FILEARGS 3
.Os
.Sh NAME
+.Nm cap_fileargs ,
.Nm fileargs_cinit ,
.Nm fileargs_cinitnv ,
.Nm fileargs_init ,
@@ -35,9 +36,8 @@
.Nm fileargs_open ,
.Nm fileargs_fopen
.Nd "library for handling files in capability mode"
-.Sh LIBRARY
-.Lb libcap_fileargs
.Sh SYNOPSIS
+.Lb libcap_fileargs
.In sys/nv.h
.In libcasper.h
.In casper/cap_fileargs.h
@@ -60,52 +60,57 @@
.Ft "char *"
.Fn fileargs_realpath "fileargs_t *fa" "const char *pathname" "char *reserved_path"
.Sh DESCRIPTION
-The library is used to simplify Capsicumizing a tools that are using file system.
-Idea behind the library is that we are passing a remaining
-.Fa argc
-and
+The
+.Nm
+library is used to simplify Capsicumizing tools that are using file system.
+The idea behind the library is that we pass the remaining arguments from
.Fa argv
-which contains a list of files that should be open for this program.
-The library will create a service that will serve those files.
+(with count specified by
+.Fa argc )
+which contains the list of files that should be opened by the program.
+The library creates a service that will serve those files.
.Pp
The function
.Fn fileargs_init
-create a service to the
+creates a service to the
.Nm system.fileargs .
The
.Fa argv
contains a list of files that should be opened.
The argument can be set to
.Dv NULL
-which will not create a service and all files will be prohibited to be opened.
+to create no service and prohibit all files from being opened.
The
.Fa argc
-argument contains a number of passed files.
+argument contains the number of files passed to the program.
The
.Fa flags
-argument limits opened files for either execution or reading and/or writing.
+argument specifies whether files can be opened for execution, for reading,
+and/or for writing.
The
.Fa mode
-argument tells which what mode file should be created if the
-.Dv O_CREATE
-flag is present .
-For more details of the
+argument specifies the permissions to use when creating new files if the
+.Dv O_CREAT
+flag is set.
+For more information about the
.Fa flags
and
.Fa mode
-arguments see
+arguments, see
.Xr open 2 .
The
.Fa rightsp
-argument contains a list of the capability rights which file should be limited to.
-For more details of the capability rights see
+argument specifies the capability rights that will be applied to restrict
+access to the files.
+For more information about capability rights, see
.Xr cap_rights_init 3 .
The
.Fa operations
-argument limits the operations that are available using
+argument specifies which operations are permitted when using
.Nm system.fileargs .
+The following flags can be combined to form the
.Fa operations
-is a combination of:
+value:
.Bl -ohang -offset indent
.It FA_OPEN
Allow
@@ -122,121 +127,117 @@ Allow
.Pp
The function
.Fn fileargs_cinit
-is equivalent to
-.Fn fileargs_init
-except that the connection to the Casper needs to be provided.
+behaves identically to
+.Fn fileargs_init ,
+but requires an existing Casper connection to be passed as an argument.
.Pp
The functions
.Fn fileargs_initnv
and
.Fn fileargs_cinitnv
-are respectively equivalent to
+are equivalent to
.Fn fileargs_init
and
.Fn fileargs_cinit
-expect that all arguments all provided as
-.Xr nvlist 9 .
-For details see
-.Sx LIMITS .
+respectively, but take their arguments in the form of an
+.Xr nvlist 9
+structure.
+See the
+.Sx LIMITS
+section for details on the expected argument types and values.
.Pp
The
-.Fa fileargs_free
-close connection to the
+.Fn fileargs_free
+function closes the connection to the
.Nm system.fileargs
-service and free are structures.
-The function handle
+service and frees all associated data structures.
+The function safely handles
.Dv NULL
-argument.
+arguments.
.Pp
The function
.Fn fileargs_lstat
-is equivalent to
+provides the same functionality as
.Xr lstat 2 .
.Pp
The functions
.Fn fileargs_open
and
.Fn fileargs_fopen
-are respectively equivalent to
+behave identically to
.Xr open 2
and
.Xr fopen 3
-expect that all arguments are fetched from the
+respectively, but retrieve their arguments from the
.Va fileargs_t
structure.
.Pp
The function
.Fn fileargs_realpath
-is equivalent to
-.Xr realpath 3 .
+provides the same functionality as the standard C library function
+.Xr realpath 3 ,
+resolving all symbolic links and references in a pathname.
.Pp
+The following functions are reentrant but require synchronization for
+thread safety:
.Fn fileargs_open ,
.Fn fileargs_lstat ,
.Fn fileargs_realpath ,
.Fn fileargs_cinitnv ,
.Fn fileargs_initnv ,
and
-.Fn fileargs_fopen
-are reentrant but not thread-safe.
-That is, they may be called from separate threads only with different
+.Fn fileargs_fopen .
+Multiple threads can call these functions safely only if they use different
.Vt cap_channel_t
-arguments or with synchronization.
+arguments or proper synchronization mechanisms.
.Sh LIMITS
-This section describe which values and types should be used to pass arguments to the
+This section describes the required and optional arguments that must be
+passed to
.Fa system.fileargs
-through the
+via the
.Fn fileargs_initnv
and
.Fn fileargs_cinitnv
-functions.
-The
+functions using an
.Xr nvlist 9
-for that functions must contain the following values and types:
+structure.
+.Pp
+The following arguments are required:
.Bl -ohang -offset indent
-.It flags ( NV_TYPE_NUMBER )
-The
-.Va flags
-limits opened files for either execution or reading and/or writing.
-.It mode (NV_TYPE_NUMBER)
-If in the
-.Va flags
-argument the
+.It flags Pq Dv NV_TYPE_NUMBER
+Specifies access permissions for opened files.
+.It mode Pq Dv NV_TYPE_NUMBER
+Required when the
.Dv O_CREATE
-flag was defined the
-.Xr nvlist 9
-must contain the
-.Va mode .
-The
-.Va mode
-argument tells which what mode file should be created.
-.It operations (NV_TYPE_NUMBER)
-The
-.Va operations
-limits the usable operations for
+flag is set in
+.Va flags .
+Specifies the permissions to use when creating new files.
+.It operations Pq Dv NV_TYPE_NUMBER
+Specifies which operations are allowed for
.Fa system.fileargs .
-The possible values are explained as
+See the description of the
.Va operations
-argument with
-.Fn fileargs_init .
+argument in
+.Fn fileargs_init
+for possible values.
.El
.Pp
-The
+The following arguments are optional in the
.Xr nvlist 9
-for that functions may contain the following values and types:
+structure:
.Bl -ohang -offset indent
-.It cap_rights ( NV_TYPE_BINARY )
+.It cap_rights Pq Dv NV_TYPE_BINARY
The
.Va cap_rights
-argument contains a list of the capability rights which file should be limited to.
-.It ( NV_TYPE_NULL )
-Any number of
+argument specifies the capability rights that will be applied to restrict
+access to opened files.
+.It filenames Pq Dv NV_TYPE_NULL
+Multiple
.Dv NV_TYPE_NULL
-where the name of the element is name of the file which can be opened.
+elements can be provided, where each element's name represents a file
+path that is allowed to be opened.
.El
.Sh EXAMPLES
-The following example first parse some options and then create the
-.Nm system.fileargs
-service with remaining arguments.
.Bd -literal
int ch, fd, i;
cap_rights_t rights;
@@ -287,16 +288,13 @@ fileargs_free(fa);
.Xr nv 9
.Sh HISTORY
The
-.Nm cap_fileargs
+.Nm
service first appeared in
.Fx 10.3 .
.Sh AUTHORS
.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org
.Sh BUGS
The
-.Lb cap_fileargs
-included in
-.Fx
-is considered experimental, and should not be deployed in production
-environments without careful consideration of the risks associated with
-the use of experimental operating system features.
+.Nm
+service is considered experimental and should be thoroughly evaluated
+for risks before deploying in production environments.
diff --git a/lib/libcasper/services/cap_fileargs/cap_fileargs.h b/lib/libcasper/services/cap_fileargs/cap_fileargs.h
index 8207671d9753..d3a0150044d7 100644
--- a/lib/libcasper/services/cap_fileargs/cap_fileargs.h
+++ b/lib/libcasper/services/cap_fileargs/cap_fileargs.h
@@ -75,7 +75,7 @@ fileargs_init(int argc __unused, char *argv[] __unused, int flags, mode_t mode,
cap_rights_t *rightsp __unused, int operations __unused) {
fileargs_t *fa;
- fa = malloc(sizeof(*fa));
+ fa = (fileargs_t *)malloc(sizeof(*fa));
if (fa != NULL) {
fa->fa_flags = flags;
fa->fa_mode = mode;
diff --git a/lib/libcasper/services/cap_net/tests/net_test.c b/lib/libcasper/services/cap_net/tests/net_test.c
index e1045341fe47..adf5773233c8 100644
--- a/lib/libcasper/services/cap_net/tests/net_test.c
+++ b/lib/libcasper/services/cap_net/tests/net_test.c
@@ -331,7 +331,11 @@ test_extend_mode(cap_channel_t *capnet, int current)
}
}
-ATF_TC_WITHOUT_HEAD(capnet__getnameinfo);
+ATF_TC(capnet__getnameinfo);
+ATF_TC_HEAD(capnet__getnameinfo, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__getnameinfo, tc)
{
cap_channel_t *capnet;
@@ -344,7 +348,11 @@ ATF_TC_BODY(capnet__getnameinfo, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__connect);
+ATF_TC(capnet__connect);
+ATF_TC_HEAD(capnet__connect, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__connect, tc)
{
cap_channel_t *capnet;
@@ -356,7 +364,11 @@ ATF_TC_BODY(capnet__connect, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__bind);
+ATF_TC(capnet__bind);
+ATF_TC_HEAD(capnet__bind, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__bind, tc)
{
cap_channel_t *capnet;
@@ -368,7 +380,11 @@ ATF_TC_BODY(capnet__bind, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__getaddrinfo);
+ATF_TC(capnet__getaddrinfo);
+ATF_TC_HEAD(capnet__getaddrinfo, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__getaddrinfo, tc)
{
cap_channel_t *capnet;
@@ -386,7 +402,11 @@ ATF_TC_BODY(capnet__getaddrinfo, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__gethostbyname);
+ATF_TC(capnet__gethostbyname);
+ATF_TC_HEAD(capnet__gethostbyname, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__gethostbyname, tc)
{
cap_channel_t *capnet;
@@ -398,7 +418,11 @@ ATF_TC_BODY(capnet__gethostbyname, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__gethostbyaddr);
+ATF_TC(capnet__gethostbyaddr);
+ATF_TC_HEAD(capnet__gethostbyaddr, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__gethostbyaddr, tc)
{
cap_channel_t *capnet;
@@ -411,7 +435,11 @@ ATF_TC_BODY(capnet__gethostbyaddr, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__getnameinfo_buffer);
+ATF_TC(capnet__getnameinfo_buffer);
+ATF_TC_HEAD(capnet__getnameinfo_buffer, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__getnameinfo_buffer, tc)
{
cap_channel_t *chan;
@@ -450,7 +478,11 @@ ATF_TC_BODY(capnet__getnameinfo_buffer, tc)
cap_close(chan);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name_mode);
+ATF_TC(capnet__limits_addr2name_mode);
+ATF_TC_HEAD(capnet__limits_addr2name_mode, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_addr2name_mode, tc)
{
cap_channel_t *capnet;
@@ -481,7 +513,11 @@ ATF_TC_BODY(capnet__limits_addr2name_mode, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name_family);
+ATF_TC(capnet__limits_addr2name_family);
+ATF_TC_HEAD(capnet__limits_addr2name_family, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_addr2name_family, tc)
{
cap_channel_t *capnet;
@@ -526,7 +562,11 @@ ATF_TC_BODY(capnet__limits_addr2name_family, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name);
+ATF_TC(capnet__limits_addr2name);
+ATF_TC_HEAD(capnet__limits_addr2name, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_addr2name, tc)
{
cap_channel_t *capnet;
@@ -580,7 +620,11 @@ ATF_TC_BODY(capnet__limits_addr2name, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_addr2name_mode);
+ATF_TC(capnet__limits_deprecated_addr2name_mode);
+ATF_TC_HEAD(capnet__limits_deprecated_addr2name_mode, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_deprecated_addr2name_mode, tc)
{
cap_channel_t *capnet;
@@ -609,7 +653,11 @@ ATF_TC_BODY(capnet__limits_deprecated_addr2name_mode, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_addr2name_family);
+ATF_TC(capnet__limits_deprecated_addr2name_family);
+ATF_TC_HEAD(capnet__limits_deprecated_addr2name_family, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_deprecated_addr2name_family, tc)
{
cap_channel_t *capnet;
@@ -660,7 +708,11 @@ ATF_TC_BODY(capnet__limits_deprecated_addr2name_family, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_addr2name);
+ATF_TC(capnet__limits_deprecated_addr2name);
+ATF_TC_HEAD(capnet__limits_deprecated_addr2name, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_deprecated_addr2name, tc)
{
cap_channel_t *capnet;
@@ -712,7 +764,11 @@ ATF_TC_BODY(capnet__limits_deprecated_addr2name, tc)
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_mode);
+ATF_TC(capnet__limits_name2addr_mode);
+ATF_TC_HEAD(capnet__limits_name2addr_mode, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_name2addr_mode, tc)
{
cap_channel_t *capnet;
@@ -744,7 +800,11 @@ ATF_TC_BODY(capnet__limits_name2addr_mode, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts);
+ATF_TC(capnet__limits_name2addr_hosts);
+ATF_TC_HEAD(capnet__limits_name2addr_hosts, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_name2addr_hosts, tc)
{
cap_channel_t *capnet;
@@ -797,7 +857,11 @@ ATF_TC_BODY(capnet__limits_name2addr_hosts, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts_servnames_strict);
+ATF_TC(capnet__limits_name2addr_hosts_servnames_strict);
+ATF_TC_HEAD(capnet__limits_name2addr_hosts_servnames_strict, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_strict, tc)
{
cap_channel_t *capnet;
@@ -829,7 +893,11 @@ ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_strict, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts_servnames_mix);
+ATF_TC(capnet__limits_name2addr_hosts_servnames_mix);
+ATF_TC_HEAD(capnet__limits_name2addr_hosts_servnames_mix, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_mix, tc)
{
cap_channel_t *capnet;
@@ -882,7 +950,11 @@ ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_mix, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_family);
+ATF_TC(capnet__limits_name2addr_family);
+ATF_TC_HEAD(capnet__limits_name2addr_family, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_name2addr_family, tc)
{
cap_channel_t *capnet;
@@ -941,7 +1013,11 @@ ATF_TC_BODY(capnet__limits_name2addr_family, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_name2addr_mode);
+ATF_TC(capnet__limits_deprecated_name2addr_mode);
+ATF_TC_HEAD(capnet__limits_deprecated_name2addr_mode, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_deprecated_name2addr_mode, tc)
{
cap_channel_t *capnet;
@@ -972,7 +1048,11 @@ ATF_TC_BODY(capnet__limits_deprecated_name2addr_mode, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_name2addr_hosts);
+ATF_TC(capnet__limits_deprecated_name2addr_hosts);
+ATF_TC_HEAD(capnet__limits_deprecated_name2addr_hosts, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_deprecated_name2addr_hosts, tc)
{
cap_channel_t *capnet;
@@ -1011,7 +1091,11 @@ ATF_TC_BODY(capnet__limits_deprecated_name2addr_hosts, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_name2addr_family);
+ATF_TC(capnet__limits_deprecated_name2addr_family);
+ATF_TC_HEAD(capnet__limits_deprecated_name2addr_family, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_deprecated_name2addr_family, tc)
{
cap_channel_t *capnet;
@@ -1065,7 +1149,11 @@ ATF_TC_BODY(capnet__limits_deprecated_name2addr_family, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_bind_mode);
+ATF_TC(capnet__limits_bind_mode);
+ATF_TC_HEAD(capnet__limits_bind_mode, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_bind_mode, tc)
{
cap_channel_t *capnet;
@@ -1097,7 +1185,11 @@ ATF_TC_BODY(capnet__limits_bind_mode, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_bind);
+ATF_TC(capnet__limits_bind);
+ATF_TC_HEAD(capnet__limits_bind, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_bind, tc)
{
cap_channel_t *capnet;
@@ -1122,7 +1214,11 @@ ATF_TC_BODY(capnet__limits_bind, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_connect_mode);
+ATF_TC(capnet__limits_connect_mode);
+ATF_TC_HEAD(capnet__limits_connect_mode, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_connect_mode, tc)
{
cap_channel_t *capnet;
@@ -1154,7 +1250,11 @@ ATF_TC_BODY(capnet__limits_connect_mode, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_connect_dns_mode);
+ATF_TC(capnet__limits_connect_dns_mode);
+ATF_TC_HEAD(capnet__limits_connect_dns_mode, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_connect_dns_mode, tc)
{
cap_channel_t *capnet;
@@ -1186,7 +1286,11 @@ ATF_TC_BODY(capnet__limits_connect_dns_mode, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_connect);
+ATF_TC(capnet__limits_connect);
+ATF_TC_HEAD(capnet__limits_connect, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_connect, tc)
{
cap_channel_t *capnet;
@@ -1230,7 +1334,11 @@ ATF_TC_BODY(capnet__limits_connect, tc)
cap_close(capnet);
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_connecttodns);
+ATF_TC(capnet__limits_connecttodns);
+ATF_TC_HEAD(capnet__limits_connecttodns, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_connecttodns, tc)
{
cap_channel_t *capnet;
@@ -1279,7 +1387,11 @@ ATF_TC_BODY(capnet__limits_connecttodns, tc)
}
-ATF_TC_WITHOUT_HEAD(capnet__limits_deprecated_connecttodns);
+ATF_TC(capnet__limits_deprecated_connecttodns);
+ATF_TC_HEAD(capnet__limits_deprecated_connecttodns, tc)
+{
+ atf_tc_set_md_var(tc, "require.config", "allow_network_access");
+}
ATF_TC_BODY(capnet__limits_deprecated_connecttodns, tc)
{
cap_channel_t *capnet;
diff --git a/lib/libcom_err/Makefile b/lib/libcom_err/Makefile
index f070fd534469..dab4794fcded 100644
--- a/lib/libcom_err/Makefile
+++ b/lib/libcom_err/Makefile
@@ -1,4 +1,5 @@
-PACKAGE= kerberos-lib
+PACKAGE= kerberos
+LIB_PACKAGE=
LIB= com_err
SRCS= com_err.c error.c
diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile
index e939bae1bc25..2580c398155e 100644
--- a/lib/libcrypt/Makefile
+++ b/lib/libcrypt/Makefile
@@ -45,7 +45,7 @@ libcrypt.ald: ${.CURDIR}/${STATIC_LDSCRIPT}
all: ${STATIC_LDSCRIPT} libcrypt.ald
install-libcrypt.a: libcrypt.ald
- ${INSTALL} ${TAG_ARGS:D${TAG_ARGS},dev} -S -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
+ ${INSTALL} ${DEV_TAG_ARGS} -S -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
${_INSTALLFLAGS} libcrypt.ald ${DESTDIR}${_LIBDIR}/lib${LIB}.a
realinstall: install-libcrypt.a
diff --git a/lib/libdiff/Makefile b/lib/libdiff/Makefile
index 8541ff424de2..25f849a69e05 100644
--- a/lib/libdiff/Makefile
+++ b/lib/libdiff/Makefile
@@ -8,7 +8,7 @@ INTERNALLIB= # API not published or supported.
SRCS= diff_atomize_text.c diff_main.c diff_myers.c \
diff_patience.c diff_output.c diff_output_plain.c \
- diff_output_unidiff.c diff_output_edscript.c recallocarray.c
+ diff_output_unidiff.c diff_output_edscript.c
WARNS=
CFLAGS+= -I${SRCTOP}/contrib/libdiff/compat/include
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile
index f0254c1f42bc..c7a54253dae9 100644
--- a/lib/libedit/Makefile
+++ b/lib/libedit/Makefile
@@ -1,7 +1,5 @@
# $NetBSD: Makefile,v 1.56 2016/03/02 19:24:20 christos Exp $
-PACKAGE=clibs
-
EDITDIR= ${SRCTOP}/contrib/libedit
.PATH: ${EDITDIR}
@@ -93,6 +91,7 @@ tc1.o: ${EDITDIR}/TEST/tc1.c
test: tc1.o libedit.a ${DPADD} ${LIBTERMCAP}
${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD}
+.include "Makefile.inc"
.include <bsd.lib.mk>
CWARNFLAGS.chartype.c= ${NO_WUSE_AFTER_FREE}
diff --git a/lib/libedit/Makefile.inc b/lib/libedit/Makefile.inc
new file mode 100644
index 000000000000..9ec65b0d266f
--- /dev/null
+++ b/lib/libedit/Makefile.inc
@@ -0,0 +1 @@
+PACKAGE?=runtime
diff --git a/lib/libelftc/Makefile b/lib/libelftc/Makefile
index a932b0c4b2a4..a6079b817d87 100644
--- a/lib/libelftc/Makefile
+++ b/lib/libelftc/Makefile
@@ -1,5 +1,6 @@
.include <bsd.own.mk>
+PACKAGE= toolchain
INTERNALLIB=
ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
diff --git a/lib/libexpat/expat_config.h b/lib/libexpat/expat_config.h
index 748f75ee157d..565404f1577b 100644
--- a/lib/libexpat/expat_config.h
+++ b/lib/libexpat/expat_config.h
@@ -31,7 +31,7 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
-/* Define to 1 if you have the `getpagesize' function. */
+/* Define to 1 if you have the 'getpagesize' function. */
#define HAVE_GETPAGESIZE 1
/* Define to 1 if you have the `getrandom' function. */
@@ -40,10 +40,10 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
-/* Define to 1 if you have the `bsd' library (-lbsd). */
+/* Define to 1 if you have the 'bsd' library (-lbsd). */
/* #undef HAVE_LIBBSD */
-/* Define to 1 if you have a working `mmap' system call. */
+/* Define to 1 if you have a working 'mmap' system call. */
#define HAVE_MMAP 1
/* Define to 1 if you have the <stdint.h> header file. */
@@ -89,7 +89,7 @@
#define PACKAGE_NAME "expat"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "expat 2.7.1"
+#define PACKAGE_STRING "expat 2.7.3"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "expat"
@@ -98,15 +98,15 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.7.1"
+#define PACKAGE_VERSION "2.7.3"
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "2.7.1"
+#define VERSION "2.7.3"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
@@ -140,10 +140,10 @@
/* Define to make XML Namespaces functionality available. */
#define XML_NS 1
-/* Define to empty if `const' does not conform to ANSI C. */
+/* Define to empty if 'const' does not conform to ANSI C. */
/* #undef const */
-/* Define to `long int' if <sys/types.h> does not define. */
+/* Define to 'long int' if <sys/types.h> does not define. */
/* #undef off_t */
#endif // ndef EXPAT_CONFIG_H
diff --git a/lib/libexpat/libbsdxml.3 b/lib/libexpat/libbsdxml.3
index c91184840b70..d25249bbc155 100644
--- a/lib/libexpat/libbsdxml.3
+++ b/lib/libexpat/libbsdxml.3
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"/
-.Dd April 7, 2025
+.Dd September 28, 2025
.Dt LIBBSDXML 3
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Sh DESCRIPTION
The
.Nm
-library is a verbatim copy of the eXpat XML library version 2.7.1.
+library is a verbatim copy of the eXpat XML library version 2.7.3.
.Pp
The
.Nm
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
index 0d85ed468284..786d5647d993 100644
--- a/lib/libfetch/common.c
+++ b/lib/libfetch/common.c
@@ -277,13 +277,16 @@ conn_t *
fetch_reopen(int sd)
{
conn_t *conn;
+ int flags;
int opt = 1;
/* allocate and fill connection structure */
if ((conn = calloc(1, sizeof(*conn))) == NULL)
return (NULL);
- fcntl(sd, F_SETFD, FD_CLOEXEC);
- setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof opt);
+ flags = fcntl(sd, F_GETFD);
+ if (flags != -1 && (flags & FD_CLOEXEC) == 0)
+ (void)fcntl(sd, F_SETFD, flags | FD_CLOEXEC);
+ (void)setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
conn->sd = sd;
++conn->ref;
return (conn);
diff --git a/lib/libfido2/Makefile b/lib/libfido2/Makefile
index 10c008967e3d..021a32dd514b 100644
--- a/lib/libfido2/Makefile
+++ b/lib/libfido2/Makefile
@@ -43,7 +43,6 @@ SRCS+= u2f.c
SRCS+= util.c
SRCS+= openbsd-compat/freezero.c
-SRCS+= openbsd-compat/recallocarray.c
CFLAGS+= -I ${DIST}/src -I${SRCTOP}/contrib/libcbor/src -I${.CURDIR}/../libcbor
CFLAGS+= -D_FIDO_INTERNAL
diff --git a/lib/libgpio/Makefile b/lib/libgpio/Makefile
index 42f822e97ba0..271595339792 100644
--- a/lib/libgpio/Makefile
+++ b/lib/libgpio/Makefile
@@ -27,6 +27,8 @@ MLINKS= gpio.3 gpio_open.3 \
gpio.3 gpio_pin_pulldown.3 \
gpio.3 gpio_pin_invin.3 \
gpio.3 gpio_pin_invout.3 \
- gpio.3 gpio_pin_pulsate.3
+ gpio.3 gpio_pin_pulsate.3 \
+ gpio.3 gpio_configure_events.3 \
+ gpio.3 gpio_fileno.3
.include <bsd.lib.mk>
diff --git a/lib/libgpio/gpio.3 b/lib/libgpio/gpio.3
index ed2860776c3c..cb413b838bd0 100644
--- a/lib/libgpio/gpio.3
+++ b/lib/libgpio/gpio.3
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 1, 2015
+.Dd September 3, 2025
.Dt GPIO 3
.Os
.Sh NAME
@@ -79,6 +79,10 @@
.Fn gpio_pin_invout "gpio_handle_t handle" "gpio_pin_t pin"
.Ft int
.Fn gpio_pin_pulsate "gpio_handle_t handle" "gpio_pin_t pin"
+.Ft int
+.Fn gpio_configure_events "gpio_handle_t handle" "uint32_t report_type" "uint32_t fifo_size"
+.Ft int
+.Fn gpio_fileno "gpio_handle_t handle"
.Sh DESCRIPTION
The
.Nm libgpio
@@ -125,7 +129,7 @@ The pin number should also be passed in through the
variable.
All other structure members will be ignored by this function.
The list of flags can be found in
-.Pa /usr/include/sys/gpio.h .
+.In sys/gpio.h .
.Pp
The get or set the state of a GPIO pin, the functions
.Fn gpio_pin_get
@@ -156,6 +160,66 @@ and
.Fn gpio_pin_pulsate
are wrappers around
.Fn gpio_pin_set_flags .
+.Pp
+The function
+.Fn gpio_configure_events
+configures the interrupt report type and FIFO size for buffered
+gpio interrupts.
+The report type is specified by one of the following values:
+.Bl -tag -width indent
+.It Dv GPIO_EVENT_REPORT_DETAIL
+Events are reported using
+.Ft struct gpio_event_detail .
+.It Dv GPIO_EVENT_REPORT_SUMMARY
+Events are reported using
+.Ft struct gpio_event_summary .
+.El
+.Pp
+By default, the report type is
+.Dv GPIO_EVENT_REPORT_DETAIL ,
+with a default FIFO size of 2 * number of pins belonging to the
+.Ft gpio_device_t
+instance.
+The FIFO argument is only meaningful when
+.Fa report_type
+is
+.Dv GPIO_EVENT_REPORT_DETAIL .
+The structures associated with each report type are defined in
+.In sys/gpio.h .
+This setting is tracked on a per device instance basis.
+The FIFO size cannot be reduced below the default value,
+nor can it be decreased after it has been increased.
+If any pin on the device has already been configured for interrupts,
+.Fn gpio_configure_events
+fails and returns -1.
+On success 0 is returned.
+.Pp
+The function
+.Fn gpio_fileno
+returns the file descriptor associated with the
+.Ft gpio_handle_t
+instance.
+.Pp
+File operations have the following semantics:
+.Bl -tag -width "read (2)"
+.It Xr read 2
+Read one or more gpio interrupts that have occured
+since the last successful
+.Xr read 2 .
+The results are placed into the output buffer
+of the type previously established via
+.Fn gpio_configure_events .
+If there are no pending interrupts,
+.Xr read 2
+blocks until an interrupt occurs, unless
+.Dv O_NONBLOCK
+is set.
+.It Xr poll 2
+When receiving notification via
+.Xr poll 2
+or similar interfaces, the file descriptor becomes readable when
+one or more gpio interrupts are pending.
+.El
.Sh EXAMPLES
The following example shows how to configure pin 16 as output and then
drive it high:
diff --git a/lib/libgpio/gpio.c b/lib/libgpio/gpio.c
index e37ac1cdf8e8..c789bb34cacd 100644
--- a/lib/libgpio/gpio.c
+++ b/lib/libgpio/gpio.c
@@ -274,3 +274,23 @@ gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin)
{
return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE));
}
+
+int
+gpio_configure_events(gpio_handle_t handle, uint32_t report_type,
+ uint32_t fifo_size)
+{
+ struct gpio_event_config gpevent_config;
+
+ gpevent_config.gp_report_type = report_type;
+ gpevent_config.gp_fifo_size = fifo_size;
+ if (ioctl(handle, GPIOCONFIGEVENTS, &gpevent_config) < 0)
+ return (-1);
+
+ return (0);
+}
+
+int
+gpio_fileno(gpio_handle_t handle)
+{
+ return (handle);
+}
diff --git a/lib/libgpio/libgpio.h b/lib/libgpio/libgpio.h
index 35651ecd8cca..abffc7b1b6ab 100644
--- a/lib/libgpio/libgpio.h
+++ b/lib/libgpio/libgpio.h
@@ -102,6 +102,19 @@ int gpio_pin_pulldown(gpio_handle_t, gpio_pin_t);
int gpio_pin_invin(gpio_handle_t, gpio_pin_t);
int gpio_pin_invout(gpio_handle_t, gpio_pin_t);
int gpio_pin_pulsate(gpio_handle_t, gpio_pin_t);
+/*
+ * GPIO event reporting configuration
+ *
+ * Set the event reporting type, the default being GPIO_EVENT_REPORT_DETAIL,
+ * and fifo size of 2 * number of pins belonging to the gpioc device instance.
+ * FIFO size can only be changed when report_type is GPIO_EVENT_REPORT_DETAIL.
+ */
+int gpio_configure_events(gpio_handle_t, uint32_t, uint32_t);
+/*
+ * Retrieve the file descriptor associated with gpio_handle_t, which can
+ * be used for gpio interrupts.
+ */
+int gpio_fileno(gpio_handle_t);
__END_DECLS
diff --git a/lib/libifconfig/Makefile b/lib/libifconfig/Makefile
index e8e0651dc0d6..02629eb88f25 100644
--- a/lib/libifconfig/Makefile
+++ b/lib/libifconfig/Makefile
@@ -1,4 +1,3 @@
-PACKAGE= lib${LIB}
LIB= ifconfig
INTERNALLIB= true
@@ -18,6 +17,7 @@ SRCS= libifconfig.c \
libifconfig_internal.c \
libifconfig_lagg.c \
libifconfig_media.c \
+ libifconfig_nl.c \
libifconfig_sfp.c
GEN= libifconfig_sfp_tables.h \
diff --git a/lib/libifconfig/Symbol.map b/lib/libifconfig/Symbol.map
index 2d80fb31652a..2e11ff963909 100644
--- a/lib/libifconfig/Symbol.map
+++ b/lib/libifconfig/Symbol.map
@@ -40,7 +40,6 @@ FBSD_1.6 {
ifconfig_open;
ifconfig_set_capability;
ifconfig_set_description;
- ifconfig_set_fib;
ifconfig_set_metric;
ifconfig_set_mtu;
ifconfig_set_name;
@@ -81,7 +80,6 @@ FBSD_1.6 {
ifconfig_sfp_fc_speed_symbol;
ifconfig_sfp_id_description;
ifconfig_sfp_id_display;
- ifconfig_sfp_id_is_qsfp;
ifconfig_sfp_id_symbol;
ifconfig_sfp_rev_description;
ifconfig_sfp_rev_symbol;
diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h
index fc835485a51e..817f52bd094e 100644
--- a/lib/libifconfig/libifconfig.h
+++ b/lib/libifconfig/libifconfig.h
@@ -35,6 +35,8 @@
#include <netinet/ip_carp.h>
#include <netinet6/in6_var.h>
+#include <stdbool.h>
+
#define ND6_IFF_DEFAULTIF 0x8000
typedef enum {
@@ -69,6 +71,8 @@ struct ifconfig_bridge_status {
size_t members_count; /**< how many member interfaces */
uint32_t cache_size; /**< size of address cache */
uint32_t cache_lifetime; /**< address cache entry lifetime */
+ ifbr_flags_t flags; /**< bridge flags */
+ ether_vlanid_t defpvid; /**< default pvid */
};
struct ifconfig_capabilities {
@@ -169,7 +173,6 @@ int ifconfig_set_name(ifconfig_handle_t *h, const char *name,
const char *newname);
int ifconfig_get_orig_name(ifconfig_handle_t *h, const char *ifname,
char **orig_name);
-int ifconfig_set_fib(ifconfig_handle_t *h, const char *name, int fib);
int ifconfig_get_fib(ifconfig_handle_t *h, const char *name, int *fib);
int ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu);
int ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu);
@@ -380,3 +383,12 @@ int ifconfig_set_vlantag(ifconfig_handle_t *h, const char *name,
* length of *lenp * IFNAMSIZ bytes.
*/
int ifconfig_list_cloners(ifconfig_handle_t *h, char **bufp, size_t *lenp);
+
+/** Brings the interface up/down
+ * @param h An open ifconfig state object
+ * @param ifname The interface name
+ * @param up true to bring the interface up, false to bring it down
+ * @return 0 on success, nonzero on failure.
+ * On failure, the error info on the handle is set.
+ */
+int ifconfig_set_up(ifconfig_handle_t *h, const char *ifname, bool up);
diff --git a/lib/libifconfig/libifconfig_bridge.c b/lib/libifconfig/libifconfig_bridge.c
index b4a920f488c5..675bf5dd2ff5 100644
--- a/lib/libifconfig/libifconfig_bridge.c
+++ b/lib/libifconfig/libifconfig_bridge.c
@@ -92,6 +92,18 @@ ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h,
}
bridge->inner.cache_lifetime = cache_param.ifbrp_ctime;
+ if (ifconfig_bridge_ioctlwrap(h, name, BRDGGFLAGS,
+ &cache_param, sizeof(cache_param), false) != 0) {
+ goto err;
+ }
+ bridge->inner.flags = cache_param.ifbrp_flags;
+
+ if (ifconfig_bridge_ioctlwrap(h, name, BRDGGDEFPVID,
+ &cache_param, sizeof(cache_param), false) != 0) {
+ goto err;
+ }
+ bridge->inner.defpvid = cache_param.ifbrp_defpvid;
+
if (ifconfig_bridge_ioctlwrap(h, name, BRDGPARAM,
&bridge->params, sizeof(bridge->params), false) != 0) {
goto err;
diff --git a/lib/libifconfig/libifconfig_nl.c b/lib/libifconfig/libifconfig_nl.c
new file mode 100644
index 000000000000..7d9decabe26f
--- /dev/null
+++ b/lib/libifconfig/libifconfig_nl.c
@@ -0,0 +1,72 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025, Muhammad Saheed <saheed@FreeBSD.org>
+ */
+
+#include <netlink/netlink.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/route/common.h>
+#include <netlink/route/interface.h>
+
+#include "libifconfig.h"
+#include "libifconfig_internal.h"
+
+static int ifconfig_modify_flags(ifconfig_handle_t *h, const char *ifname,
+ int ifi_flags, int ifi_change);
+
+static int
+ifconfig_modify_flags(ifconfig_handle_t *h, const char *ifname, int ifi_flags,
+ int ifi_change)
+{
+ int ret = 0;
+ struct snl_state ss;
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ struct ifinfomsg *ifi;
+ struct snl_errmsg_data e = { 0 };
+
+ if (!snl_init(&ss, NETLINK_ROUTE)) {
+ ifconfig_error(h, NETLINK, ENOTSUP);
+ return (-1);
+ }
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_msg_request(&nw, NL_RTM_NEWLINK);
+ ifi = snl_reserve_msg_object(&nw, struct ifinfomsg);
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
+
+ ifi->ifi_flags = ifi_flags;
+ ifi->ifi_change = ifi_change;
+
+ hdr = snl_finalize_msg(&nw);
+ if (hdr == NULL) {
+ ifconfig_error(h, NETLINK, ENOMEM);
+ ret = -1;
+ goto out;
+ }
+
+ if (!snl_send_message(&ss, hdr)) {
+ ifconfig_error(h, NETLINK, EIO);
+ ret = -1;
+ goto out;
+ }
+
+ if (!snl_read_reply_code(&ss, hdr->nlmsg_seq, &e)) {
+ ifconfig_error(h, NETLINK, e.error);
+ ret = -1;
+ goto out;
+ }
+
+out:
+ snl_free(&ss);
+ return (ret);
+}
+
+int
+ifconfig_set_up(ifconfig_handle_t *h, const char *ifname, bool up)
+{
+ int flag = up ? IFF_UP : ~IFF_UP;
+
+ return (ifconfig_modify_flags(h, ifname, flag, IFF_UP));
+}
diff --git a/lib/libiscsiutil/Makefile b/lib/libiscsiutil/Makefile
index c99fb6366536..d9762302fd40 100644
--- a/lib/libiscsiutil/Makefile
+++ b/lib/libiscsiutil/Makefile
@@ -1,6 +1,5 @@
LIB= iscsiutil
INTERNALLIB=
-PACKAGE= iscsi
INCS= libiscsiutil.h
diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
index 30282e67866c..ad3348af0d2d 100644
--- a/lib/libjail/jail.c
+++ b/lib/libjail/jail.c
@@ -75,8 +75,9 @@ int
jail_setv(int flags, ...)
{
va_list ap, tap;
- struct jailparam *jp;
- const char *name, *value;
+ struct jailparam *jp, *jp_desc;
+ const char *name;
+ char *value, *desc_value;
int njp, jid;
/* Create the parameter list and import the parameters. */
@@ -86,15 +87,24 @@ jail_setv(int flags, ...)
(void)va_arg(tap, char *);
va_end(tap);
jp = alloca(njp * sizeof(struct jailparam));
- for (njp = 0; (name = va_arg(ap, char *)) != NULL;) {
+ jp_desc = NULL;
+ desc_value = NULL;
+ for (njp = 0; (name = va_arg(ap, char *)) != NULL; njp++) {
value = va_arg(ap, char *);
if (jailparam_init(jp + njp, name) < 0)
goto error;
- if (jailparam_import(jp + njp++, value) < 0)
+ if (jailparam_import(jp + njp, value) < 0)
goto error;
+ if (!strcmp(name, "desc") &&
+ (flags & (JAIL_GET_DESC | JAIL_OWN_DESC))) {
+ jp_desc = jp + njp;
+ desc_value = value;
+ }
}
va_end(ap);
jid = jailparam_set(jp, njp, flags);
+ if (jid > 0 && jp_desc != NULL)
+ sprintf(desc_value, "%d", *(int *)jp_desc->jp_value);
jailparam_free(jp, njp);
return (jid);
@@ -112,9 +122,10 @@ int
jail_getv(int flags, ...)
{
va_list ap, tap;
- struct jailparam *jp, *jp_lastjid, *jp_jid, *jp_name, *jp_key;
+ struct jailparam *jp, *jp_desc, *jp_lastjid, *jp_jid, *jp_name, *jp_key;
char *valarg, *value;
- const char *name, *key_value, *lastjid_value, *jid_value, *name_value;
+ const char *name, *key_value, *desc_value, *lastjid_value, *jid_value;
+ const char *name_value;
int njp, i, jid;
/* Create the parameter list and find the key. */
@@ -126,15 +137,19 @@ jail_getv(int flags, ...)
jp = alloca(njp * sizeof(struct jailparam));
va_copy(tap, ap);
- jp_lastjid = jp_jid = jp_name = NULL;
- lastjid_value = jid_value = name_value = NULL;
+ jp_desc = jp_lastjid = jp_jid = jp_name = NULL;
+ desc_value = lastjid_value = jid_value = name_value = NULL;
for (njp = 0; (name = va_arg(tap, char *)) != NULL; njp++) {
value = va_arg(tap, char *);
if (jailparam_init(jp + njp, name) < 0) {
va_end(tap);
goto error;
}
- if (!strcmp(jp[njp].jp_name, "lastjid")) {
+ if (!strcmp(jp[njp].jp_name, "desc") &&
+ (flags & (JAIL_USE_DESC | JAIL_AT_DESC))) {
+ jp_desc = jp + njp;
+ desc_value = value;
+ } else if (!strcmp(jp[njp].jp_name, "lastjid")) {
jp_lastjid = jp + njp;
lastjid_value = value;
} else if (!strcmp(jp[njp].jp_name, "jid")) {
@@ -147,7 +162,10 @@ jail_getv(int flags, ...)
}
va_end(tap);
/* Import the key parameter. */
- if (jp_lastjid != NULL) {
+ if (jp_desc != NULL && (flags & JAIL_USE_DESC)) {
+ jp_key = jp_desc;
+ key_value = desc_value;
+ } else if (jp_lastjid != NULL) {
jp_key = jp_lastjid;
key_value = lastjid_value;
} else if (jp_jid != NULL && strtol(jid_value, NULL, 10) != 0) {
@@ -163,6 +181,9 @@ jail_getv(int flags, ...)
}
if (jailparam_import(jp_key, key_value) < 0)
goto error;
+ if (jp_desc != NULL && jp_desc != jp_key &&
+ jailparam_import(jp_desc, desc_value) < 0)
+ goto error;
/* Get the jail and export the parameters. */
jid = jailparam_get(jp, njp, flags);
if (jid < 0)
@@ -571,7 +592,7 @@ int
jailparam_get(struct jailparam *jp, unsigned njp, int flags)
{
struct iovec *jiov;
- struct jailparam *jp_lastjid, *jp_jid, *jp_name, *jp_key;
+ struct jailparam *jp_desc, *jp_lastjid, *jp_jid, *jp_name, *jp_key;
int i, ai, ki, jid, arrays, sanity;
unsigned j;
@@ -580,10 +601,13 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags)
* Find the key and any array parameters.
*/
jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1));
- jp_lastjid = jp_jid = jp_name = NULL;
+ jp_desc = jp_lastjid = jp_jid = jp_name = NULL;
arrays = 0;
for (ai = j = 0; j < njp; j++) {
- if (!strcmp(jp[j].jp_name, "lastjid"))
+ if (!strcmp(jp[j].jp_name, "desc") &&
+ (flags & (JAIL_USE_DESC | JAIL_AT_DESC)))
+ jp_desc = jp + j;
+ else if (!strcmp(jp[j].jp_name, "lastjid"))
jp_lastjid = jp + j;
else if (!strcmp(jp[j].jp_name, "jid"))
jp_jid = jp + j;
@@ -599,7 +623,9 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags)
ai++;
}
}
- jp_key = jp_lastjid ? jp_lastjid :
+ jp_key = jp_desc && jp_desc->jp_valuelen == sizeof(int) &&
+ jp_desc->jp_value && (flags & JAIL_USE_DESC) ? jp_desc :
+ jp_lastjid ? jp_lastjid :
jp_jid && jp_jid->jp_valuelen == sizeof(int) &&
jp_jid->jp_value && *(int *)jp_jid->jp_value ? jp_jid : jp_name;
if (jp_key == NULL || jp_key->jp_value == NULL) {
@@ -622,6 +648,14 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags)
jiov[ki].iov_len = JAIL_ERRMSGLEN;
ki++;
jail_errmsg[0] = 0;
+ if (jp_desc != NULL && jp_desc != jp_key) {
+ jiov[ki].iov_base = jp_desc->jp_name;
+ jiov[ki].iov_len = strlen(jp_desc->jp_name) + 1;
+ ki++;
+ jiov[ki].iov_base = jp_desc->jp_value;
+ jiov[ki].iov_len = jp_desc->jp_valuelen;
+ ki++;
+ }
if (arrays && jail_get(jiov, ki, flags) < 0) {
if (!jail_errmsg[0])
snprintf(jail_errmsg, sizeof(jail_errmsg),
@@ -649,7 +683,7 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags)
jiov[ai].iov_base = jp[j].jp_value;
memset(jiov[ai].iov_base, 0, jiov[ai].iov_len);
ai++;
- } else if (jp + j != jp_key) {
+ } else if (jp + j != jp_key && jp + j != jp_desc) {
jiov[i].iov_base = jp[j].jp_name;
jiov[i].iov_len = strlen(jp[j].jp_name) + 1;
i++;
@@ -886,13 +920,21 @@ jailparam_type(struct jailparam *jp)
} desc;
int mib[CTL_MAXNAME];
- /* The "lastjid" parameter isn't real. */
+ /*
+ * Some pseudo-parameters don't show up in the sysctl
+ * parameter list.
+ */
name = jp->jp_name;
if (!strcmp(name, "lastjid")) {
jp->jp_valuelen = sizeof(int);
jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_WR;
return (0);
}
+ if (!strcmp(name, "desc")) {
+ jp->jp_valuelen = sizeof(int);
+ jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_RW;
+ return (0);
+ }
/* Find the sysctl that describes the parameter. */
mib[0] = 0;
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index b2b7c6ecce56..fed483978e62 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -150,13 +150,14 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
kp->ki_cr_flags = 0;
if (ucred.cr_flags & CRED_FLAG_CAPMODE)
kp->ki_cr_flags |= KI_CRF_CAPABILITY_MODE;
- if (ucred.cr_ngroups > KI_NGROUPS) {
+ if (1 + ucred.cr_ngroups > KI_NGROUPS) {
kp->ki_ngroups = KI_NGROUPS;
kp->ki_cr_flags |= KI_CRF_GRP_OVERFLOW;
} else
- kp->ki_ngroups = ucred.cr_ngroups;
- kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups,
- kp->ki_ngroups * sizeof(gid_t));
+ kp->ki_ngroups = 1 + ucred.cr_ngroups;
+ kp->ki_groups[0] = ucred.cr_gid;
+ kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups + 1,
+ (kp->ki_ngroups - 1) * sizeof(gid_t));
if (ucred.cr_prison != NULL) {
if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) {
_kvm_err(kd, kd->program,
diff --git a/lib/liblzma/Makefile b/lib/liblzma/Makefile
index 27e0521f5884..9c6ece74ffd0 100644
--- a/lib/liblzma/Makefile
+++ b/lib/liblzma/Makefile
@@ -1,4 +1,6 @@
-PACKAGE=lib${LIB}
+PACKAGE= xz
+LIB_PACKAGE=
+
LIB= lzma
LZMADIR= ${SRCTOP}/contrib/xz/src/liblzma
diff --git a/lib/libmilter/Makefile b/lib/libmilter/Makefile
index dd6a481d1a15..ff16b4d00297 100644
--- a/lib/libmilter/Makefile
+++ b/lib/libmilter/Makefile
@@ -1,6 +1,6 @@
.include <src.opts.mk>
-PACKAGE=sendmail
+PACKAGE=lib${LIB}
SENDMAIL_DIR=${SRCTOP}/contrib/sendmail
.PATH: ${SENDMAIL_DIR}/libmilter ${SENDMAIL_DIR}/libsm
diff --git a/lib/libmixer/Makefile b/lib/libmixer/Makefile
index a0bb37a85fb8..49621ad1f188 100644
--- a/lib/libmixer/Makefile
+++ b/lib/libmixer/Makefile
@@ -1,3 +1,5 @@
+PACKAGE= sound
+
LIB= mixer
SRCS= ${LIB}.c
INCS= ${LIB}.h
diff --git a/lib/libnetbsd/Makefile b/lib/libnetbsd/Makefile
index 1639caf20d6b..4088c2b57176 100644
--- a/lib/libnetbsd/Makefile
+++ b/lib/libnetbsd/Makefile
@@ -1,6 +1,5 @@
.include <bsd.own.mk>
-PACKAGE=lib${LIB}
LIB= netbsd
CFLAGS+= -I${.CURDIR}
diff --git a/lib/libnvmf/Makefile b/lib/libnvmf/Makefile
index b01f5ab82cac..945c31a2986c 100644
--- a/lib/libnvmf/Makefile
+++ b/lib/libnvmf/Makefile
@@ -3,7 +3,6 @@
LIB= nvmf
INTERNALLIB=
-PACKAGE= nvmf
INCS= libnvmf.h
diff --git a/lib/libnvmf/libnvmf.h b/lib/libnvmf/libnvmf.h
index 7cdd7e433455..f095af8bb02a 100644
--- a/lib/libnvmf/libnvmf.h
+++ b/lib/libnvmf/libnvmf.h
@@ -51,6 +51,8 @@ struct nvmf_qpair_params {
};
};
+__BEGIN_DECLS
+
/* Transport-independent APIs. */
/*
@@ -111,8 +113,13 @@ const void *nvmf_capsule_cqe(const struct nvmf_capsule *nc);
/* Return a string name for a transport type. */
const char *nvmf_transport_type(uint8_t trtype);
-/* Validate a NVMe Qualified Name. */
+/*
+ * Validate a NVMe Qualified Name. The second version enforces
+ * stricter checks inline with the specification. The first version
+ * enforces more minimal checks.
+ */
bool nvmf_nqn_valid(const char *nqn);
+bool nvmf_nqn_valid_strict(const char *nqn);
/* Controller-specific APIs. */
@@ -379,4 +386,6 @@ int nvmf_reconnect_host(int fd, const struct nvme_discovery_log_entry *dle,
*/
int nvmf_connection_status(int fd, nvlist_t **nvlp);
+__END_DECLS
+
#endif /* !__LIBNVMF_H__ */
diff --git a/lib/libnvmf/nvmf_controller.c b/lib/libnvmf/nvmf_controller.c
index 971dccbe039e..f26f11633e03 100644
--- a/lib/libnvmf/nvmf_controller.c
+++ b/lib/libnvmf/nvmf_controller.c
@@ -7,6 +7,7 @@
#include <sys/utsname.h>
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
@@ -15,6 +16,55 @@
#include "internal.h"
#include "nvmft_subr.h"
+bool
+nvmf_nqn_valid_strict(const char *nqn)
+{
+ size_t len;
+
+ if (!nvmf_nqn_valid(nqn))
+ return (false);
+
+ /*
+ * Stricter checks from the spec. Linux does not seem to
+ * require these.
+ */
+ len = strlen(nqn);
+
+ /*
+ * NVMF_NQN_MIN_LEN does not include '.' and require at least
+ * one character of a domain name.
+ */
+ if (len < NVMF_NQN_MIN_LEN + 2)
+ return (false);
+ if (memcmp("nqn.", nqn, strlen("nqn.")) != 0)
+ return (false);
+ nqn += strlen("nqn.");
+
+ /* Next 4 digits must be a year. */
+ for (u_int i = 0; i < 4; i++) {
+ if (!isdigit(nqn[i]))
+ return (false);
+ }
+ nqn += 4;
+
+ /* '-' between year and month. */
+ if (nqn[0] != '-')
+ return (false);
+ nqn++;
+
+ /* 2 digit month. */
+ for (u_int i = 0; i < 2; i++) {
+ if (!isdigit(nqn[i]))
+ return (false);
+ }
+ nqn += 2;
+
+ /* '.' between month and reverse domain name. */
+ if (nqn[0] != '.')
+ return (false);
+ return (true);
+}
+
void
nvmf_init_cqe(void *cqe, const struct nvmf_capsule *nc, uint16_t status)
{
diff --git a/lib/libnvmf/nvmf_tcp.c b/lib/libnvmf/nvmf_tcp.c
index 6f41ca7ff502..48ddabaf506a 100644
--- a/lib/libnvmf/nvmf_tcp.c
+++ b/lib/libnvmf/nvmf_tcp.c
@@ -728,7 +728,7 @@ nvmf_tcp_handle_r2t(struct nvmf_tcp_qpair *qp, struct nvmf_tcp_rxpdu *pdu)
}
/*
- * XXX: The spec does not specify how to handle R2T tranfers
+ * XXX: The spec does not specify how to handle R2T transfers
* out of range of the original command.
*/
data_len = le32toh(r2t->r2tl);
diff --git a/lib/libopenbsd/Makefile b/lib/libopenbsd/Makefile
index dca1c08b0aed..80ae0f90621a 100644
--- a/lib/libopenbsd/Makefile
+++ b/lib/libopenbsd/Makefile
@@ -1,9 +1,12 @@
-PACKAGE=lib${LIB}
LIB= openbsd
SRCS= imsg-buffer.c \
imsg.c \
- ohash.c \
- recallocarray.c
+ ohash.c
+.if defined(BOOTSTRAPPING)
+.PATH: ${SRCTOP}/lib/libc/stdlib
+SRCS+= recallocarray.c
+.endif
+
.if !defined(BOOTSTRAPPING)
# Skip getdtablecount.c when bootstrapping since it doesn't compile for Linux
# and is not used by any of the bootstrap tools
diff --git a/lib/libopencsd/Makefile b/lib/libopencsd/Makefile
index 649e756eacf6..b37a864f7cbb 100644
--- a/lib/libopencsd/Makefile
+++ b/lib/libopencsd/Makefile
@@ -1,8 +1,3 @@
-PACKAGE=lib${LIB}
-SHLIBDIR?= /lib
-
-.include <src.opts.mk>
-
OPENCSDSRC= ${SRCTOP}/contrib/opencsd
.PATH: ${OPENCSDSRC}/decoder/source/ete/ \
@@ -182,6 +177,7 @@ INCSGROUPS=INCS APIINCS ETEINCS ETMV3INCS ETMV4INCS PTMINCS STMINCS
LIBADD= cxxrt
WARNS?= 1
+PRIVATELIB= true
HAS_TESTS=
diff --git a/lib/libpam/modules/modules.inc b/lib/libpam/modules/modules.inc
index f3ab65333f4f..1e9eb8970317 100644
--- a/lib/libpam/modules/modules.inc
+++ b/lib/libpam/modules/modules.inc
@@ -30,4 +30,4 @@ MODULES += pam_ssh
.endif
MODULES += pam_tacplus
MODULES += pam_unix
-MODULES += pam_xdg \ No newline at end of file
+MODULES += pam_xdg
diff --git a/lib/libpam/modules/pam_krb5/Makefile b/lib/libpam/modules/pam_krb5/Makefile
index b537bf37b7f3..7634930a7202 100644
--- a/lib/libpam/modules/pam_krb5/Makefile
+++ b/lib/libpam/modules/pam_krb5/Makefile
@@ -32,7 +32,7 @@ SRCDIR= ${SRCTOP}/contrib/pam-krb5
${SRCDIR}/pam-util \
${SRCDIR}
-PACKAGE= krb5
+PACKAGE= kerberos
LIB= pam_krb5
LIBADD= com_err krb5
@@ -63,7 +63,6 @@ MLINKS= pam-krb5.8 pam_krb5.8
CFLAGS= -I${SRCDIR} \
-I${.CURDIR} \
-fno-strict-aliasing \
- -Wno-error=incompatible-pointer-types-discards-qualifiers \
-DHAVE_CONFIG_H
WARNS?= 3
diff --git a/lib/libpam/modules/pam_ksu/pam_ksu.c b/lib/libpam/modules/pam_ksu/pam_ksu.c
index 002613188d8c..04c276a423d3 100644
--- a/lib/libpam/modules/pam_ksu/pam_ksu.c
+++ b/lib/libpam/modules/pam_ksu/pam_ksu.c
@@ -58,24 +58,13 @@ static int auth_krb5(pam_handle_t *, krb5_context, const char *,
#define KRB5_DEFAULT_CCFILE_ROOT "/tmp/krb5cc_"
#define KRB5_DEFAULT_CCROOT "FILE:" KRB5_DEFAULT_CCFILE_ROOT
-/*
- * XXX We will replace krb5_build_principal_va() with
- * XXX krb5_build_principal_alloc_va() when Heimdal is finally
- * XXX removed.
- */
-krb5_error_code KRB5_CALLCONV
-krb5_build_principal_va(krb5_context context,
- krb5_principal princ,
- unsigned int rlen,
- const char *realm,
- va_list ap);
typedef char *heim_general_string;
typedef heim_general_string Realm;
typedef Realm krb5_realm;
typedef const char *krb5_const_realm;
static krb5_error_code
-krb5_make_principal(krb5_context context, krb5_principal principal,
+krb5_make_principal(krb5_context context, krb5_principal *principal,
krb5_const_realm realm, ...)
{
krb5_realm temp_realm = NULL;
@@ -88,15 +77,9 @@ krb5_make_principal(krb5_context context, krb5_principal principal,
realm=temp_realm;
}
va_start(ap, realm);
- /*
- * XXX Ideally we should be using krb5_build_principal_alloc_va()
- * XXX here because krb5_build_principal_va() is deprecated. But,
- * XXX this would require changes elsewhere in the calling code
- * XXX to call krb5_free_principal() elsewhere to free the
- * XXX principal. We can do that after Heimdal is removed from
- * XXX our tree.
- */
- rc = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
+
+ rc = krb5_build_principal_alloc_va(context, principal, strlen(realm),
+ realm, ap);
va_end(ap);
if (temp_realm)
free(temp_realm);
@@ -273,13 +256,7 @@ get_su_principal(krb5_context context, const char *target_user, const char *curr
if (rv != 0)
return (errno);
if (default_principal == NULL) {
-#ifdef MK_MITKRB5
- /* For MIT KRB5. */
- rv = krb5_make_principal(context, default_principal, NULL, current_user, NULL);
-#else
- /* For Heimdal. */
rv = krb5_make_principal(context, &default_principal, NULL, current_user, NULL);
-#endif
if (rv != 0) {
PAM_LOG("Could not determine default principal name.");
return (rv);
diff --git a/lib/libpam/modules/pam_xdg/pam_xdg.8 b/lib/libpam/modules/pam_xdg/pam_xdg.8
index 9b335751a9fb..031010953e98 100644
--- a/lib/libpam/modules/pam_xdg/pam_xdg.8
+++ b/lib/libpam/modules/pam_xdg/pam_xdg.8
@@ -50,7 +50,6 @@ Use an alternate base directory
.Bl -tag -width indent
.It Ev XDG_RUNTIME_DIR
The location of the runtime files base directory created by this module.
-Note that the module does not set this environment variable.
.El
.Sh STANDARDS
The directory created by this module conforms to the
diff --git a/lib/libpfctl/Makefile b/lib/libpfctl/Makefile
index d301d7850b44..4b16d81181a3 100644
--- a/lib/libpfctl/Makefile
+++ b/lib/libpfctl/Makefile
@@ -1,4 +1,3 @@
-PACKAGE= lib${LIB}
LIB= pfctl
INTERNALLIB= true
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index e4123fe02211..8c4b26b98054 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -391,6 +391,8 @@ static const struct snl_attr_parser ap_getstatus[] = {
{ .type = PF_GS_CHKSUM, .off = _OUT(pf_chksum), .arg_u32 = PF_MD5_DIGEST_LENGTH, .cb = snl_attr_get_bytes },
{ .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array },
{ .type = PF_GS_PCOUNTERS, .off = _OUT(pcounters), .arg_u32 = 2 * 2 * 2, .cb = snl_attr_get_uint64_array },
+ { .type = PF_GS_NCOUNTERS, .off = _OUT(ncounters), .cb = snl_attr_get_counters },
+ { .type = PF_GS_FRAGMENTS, .off = _OUT(fragments), .cb = snl_attr_get_uint64 },
};
SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, snl_f_p_empty, ap_getstatus);
#undef _OUT
@@ -429,6 +431,7 @@ pfctl_get_status_h(struct pfctl_handle *h)
TAILQ_INIT(&status->lcounters);
TAILQ_INIT(&status->fcounters);
TAILQ_INIT(&status->scounters);
+ TAILQ_INIT(&status->ncounters);
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
if (! snl_parse_nlmsg(&h->ss, hdr, &getstatus_parser, status))
@@ -558,6 +561,10 @@ pfctl_free_status(struct pfctl_status *status)
free(c->name);
free(c);
}
+ TAILQ_FOREACH_SAFE(c, &status->ncounters, entry, tmp) {
+ free(c->name);
+ free(c);
+ }
free(status);
}
@@ -1284,8 +1291,8 @@ snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfct
snl_add_msg_attr_u8(nw, PF_RT_KEEP_STATE, r->keep_state);
snl_add_msg_attr_u8(nw, PF_RT_AF, r->af);
snl_add_msg_attr_u8(nw, PF_RT_PROTO, r->proto);
- snl_add_msg_attr_u8(nw, PF_RT_TYPE, r->type);
- snl_add_msg_attr_u8(nw, PF_RT_CODE, r->code);
+ snl_add_msg_attr_u16(nw, PF_RT_TYPE_2, r->type);
+ snl_add_msg_attr_u16(nw, PF_RT_CODE_2, r->code);
snl_add_msg_attr_u8(nw, PF_RT_FLAGS, r->flags);
snl_add_msg_attr_u8(nw, PF_RT_FLAGSET, r->flagset);
snl_add_msg_attr_u8(nw, PF_RT_MIN_TTL, r->min_ttl);
@@ -1694,6 +1701,9 @@ static struct snl_attr_parser ap_getrule[] = {
{ .type = PF_RT_SRC_NODES_ROUTE, .off = _OUT(r.src_nodes_type[PF_SN_ROUTE]), .cb = snl_attr_get_uint64 },
{ .type = PF_RT_PKTRATE, .off = _OUT(r.pktrate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested },
{ .type = PF_RT_MAX_PKT_SIZE, .off =_OUT(r.max_pkt_size), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_TYPE_2, .off = _OUT(r.type), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_CODE_2, .off = _OUT(r.code), .cb = snl_attr_get_uint16 },
+ { .type = PF_RT_EXPTIME, .off = _OUT(r.exptime), .cb = snl_attr_get_time_t },
};
#undef _OUT
SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule);
@@ -1940,6 +1950,7 @@ static struct snl_attr_parser ap_state[] = {
{ .type = PF_ST_RT, .off = _OUT(rt), .cb = snl_attr_get_uint8 },
{ .type = PF_ST_RT_IFNAME, .off = _OUT(rt_ifname), .cb = snl_attr_store_ifname },
{ .type = PF_ST_SRC_NODE_FLAGS, .off = _OUT(src_node_flags), .cb = snl_attr_get_uint8 },
+ { .type = PF_ST_RT_AF, .off = _OUT(rt_af), .cb = snl_attr_get_uint8 },
};
#undef _IN
#undef _OUT
@@ -2396,6 +2407,150 @@ pfctl_table_add_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
return (0);
}
+static void
+snl_add_msg_attr_table(struct snl_writer *nw, uint32_t type,
+ const struct pfr_table *tbl)
+{
+ int off;
+
+ off = snl_add_msg_attr_nested(nw, type);
+
+ snl_add_msg_attr_string(nw, PF_T_ANCHOR, tbl->pfrt_anchor);
+ snl_add_msg_attr_string(nw, PF_T_NAME, tbl->pfrt_name);
+ snl_add_msg_attr_u32(nw, PF_T_TABLE_FLAGS, tbl->pfrt_flags);
+
+ snl_end_attr_nested(nw, off);
+}
+
+static void
+snl_add_msg_attr_pfr_addr(struct snl_writer *nw, uint32_t type,
+ const struct pfr_addr *addr)
+{
+ int off;
+
+ off = snl_add_msg_attr_nested(nw, type);
+
+ snl_add_msg_attr_u8(nw, PFR_A_AF, addr->pfra_af);
+ snl_add_msg_attr_u8(nw, PFR_A_NET, addr->pfra_net);
+ snl_add_msg_attr_bool(nw, PFR_A_NOT, addr->pfra_not);
+ snl_add_msg_attr_ip6(nw, PFR_A_ADDR, &addr->pfra_ip6addr);
+
+ snl_end_attr_nested(nw, off);
+}
+
+static struct snl_attr_parser ap_table_add_addr[] = {
+ { .type = PF_TA_NBR_ADDED, .off = 0, .cb = snl_attr_get_uint32 },
+};
+SNL_DECLARE_PARSER(table_add_addr_parser, struct genlmsghdr, snl_f_p_empty, ap_table_add_addr);
+
+static int
+_pfctl_table_add_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pfr_addr
+ *addrs, int size, int *nadd, int flags)
+{
+ struct snl_writer nw;
+ struct snl_errmsg_data e = {};
+ struct nlmsghdr *hdr;
+ uint32_t seq_id;
+ uint32_t added;
+ int family_id;
+
+ family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
+ if (family_id == 0)
+ return (ENOTSUP);
+
+ snl_init_writer(&h->ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_TABLE_ADD_ADDR);
+
+ snl_add_msg_attr_table(&nw, PF_TA_TABLE, tbl);
+ snl_add_msg_attr_u32(&nw, PF_TA_FLAGS, flags);
+ for (int i = 0; i < size; i++)
+ snl_add_msg_attr_pfr_addr(&nw, PF_TA_ADDR, &addrs[i]);
+
+ if ((hdr = snl_finalize_msg(&nw)) == NULL)
+ return (ENXIO);
+ seq_id = hdr->nlmsg_seq;
+
+ if (! snl_send_message(&h->ss, hdr))
+ return (ENXIO);
+
+ while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
+ if (! snl_parse_nlmsg(&h->ss, hdr, &table_add_addr_parser, &added))
+ continue;
+ }
+
+ if (nadd)
+ *nadd = added;
+
+ return (e.error);
+}
+
+int
+pfctl_table_add_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pfr_addr
+ *addr, int size, int *nadd, int flags)
+{
+ int ret;
+ int off = 0;
+ int partial_added;
+ int chunk_size;
+
+ do {
+ chunk_size = MIN(size - off, 256);
+ ret = _pfctl_table_add_addrs_h(h, tbl, &addr[off], chunk_size, &partial_added, flags);
+ if (ret != 0)
+ break;
+ if (nadd)
+ *nadd += partial_added;
+ off += chunk_size;
+ } while (off < size);
+
+ return (ret);
+}
+
+static struct snl_attr_parser ap_table_del_addr[] = {
+ { .type = PF_TA_NBR_DELETED, .off = 0, .cb = snl_attr_get_uint32 },
+};
+SNL_DECLARE_PARSER(table_del_addr_parser, struct genlmsghdr, snl_f_p_empty, ap_table_del_addr);
+static int
+_pfctl_table_del_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pfr_addr
+ *addrs, int size, int *ndel, int flags)
+{
+ struct snl_writer nw;
+ struct snl_errmsg_data e = {};
+ struct nlmsghdr *hdr;
+ uint32_t seq_id;
+ uint32_t deleted;
+ int family_id;
+
+ family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
+ if (family_id == 0)
+ return (ENOTSUP);
+
+ snl_init_writer(&h->ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_TABLE_DEL_ADDR);
+
+ snl_add_msg_attr_table(&nw, PF_TA_TABLE, tbl);
+ snl_add_msg_attr_u32(&nw, PF_TA_FLAGS, flags);
+ for (int i = 0; i < size; i++)
+ snl_add_msg_attr_pfr_addr(&nw, PF_TA_ADDR, &addrs[i]);
+
+ if ((hdr = snl_finalize_msg(&nw)) == NULL)
+ return (ENXIO);
+ seq_id = hdr->nlmsg_seq;
+
+ if (! snl_send_message(&h->ss, hdr))
+ return (ENXIO);
+
+ while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
+ if (! snl_parse_nlmsg(&h->ss, hdr, &table_del_addr_parser, &deleted))
+ continue;
+ }
+
+ if (ndel)
+ *ndel = deleted;
+
+ return (e.error);
+}
+
int
pfctl_table_del_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
*addr, int size, int *ndel, int flags)
@@ -2420,6 +2575,29 @@ pfctl_table_del_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
}
int
+pfctl_table_del_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pfr_addr
+ *addr, int size, int *ndel, int flags)
+{
+ int ret;
+ int off = 0;
+ int partial_deleted;
+ int chunk_size;
+
+ do {
+ chunk_size = MIN(size - off, 256);
+ ret = _pfctl_table_del_addrs_h(h, tbl, &addr[off], chunk_size,
+ &partial_deleted, flags);
+ if (ret != 0)
+ break;
+ if (ndel)
+ *ndel += partial_deleted;
+ off += chunk_size;
+ } while (off < size);
+
+ return (ret);
+}
+
+int
pfctl_table_set_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
*addr, int size, int *size2, int *nadd, int *ndel, int *nchange, int flags)
{
@@ -3043,7 +3221,7 @@ static struct snl_attr_parser ap_srcnode[] = {
{ .type = PF_SN_CREATION, .off = _OUT(creation), .cb = snl_attr_get_uint64 },
{ .type = PF_SN_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint64 },
{ .type = PF_SN_CONNECTION_RATE, .off = _OUT(conn_rate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested },
- { .type = PF_SN_NAF, .off = _OUT(naf), .cb = snl_attr_get_uint8 },
+ { .type = PF_SN_RAF, .off = _OUT(raf), .cb = snl_attr_get_uint8 },
{ .type = PF_SN_NODE_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 },
};
#undef _OUT
@@ -3348,6 +3526,11 @@ pfctl_clear_tstats(struct pfctl_handle *h, const struct pfr_table *filter,
return (e.error);
}
+static struct snl_attr_parser ap_clr_addrs[] = {
+ { .type = PF_T_NBR_DELETED, .off = 0, .cb = snl_attr_get_uint64 },
+};
+SNL_DECLARE_PARSER(clr_addrs_parser, struct genlmsghdr, snl_f_p_empty, ap_clr_addrs);
+
int
pfctl_clear_addrs(struct pfctl_handle *h, const struct pfr_table *filter,
int *ndel, int flags)
@@ -3380,7 +3563,7 @@ pfctl_clear_addrs(struct pfctl_handle *h, const struct pfr_table *filter,
return (ENXIO);
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
- if (!snl_parse_nlmsg(&h->ss, hdr, &tstats_clr_parser, &del))
+ if (!snl_parse_nlmsg(&h->ss, hdr, &clr_addrs_parser, &del))
continue;
if (ndel)
*ndel = (uint32_t)del;
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index 98a80758ca74..5880e1a88371 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -62,6 +62,8 @@ struct pfctl_status {
struct pfctl_status_counters lcounters;
struct pfctl_status_counters fcounters;
struct pfctl_status_counters scounters;
+ struct pfctl_status_counters ncounters;
+ uint64_t fragments;
uint64_t pcounters[2][2][2];
uint64_t bcounters[2][2];
};
@@ -143,9 +145,18 @@ struct pfctl_eth_anchor {
int match; /* XXX: used for pfctl black magic */
};
+struct pfctl_pooladdr {
+ struct pf_addr_wrap addr;
+ TAILQ_ENTRY(pfctl_pooladdr) entries;
+ char ifname[IFNAMSIZ];
+ sa_family_t af;
+};
+
+TAILQ_HEAD(pfctl_palist, pfctl_pooladdr);
+
struct pfctl_pool {
- struct pf_palist list;
- struct pf_pooladdr *cur;
+ struct pfctl_palist list;
+ struct pfctl_pooladdr *cur;
struct pf_poolhashkey key;
struct pf_addr counter;
struct pf_mape_portset mape;
@@ -252,8 +263,8 @@ struct pfctl_rule {
uint8_t keep_state;
sa_family_t af;
uint8_t proto;
- uint8_t type;
- uint8_t code;
+ uint16_t type;
+ uint16_t code;
uint8_t flags;
uint8_t flagset;
uint8_t min_ttl;
@@ -274,6 +285,8 @@ struct pfctl_rule {
struct pf_addr addr;
uint16_t port;
} divert;
+
+ time_t exptime;
};
TAILQ_HEAD(pfctl_rulequeue, pfctl_rule);
@@ -383,6 +396,7 @@ struct pfctl_state {
uint8_t set_prio[2];
uint8_t rt;
char rt_ifname[IFNAMSIZ];
+ sa_family_t rt_af;
uint8_t src_node_flags;
};
@@ -414,7 +428,7 @@ struct pfctl_src_node {
uint32_t states;
uint32_t conn;
sa_family_t af;
- sa_family_t naf;
+ sa_family_t raf;
uint8_t ruletype;
uint64_t creation;
uint64_t expire;
@@ -501,8 +515,12 @@ int pfctl_clear_nat(int dev, const char *anchorname);
int pfctl_clear_eth_rules(int dev, const char *anchorname);
int pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s);
int pfctl_get_syncookies(int dev, struct pfctl_syncookies *s);
+int pfctl_table_add_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pfr_addr
+ *addr, int size, int *nadd, int flags);
int pfctl_table_add_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
*addr, int size, int *nadd, int flags);
+int pfctl_table_del_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl,
+ struct pfr_addr *addr, int size, int *ndel, int flags);
int pfctl_table_del_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
*addr, int size, int *ndel, int flags);
int pfctl_table_set_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
diff --git a/lib/libpmc/Makefile b/lib/libpmc/Makefile
index 8728b0c1c76d..590f719ebff4 100644
--- a/lib/libpmc/Makefile
+++ b/lib/libpmc/Makefile
@@ -1,5 +1,5 @@
-LIB_CXX= pmc
-
+PACKAGE=pmc
+LIB_CXX=pmc
SRCS= libpmc.c pmclog.c libpmc_pmu_util.c libpmc_json.cc
INCS= pmc.h pmclog.h pmcformat.h
diff --git a/lib/libpmcstat/Makefile b/lib/libpmcstat/Makefile
index d1d23cdd57c7..7ca93329e20f 100644
--- a/lib/libpmcstat/Makefile
+++ b/lib/libpmcstat/Makefile
@@ -1,4 +1,3 @@
-PACKAGE=lib${LIB}
LIB= pmcstat
INTERNALLIB=
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index eb8137f6c76f..df77cabcd36b 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -1330,8 +1330,7 @@ procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
return (1);
}
vn->vn_mntdir = getmnton(kd, vnode.v_mount);
- if ((vnode.v_type == VBLK || vnode.v_type == VCHR) &&
- vnode.v_rdev != NULL){
+ if (VTYPE_ISDEV(vnode.v_type) && vnode.v_rdev != NULL) {
vn->vn_dev = dev2udev(kd, vnode.v_rdev);
(void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname);
} else {
@@ -1974,6 +1973,7 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
struct ucred ucred;
gid_t *groups;
size_t len;
+ unsigned int ngroups;
assert(kd != NULL);
assert(kp != NULL);
@@ -1991,19 +1991,22 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
proc.p_ucred, kp->ki_pid);
return (NULL);
}
- len = ucred.cr_ngroups * sizeof(gid_t);
+ ngroups = 1 + ucred.cr_ngroups;
+ len = ngroups * sizeof(gid_t);
groups = malloc(len);
if (groups == NULL) {
warn("malloc(%zu)", len);
return (NULL);
}
- if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) {
+ groups[0] = ucred.cr_gid;
+ if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups + 1,
+ len - sizeof(gid_t))) {
warnx("can't read groups at %p for pid %d",
ucred.cr_groups, kp->ki_pid);
free(groups);
return (NULL);
}
- *cntp = ucred.cr_ngroups;
+ *cntp = ngroups;
return (groups);
}
diff --git a/lib/libregex/tests/gnuext.in b/lib/libregex/tests/gnuext.in
index 8f49854235a9..3ce0f4af1b34 100644
--- a/lib/libregex/tests/gnuext.in
+++ b/lib/libregex/tests/gnuext.in
@@ -10,9 +10,9 @@ a\|b\|c b abc a
(ab)\1 - abab abab
\1(ab) C ESUBREG
(a)(b)(c)(d)(e)(f)(g)(h)(i)\9 - abcdefghii abcdefghii
-# \w, \W, \s, \S (alnum, ^alnum, space, ^space)
-\w+ - -%@a0X- a0X
-\w\+ b -%@a0X- a0X
+# \w, \W, \s, \S (_alnum, ^_alnum, space, ^space)
+\w+ - -%@a_0X- a_0X
+\w\+ b -%@a_0X- a_0X
\s+ - aSNTb SNT
\s\+ b aSNTb SNT
# Word boundaries (\b, \B, \<, \>, \`, \')
diff --git a/lib/librpcsec_gss/Makefile b/lib/librpcsec_gss/Makefile
index a29d9780c1ab..eebc975acbd2 100644
--- a/lib/librpcsec_gss/Makefile
+++ b/lib/librpcsec_gss/Makefile
@@ -1,10 +1,16 @@
+.include <src.opts.mk>
+
PACKAGE=lib${LIB}
LIB= rpcsec_gss
SHLIB_MAJOR= 1
SRCS+= rpcsec_gss.c rpcsec_gss_prot.c rpcsec_gss_conf.c rpcsec_gss_misc.c \
svc_rpcsec_gss.c
+.if ${MK_MITKRB5} == "no"
LIBADD= gssapi
+.else
+LIBADD= gssapi_krb5
+.endif
VERSION_DEF= ${SRCTOP}/lib/libc/Versions.def
SYMBOL_MAPS= ${.CURDIR}/Symbol.map
diff --git a/lib/libsamplerate/Makefile b/lib/libsamplerate/Makefile
new file mode 100644
index 000000000000..4c55d5c2cb82
--- /dev/null
+++ b/lib/libsamplerate/Makefile
@@ -0,0 +1,20 @@
+.PATH: ${SRCTOP}/contrib/libsamplerate
+
+PACKAGE= sound
+
+LIB= samplerate
+PRIVATELIB=
+
+SRCS= samplerate.c \
+ src_linear.c \
+ src_sinc.c \
+ src_zoh.c
+
+INCS= samplerate.h
+
+CFLAGS+= -DENABLE_SINC_BEST_CONVERTER \
+ -DENABLE_SINC_MEDIUM_CONVERTER \
+ -DENABLE_SINC_FAST_CONVERTER \
+ -I${SRCTOP}/contrib/libsamplerate
+
+.include <bsd.lib.mk>
diff --git a/lib/libsdp/Makefile b/lib/libsdp/Makefile
index f0153e756dfd..8177c9bdbd1a 100644
--- a/lib/libsdp/Makefile
+++ b/lib/libsdp/Makefile
@@ -1,6 +1,7 @@
# $Id: Makefile,v 1.2 2003/09/07 20:34:19 max Exp $
-PACKAGE=lib${LIB}
+PACKAGE= bluetooth
+LIB_PACKAGE=
LIB= sdp
MAN= sdp.3
diff --git a/lib/libsdp/sdp.3 b/lib/libsdp/sdp.3
index dcd9077798ea..015f9cd8fb44 100644
--- a/lib/libsdp/sdp.3
+++ b/lib/libsdp/sdp.3
@@ -24,7 +24,7 @@
.\"
.\" $Id: sdp.3,v 1.1 2003/09/07 20:34:19 max Exp $
.\"
-.Dd April 30, 2018
+.Dd September 16, 2025
.Dt SDP 3
.Os
.Sh NAME
@@ -87,7 +87,7 @@
.Fn sdp_uuid2desc "uint16_t uuid"
.Ft int32_t
.Fo sdp_register_service
-.Fa "void *xss" "uint16_t uuid" "bdaddr_p const bdaddr" "uint8_t const *data"
+.Fa "void *xss" "uint16_t uuid" "const bdaddr_t *bdaddr" "uint8_t const *data"
.Fa "uint32_t datalen" "uint32_t *handle"
.Fc
.Ft int32_t
diff --git a/lib/libsdp/sdp.h b/lib/libsdp/sdp.h
index faad36aefca6..0c9474a70eff 100644
--- a/lib/libsdp/sdp.h
+++ b/lib/libsdp/sdp.h
@@ -702,7 +702,7 @@ typedef struct sdp_panu_profile sdp_panu_profile_t;
typedef struct sdp_panu_profile * sdp_panu_profile_p;
int32_t sdp_register_service (void *xss, uint16_t uuid,
- bdaddr_p const bdaddr, uint8_t const *data,
+ const bdaddr_t *bdaddr, uint8_t const *data,
uint32_t datalen, uint32_t *handle);
int32_t sdp_unregister_service (void *xss, uint32_t handle);
int32_t sdp_change_service (void *xss, uint32_t handle,
diff --git a/lib/libsdp/service.c b/lib/libsdp/service.c
index 9f07d1ba86ba..2cce6c133600 100644
--- a/lib/libsdp/service.c
+++ b/lib/libsdp/service.c
@@ -45,7 +45,7 @@
static int32_t sdp_receive_error_pdu(sdp_session_p ss);
int32_t
-sdp_register_service(void *xss, uint16_t uuid, bdaddr_p const bdaddr,
+sdp_register_service(void *xss, uint16_t uuid, const bdaddr_t *bdaddr,
uint8_t const *data, uint32_t datalen, uint32_t *handle)
{
sdp_session_p ss = (sdp_session_p) xss;
diff --git a/lib/libsecureboot/h/libsecureboot.h b/lib/libsecureboot/h/libsecureboot.h
index 017558536825..d32df9594332 100644
--- a/lib/libsecureboot/h/libsecureboot.h
+++ b/lib/libsecureboot/h/libsecureboot.h
@@ -29,6 +29,7 @@
#include <sys/param.h>
#ifdef _STANDALONE
+#define _DEBUG_LEVEL_VAR DebugVe
#include <stand.h>
#else
#include <sys/types.h>
diff --git a/lib/libsm/Makefile b/lib/libsm/Makefile
index 448abad59192..538407754f6a 100644
--- a/lib/libsm/Makefile
+++ b/lib/libsm/Makefile
@@ -1,6 +1,5 @@
.include <src.opts.mk>
-PACKAGE=sendmail
SENDMAIL_DIR=${SRCTOP}/contrib/sendmail
.PATH: ${SENDMAIL_DIR}/libsm
diff --git a/lib/libsmdb/Makefile b/lib/libsmdb/Makefile
index 898af78d6101..e82deda57615 100644
--- a/lib/libsmdb/Makefile
+++ b/lib/libsmdb/Makefile
@@ -1,4 +1,3 @@
-PACKAGE=lib${LIB}
SENDMAIL_DIR=${SRCTOP}/contrib/sendmail
.PATH: ${SENDMAIL_DIR}/libsmdb
diff --git a/lib/libsmutil/Makefile b/lib/libsmutil/Makefile
index ef526ff8656d..37ad71e84f58 100644
--- a/lib/libsmutil/Makefile
+++ b/lib/libsmutil/Makefile
@@ -1,6 +1,5 @@
.include <src.opts.mk>
-PACKAGE=lib${LIB}
SENDMAIL_DIR=${SRCTOP}/contrib/sendmail
.PATH: ${SENDMAIL_DIR}/libsmutil
diff --git a/lib/libstdbuf/Makefile b/lib/libstdbuf/Makefile
index 102c6745c593..9e289e0018fc 100644
--- a/lib/libstdbuf/Makefile
+++ b/lib/libstdbuf/Makefile
@@ -1,6 +1,5 @@
.include <bsd.own.mk>
-PACKAGE=lib${LIB}
LIB= stdbuf
SRCS= stdbuf.c
SHLIB_MAJOR= 1
diff --git a/lib/libstdthreads/Makefile b/lib/libstdthreads/Makefile
index 49d024052420..dcdac58efc12 100644
--- a/lib/libstdthreads/Makefile
+++ b/lib/libstdthreads/Makefile
@@ -1,4 +1,4 @@
-PACKAGE=lib${LIB}
+PACKAGE=runtime
LIB= stdthreads
SHLIB_MAJOR= 0
diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys
index 3eb4bf85153d..bd65b58083c2 100644
--- a/lib/libsys/Makefile.sys
+++ b/lib/libsys/Makefile.sys
@@ -52,7 +52,6 @@ STATICOBJS+= interposing_table.o
PSEUDO= \
__realpathat \
clock_gettime \
- exit \
getlogin \
gettimeofday \
sched_getcpu
@@ -135,15 +134,28 @@ FEATURE_NOTE='\#include <sys/elf_common.h>\nGNU_PROPERTY_AARCH64_FEATURE_1_NOTE(
FEATURE_NOTE=''
.endif
-${SASM}:
- printf '/* %sgenerated by libc/sys/Makefile.inc */\n' @ > ${.TARGET}
+# Add this file as a dependency of the generated assembly along with
+# the two included files compat.h and SYS.h. Depending on this Makefile
+# will cause some needless regenerations, but handles both changes in
+# generated assembly and movement between MIASM and PSEUDO/INTERPOSED.
+# The dependency on compat.h and SYS.h should properly be on the
+# <foo>.S-><foo>.o rules, but there are too many .o variants for it to
+# be easy and touching the geneated source files has the same effect in
+# practice.
+__makefile_sys:= ${.PARSEDIR}/${.PARSEFILE}
+__asm_deps= ${__makefile_sys} \
+ ${LIBC_SRCTOP}/include/compat.h \
+ ${LIBSYS_SRCTOP}/${LIBC_ARCH}/SYS.h
+
+${SASM}: ${__asm_deps}
+ printf '/* %sgenerated by libsys/Makefile.sys */\n' @ > ${.TARGET}
printf '#include "compat.h"\n' >> ${.TARGET}
printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' >> ${.TARGET}
printf ${NOTE_GNU_STACK} >>${.TARGET}
printf ${FEATURE_NOTE} >> ${.TARGET}
-${SPSEUDO}:
- printf '/* %sgenerated by libc/sys/Makefile.inc */\n' @ > ${.TARGET}
+${SPSEUDO}: ${__asm_deps}
+ printf '/* %sgenerated by libsys/Makefile.sys */\n' @ > ${.TARGET}
printf '#include "compat.h"\n' >> ${.TARGET}
printf '#include "SYS.h"\nPSEUDO(${.PREFIX:S/_//})\n' \
>> ${.TARGET}
diff --git a/lib/libsys/Symbol.map b/lib/libsys/Symbol.map
index eb71c813ae86..ae12124ca210 100644
--- a/lib/libsys/Symbol.map
+++ b/lib/libsys/Symbol.map
@@ -4,10 +4,4 @@ FBSDprivate_1.0 {
__getosreldate;
__libsys_interposing_slot;
_elf_aux_info;
- freebsd11_fstat;
- freebsd11_fstatat;
- freebsd11_getfsstat;
- freebsd11_lstat;
- freebsd11_stat;
- freebsd11_statfs;
};
diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map
index 45e0160100af..e3fd8ac10621 100644
--- a/lib/libsys/Symbol.sys.map
+++ b/lib/libsys/Symbol.sys.map
@@ -89,7 +89,6 @@ FBSD_1.0 {
geteuid;
getfh;
getgid;
- getgroups;
getitimer;
getpagesize;
getpeername;
@@ -204,7 +203,6 @@ FBSD_1.0 {
setegid;
seteuid;
setgid;
- setgroups;
setitimer;
setlogin;
setpgid;
@@ -380,11 +378,15 @@ FBSD_1.7 {
FBSD_1.8 {
exterrctl;
fchroot;
+ getgroups;
getrlimitusage;
inotify_add_watch_at;
inotify_rm_watch;
+ jail_attach_jd;
+ jail_remove_jd;
kcmp;
setcred;
+ setgroups;
};
FBSDprivate_1.0 {
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
index 1799906eb885..6bd768708a78 100644
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -65,7 +65,7 @@ struct uuid;
union semun;
__BEGIN_DECLS
-typedef void (__sys_exit_t)(int);
+typedef void (__sys__exit_t)(int);
typedef int (__sys_fork_t)(void);
typedef ssize_t (__sys_read_t)(int, void *, size_t);
typedef ssize_t (__sys_write_t)(int, const void *, size_t);
@@ -121,8 +121,6 @@ typedef int (__sys_munmap_t)(void *, size_t);
typedef int (__sys_mprotect_t)(void *, size_t, int);
typedef int (__sys_madvise_t)(void *, size_t, int);
typedef int (__sys_mincore_t)(const void *, size_t, char *);
-typedef int (__sys_getgroups_t)(int, gid_t *);
-typedef int (__sys_setgroups_t)(int, const gid_t *);
typedef int (__sys_getpgrp_t)(void);
typedef int (__sys_setpgid_t)(int, int);
typedef int (__sys_setitimer_t)(int, const struct itimerval *, struct itimerval *);
@@ -180,7 +178,7 @@ typedef int (__sys_pathconf_t)(const char *, int);
typedef int (__sys_fpathconf_t)(int, int);
typedef int (__sys_getrlimit_t)(u_int, struct rlimit *);
typedef int (__sys_setrlimit_t)(u_int, struct rlimit *);
-typedef int (__sys___sysctl_t)(int *, u_int, void *, size_t *, const void *, size_t);
+typedef int (__sys___sysctl_t)(const int *, u_int, void *, size_t *, const void *, size_t);
typedef int (__sys_mlock_t)(const void *, size_t);
typedef int (__sys_munlock_t)(const void *, size_t);
typedef int (__sys_undelete_t)(const char *);
@@ -468,8 +466,12 @@ typedef int (__sys_setcred_t)(u_int, const struct setcred *, size_t);
typedef int (__sys_exterrctl_t)(u_int, u_int, void *);
typedef int (__sys_inotify_add_watch_at_t)(int, int, const char *, uint32_t);
typedef int (__sys_inotify_rm_watch_t)(int, int);
+typedef int (__sys_getgroups_t)(int, gid_t *);
+typedef int (__sys_setgroups_t)(int, const gid_t *);
+typedef int (__sys_jail_attach_jd_t)(int);
+typedef int (__sys_jail_remove_jd_t)(int);
-void __sys_exit(int rval);
+_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
ssize_t __sys_read(int fd, void * buf, size_t nbyte);
ssize_t __sys_write(int fd, const void * buf, size_t nbyte);
@@ -525,8 +527,6 @@ int __sys_munmap(void * addr, size_t len);
int __sys_mprotect(void * addr, size_t len, int prot);
int __sys_madvise(void * addr, size_t len, int behav);
int __sys_mincore(const void * addr, size_t len, char * vec);
-int __sys_getgroups(int gidsetsize, gid_t * gidset);
-int __sys_setgroups(int gidsetsize, const gid_t * gidset);
int __sys_getpgrp(void);
int __sys_setpgid(int pid, int pgid);
int __sys_setitimer(int which, const struct itimerval * itv, struct itimerval * oitv);
@@ -584,7 +584,7 @@ int __sys_pathconf(const char * path, int name);
int __sys_fpathconf(int fd, int name);
int __sys_getrlimit(u_int which, struct rlimit * rlp);
int __sys_setrlimit(u_int which, struct rlimit * rlp);
-int __sys___sysctl(int * name, u_int namelen, void * old, size_t * oldlenp, const void * new, size_t newlen);
+int __sys___sysctl(const int * name, u_int namelen, void * old, size_t * oldlenp, const void * new, size_t newlen);
int __sys_mlock(const void * addr, size_t len);
int __sys_munlock(const void * addr, size_t len);
int __sys_undelete(const char * path);
@@ -872,6 +872,10 @@ int __sys_setcred(u_int flags, const struct setcred * wcred, size_t size);
int __sys_exterrctl(u_int op, u_int flags, void * ptr);
int __sys_inotify_add_watch_at(int fd, int dfd, const char * path, uint32_t mask);
int __sys_inotify_rm_watch(int fd, int wd);
+int __sys_getgroups(int gidsetsize, gid_t * gidset);
+int __sys_setgroups(int gidsetsize, const gid_t * gidset);
+int __sys_jail_attach_jd(int fd);
+int __sys_jail_remove_jd(int fd);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/amd64/amd64_get_fsbase.c b/lib/libsys/amd64/amd64_get_fsbase.c
index 00f16a5e404f..b5e87f8a3ce5 100644
--- a/lib/libsys/amd64/amd64_get_fsbase.c
+++ b/lib/libsys/amd64/amd64_get_fsbase.c
@@ -30,7 +30,6 @@
* SUCH DAMAGE.
*/
-#define _WANT_P_OSREL
#include <sys/param.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
@@ -41,7 +40,6 @@
static int
amd64_get_fsbase_cpu(void **addr)
{
-
*addr = (void *)rdfsbase();
return (0);
}
@@ -49,15 +47,12 @@ amd64_get_fsbase_cpu(void **addr)
static int
amd64_get_fsbase_syscall(void **addr)
{
-
return (sysarch(AMD64_GET_FSBASE, addr));
}
DEFINE_UIFUNC(, int, amd64_get_fsbase, (void **))
{
-
- if (__getosreldate() >= P_OSREL_WRFSBASE &&
- (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
+ if ((cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
return (amd64_get_fsbase_cpu);
return (amd64_get_fsbase_syscall);
}
diff --git a/lib/libsys/amd64/amd64_get_gsbase.c b/lib/libsys/amd64/amd64_get_gsbase.c
index ef135b1eed7f..51be412ddd7a 100644
--- a/lib/libsys/amd64/amd64_get_gsbase.c
+++ b/lib/libsys/amd64/amd64_get_gsbase.c
@@ -30,7 +30,6 @@
* SUCH DAMAGE.
*/
-#define _WANT_P_OSREL
#include <sys/param.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
@@ -41,7 +40,6 @@
static int
amd64_get_gsbase_cpu(void **addr)
{
-
*addr = (void *)rdgsbase();
return (0);
}
@@ -49,15 +47,12 @@ amd64_get_gsbase_cpu(void **addr)
static int
amd64_get_gsbase_syscall(void **addr)
{
-
return (sysarch(AMD64_GET_GSBASE, addr));
}
DEFINE_UIFUNC(, int, amd64_get_gsbase, (void **))
{
-
- if (__getosreldate() >= P_OSREL_WRFSBASE &&
- (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
+ if ((cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
return (amd64_get_gsbase_cpu);
return (amd64_get_gsbase_syscall);
}
diff --git a/lib/libsys/amd64/amd64_set_fsbase.c b/lib/libsys/amd64/amd64_set_fsbase.c
index f1690fde6e17..5265bd712f17 100644
--- a/lib/libsys/amd64/amd64_set_fsbase.c
+++ b/lib/libsys/amd64/amd64_set_fsbase.c
@@ -30,7 +30,6 @@
* SUCH DAMAGE.
*/
-#define _WANT_P_OSREL
#include <sys/param.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
@@ -41,7 +40,6 @@
static int
amd64_set_fsbase_cpu(void *addr)
{
-
wrfsbase((uintptr_t)addr);
return (0);
}
@@ -49,15 +47,12 @@ amd64_set_fsbase_cpu(void *addr)
static int
amd64_set_fsbase_syscall(void *addr)
{
-
return (sysarch(AMD64_SET_FSBASE, &addr));
}
DEFINE_UIFUNC(, int, amd64_set_fsbase, (void *))
{
-
- if (__getosreldate() >= P_OSREL_WRFSBASE &&
- (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
+ if ((cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
return (amd64_set_fsbase_cpu);
return (amd64_set_fsbase_syscall);
}
diff --git a/lib/libsys/amd64/amd64_set_gsbase.c b/lib/libsys/amd64/amd64_set_gsbase.c
index 756bbae18844..94f5736ed1ab 100644
--- a/lib/libsys/amd64/amd64_set_gsbase.c
+++ b/lib/libsys/amd64/amd64_set_gsbase.c
@@ -30,7 +30,6 @@
* SUCH DAMAGE.
*/
-#define _WANT_P_OSREL
#include <sys/param.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
@@ -41,7 +40,6 @@
static int
amd64_set_gsbase_cpu(void *addr)
{
-
wrgsbase((uintptr_t)addr);
return (0);
}
@@ -49,15 +47,12 @@ amd64_set_gsbase_cpu(void *addr)
static int
amd64_set_gsbase_syscall(void *addr)
{
-
return (sysarch(AMD64_SET_GSBASE, &addr));
}
DEFINE_UIFUNC(, int, amd64_set_gsbase, (void *))
{
-
- if (__getosreldate() >= P_OSREL_WRFSBASE &&
- (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
+ if ((cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
return (amd64_set_gsbase_cpu);
return (amd64_set_gsbase_syscall);
}
diff --git a/lib/libsys/chroot.2 b/lib/libsys/chroot.2
index 4c06e3673e03..3347df5cceee 100644
--- a/lib/libsys/chroot.2
+++ b/lib/libsys/chroot.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 15, 2024
+.Dd August 2, 2025
.Dt CHROOT 2
.Os
.Sh NAME
@@ -61,7 +61,12 @@ It should be noted that
.Fn chroot
has no effect on the process's current directory.
.Pp
-This call is restricted to the super-user.
+This call is restricted to the super-user, unless the
+.Ql security.bsd.unprivileged_chroot
+sysctl variable is set to 1
+and the process has enabled the
+.Dv PROC_NO_NEW_PRIVS_CTL
+.Xr procctl 2 .
.Pp
Depending on the setting of the
.Ql kern.chroot_allow_open_directories
@@ -106,14 +111,37 @@ except it takes a file descriptor instead of path.
.Sh ERRORS
The
.Fn chroot
+and
+.Fn fchroot
+system calls
+will fail and the root directory will be unchanged if:
+.Bl -tag -width Er
+.It Bq Er EPERM
+The effective user ID is not the super-user and the
+.Ql security.bsd.unprivileged_chroot
+sysctl is 0.
+.It Bq Er EPERM
+The effective user ID is not the super-user and the
+process has not enabled the
+.Dv PROC_NO_NEW_PRIVS_CTL
+.Xr procctl 2 .
+.It Bq Er EPERM
+One or more filedescriptors are open directories and the
+.Ql kern.chroot_allow_open_directories
+sysctl is not set to permit this.
+.It Bq Er EIO
+An I/O error occurred while reading from or writing to the file system.
+.It Bq Er EINTEGRITY
+Corrupted data was detected while reading from the file system.
+.El
+.Pp
+The
+.Fn chroot
system call
will fail and the root directory will be unchanged if:
.Bl -tag -width Er
.It Bq Er ENOTDIR
A component of the path name is not a directory.
-.It Bq Er EPERM
-The effective user ID is not the super-user, or one or more
-filedescriptors are open directories.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters,
or an entire path name exceeded 1023 characters.
@@ -128,10 +156,6 @@ The
.Fa dirname
argument
points outside the process's allocated address space.
-.It Bq Er EIO
-An I/O error occurred while reading from or writing to the file system.
-.It Bq Er EINTEGRITY
-Corrupted data was detected while reading from the file system.
.El
.Pp
The
@@ -146,15 +170,8 @@ file descriptor.
The argument
.Fa fd
is not a valid file descriptor.
-.It Bq Er EIO
-An I/O error occurred while reading from or writing to the file system.
-.It Bq Er EINTEGRITY
-Corrupted data was detected while reading from the file system.
.It Bq Er ENOTDIR
The file descriptor does not reference a directory.
-.It Bq Er EPERM
-The effective user ID is not the super-user, or one or more
-filedescriptors are open directories.
.El
.Sh SEE ALSO
.Xr chdir 2 ,
diff --git a/lib/libsys/copy_file_range.2 b/lib/libsys/copy_file_range.2
index bcd9170842d5..829a5a5d3c13 100644
--- a/lib/libsys/copy_file_range.2
+++ b/lib/libsys/copy_file_range.2
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 28, 2023
+.Dd August 16, 2025
.Dt COPY_FILE_RANGE 2
.Os
.Sh NAME
@@ -74,6 +74,7 @@ argument must be opened for reading and the
.Fa outfd
argument must be opened for writing, but not
.Dv O_APPEND .
+.Pp
If
.Fa inoffp
or
@@ -101,9 +102,29 @@ respectively will be used/updated and the file offset for
or
.Fa outfd
respectively will not be affected.
-The
+.Pp
+The only
+.Fa flags
+argument currently defined is
+.Dv COPY_FILE_RANGE_CLONE .
+When this flag is set,
+.Fn copy_file_range
+will return
+.Er EOPNOTSUPP
+if the copy cannot be done via
+block cloning.
+When
.Fa flags
-argument must be 0.
+is 0, a file system may do the copy via block cloning
+or by data copying.
+Block cloning is only possible when the offsets (plus
+.Fa len
+if not to EOF on the input file) are block
+aligned.
+The correct block alignment can normally be acquired via the
+.Dv _PC_CLONE_BLKSIZE
+query for
+.Xr pathconf 2 .
.Pp
This system call attempts to maintain holes in the output file for
the byte range being copied.
@@ -203,9 +224,15 @@ refers to a directory.
File system that stores
.Fa outfd
is full.
+.It Bq Er EOPNOTSUPP
+Cannot do the copy via block cloning and the
+.Dv COPY_FILE_RANGE_CLONE
+.Fa flags
+argument is specified.
.El
.Sh SEE ALSO
-.Xr lseek 2
+.Xr lseek 2 ,
+.Xr pathconf 2
.Sh STANDARDS
The
.Fn copy_file_range
diff --git a/lib/libsys/fhopen.2 b/lib/libsys/fhopen.2
index aba53f1dd907..b281ac3d8949 100644
--- a/lib/libsys/fhopen.2
+++ b/lib/libsys/fhopen.2
@@ -31,7 +31,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd April 6, 2025
+.Dd July 20, 2025
.Dt FHOPEN 2
.Os
.Sh NAME
@@ -140,7 +140,7 @@ is no longer valid.
.Xr fstatfs 2 ,
.Xr getfh 2 ,
.Xr open 2 ,
-.Xr named_attribute 9
+.Xr named_attribute 7
.Sh HISTORY
The
.Fn fhopen ,
diff --git a/lib/libsys/getgroups.2 b/lib/libsys/getgroups.2
index 91cca2748ec2..4e94b32d4e7b 100644
--- a/lib/libsys/getgroups.2
+++ b/lib/libsys/getgroups.2
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd January 21, 2011
+.Dd October 10, 2025
.Dt GETGROUPS 2
.Os
.Sh NAME
.Nm getgroups
-.Nd get group access list
+.Nd get the calling process' supplementary groups
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -40,36 +48,39 @@
.Sh DESCRIPTION
The
.Fn getgroups
-system call
-gets the current group access list of the user process
-and stores it in the array
-.Fa gidset .
-The
+system call gets the calling process' supplementary groups and stores them in
+the
+.Fa gidset
+array in strictly ascending order.
+The value of
.Fa gidsetlen
-argument
-indicates the number of entries that may be placed in
+indicates the maximum number of entries that may be placed in
.Fa gidset .
-The
-.Fn getgroups
-system call
-returns the actual number of groups returned in
-.Fa gidset .
-At least one and as many as {NGROUPS_MAX}+1 values may be returned.
+.Pp
If
.Fa gidsetlen
is zero,
.Fn getgroups
-returns the number of supplementary group IDs associated with
-the calling process without modifying the array pointed to by
+returns the cardinal of the calling process' supplementary groups set and
+ignores argument
.Fa gidset .
.Pp
+No more than
+.Dv {NGROUPS_MAX}
+values may ever be returned.
The value of
.Dv {NGROUPS_MAX}
should be obtained using
.Xr sysconf 3
to avoid hard-coding it into the executable.
.Sh RETURN VALUES
-A successful call returns the number of groups in the group set.
+On success, the
+.Fn getgroups
+system call returns the cardinal of the supplementary groups set.
+It always succeeds if argument
+.Fa gidsetlen
+is zero.
+.Pp
A value of -1 indicates that an error occurred, and the error
code is stored in the global variable
.Va errno .
@@ -81,12 +92,12 @@ are:
.It Bq Er EINVAL
The argument
.Fa gidsetlen
-is smaller than the number of groups in the group set.
+is smaller than the number of supplementary groups
+.Pq but not zero .
.It Bq Er EFAULT
-The argument
+An invalid address was encountered while reading from the
.Fa gidset
-specifies
-an invalid address.
+array.
.El
.Sh SEE ALSO
.Xr setgroups 2 ,
@@ -96,9 +107,48 @@ an invalid address.
The
.Fn getgroups
system call conforms to
-.St -p1003.1-2008 .
+.St -p1003.1-2008 ,
+not reporting the effective group ID.
.Sh HISTORY
The
.Fn getgroups
system call appeared in
.Bx 4.2 .
+.Pp
+Since
+.Fx 14.3 ,
+the
+.Fn getgroups
+system call has been reporting the supplementary groups in strictly ascending
+order.
+.Pp
+Before
+.Fx 15.0 ,
+the
+.Fn getgroups
+system call would additionally return the effective group ID as the first
+element of the array, before the supplementary groups.
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn getgroups
+system call gets the supplementary groups set in the
+.Fa gidset
+array.
+In particular, as evoked in
+.Sx HISTORY ,
+it does not anymore retrieve the effective group ID in the first slot of
+.Fa gidset .
+Programs that process this slot in a specific way must be modified to obtain the
+effective group ID through other means, such as a call to
+.Xr getegid 2 .
+.Pp
+The effective group ID is present in the supplementary groups set if and only if
+it was explicitly set as a supplementary group.
+The function
+.Fn initgroups
+enforces that, while the
+.Fn setgroups
+system call does not.
+Please consult the
+.Xr initgroups 3
+manual page for the rationale.
diff --git a/lib/libsys/getsockopt.2 b/lib/libsys/getsockopt.2
index 8839b61597a2..3867824681d7 100644
--- a/lib/libsys/getsockopt.2
+++ b/lib/libsys/getsockopt.2
@@ -593,6 +593,15 @@ specified amount of time has elapsed since the initial call to
If
.Fa sp_fd
is -1, the socket will be unspliced immediately.
+A successful
+.Xr select 2 ,
+.Xr poll 2 ,
+or
+.Xr kqueue 2
+operation testing the ability to read from the source socket indicates
+that the splicing has terminated and at least one byte is available for
+reading.
+When one of the sockets gets closed, splicing ends.
.Pp
When passed to
.Fn getsockopt ,
diff --git a/lib/libsys/jail.2 b/lib/libsys/jail.2
index 8f8b9925c712..ee4e5b03d38e 100644
--- a/lib/libsys/jail.2
+++ b/lib/libsys/jail.2
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd November 29, 2023
+.Dd September 15, 2025
.Dt JAIL 2
.Os
.Sh NAME
@@ -31,7 +31,9 @@
.Nm jail_get ,
.Nm jail_set ,
.Nm jail_remove ,
-.Nm jail_attach
+.Nm jail_attach ,
+.Nm jail_remove_jd ,
+.Nm jail_attach_jd
.Nd create and manage system jails
.Sh LIBRARY
.Lb libc
@@ -44,6 +46,10 @@
.Fn jail_attach "int jid"
.Ft int
.Fn jail_remove "int jid"
+.Ft int
+.Fn jail_attach_jd "int fd"
+.Ft int
+.Fn jail_remove_jd "int fd"
.In sys/uio.h
.Ft int
.Fn jail_get "struct iovec *iov" "u_int niov" "int flags"
@@ -188,6 +194,29 @@ system call.
This is deprecated in
.Fn jail_set
and has no effect.
+.It Dv JAIL_USE_DESC
+Identify the jail by a descriptor in the
+.Va desc
+parameter.
+.It Dv JAIL_AT_DESC
+Operate in the context of the jail described by the
+.Va desc
+parameter, instead of the current jail.
+Only one of
+.Dv JAIL_USE_DESC
+or
+.Dv JAIL_AT_DESC
+may be specified.
+.It Dv JAIL_GET_DESC
+Return a new jail descriptor for the jail in the
+.Va desc
+parameter.
+.It Dv JAIL_OWN_DESC
+Return an
+.Dq owning
+jail descriptor in the
+.Va desc
+parameter.
.El
.Pp
The
@@ -221,6 +250,9 @@ arguments consists of one or more following flags:
.Bl -tag -width indent
.It Dv JAIL_DYING
Allow getting a jail that is in the process of being removed.
+.It Dv JAIL_USE_DESC , Dv JAIL_AT_DESC , Dv JAIL_GET_DESC , Dv JAIL_OWN_DESC
+These have the same meaning as they do in
+.Fn jail_set .
.El
.Pp
The
@@ -238,6 +270,76 @@ system call removes the jail identified by
.Fa jid .
It will kill all processes belonging to the jail, and remove any children
of that jail.
+.Pp
+The
+.Fn jail_attach_fd
+and
+.Fn jail_remove_fd
+system calls work the same as
+.Fn jail_attach
+and
+.Fn jail_remove ,
+except that they operate on the jail identified by jail descriptor
+.Fa fd .
+.Ss Jail Descriptors
+In addition to the jail ID,
+jails can be referred to using a jail descriptor,
+a type of file descriptor tied to a particular jail.
+Jail descriptors are created by calling
+.Fn jail_set
+or
+.Fn jail_get
+with the special parameter
+.Va desc ,
+and either the
+.Dv JAIL_GET_DESC
+or
+.Dv JAIL_OWN_DESC
+flags set.
+The difference between the two flags is that descriptors created with
+.Dv JAIL_OWN_DESC
+.Po
+called
+.Dq owning
+descriptors
+.Pc
+will automatically remove the jail when the descriptor is closed.
+.Pp
+Jail descriptors can be passed back to
+.Fn jail_set
+or
+.Fm jail_get
+with the
+.Va desc
+parameter,
+and either the
+.Dv JAIL_USE_DESC
+or
+.Dv JAIL_AT_DESC
+flags set.
+With
+.Dv JAIL_USE_DESC ,
+the descriptor identifies the jail to operate on,
+instead of the
+.Va jid
+or
+.Va name
+parameter.
+With
+.Dv JAIL_AT_DESC ,
+the descriptor is used in place of the current jail,
+allowing accessing or creating jails that are children of the
+descriptor jail.
+.Pp
+The system calls
+.Fn jail_attach_jd
+and
+.Fn jail_aremove_jd
+work the same as
+.Fn jail_attach
+and
+.Fn jail_remove ,
+except that they operate on the jail referred to by the passed descriptor.
.Sh RETURN VALUES
If successful,
.Fn jail ,
@@ -249,7 +351,7 @@ They return \-1 on failure, and set
.Va errno
to indicate the error.
.Pp
-.Rv -std jail_attach jail_remove
+.Rv -std jail_attach jail_remove jail_attach_jd jail_remove_jd
.Sh ERRORS
The
.Fn jail
@@ -281,6 +383,13 @@ the super-user, or because it would exceed the jail's
.Va children.max
limit.
.It Bq Er EPERM
+The jail descriptor in the
+.Va desc
+parameter was created by a user other than the super-user,
+and the
+.Dv JAIL_USE_DESC
+flag was set.
+.It Bq Er EPERM
A jail parameter was set to a less restrictive value then the current
environment.
.It Bq Er EFAULT
@@ -298,8 +407,12 @@ flag is not set.
.It Bq Er ENOENT
The jail referred to by a
.Va jid
-is not accessible by the process, because the process is in a different
-jail.
+parameter is not accessible by the process, because the process is in a
+different jail.
+.It Bq Er ENOENT
+The jail referred to by a
+.Va desc
+parameter has been removed.
.It Bq Er EEXIST
The jail referred to by a
.Va jid
@@ -326,6 +439,24 @@ flags is not set.
A supplied string parameter is longer than allowed.
.It Bq Er EAGAIN
There are no jail IDs left.
+.It Bq Er EMFILE
+A jail descriptor could not be created for the
+.Va desc
+parameter with either the
+.Dv JAIL_GET_DESC
+or
+.Dv JAIL_OWN_DESC
+flag set,
+because the process has already reached its limit for open file descriptors.
+.It Bq Er ENFILE
+A jail descriptor could not be created for the
+.Va desc
+parameter with either the
+.Dv JAIL_GET_DESC
+or
+.Dv JAIL_OWN_DESC
+flag set,
+because the system file table is full.
.El
.Pp
The
@@ -333,10 +464,6 @@ The
system call
will fail if:
.Bl -tag -width Er
-.It Bq Er EFAULT
-.Fa Iov ,
-or one of the addresses contained within it,
-points to an address outside the allocated address space of the process.
.It Bq Er ENOENT
The jail referred to by a
.Va jid
@@ -352,10 +479,37 @@ jail.
The
.Va lastjid
parameter is greater than the highest current jail ID.
+.It Bq Er ENOENT
+The jail referred to by a
+.Va desc
+parameter has been removed
+.Pq even if the Dv JAIL_CREATE flag has been set .
.It Bq Er EINVAL
A supplied parameter is the wrong size.
.It Bq Er EINVAL
+A supplied parameter is out of range.
+.It Bq Er EINVAL
+A supplied string parameter is not null-terminated.
+.It Bq Er EINVAL
A supplied parameter name does not match any known parameters.
+.It Bq Er EMFILE
+A jail descriptor could not be created for the
+.Va desc
+parameter with either the
+.Dv JAIL_GET_DESC
+or
+.Dv JAIL_OWN_DESC
+flag set,
+because the process has already reached its limit for open file descriptors.
+.It Bq Er ENFILE
+A jail descriptor could not be created for the
+.Va desc
+parameter with either the
+.Dv JAIL_GET_DESC
+or
+.Dv JAIL_OWN_DESC
+flag set,
+because the system file table is full.
.El
.Pp
The
@@ -373,14 +527,37 @@ The jail specified by
does not exist.
.El
.Pp
+The
+.Fn jail_attach_jd
+and
+.Fn jail_remove_jd
+system calls
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa fd
+argument is not a valid jail descriptor.
+.It Bq Er EPERM
+The jail descriptor was created by a user other than the super-user.
+.It Bq Er EINVAL
+The jail specified by
+.Fa jid
+has been removed.
+.El
+.Pp
Further
.Fn jail ,
.Fn jail_set ,
+.Fn jail_attach ,
and
-.Fn jail_attach
+.Fn jail_attach_jd
call
.Xr chroot 2
internally, so they can fail for all the same reasons.
+In particular, they return the
+.Bq Er EPERM
+error when the process to join a jail has open directories.
Please consult the
.Xr chroot 2
manual page for details.
diff --git a/lib/libsys/kqueue.2 b/lib/libsys/kqueue.2
index d6e949baa24c..a8ebabf02cf7 100644
--- a/lib/libsys/kqueue.2
+++ b/lib/libsys/kqueue.2
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 26, 2023
+.Dd September 12, 2025
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -97,10 +97,37 @@ system call also creates a new kernel event queue, and additionally takes
a
.Fa flags
argument, which is a bitwise-inclusive OR of the following flags:
-.Bl -tag -width "KQUEUE_CLOEXEC"
+.Bl -tag -width "KQUEUE_CPONFORK"
.It Dv KQUEUE_CLOEXEC
The returned file descriptor is automatically closed on
.Xr execve 2
+.It Dv KQUEUE_CPONFORK
+When this flag is set, the created kqueue is copied into
+the child process on
+.Xr fork 2
+calls.
+The kqueue descriptor index of the new kqueue will be inherited by the child,
+that is, the numeric value of the descriptor will remain the same.
+.Pp
+Copying is deep, that is, each registered event in the original kqueue is
+copied (and not shared) into the new kqueue.
+This is contrary to how other descriptor types are handled upon
+.Xr fork 2 ,
+where the copied file descriptor references the same file object
+as the source descriptor (shallow copy).
+.Pp
+By default, in other words, when the flag is not set, kqueues from
+the parent are not copied on fork to the child process.
+The corresponding file descriptor indeces are unused in the child.
+.Pp
+Registered events that reference file descriptors which are not
+duplicated on fork, are not copied into the new kqueue.
+For instance, if the event references a file descriptor opened with the
+.Dv O_CLOEXEC
+flag set, it is not copied.
+Similarly, if event references a kqueue opened without the
+.Dv KQUEUE_CPONFORK
+flag, the event is not copied.
.El
.Pp
The
@@ -593,6 +620,64 @@ returns the number of times the signal has occurred since the last call to
This filter automatically sets the
.Dv EV_CLEAR
flag internally.
+.It Dv EVFILT_JAIL
+Takes the jail ID to monitor as the identifier and the events to watch for
+in
+.Va fflags ,
+and returns when the jail performs one or more of the requested events.
+If a process can normally see a jail, it can attach an event to it.
+An identifier of zero will watch the process's own jail.
+The events to monitor are:
+.Bl -tag -width "Dv NOTE_JAIL_ATTACH"
+.It Dv NOTE_JAIL_SET
+The jail has been changed via
+.Xr jail_set 2 .
+.It Dv NOTE_JAIL_ATTACH
+A process has attached to the jail via
+.Xr jail_attach 2
+or a similar call.
+The process ID will be stored in
+.Va data .
+If more than one process has attached since the last call to
+.Fn kevent ,
+.Va data
+will be zero.
+.It Dv NOTE_JAIL_REMOVE
+The jail has been removed.
+.It Dv NOTE_JAIL_CHILD
+A child of the watched jail has been created.
+Its jail ID will be stored in
+.Va data .
+If more than one jail has been created since the last call to
+.Fn kevent ,
+.Va data
+will be zero.
+.El
+.Pp
+On return,
+.Va fflags
+contains the events which triggered the filter.
+It will also contain
+.Dv NOTE_JAIL_MULTI
+if more than one
+.Dv NOTE_JAIL_ATTACH
+or
+.Dv NOTE_JAIL_CHILD
+event has been received since the last call to
+.Fn kevent .
+.It Dv EVFILT_JAILDESC
+Takes a jail descriptor returned by
+.Xr jail_set 2
+or
+.Xr jail_get 2
+as the identifier and the events to watch for in
+.Va fflags ,
+and returns when the jail performs one or more of the requested events.
+The events to monitor and the resulting
+.Va fflags
+are the same as those listed in
+.Dv EVFILT_JAIL ,
+above.
.It Dv EVFILT_TIMER
Establishes an arbitrary timer identified by
.Va ident .
diff --git a/lib/libsys/mkdir.2 b/lib/libsys/mkdir.2
index e1f1624cebc4..100f44d1dcf9 100644
--- a/lib/libsys/mkdir.2
+++ b/lib/libsys/mkdir.2
@@ -176,4 +176,4 @@ system call appeared in
The
.Fn mkdir
system call appeared in
-.At v1 .
+.Bx 4.2 .
diff --git a/lib/libsys/pathconf.2 b/lib/libsys/pathconf.2
index 79ac8310000d..5a983a3a13e2 100644
--- a/lib/libsys/pathconf.2
+++ b/lib/libsys/pathconf.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 5, 2025
+.Dd August 6, 2025
.Dt PATHCONF 2
.Os
.Sh NAME
@@ -187,6 +187,11 @@ and
flags can be set by
.Xr chflags 2 ,
otherwise 0.
+.It Li _PC_CLONE_BLKSIZE
+Returns the block size required for block cloning via
+.Xr copy_file_range 2
+for a file system if block cloning is supported,
+otherwise 0.
.El
.Sh RETURN VALUES
If the call to
@@ -264,6 +269,7 @@ Corrupted data was detected while reading from the file system.
.El
.Sh SEE ALSO
.Xr chflags 2 ,
+.Xr copy_file_range 2 ,
.Xr lseek 2 ,
.Xr sysctl 3
.Sh HISTORY
diff --git a/lib/libsys/setcred.2 b/lib/libsys/setcred.2
index 86f61ddfdb30..f5d1f15b631b 100644
--- a/lib/libsys/setcred.2
+++ b/lib/libsys/setcred.2
@@ -6,7 +6,7 @@
.\" This documentation was written by Olivier Certner <olce.freebsd@certner.fr>
.\" at Kumacom SARL under sponsorship from the FreeBSD Foundation.
.\"
-.Dd December 19, 2024
+.Dd August 29, 2025
.Dt SETCRED 2
.Os
.Sh NAME
@@ -119,11 +119,6 @@ It must be less than or equal to
An array of IDs to set the supplementary groups to, if flag
.Dv SETCREDF_SUPP_GROUPS
is specified.
-Note that all groups in this array will be set as supplementary groups only, in
-contrast to
-.Xr setgroups 2
-which treats the first element specially as the new effective group, not adding
-it to supplementary groups.
.It Fa sc_label
A pointer to a valid MAC label structure, e.g., built with the
.Xr mac_from_text 3
diff --git a/lib/libsys/setgroups.2 b/lib/libsys/setgroups.2
index a226aeafea96..0ec99507cfb0 100644
--- a/lib/libsys/setgroups.2
+++ b/lib/libsys/setgroups.2
@@ -1,5 +1,13 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1983, 1991, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2025 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Olivier Certner
+.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
+.\" Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -25,12 +33,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd January 19, 2018
+.Dd September 17, 2025
.Dt SETGROUPS 2
.Os
.Sh NAME
.Nm setgroups
-.Nd set group access list
+.Nd set the calling process' supplementary groups
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -41,35 +49,21 @@
.Sh DESCRIPTION
The
.Fn setgroups
-system call
-sets the group access list of the current user process
-according to the array
-.Fa gidset .
+system call sets the calling process' supplementary groups according to the
+.Fa gidset
+array.
The
.Fa ngroups
-argument
-indicates the number of entries in the array and must be no
-more than
-.Dv {NGROUPS_MAX}+1 .
+argument indicates the number of entries in the array and must be no more than
+.Dv {NGROUPS_MAX} .
.Pp
-Only the super-user may set a new group list.
+The
+.Fa ngroups
+argument may be set to zero to clear all supplementary groups, in which case
+.Fa gidset
+is ignored.
.Pp
-The first entry of the group array
-.Pq Va gidset[0]
-is used as the effective group-ID for the process.
-This entry is over-written when a setgid program is run.
-To avoid losing access to the privileges of the
-.Va gidset[0]
-entry, it should be duplicated later in the group array.
-By convention,
-this happens because the group value indicated
-in the password file also appears in
-.Pa /etc/group .
-The group value in the password file is placed in
-.Va gidset[0]
-and that value then gets added a second time when the
-.Pa /etc/group
-file is scanned to create the group set.
+Only the super-user may install a new supplementary groups set.
.Sh RETURN VALUES
.Rv -std setgroups
.Sh ERRORS
@@ -83,19 +77,86 @@ The caller is not the super-user.
The number specified in the
.Fa ngroups
argument is larger than the
-.Dv {NGROUPS_MAX}+1
+.Dv {NGROUPS_MAX}
limit.
.It Bq Er EFAULT
-The address specified for
+Part of the groups array starting at
.Fa gidset
-is outside the process
-address space.
+is outside the process address space.
.El
.Sh SEE ALSO
.Xr getgroups 2 ,
+.Xr setcred 2 ,
.Xr initgroups 3
.Sh HISTORY
The
.Fn setgroups
system call appeared in
.Bx 4.2 .
+.Pp
+Before
+.Fx 15.0 ,
+the
+.Fn setgroups
+system call would set the effective group ID for the process to the first
+element of
+.Fa gidset ,
+and only the other elements as supplementary groups.
+Despite treating the first element as the effective group ID to set, it accepted
+an empty
+.Fa gidset
+.Po
+.Fa ngroups
+being zero
+.Pc
+as a stance requiring to drop all supplementary groups, leaving the effective
+group ID unchanged.
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn setgroups
+system call sets the process' supplementary groups to those contained in the
+.Fa gidset
+array.
+In particular, as evoked in
+.Sx HISTORY ,
+it does not anymore treat the first element of
+.Fa gidset
+separately.
+Formerly, it would set it as the effective group ID while only the others were
+used as supplementary groups.
+.Pp
+Programs solely relying on
+.Fn setgroups
+to change the effective group ID must be modified, e.g., to also call
+.Xr setegid 2
+or to instead use
+.Xr setcred 2 ,
+else they will unwillingly keep their effective group ID.
+.Pp
+Programs using
+.Fn setgroups
+with the effective group ID as the first element of array
+.Fa gidset
+and not duplicating it in the rest of the array, which includes those using
+.Fn initgroups ,
+now insert this group ID in the supplementary groups set.
+This is in general desirable, as explained in the
+.Xr initgroups 3
+manual page, and has the consequence that subsequent process' effective group
+ID's changes do not remove membership of the original effective group ID, since
+these changes do not affect the supplementary groups.
+Applications that expressly do not want that must be modified to stop passing
+the effective group ID as the first element to
+.Fn setgroups .
+.Pp
+To clear all the calling process' supplementary groups, always use the statement
+.Bd -literal -offset indent
+setgroups(0, NULL);
+.Ed
+.Pp
+which works also on older FreeBSD version
+.Po
+see the
+.Sx HISTORY
+section
+.Pc .
diff --git a/lib/libsys/shm_open.2 b/lib/libsys/shm_open.2
index 8bea939690ba..c3196d966e6b 100644
--- a/lib/libsys/shm_open.2
+++ b/lib/libsys/shm_open.2
@@ -26,7 +26,7 @@
.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd January 30, 2023
+.Dd August 4, 2025
.Dt SHM_OPEN 2
.Os
.Sh NAME
@@ -74,8 +74,9 @@ must be included in
The optional flags
.Dv O_CREAT ,
.Dv O_EXCL ,
+.Dv O_TRUNC ,
and
-.Dv O_TRUNC
+.Dv O_CLOFORK
may also be specified.
.Pp
If
diff --git a/lib/libsys/socket.2 b/lib/libsys/socket.2
index b211611c6354..48b8f4e87489 100644
--- a/lib/libsys/socket.2
+++ b/lib/libsys/socket.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 17, 2025
+.Dd September 28, 2025
.Dt SOCKET 2
.Os
.Sh NAME
@@ -64,7 +64,7 @@ PF_NETGRAPH Netgraph sockets,
PF_NETLINK Netlink protocols,
PF_BLUETOOTH Bluetooth protocols,
PF_INET_SDP OFED socket direct protocol (IPv4),
-AF_HYPERV HyperV sockets
+PF_HYPERV HyperV sockets
.Ed
.Pp
Each protocol family is connected to an address family, which has the
@@ -89,32 +89,6 @@ SOCK_RAW Raw-protocol interface,
SOCK_SEQPACKET Sequenced packet stream
.Ed
.Pp
-A
-.Dv SOCK_STREAM
-type provides sequenced, reliable,
-two-way connection based byte streams.
-An out-of-band data transmission mechanism may be supported.
-A
-.Dv SOCK_DGRAM
-socket supports
-datagrams (connectionless, unreliable messages of
-a fixed (typically small) maximum length).
-A
-.Dv SOCK_SEQPACKET
-socket may provide a sequenced, reliable,
-two-way connection-based data transmission path for datagrams
-of fixed maximum length; a consumer may be required to read
-an entire packet with each read system call.
-This facility may have protocol-specific properties.
-.Dv SOCK_RAW
-sockets provide access to internal network protocols and interfaces.
-The
-.Dv SOCK_RAW
-type is available only to the super-user and is described in
-.Xr ip 4
-and
-.Xr ip6 4 .
-.Pp
Additionally, the following flags are allowed in the
.Fa type
argument:
@@ -140,32 +114,23 @@ particular to the
in which communication
is to take place; see
.Xr protocols 5 .
-.Pp
The
.Fa protocol
argument may be set to zero (0) to request the default
implementation of a socket type for the protocol, if any.
-.Pp
-Sockets of type
+.Sh STREAM SOCKET TYPE
+The
+.Dv SOCK_STREAM
+socket type provides reliable, sequenced, full-duplex octet streams between
+the socket and a peer to which the socket is connected.
+A socket of type
.Dv SOCK_STREAM
-are full-duplex byte streams, similar
-to pipes.
-A stream socket must be in a
+needs to be in a
.Em connected
-state before any data may be sent or received
-on it.
+state before any data can be sent or received.
A connection to another socket is created with a
.Xr connect 2
system call.
-Once connected, data may be transferred using
-.Xr read 2
-and
-.Xr write 2
-calls or some variant of the
-.Xr send 2
-and
-.Xr recv 2
-functions.
(Some protocol families, such as the Internet family,
support the notion of an
.Dq implied connect ,
@@ -173,62 +138,210 @@ which permits data to be sent piggybacked onto a connect operation by
using the
.Xr sendto 2
system call.)
-When a session has been completed a
-.Xr close 2
-may be performed.
-Out-of-band data may also be transmitted as described in
+Once connected, data may be sent using
+.Xr send 2 ,
+.Xr sendto 2 ,
+.Xr sendmsg 2
+and
+.Xr write 2
+system calls.
+Data may be received using
+.Xr recv 2 ,
+.Xr recvfrom 2 ,
+.Xr recvmsg 2 ,
+and
+.Xr read 2
+system calls.
+Record boundaries are not maintained; data sent on a stream socket using output
+operations of one size can be received using input operations of smaller or
+larger sizes without loss of data.
+Data may be buffered; successful return from an output function does not imply
+that the data has been delivered to the peer or even transmitted from the local
+system.
+For certain protocols out-of-band data may also be transmitted as described in
.Xr send 2
and received as described in
.Xr recv 2 .
.Pp
-The communications protocols used to implement a
-.Dv SOCK_STREAM
-ensure that data
-is not lost or duplicated.
-If a piece of data for which the
-peer protocol has buffer space cannot be successfully transmitted
-within a reasonable length of time, then
-the connection is considered broken and calls
-will indicate an error with
--1 returns and with
-.Er ETIMEDOUT
-as the specific code
-in the global variable
-.Va errno .
-The protocols optionally keep sockets
-.Dq warm
-by forcing transmissions
-roughly every minute in the absence of other activity.
-An error is then indicated if no response can be
-elicited on an otherwise
-idle connection for an extended period (e.g.\& 5 minutes).
-By default, a
+If data cannot be successfully transmitted within a given time then the
+connection is considered broken, and subsequent operations shall fail with
+a protocol specific error code.
+A
.Dv SIGPIPE
-signal is raised if a process sends
-on a broken stream, but this behavior may be inhibited via
+signal is raised if a thread attempts to send data on a broken stream (one that
+is no longer connected).
+The signal can be suppressed by the
+.Dv MSG_NOSIGNAL
+flag with distinct
+.Xr send 2 ,
+.Xr sendto 2 ,
+and
+.Xr sendmsg 2
+system calls or by the
+.Dv SO_NOSIGPIPE
+socket option set on the socket with
.Xr setsockopt 2 .
.Pp
-.Dv SOCK_SEQPACKET
-sockets employ the same system calls
-as
+The
.Dv SOCK_STREAM
-sockets.
-The only difference
-is that
-.Xr read 2
-calls will return only the amount of data requested,
-and any remaining in the arriving packet will be discarded.
+socket is supported by the following protocol families:
+.Dv PF_INET ,
+.Dv PF_INET6 ,
+.Dv PF_UNIX ,
+.Dv PF_BLUETOOTH ,
+.Dv PF_HYPERV ,
+and
+.Dv PF_INET_SDP .
+Out-of-band data transmission mechanism is supported for stream sockets of
+.Dv PF_INET
+and
+.Dv PF_INET6
+protocol families.
+.Sh DATAGRAM SOCKET TYPE
+The
+.Dv SOCK_DGRAM
+socket type supports connectionless data transfer which is not necessarily
+acknowledged or reliable.
+Datagrams can be sent to the address specified (possibly multicast or
+broadcast) in each output operation, and incoming datagrams can be received
+from multiple sources.
+The source address of each datagram is available when receiving the datagram
+with
+.Xr recvfrom 2
+or
+.Xr recvmsg 2 .
+An application can also pre-specify a peer address with
+.Xr sendto 2
+or
+.Xr sendmsg 2 ,
+in which case calls to output functions that do not specify a peer address
+shall send to the pre-specified peer.
+If a peer has been specified, only datagrams from that peer shall be received.
+A datagram shall be sent in a single output operation, and needs to be received
+in a single input operation.
+The maximum size of a datagram is protocol-specific.
+Output datagrams may be buffered within the system; thus, a successful return
+from an output function does not guarantee that a datagram is actually sent or
+received.
.Pp
+The
.Dv SOCK_DGRAM
+socket is supported by the following protocol families:
+.Dv PF_INET ,
+.Dv PF_INET6 ,
+.Dv PF_UNIX ,
+.Dv PF_NETGRAPH ,
and
-.Dv SOCK_RAW
-sockets allow sending of datagrams to correspondents
-named in
+.Dv PF_NETLINK .
+.Sh SEQUENCED PACKET SOCKET TYPE
+The
+.Dv SOCK_SEQPACKET
+socket type is similar to the
+.Dv SOCK_STREAM
+type, and is also connection-oriented.
+The only difference between these types is that record boundaries are
+maintained using the
+.Dv SOCK_SEQPACKET
+type.
+A record can be sent using one or more output operations and received using one
+or more input operations, but a single operation never transfers parts of more
+than one record.
+Record boundaries are set by the sender with the
+.Dv MSG_EOR
+flag of
.Xr send 2
-calls.
-Datagrams are generally received with
+or
+.Xr sendmsg 2
+functions.
+There is no possibility to set a record boundary with
+.Xr write 2 .
+Record boundaries are visible to the receiver via the
+.Dv MSG_EOR
+flag in the received message flags returned by the
+.Xr recvmsg 2
+function.
+It is protocol-specific whether a maximum record size is imposed.
+.Pp
+The
+.Dv SOCK_SEQPACKET
+socket is supported by the following protocol families:
+.Dv PF_INET ,
+.Dv PF_INET6 ,
+and
+.Dv PF_UNIX .
+.Pp
+.Sh RAW SOCKET TYPE
+The
+.Dv SOCK_RAW
+socket type provides access to internal network protocols and interfaces.
+It is a datagram socket in its nature, thus has the same semantics of
+read and write operations.
+The
+.Dv SOCK_RAW
+type is available only to the super-user and is described in
+.Xr ip 4
+and
+.Xr ip6 4 .
+.Sh NON-BLOCKING MODE
+A socket can be created in
+.Em non-blocking mode
+with the help of
+.Dv SOCK_NONBLOCK
+flag.
+Alternatively, the non-blocking mode on a socket can be turned on and off with
+the help of the
+.Dv O_NONBLOCK
+flag of the
+.Xr fcntl 2
+system call.
+.Pp
+When a non-blocking socket has not enough data in its receive buffer to fulfill
+the application supplied buffer, then data receiving system calls like
+.Xr recv 2 ,
.Xr recvfrom 2 ,
-which returns the next datagram with its return address.
+.Xr recvmsg 2
+and
+.Xr read 2
+will not block waiting for the data but immediately return.
+Return value will indicate amount of bytes read into the supplied buffer.
+The
+.Va errno
+will be set to
+.Dv EAGAIN
+.Po
+has same value as
+.Dv EWOULDBLOCK
+.Pc .
+.Pp
+If application tries to send more data on a non-blocking socket than the socket
+send buffer can accomodate with
+.Xr send 2 ,
+.Xr sendto 2 ,
+.Xr sendmsg 2
+or
+.Xr write 2
+system calls partial data will be sent.
+Return value will indicate amount of bytes sent.
+The
+.Va errno
+will be set to
+.Dv EAGAIN .
+Note that sockets of
+.Dv SOCK_DGRAM
+type are unreliable, thus for these sockets sending operations will never fail
+with
+.Dv EAGAIN
+in non-blocking mode neither will block in blocking mode.
+.Sh OTHER OPERATIONS ON SOCKETS
+Since socket descriptors are file descriptors, many generic file operations
+performed by
+.Xr fcntl 2 ,
+apply.
+Socket descriptors can be used with all event engines, such as
+.Xr kevent 2 ,
+.Xr select 2
+and
+.Xr poll 2 .
.Pp
An
.Xr fcntl 2
@@ -250,6 +363,12 @@ The
and
.Xr getsockopt 2
system calls are used to set and get options, respectively.
+.Pp
+Connection associated with a socket can be terminated by
+.Xr close 2
+system call.
+One direction of communication can be disabled with
+.Xr shutdown 2 .
.Sh RETURN VALUES
A -1 is returned if an error occurs, otherwise the return
value is a descriptor referencing the socket.
@@ -282,16 +401,23 @@ The socket type is not supported by the protocol.
.Sh SEE ALSO
.Xr accept 2 ,
.Xr bind 2 ,
+.Xr close 2 ,
.Xr connect 2 ,
+.Xr fcntl 2 ,
.Xr getpeername 2 ,
.Xr getsockname 2 ,
.Xr getsockopt 2 ,
.Xr ioctl 2 ,
+.Xr kevent 2 ,
.Xr listen 2 ,
+.Xr poll 2 ,
.Xr read 2 ,
.Xr recv 2 ,
.Xr select 2 ,
.Xr send 2 ,
+.Xr sendmsg 2 ,
+.Xr sendto 2 ,
+.Xr signal 3 ,
.Xr shutdown 2 ,
.Xr socketpair 2 ,
.Xr write 2 ,
diff --git a/lib/libsys/stat.2 b/lib/libsys/stat.2
index bd9005710147..8107740bd901 100644
--- a/lib/libsys/stat.2
+++ b/lib/libsys/stat.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 30, 2021
+.Dd August 17, 2025
.Dt STAT 2
.Os
.Sh NAME
@@ -169,6 +169,9 @@ Flags enabled for the file.
See
.Xr chflags 2
for the list of flags and their description.
+.It Va st_rdev
+Numeric ID of the device referenced by the file, if the file is a
+character or block special; otherwise unspecified.
.El
.Pp
The
diff --git a/lib/libsys/statfs.2 b/lib/libsys/statfs.2
index 49e8b5120558..ab65def11ebb 100644
--- a/lib/libsys/statfs.2
+++ b/lib/libsys/statfs.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 7, 2025
+.Dd July 20, 2025
.Dt STATFS 2
.Os
.Sh NAME
@@ -127,7 +127,7 @@ Mandatory Access Control (MAC) support for individual objects
.Xr mac 4 ) .
.It Dv MNT_NAMEDATTR
The file system supports named attributes as described in
-.Xr named_attribute 9 .
+.Xr named_attribute 7 .
.It Dv MNT_NFS4ACLS
ACLs in NFSv4 variant are supported.
.It Dv MNT_NOATIME
@@ -264,7 +264,7 @@ each file or directory name or disk label
.Sh SEE ALSO
.Xr fhstatfs 2 ,
.Xr getfsstat 2 ,
-.Xr named_attribute 9
+.Xr named_attribute 7
.Sh HISTORY
The
.Fn statfs
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
index 69fce2ea7c63..b5400b9849b3 100644
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -7,7 +7,7 @@
FBSDprivate_1.0 {
_syscall;
__sys_syscall;
- __sys_exit;
+ __sys__exit;
_fork;
__sys_fork;
_read;
@@ -117,10 +117,6 @@ FBSDprivate_1.0 {
__sys_madvise;
_mincore;
__sys_mincore;
- _getgroups;
- __sys_getgroups;
- _setgroups;
- __sys_setgroups;
_getpgrp;
__sys_getpgrp;
_setpgid;
@@ -813,4 +809,12 @@ FBSDprivate_1.0 {
__sys_inotify_add_watch_at;
_inotify_rm_watch;
__sys_inotify_rm_watch;
+ _getgroups;
+ __sys_getgroups;
+ _setgroups;
+ __sys_setgroups;
+ _jail_attach_jd;
+ __sys_jail_attach_jd;
+ _jail_remove_jd;
+ __sys_jail_remove_jd;
};
diff --git a/lib/libsysdecode/Makefile b/lib/libsysdecode/Makefile
index ca020552a6e9..11f45355b8e2 100644
--- a/lib/libsysdecode/Makefile
+++ b/lib/libsysdecode/Makefile
@@ -27,7 +27,7 @@ MAN= sysdecode.3 \
sysdecode_sigcode.3 \
sysdecode_sockopt_name.3 \
sysdecode_socket_protocol.3 \
- sysdecode_syscallnames.3 \
+ sysdecode_syscallname.3 \
sysdecode_utrace.3
MLINKS= sysdecode_abi_to_freebsd_errno.3 sysdecode_freebsd_to_abi_errno.3
MLINKS+=sysdecode_enum.3 sysdecode_acltype.3 \
diff --git a/lib/libsysdecode/Makefile.depend b/lib/libsysdecode/Makefile.depend
index 1c40e21d361d..a9ccf3aa0870 100644
--- a/lib/libsysdecode/Makefile.depend
+++ b/lib/libsysdecode/Makefile.depend
@@ -38,7 +38,7 @@ DIRDEPS = \
lib/libarchive \
lib/libbe \
lib/libbegemot \
- lib/libblacklist \
+ lib/libblocklist \
lib/libblocksruntime \
lib/libbluetooth \
lib/libbsddialog \
diff --git a/lib/libsysdecode/sysdecode.3 b/lib/libsysdecode/sysdecode.3
index 0aa4155c004b..32f7fad4e6c5 100644
--- a/lib/libsysdecode/sysdecode.3
+++ b/lib/libsysdecode/sysdecode.3
@@ -73,7 +73,7 @@ A placeholder for use when the ABI is not known.
.Xr sysdecode_sigcode 3 ,
.Xr sysdecode_socket_protocol 3 ,
.Xr sysdecode_sockopt_name 3 ,
-.Xr sysdecode_syscallnames 3 ,
+.Xr sysdecode_syscallname 3 ,
.Xr sysdecode_utrace 3
.Sh HISTORY
The
diff --git a/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 b/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3
index 8f710d1e3756..51955f062393 100644
--- a/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3
+++ b/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3
@@ -89,4 +89,4 @@ see
.Xr sysdecode 3 .
.Sh SEE ALSO
.Xr sysdecode 3 ,
-.Xr sysdecode_syscallnames 3
+.Xr sysdecode_syscallname 3
diff --git a/lib/libsysdecode/sysdecode_syscallnames.3 b/lib/libsysdecode/sysdecode_syscallname.3
index 610cbc9b2115..8ba88fd3c43e 100644
--- a/lib/libsysdecode/sysdecode_syscallnames.3
+++ b/lib/libsysdecode/sysdecode_syscallname.3
@@ -23,17 +23,17 @@
.\" SUCH DAMAGE.
.\"
.Dd October 17, 2016
-.Dt sysdecode_syscallnames 3
+.Dt sysdecode_syscallname 3
.Os
.Sh NAME
-.Nm sysdecode_syscallnames
+.Nm sysdecode_syscallname
.Nd lookup name of system calls
.Sh LIBRARY
.Lb libsysdecode
.Sh SYNOPSIS
.In sysdecode.h
.Ft const char *
-.Fn sysdecode_syscallnames "enum sysdecode_abi abi" "unsigned int code"
+.Fn sysdecode_syscallname "enum sysdecode_abi abi" "unsigned int code"
.Sh DESCRIPTION
This function returns a pointer to the name of a system call identified by
.Fa code
diff --git a/lib/libtelnet/Makefile b/lib/libtelnet/Makefile
index 6bc2f5a51de0..2eeac2d44f98 100644
--- a/lib/libtelnet/Makefile
+++ b/lib/libtelnet/Makefile
@@ -1,6 +1,5 @@
.include <src.opts.mk>
-PACKAGE=lib${LIB}
TELNETDIR= ${SRCTOP}/contrib/telnet
.PATH: ${TELNETDIR}/libtelnet
diff --git a/lib/libthr/thread/thr_getthreadid_np.c b/lib/libthr/thread/thr_getthreadid_np.c
index ade332519dfb..ffecd0bc7ea9 100644
--- a/lib/libthr/thread/thr_getthreadid_np.c
+++ b/lib/libthr/thread/thr_getthreadid_np.c
@@ -36,7 +36,7 @@ __weak_reference(_thr_getthreadid_np, _pthread_getthreadid_np);
__weak_reference(_thr_getthreadid_np, pthread_getthreadid_np);
/*
- * Provide the equivelant to AIX pthread_getthreadid_np() function.
+ * Provide the equivalent to AIX pthread_getthreadid_np() function.
*/
int
_thr_getthreadid_np(void)
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index 64cf7d004070..0f9e3749d75f 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -170,7 +170,6 @@ STATIC_LIB_REQUIRE(_sem_trywait);
STATIC_LIB_REQUIRE(_sem_wait);
STATIC_LIB_REQUIRE(_sigaction);
STATIC_LIB_REQUIRE(_sigprocmask);
-STATIC_LIB_REQUIRE(_sigsuspend);
STATIC_LIB_REQUIRE(_sigtimedwait);
STATIC_LIB_REQUIRE(_sigwait);
STATIC_LIB_REQUIRE(_sigwaitinfo);
diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c
index 2cd3de512d1c..4bff5497a804 100644
--- a/lib/libthr/thread/thr_sig.c
+++ b/lib/libthr/thread/thr_sig.c
@@ -683,14 +683,6 @@ _thr_sigmask(int how, const sigset_t *set, sigset_t *oset)
}
int
-_sigsuspend(const sigset_t *set)
-{
- sigset_t newset;
-
- return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset)));
-}
-
-int
__thr_sigsuspend(const sigset_t *set)
{
struct pthread *curthread;
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
index ab913f834bb3..3b1911d7a5cd 100644
--- a/lib/libufs/Makefile
+++ b/lib/libufs/Makefile
@@ -1,4 +1,6 @@
-PACKAGE= libufs
+PACKAGE= ufs
+LIB_PACKAGE=
+
LIB= ufs
SHLIBDIR?= /lib
SHLIB_MAJOR= 8
diff --git a/lib/libunbound/Makefile b/lib/libunbound/Makefile
index cdc965c20763..1a31e50e6416 100644
--- a/lib/libunbound/Makefile
+++ b/lib/libunbound/Makefile
@@ -1,4 +1,3 @@
-PACKAGE=lib${LIB}
# Vendor sources and generated files
LDNSDIR= ${SRCTOP}/contrib/ldns
UNBOUNDDIR= ${SRCTOP}/contrib/unbound
@@ -6,30 +5,28 @@ UNBOUNDDIR= ${SRCTOP}/contrib/unbound
# Hold my beer and watch this
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/cachedb ${UNBOUNDDIR}/dns64 ${UNBOUNDDIR}/iterator ${UNBOUNDDIR}/sldns ${UNBOUNDDIR}/libunbound ${UNBOUNDDIR}/services ${UNBOUNDDIR}/services/cache ${UNBOUNDDIR}/util ${UNBOUNDDIR}/util/data ${UNBOUNDDIR}/respip ${UNBOUNDDIR}/util/storage ${UNBOUNDDIR}/validator
-LIB= unbound
+PACKAGE= local-unbound
+
+LIB= unbound
PRIVATELIB=
-PACKAGE= unbound
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR} -I${.OBJDIR} -I${.CURDIR}
CFLAGS+= -DOPENSSL_API_COMPAT=0x10100000L
-SRCS= alloc.c as112.c authzone.c autotrust.c cachedb.c config_file.c \
- configlexer.l configparser.y context.c dname.c dns.c dns64.c \
- dnstree.c edns.c fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c \
- iter_fwd.c iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c \
- iter_utils.c iterator.c keyraw.c libunbound.c libworker.c \
- listen_dnsport.c localzone.c locks.c log.c lookup3.c lruhash.c \
- mesh.c mini_event.c modstack.c module.c msgencode.c msgparse.c \
- msgreply.c net_help.c netevent.c outbound_list.c outside_network.c \
- packed_rrset.c parse.c parseutil.c proxy_protocol.c \
- random.c rbtree.c redis.c \
- regional.c respip.c rfc_1982.c rpz.c rrdef.c rrset.c rtt.c sbuffer.c \
- siphash.c slabhash.c \
- str2wire.c tcp_conn_limit.c timehist.c timeval_func.c \
- tube.c ub_event_pluggable.c \
- val_anchor.c val_kcache.c val_kentry.c val_neg.c val_nsec.c \
- val_nsec3.c val_secalgo.c val_sigcrypt.c val_utils.c validator.c \
- view.c winsock_event.c wire2str.c
+SRCS= alloc.c as112.c authzone.c autotrust.c config_file.c configlexer.l \
+ configparser.y context.c dname.c dns.c dns64.c dnstree.c edns.c \
+ fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c iter_fwd.c \
+ iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c iter_utils.c \
+ iterator.c keyraw.c libunbound.c libworker.c listen_dnsport.c \
+ localzone.c locks.c log.c lookup3.c lruhash.c mesh.c mini_event.c \
+ modstack.c module.c msgencode.c msgparse.c msgreply.c net_help.c \
+ netevent.c outbound_list.c outside_network.c packed_rrset.c parse.c \
+ parseutil.c proxy_protocol.c random.c rbtree.c regional.c respip.c \
+ rfc_1982.c rpz.c rrdef.c rrset.c rtt.c sbuffer.c siphash.c \
+ slabhash.c str2wire.c tcp_conn_limit.c timehist.c timeval_func.c \
+ tube.c ub_event_pluggable.c val_anchor.c val_kcache.c val_kentry.c \
+ val_neg.c val_nsec.c val_nsec3.c val_secalgo.c val_sigcrypt.c \
+ val_utils.c validator.c view.c winsock_event.c wire2str.c
WARNS?= 2
NO_WTHREAD_SAFETY= true
diff --git a/lib/libunbound/config.h b/lib/libunbound/config.h
index a986bfc869a3..1cedf5b4de36 100644
--- a/lib/libunbound/config.h
+++ b/lib/libunbound/config.h
@@ -20,7 +20,7 @@
/* #undef COMPAT_SHA512 */
/* Command line arguments used with configure */
-#define CONFCMDLINE "--with-ssl=/usr --with-libexpat=/usr --disable-dnscrypt --disable-dnstap --enable-ecdsa --disable-event-api --enable-gost --with-libevent --disable-subnet --disable-tfo-client --disable-tfo-server --with-pthreads--prefix=/usr --localstatedir=/var/unbound --mandir=/usr/share/man --build=freebsd"
+#define CONFCMDLINE "--prefix= --exec-prefix=/usr --with-conf-file=/var/unbound/unbound.conf --with-run-dir=/var/unbound --with-username=unbound"
/* Pathname to the Unbound configuration file */
#define CONFIGFILE "/var/unbound/unbound.conf"
@@ -49,13 +49,13 @@
internal symbols */
/* #undef EXPORT_ALL_SYMBOLS */
-/* Define to 1 if you have the `accept4' function. */
+/* Define to 1 if you have the 'accept4' function. */
#define HAVE_ACCEPT4 1
-/* Define to 1 if you have the `arc4random' function. */
+/* Define to 1 if you have the 'arc4random' function. */
#define HAVE_ARC4RANDOM 1
-/* Define to 1 if you have the `arc4random_uniform' function. */
+/* Define to 1 if you have the 'arc4random_uniform' function. */
#define HAVE_ARC4RANDOM_UNIFORM 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
@@ -77,13 +77,10 @@
#define HAVE_ATTR_WEAK 1
/* If we have be64toh */
-/* #undef HAVE_BE64TOH */
+#define HAVE_BE64TOH 1
-/* Define to 1 if you have the `BIO_set_callback_ex' function. */
-/* #undef HAVE_BIO_SET_CALLBACK_EX */
-
-/* Define to 1 if you have the `BIO_set_callback_ex' function. */
-/* #undef HAVE_BIO_SET_CALLBACK_EX */
+/* Define to 1 if you have the 'BIO_set_callback_ex' function. */
+#define HAVE_BIO_SET_CALLBACK_EX 1
/* Define to 1 if you have the <bsd/stdlib.h> header file. */
/* #undef HAVE_BSD_STDLIB_H */
@@ -91,241 +88,241 @@
/* Define to 1 if you have the <bsd/string.h> header file. */
/* #undef HAVE_BSD_STRING_H */
-/* Define to 1 if you have the `chown' function. */
+/* Define to 1 if you have the 'chown' function. */
#define HAVE_CHOWN 1
-/* Define to 1 if you have the `chroot' function. */
+/* Define to 1 if you have the 'chroot' function. */
#define HAVE_CHROOT 1
-/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* Define to 1 if you have the 'CRYPTO_cleanup_all_ex_data' function. */
/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
-/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */
+/* Define to 1 if you have the 'CRYPTO_THREADID_set_callback' function. */
/* #undef HAVE_CRYPTO_THREADID_SET_CALLBACK */
-/* Define to 1 if you have the `ctime_r' function. */
+/* Define to 1 if you have the 'ctime_r' function. */
#define HAVE_CTIME_R 1
-/* Define to 1 if you have the `daemon' function. */
+/* Define to 1 if you have the 'daemon' function. */
#define HAVE_DAEMON 1
-/* Define to 1 if you have the declaration of `arc4random', and to 0 if you
+/* Define to 1 if you have the declaration of 'arc4random', and to 0 if you
don't. */
/* #undef HAVE_DECL_ARC4RANDOM */
-/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0
+/* Define to 1 if you have the declaration of 'arc4random_uniform', and to 0
if you don't. */
/* #undef HAVE_DECL_ARC4RANDOM_UNIFORM */
-/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if
+/* Define to 1 if you have the declaration of 'evsignal_assign', and to 0 if
you don't. */
/* #undef HAVE_DECL_EVSIGNAL_ASSIGN */
-/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
+/* Define to 1 if you have the declaration of 'inet_ntop', and to 0 if you
don't. */
#define HAVE_DECL_INET_NTOP 1
-/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you
+/* Define to 1 if you have the declaration of 'inet_pton', and to 0 if you
don't. */
#define HAVE_DECL_INET_PTON 1
-/* Define to 1 if you have the declaration of `nghttp2_session_server_new',
+/* Define to 1 if you have the declaration of 'nghttp2_session_server_new',
and to 0 if you don't. */
/* #undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW */
-/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
+/* Define to 1 if you have the declaration of 'ngtcp2_conn_server_new', and to
+ 0 if you don't. */
+/* #undef HAVE_DECL_NGTCP2_CONN_SERVER_NEW */
+
+/* Define to 1 if you have the declaration of 'ngtcp2_crypto_encrypt_cb', and
+ to 0 if you don't. */
+/* #undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB */
+
+/* Define to 1 if you have the declaration of 'NID_ED25519', and to 0 if you
don't. */
#define HAVE_DECL_NID_ED25519 1
-/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you
+/* Define to 1 if you have the declaration of 'NID_ED448', and to 0 if you
don't. */
#define HAVE_DECL_NID_ED448 1
-/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
+/* Define to 1 if you have the declaration of 'NID_secp384r1', and to 0 if you
don't. */
#define HAVE_DECL_NID_SECP384R1 1
-/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0
+/* Define to 1 if you have the declaration of 'NID_X9_62_prime256v1', and to 0
if you don't. */
#define HAVE_DECL_NID_X9_62_PRIME256V1 1
-/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you
+/* Define to 1 if you have the declaration of 'reallocarray', and to 0 if you
don't. */
#define HAVE_DECL_REALLOCARRAY 1
-/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you
+/* Define to 1 if you have the declaration of 'redisConnect', and to 0 if you
don't. */
/* #undef HAVE_DECL_REDISCONNECT */
-/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
+/* Define to 1 if you have the declaration of 'sk_SSL_COMP_pop_free', and to 0
if you don't. */
#define HAVE_DECL_SK_SSL_COMP_POP_FREE 1
/* Define to 1 if you have the declaration of
- `SSL_COMP_get_compression_methods', and to 0 if you don't. */
+ 'SSL_COMP_get_compression_methods', and to 0 if you don't. */
#define HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS 1
-/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to
+/* Define to 1 if you have the declaration of 'SSL_CTX_set_ecdh_auto', and to
0 if you don't. */
-/* #undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO */
+#define HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 1
-/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
+/* Define to 1 if you have the declaration of 'strlcat', and to 0 if you
don't. */
/* #undef HAVE_DECL_STRLCAT */
-/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
+/* Define to 1 if you have the declaration of 'strlcpy', and to 0 if you
don't. */
/* #undef HAVE_DECL_STRLCPY */
-/* Define to 1 if you have the declaration of `XML_StopParser', and to 0 if
+/* Define to 1 if you have the declaration of 'XML_StopParser', and to 0 if
you don't. */
#define HAVE_DECL_XML_STOPPARSER 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
-/* Define to 1 if you have the `DSA_SIG_set0' function. */
+/* Define to 1 if you have the 'DSA_SIG_set0' function. */
#define HAVE_DSA_SIG_SET0 1
/* Define to 1 if you have the <endian.h> header file. */
-/* #undef HAVE_ENDIAN_H */
+#define HAVE_ENDIAN_H 1
-/* Define to 1 if you have the `endprotoent' function. */
+/* Define to 1 if you have the 'endprotoent' function. */
#define HAVE_ENDPROTOENT 1
-/* Define to 1 if you have the `endpwent' function. */
+/* Define to 1 if you have the 'endpwent' function. */
#define HAVE_ENDPWENT 1
-/* Define to 1 if you have the `endservent' function. */
+/* Define to 1 if you have the 'endservent' function. */
#define HAVE_ENDSERVENT 1
-/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* Define to 1 if you have the 'ENGINE_cleanup' function. */
/* #undef HAVE_ENGINE_CLEANUP */
-/* Define to 1 if you have the `ERR_free_strings' function. */
+/* Define to 1 if you have the 'ERR_free_strings' function. */
/* #undef HAVE_ERR_FREE_STRINGS */
-/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
+/* Define to 1 if you have the 'ERR_load_crypto_strings' function. */
/* #undef HAVE_ERR_LOAD_CRYPTO_STRINGS */
-/* Define to 1 if you have the `event_assign' function. */
+/* Define to 1 if you have the 'event_assign' function. */
/* #undef HAVE_EVENT_ASSIGN */
-/* Define to 1 if you have the `event_base_free' function. */
+/* Define to 1 if you have the 'event_base_free' function. */
/* #undef HAVE_EVENT_BASE_FREE */
-/* Define to 1 if you have the `event_base_get_method' function. */
+/* Define to 1 if you have the 'event_base_get_method' function. */
/* #undef HAVE_EVENT_BASE_GET_METHOD */
-/* Define to 1 if you have the `event_base_new' function. */
+/* Define to 1 if you have the 'event_base_new' function. */
/* #undef HAVE_EVENT_BASE_NEW */
-/* Define to 1 if you have the `event_base_once' function. */
+/* Define to 1 if you have the 'event_base_once' function. */
/* #undef HAVE_EVENT_BASE_ONCE */
/* Define to 1 if you have the <event.h> header file. */
/* #undef HAVE_EVENT_H */
-/* Define to 1 if you have the `EVP_aes_256_cbc' function. */
+/* Define to 1 if you have the 'EVP_aes_256_cbc' function. */
#define HAVE_EVP_AES_256_CBC 1
-/* Define to 1 if you have the `EVP_cleanup' function. */
+/* Define to 1 if you have the 'EVP_cleanup' function. */
/* #undef HAVE_EVP_CLEANUP */
-/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled'
+/* Define to 1 if you have the 'EVP_default_properties_is_fips_enabled'
function. */
-/* #undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED */
-
+#define HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED 1
-/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled'
- function. */
-/* #undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED */
-
-/* Define to 1 if you have the `EVP_DigestVerify' function. */
+/* Define to 1 if you have the 'EVP_DigestVerify' function. */
#define HAVE_EVP_DIGESTVERIFY 1
-/* Define to 1 if you have the `EVP_dss1' function. */
+/* Define to 1 if you have the 'EVP_dss1' function. */
/* #undef HAVE_EVP_DSS1 */
-/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
+/* Define to 1 if you have the 'EVP_EncryptInit_ex' function. */
#define HAVE_EVP_ENCRYPTINIT_EX 1
-/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */
-/* #undef HAVE_EVP_MAC_CTX_SET_PARAMS */
+/* Define to 1 if you have the 'EVP_MAC_CTX_set_params' function. */
+#define HAVE_EVP_MAC_CTX_SET_PARAMS 1
-/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
+/* Define to 1 if you have the 'EVP_MD_CTX_new' function. */
#define HAVE_EVP_MD_CTX_NEW 1
-/* Define to 1 if you have the `EVP_sha1' function. */
+/* Define to 1 if you have the 'EVP_sha1' function. */
#define HAVE_EVP_SHA1 1
-/* Define to 1 if you have the `EVP_sha256' function. */
+/* Define to 1 if you have the 'EVP_sha256' function. */
#define HAVE_EVP_SHA256 1
-/* Define to 1 if you have the `EVP_sha512' function. */
+/* Define to 1 if you have the 'EVP_sha512' function. */
#define HAVE_EVP_SHA512 1
-/* Define to 1 if you have the `ev_default_loop' function. */
+/* Define to 1 if you have the 'ev_default_loop' function. */
/* #undef HAVE_EV_DEFAULT_LOOP */
-/* Define to 1 if you have the `ev_loop' function. */
+/* Define to 1 if you have the 'ev_loop' function. */
/* #undef HAVE_EV_LOOP */
/* Define to 1 if you have the <expat.h> header file. */
#define HAVE_EXPAT_H 1
-/* Define to 1 if you have the `explicit_bzero' function. */
+/* Define to 1 if you have the 'explicit_bzero' function. */
#define HAVE_EXPLICIT_BZERO 1
-/* Define to 1 if you have the `fcntl' function. */
+/* Define to 1 if you have the 'fcntl' function. */
#define HAVE_FCNTL 1
-/* Define to 1 if you have the `FIPS_mode' function. */
-#define HAVE_FIPS_MODE 1
+/* Define to 1 if you have the 'FIPS_mode' function. */
+/* #undef HAVE_FIPS_MODE */
-/* Define to 1 if you have the `fork' function. */
+/* Define to 1 if you have the 'fork' function. */
#define HAVE_FORK 1
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+/* Define to 1 if fseeko (and ftello) are declared in stdio.h. */
#define HAVE_FSEEKO 1
-/* Define to 1 if you have the `fsync' function. */
+/* Define to 1 if you have the 'fsync' function. */
#define HAVE_FSYNC 1
/* Whether getaddrinfo is available */
#define HAVE_GETADDRINFO 1
-/* Define to 1 if you have the `getauxval' function. */
+/* Define to 1 if you have the 'getauxval' function. */
/* #undef HAVE_GETAUXVAL */
-/* Define to 1 if you have the `getentropy' function. */
+/* Define to 1 if you have the 'getentropy' function. */
/* #undef HAVE_GETENTROPY */
-/* Define to 1 if you have the `getifaddrs' function. */
+/* Define to 1 if you have the 'getifaddrs' function. */
#define HAVE_GETIFADDRS 1
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
-/* Define to 1 if you have the `getpwnam' function. */
+/* Define to 1 if you have the 'getpwnam' function. */
#define HAVE_GETPWNAM 1
-/* Define to 1 if you have the `getrlimit' function. */
+/* Define to 1 if you have the 'getrlimit' function. */
#define HAVE_GETRLIMIT 1
-/* Define to 1 if you have the `gettid' function. */
-/* #undef HAVE_GETTID */
-
-/* Define to 1 if you have the `gettid' function. */
+/* Define to 1 if you have the 'gettid' function. */
/* #undef HAVE_GETTID */
-/* Define to 1 if you have the `glob' function. */
+/* Define to 1 if you have the 'glob' function. */
#define HAVE_GLOB 1
/* Define to 1 if you have the <glob.h> header file. */
#define HAVE_GLOB_H 1
-/* Define to 1 if you have the `gmtime_r' function. */
+/* Define to 1 if you have the 'gmtime_r' function. */
#define HAVE_GMTIME_R 1
/* Define to 1 if you have the <grp.h> header file. */
@@ -334,31 +331,28 @@
/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
/* #undef HAVE_HIREDIS_HIREDIS_H */
-/* Define to 1 if you have the `HMAC_Init_ex' function. */
+/* Define to 1 if you have the 'HMAC_Init_ex' function. */
#define HAVE_HMAC_INIT_EX 1
/* If we have htobe64 */
-/* #undef HAVE_HTOBE64 */
+#define HAVE_HTOBE64 1
/* Define to 1 if you have the <ifaddrs.h> header file. */
#define HAVE_IFADDRS_H 1
-/* Define to 1 if you have the `if_nametoindex' function. */
+/* Define to 1 if you have the 'if_nametoindex' function. */
#define HAVE_IF_NAMETOINDEX 1
-/* Define to 1 if you have the `if_nametoindex' function. */
-#define HAVE_IF_NAMETOINDEX 1
-
-/* Define to 1 if you have the `inet_aton' function. */
+/* Define to 1 if you have the 'inet_aton' function. */
#define HAVE_INET_ATON 1
-/* Define to 1 if you have the `inet_ntop' function. */
+/* Define to 1 if you have the 'inet_ntop' function. */
#define HAVE_INET_NTOP 1
-/* Define to 1 if you have the `inet_pton' function. */
+/* Define to 1 if you have the 'inet_pton' function. */
#define HAVE_INET_PTON 1
-/* Define to 1 if you have the `initgroups' function. */
+/* Define to 1 if you have the 'initgroups' function. */
#define HAVE_INITGROUPS 1
/* Define to 1 if you have the <inttypes.h> header file. */
@@ -370,10 +364,10 @@
/* Define to 1 if you have the <iphlpapi.h> header file. */
/* #undef HAVE_IPHLPAPI_H */
-/* Define to 1 if you have the `isblank' function. */
+/* Define to 1 if you have the 'isblank' function. */
#define HAVE_ISBLANK 1
-/* Define to 1 if you have the `kill' function. */
+/* Define to 1 if you have the 'kill' function. */
#define HAVE_KILL 1
/* Use portable libbsd functions */
@@ -385,7 +379,13 @@
/* Define if we have LibreSSL */
/* #undef HAVE_LIBRESSL */
-/* Define to 1 if you have the `localtime_r' function. */
+/* If we have atomic_store */
+#define HAVE_LINK_ATOMIC_STORE 1
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+/* #undef HAVE_LINUX_NET_TSTAMP_H */
+
+/* Define to 1 if you have the 'localtime_r' function. */
#define HAVE_LOCALTIME_R 1
/* Define to 1 if you have the <login_cap.h> header file. */
@@ -394,7 +394,7 @@
/* If have GNU libc compatible malloc */
#define HAVE_MALLOC 1
-/* Define to 1 if you have the `memmove' function. */
+/* Define to 1 if you have the 'memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <minix/config.h> header file. */
@@ -424,29 +424,91 @@
/* Define to 1 if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H 1
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+/* #undef HAVE_NET_PFVAR_H */
+
/* Define this to use nghttp2 client. */
/* #undef HAVE_NGHTTP2 */
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+/* Define this to use ngtcp2. */
+/* #undef HAVE_NGTCP2 */
+
+/* Define to 1 if you have the 'ngtcp2_ccerr_default' function. */
+/* #undef HAVE_NGTCP2_CCERR_DEFAULT */
+
+/* Define to 1 if you have the 'ngtcp2_conn_encode_0rtt_transport_params'
+ function. */
+/* #undef HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS */
+
+/* Define to 1 if you have the 'ngtcp2_conn_get_max_local_streams_uni'
+ function. */
+/* #undef HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI */
+
+/* Define to 1 if you have the 'ngtcp2_conn_get_num_scid' function. */
+/* #undef HAVE_NGTCP2_CONN_GET_NUM_SCID */
+
+/* Define to 1 if you have the 'ngtcp2_conn_in_closing_period' function. */
+/* #undef HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD */
+
+/* Define to 1 if you have the 'ngtcp2_conn_in_draining_period' function. */
+/* #undef HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD */
+
+/* Define if ngtcp2_conn_shutdown_stream has 4 arguments. */
+/* #undef HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4 */
+
+/* Define to 1 if you have the 'ngtcp2_conn_tls_early_data_rejected' function.
+ */
+/* #undef HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED */
+
+/* Define to 1 if you have the 'ngtcp2_crypto_encrypt_cb' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_ENCRYPT_CB */
+
+/* Define to 1 if you have the
+ 'ngtcp2_crypto_quictls_configure_client_context' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT */
+
+/* Define to 1 if you have the
+ 'ngtcp2_crypto_quictls_configure_server_context' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT */
+
+/* Define to 1 if you have the
+ 'ngtcp2_crypto_quictls_from_ossl_encryption_level' function. */
+/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL */
+
+/* Define to 1 if the system has the type 'ngtcp2_encryption_level'. */
+/* #undef HAVE_NGTCP2_ENCRYPTION_LEVEL */
+
+/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_openssl.h> header file.
+ */
+/* #undef HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H */
+
+/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_quictls.h> header file.
+ */
+/* #undef HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H */
+
+/* Define to 1 if you have the <ngtcp2/ngtcp2.h> header file. */
+/* #undef HAVE_NGTCP2_NGTCP2_H */
+
/* Use libnss for crypto */
/* #undef HAVE_NSS */
-/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */
+/* Define to 1 if you have the 'OpenSSL_add_all_digests' function. */
/* #undef HAVE_OPENSSL_ADD_ALL_DIGESTS */
/* Define to 1 if you have the <openssl/bn.h> header file. */
#define HAVE_OPENSSL_BN_H 1
-/* Define to 1 if you have the `OPENSSL_config' function. */
+/* Define to 1 if you have the 'OPENSSL_config' function. */
#define HAVE_OPENSSL_CONFIG 1
/* Define to 1 if you have the <openssl/conf.h> header file. */
#define HAVE_OPENSSL_CONF_H 1
/* Define to 1 if you have the <openssl/core_names.h> header file. */
-/* #undef HAVE_OPENSSL_CORE_NAMES_H */
+#define HAVE_OPENSSL_CORE_NAMES_H 1
/* Define to 1 if you have the <openssl/dh.h> header file. */
#define HAVE_OPENSSL_DH_H 1
@@ -460,14 +522,14 @@
/* Define to 1 if you have the <openssl/err.h> header file. */
#define HAVE_OPENSSL_ERR_H 1
-/* Define to 1 if you have the `OPENSSL_init_crypto' function. */
+/* Define to 1 if you have the 'OPENSSL_init_crypto' function. */
#define HAVE_OPENSSL_INIT_CRYPTO 1
-/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+/* Define to 1 if you have the 'OPENSSL_init_ssl' function. */
#define HAVE_OPENSSL_INIT_SSL 1
/* Define to 1 if you have the <openssl/param_build.h> header file. */
-/* #undef HAVE_OPENSSL_PARAM_BUILD_H */
+#define HAVE_OPENSSL_PARAM_BUILD_H 1
/* Define to 1 if you have the <openssl/rand.h> header file. */
#define HAVE_OPENSSL_RAND_H 1
@@ -478,10 +540,10 @@
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#define HAVE_OPENSSL_SSL_H 1
-/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */
-/* #undef HAVE_OSSL_PARAM_BLD_NEW */
+/* Define to 1 if you have the 'OSSL_PARAM_BLD_new' function. */
+#define HAVE_OSSL_PARAM_BLD_NEW 1
-/* Define to 1 if you have the `poll' function. */
+/* Define to 1 if you have the 'poll' function. */
#define HAVE_POLL 1
/* Define to 1 if you have the <poll.h> header file. */
@@ -493,10 +555,10 @@
/* Have PTHREAD_PRIO_INHERIT. */
#define HAVE_PTHREAD_PRIO_INHERIT 1
-/* Define to 1 if the system has the type `pthread_rwlock_t'. */
+/* Define to 1 if the system has the type 'pthread_rwlock_t'. */
#define HAVE_PTHREAD_RWLOCK_T 1
-/* Define to 1 if the system has the type `pthread_spinlock_t'. */
+/* Define to 1 if the system has the type 'pthread_spinlock_t'. */
#define HAVE_PTHREAD_SPINLOCK_T 1
/* Define to 1 if you have the <pwd.h> header file. */
@@ -505,100 +567,109 @@
/* Define if you have Python libraries and header files. */
/* #undef HAVE_PYTHON */
-/* Define to 1 if you have the `random' function. */
+/* Define to 1 if you have the 'random' function. */
#define HAVE_RANDOM 1
-/* Define to 1 if you have the `RAND_cleanup' function. */
+/* Define to 1 if you have the 'RAND_cleanup' function. */
/* #undef HAVE_RAND_CLEANUP */
/* If we have reallocarray(3) */
#define HAVE_REALLOCARRAY 1
-/* Define to 1 if you have the `recvmsg' function. */
+/* Define to 1 if you have the 'recvmsg' function. */
#define HAVE_RECVMSG 1
-/* Define to 1 if you have the `sendmsg' function. */
+/* Define to 1 if you have the 'sendmsg' function. */
#define HAVE_SENDMSG 1
-/* Define to 1 if you have the `setregid' function. */
+/* Define to 1 if you have the 'setregid' function. */
/* #undef HAVE_SETREGID */
-/* Define to 1 if you have the `setresgid' function. */
+/* Define to 1 if you have the 'setresgid' function. */
#define HAVE_SETRESGID 1
-/* Define to 1 if you have the `setresuid' function. */
+/* Define to 1 if you have the 'setresuid' function. */
#define HAVE_SETRESUID 1
-/* Define to 1 if you have the `setreuid' function. */
+/* Define to 1 if you have the 'setreuid' function. */
/* #undef HAVE_SETREUID */
-/* Define to 1 if you have the `setrlimit' function. */
+/* Define to 1 if you have the 'setrlimit' function. */
#define HAVE_SETRLIMIT 1
-/* Define to 1 if you have the `setsid' function. */
+/* Define to 1 if you have the 'setsid' function. */
#define HAVE_SETSID 1
-/* Define to 1 if you have the `setusercontext' function. */
+/* Define to 1 if you have the 'setusercontext' function. */
#define HAVE_SETUSERCONTEXT 1
-/* Define to 1 if you have the `SHA512_Update' function. */
+/* Define to 1 if you have the 'SHA512_Update' function. */
/* #undef HAVE_SHA512_UPDATE */
-/* Define to 1 if you have the `shmget' function. */
+/* Define to 1 if you have the 'shmget' function. */
#define HAVE_SHMGET 1
-/* Define to 1 if you have the `sigprocmask' function. */
+/* Define to 1 if you have the 'sigprocmask' function. */
#define HAVE_SIGPROCMASK 1
-/* Define to 1 if you have the `sleep' function. */
+/* Define to 1 if you have the 'sleep' function. */
#define HAVE_SLEEP 1
-/* Define to 1 if you have the `snprintf' function. */
+/* Define to 1 if you have the 'snprintf' function. */
#define HAVE_SNPRINTF 1
-/* Define to 1 if you have the `socketpair' function. */
+/* Define to 1 if you have the 'socketpair' function. */
#define HAVE_SOCKETPAIR 1
/* Using Solaris threads */
/* #undef HAVE_SOLARIS_THREADS */
-/* Define to 1 if you have the `srandom' function. */
+/* Define to 1 if you have the 'srandom' function. */
#define HAVE_SRANDOM 1
/* Define if you have the SSL libraries installed. */
#define HAVE_SSL /**/
-/* Define to 1 if you have the `SSL_CTX_set_alpn_protos' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_alpn_protos' function. */
#define HAVE_SSL_CTX_SET_ALPN_PROTOS 1
-/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_alpn_select_cb' function. */
#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB 1
-/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_ciphersuites' function. */
#define HAVE_SSL_CTX_SET_CIPHERSUITES 1
-/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
+/* Define to 1 if you have the 'SSL_CTX_set_security_level' function. */
#define HAVE_SSL_CTX_SET_SECURITY_LEVEL 1
-/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_evp_cb'
+/* Define to 1 if you have the 'SSL_CTX_set_tlsext_ticket_key_evp_cb'
function. */
-/* #undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB */
+#define HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1
+
+/* Define to 1 if you have the 'SSL_CTX_set_tmp_ecdh' function. */
+/* #undef HAVE_SSL_CTX_SET_TMP_ECDH */
-/* Define to 1 if you have the `SSL_get0_alpn_selected' function. */
+/* Define to 1 if you have the 'SSL_get0_alpn_selected' function. */
#define HAVE_SSL_GET0_ALPN_SELECTED 1
-/* Define to 1 if you have the `SSL_get0_peername' function. */
+/* Define to 1 if you have the 'SSL_get0_peername' function. */
#define HAVE_SSL_GET0_PEERNAME 1
-/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */
-/* #undef HAVE_SSL_GET1_PEER_CERTIFICATE */
+/* Define to 1 if you have the 'SSL_get1_peer_certificate' function. */
+#define HAVE_SSL_GET1_PEER_CERTIFICATE 1
-/* Define to 1 if you have the `SSL_set1_host' function. */
+/* Define to 1 if you have the 'SSL_is_quic' function. */
+/* #undef HAVE_SSL_IS_QUIC */
+
+/* Define to 1 if you have the 'SSL_set1_host' function. */
#define HAVE_SSL_SET1_HOST 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
+/* Define to 1 if you have the <stdatomic.h> header file. */
+#define HAVE_STDATOMIC_H 1
+
/* Define to 1 if you have the <stdbool.h> header file. */
#define HAVE_STDBOOL_H 1
@@ -611,7 +682,7 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
-/* Define to 1 if you have the `strftime' function. */
+/* Define to 1 if you have the 'strftime' function. */
#define HAVE_STRFTIME 1
/* Define to 1 if you have the <strings.h> header file. */
@@ -620,22 +691,39 @@
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
-/* Define to 1 if you have the `strlcat' function. */
+/* Define to 1 if you have the 'strlcat' function. */
#define HAVE_STRLCAT 1
-/* Define to 1 if you have the `strlcpy' function. */
+/* Define to 1 if you have the 'strlcpy' function. */
#define HAVE_STRLCPY 1
-/* Define to 1 if you have the `strptime' function. */
+/* Define to 1 if you have the 'strptime' function. */
#define HAVE_STRPTIME 1
-/* Define to 1 if you have the `strsep' function. */
+/* Define to 1 if you have the 'strsep' function. */
#define HAVE_STRSEP 1
-/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
+/* Define to 1 if 'ipi_spec_dst' is a member of 'struct in_pktinfo'. */
/* #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST */
-/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
+/* Define to 1 if 'tokenlen' is a member of 'struct ngtcp2_pkt_hd'. */
+/* #undef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN */
+
+/* Define to 1 if 'max_tx_udp_payload_size' is a member of 'struct
+ ngtcp2_settings'. */
+/* #undef HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE */
+
+/* Define to 1 if 'tokenlen' is a member of 'struct ngtcp2_settings'. */
+/* #undef HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN */
+
+/* Define to 1 if 'original_dcid_present' is a member of 'struct
+ ngtcp2_transport_params'. */
+/* #undef HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT */
+
+/* Define to 1 if the system has the type 'struct ngtcp2_version_cid'. */
+/* #undef HAVE_STRUCT_NGTCP2_VERSION_CID */
+
+/* Define to 1 if 'sun_len' is a member of 'struct sockaddr_un'. */
#define HAVE_STRUCT_SOCKADDR_UN_SUN_LEN 1
/* Define if you have Swig libraries and header files. */
@@ -695,16 +783,16 @@
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
-/* Define to 1 if you have the `tzset' function. */
+/* Define to 1 if you have the 'tzset' function. */
#define HAVE_TZSET 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
-/* Define to 1 if you have the `usleep' function. */
+/* Define to 1 if you have the 'usleep' function. */
#define HAVE_USLEEP 1
-/* Define to 1 if you have the `vfork' function. */
+/* Define to 1 if you have the 'vfork' function. */
#define HAVE_VFORK 1
/* Define to 1 if you have the <vfork.h> header file. */
@@ -722,22 +810,22 @@
/* Define to 1 if you have the <winsock2.h> header file. */
/* #undef HAVE_WINSOCK2_H */
-/* Define to 1 if `fork' works. */
+/* Define to 1 if 'fork' works. */
#define HAVE_WORKING_FORK 1
-/* Define to 1 if `vfork' works. */
+/* Define to 1 if 'vfork' works. */
#define HAVE_WORKING_VFORK 1
-/* Define to 1 if you have the `writev' function. */
+/* Define to 1 if you have the 'writev' function. */
#define HAVE_WRITEV 1
/* Define to 1 if you have the <ws2tcpip.h> header file. */
/* #undef HAVE_WS2TCPIP_H */
-/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */
+/* Define to 1 if you have the 'X509_VERIFY_PARAM_set1_host' function. */
#define HAVE_X509_VERIFY_PARAM_SET1_HOST 1
-/* Define to 1 if you have the `_beginthreadex' function. */
+/* Define to 1 if you have the '_beginthreadex' function. */
/* #undef HAVE__BEGINTHREADEX */
/* If HMAC_Init_ex() returns void */
@@ -796,7 +884,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "unbound 1.23.0"
+#define PACKAGE_STRING "unbound 1.24.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@@ -805,7 +893,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.23.0"
+#define PACKAGE_VERSION "1.24.0"
/* default pidfile location */
#define PIDFILE "/var/unbound/unbound.pid"
@@ -828,7 +916,7 @@
#define ROOT_CERT_FILE "/var/unbound/icannbundle.pem"
/* version number for resource files */
-#define RSRC_PACKAGE_VERSION 1,23,0,0
+#define RSRC_PACKAGE_VERSION 1,23,1,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound"
@@ -836,32 +924,17 @@
/* Shared data */
#define SHARE_DIR "/var/unbound"
-#ifdef __LP64__
-/* The size of `size_t', as computed by sizeof. */
-#define SIZEOF_SIZE_T 8
-/* The size of `size_t'. */
-/* The size of `pthread_t', as computed by sizeof. */
+/* The size of 'pthread_t', as computed by sizeof. */
#define SIZEOF_PTHREAD_T 8
-#else
-#define SIZEOF_SIZE_T 4
-/* The size of `size_t'. */
-/* The size of `pthread_t', as computed by sizeof. */
-#define SIZEOF_PTHREAD_T 4
-#endif
-/* The size of `time_t', as computed by sizeof. */
-#ifdef __i386__
-#define SIZEOF_TIME_T 4
-#else
+/* The size of 'size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of 'time_t', as computed by sizeof. */
#define SIZEOF_TIME_T 8
-#endif
-/* The size of `unsigned long', as computed by sizeof. */
-#ifdef __LP64__
+/* The size of 'unsigned long', as computed by sizeof. */
#define SIZEOF_UNSIGNED_LONG 8
-#else
-#define SIZEOF_UNSIGNED_LONG 4
-#endif
/* define if (v)snprintf does not return length needed, (but length used) */
/* #undef SNPRINTF_RET_BROKEN */
@@ -869,7 +942,7 @@
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
/* #undef SODIUM_MISUSE_HANDLER */
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
@@ -911,7 +984,7 @@
/* #undef USE_DNSTAP */
/* Define this to enable DSA support. */
-#define USE_DSA 1
+/* #undef USE_DSA */
/* Define this to enable ECDSA support. */
#define USE_ECDSA 1
@@ -935,7 +1008,7 @@
/* #undef USE_IPSET */
/* Define if you enable libevent */
-#define USE_LIBEVENT 1
+/* #undef USE_LIBEVENT */
/* Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a
default outgoing port range. This is only for the libunbound on Linux and
@@ -963,7 +1036,7 @@
/* Define this to enable SHA256 and SHA512 support. */
#define USE_SHA2 1
-/* Enable extensions on AIX 3, Interix. */
+/* Enable extensions on AIX, Interix, z/OS. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
@@ -1024,11 +1097,15 @@
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
#endif
+/* Enable extensions specified by C23 Annex F. */
+#ifndef __STDC_WANT_IEC_60559_EXT__
+# define __STDC_WANT_IEC_60559_EXT__ 1
+#endif
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
#endif
-/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
+/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
#endif
@@ -1069,30 +1146,36 @@
/* Define if you want PyUnbound. */
/* #undef WITH_PYUNBOUND */
-/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
- `char[]'. */
+/* Define to 1 if 'lex' declares 'yytext' as a 'char *' by default, not a
+ 'char[]'. */
#define YYTEXT_POINTER 1
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* Define to 1 if necessary to make fseeko visible. */
/* #undef _LARGEFILE_SOURCE */
-/* Define for large files, on AIX-style hosts. */
+/* Define to 1 on platforms where this makes off_t a 64-bit type. */
/* #undef _LARGE_FILES */
/* Enable for compile on Minix */
#define _NETBSD_SOURCE 1
+/* Number of bits in time_t, on hosts where this is settable. */
+/* #undef _TIME_BITS */
+
+/* Define to 1 on platforms where this makes time_t a 64-bit type. */
+/* #undef __MINGW_USE_VC2005_COMPAT */
+
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
compiled for windows. */
/* #undef __USE_MINGW_ANSI_STDIO */
-/* Define to empty if `const' does not conform to ANSI C. */
+/* Define to empty if 'const' does not conform to ANSI C. */
/* #undef const */
-/* Define to `int' if <sys/types.h> doesn't define. */
+/* Define as 'int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
/* in_addr_t */
@@ -1101,28 +1184,28 @@
/* in_port_t */
/* #undef in_port_t */
-/* Define to `__inline__' or `__inline' if that's what the C compiler
+/* Define to '__inline__' or '__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
-/* Define to `short' if <sys/types.h> does not define. */
+/* Define to 'short' if <sys/types.h> does not define. */
/* #undef int16_t */
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define to 'int' if <sys/types.h> does not define. */
/* #undef int32_t */
-/* Define to `long long' if <sys/types.h> does not define. */
+/* Define to 'long long' if <sys/types.h> does not define. */
/* #undef int64_t */
-/* Define to `signed char' if <sys/types.h> does not define. */
+/* Define to 'signed char' if <sys/types.h> does not define. */
/* #undef int8_t */
/* Define if replacement function should be used. */
/* #undef malloc */
-/* Define to `long int' if <sys/types.h> does not define. */
+/* Define to 'long int' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define as a signed integer type capable of holding a process identifier. */
@@ -1131,71 +1214,71 @@
/* Define to 'int' if not defined */
/* #undef rlim_t */
-/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* Define as 'unsigned int' if <stddef.h> doesn't define. */
/* #undef size_t */
/* Define to 'int' if not defined */
/* #undef socklen_t */
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define to 'int' if <sys/types.h> does not define. */
/* #undef ssize_t */
/* Define to 'unsigned char if not defined */
/* #undef u_char */
-/* Define to `int' if <sys/types.h> doesn't define. */
+/* Define as 'int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
-/* Define to `unsigned short' if <sys/types.h> does not define. */
+/* Define to 'unsigned short' if <sys/types.h> does not define. */
/* #undef uint16_t */
-/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* Define to 'unsigned int' if <sys/types.h> does not define. */
/* #undef uint32_t */
-/* Define to `unsigned long long' if <sys/types.h> does not define. */
+/* Define to 'unsigned long long' if <sys/types.h> does not define. */
/* #undef uint64_t */
-/* Define to `unsigned char' if <sys/types.h> does not define. */
+/* Define to 'unsigned char' if <sys/types.h> does not define. */
/* #undef uint8_t */
-/* Define as `fork' if `vfork' does not work. */
+/* Define as 'fork' if 'vfork' does not work. */
/* #undef vfork */
#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE)
#define _BSD_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE)
#define _DEFAULT_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__)
#define __EXTENSIONS__ 1
-#endif
+#endif
#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE)
#define _POSIX_C_SOURCE 200112
-#endif
+#endif
#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
-#endif
+#endif
#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED)
#define _XOPEN_SOURCE_EXTENDED 1
-#endif
+#endif
#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE)
#define _ALL_SOURCE 1
-#endif
+#endif
#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE)
#define _LARGEFILE_SOURCE 1
-#endif
+#endif
@@ -1279,7 +1362,7 @@
#endif
-
+
#ifdef HAVE_ATTR_FORMAT
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
__attribute__ ((format (archetype, string_index, first_to_check)))
@@ -1389,7 +1472,7 @@ void* reallocarray(void *ptr, size_t nmemb, size_t size);
#ifdef HAVE_WINSOCK2_H
#define FD_SET_T (u_int)
#else
-#define FD_SET_T
+#define FD_SET_T
#endif
@@ -1517,6 +1600,10 @@ struct sockaddr_storage;
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
+# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
+#ifdef HAVE_REALLOCARRAY
+# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
+#endif
void *unbound_stat_malloc(size_t size);
void *unbound_stat_calloc(size_t nmemb, size_t size);
void unbound_stat_free(void *ptr);
@@ -1529,6 +1616,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
const char* func);
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
int line, const char* func);
+void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
+ const char* file, int line, const char* func);
+char *unbound_stat_strdup_log(const char *s, const char* file, int line,
+ const char* func);
#elif defined(UNBOUND_ALLOC_LITE)
# include "util/alloc.h"
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3
index 74b85d4aa17e..607a7f645d95 100644
--- a/lib/libusb/libusb.3
+++ b/lib/libusb/libusb.3
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 13, 2025
+.Dd July 9, 2025
.Dt LIBUSB 3
.Os
.Sh NAME
@@ -209,6 +209,14 @@ Decrement the reference counter of the device
.Fa dev .
.Pp
.Ft int
+.Fn libusb_wrap_sys_device "libusb_context *ctx" "intptr_t sys_dev" "libusb_device_handle **dev_handle"
+This function creates a libusb handler from a previously opened fd
+.Fa sys_dev .
+This function is provided for compatibility and is currently unimplemented.
+It always returns
+.Dv LIBUSB_ERROR_NOT_SUPPORTED .
+.Pp
+.Ft int
.Fn libusb_open "libusb_device *dev" "libusb_device_handle **devh"
Open a device and obtain a device_handle.
Returns 0 on success,
@@ -366,6 +374,23 @@ argument is non-zero the feature is enabled.
Else disabled.
Returns 0 on success and a LIBUSB_ERROR code on
failure.
+.Pp
+.Ft unsigned char *
+.Fn libusb_dev_mem_alloc "libusb_device_handle *devh"
+This function attempts to allocate a DMA memory block from the given
+.Fa devh
+so that we can enjoy the zero-copy transfer from kernel.
+This function is provided for compatibility and is currently unimplemented and always returns NULL.
+.Pp
+.Ft int
+.Fn libusb_dev_mem_free "libusb_device_handle *devh" "unsigned char *buffer" "size_t size"
+This function frees the DMA memory in
+.Fa devh
+from the given
+.Fa buffer
+with
+.Fa size .
+This function is unimplemented and always returns LIBUSB_ERROR_NOT_SUPPORTED.
.Sh USB DESCRIPTORS
.Ft int
.Fn libusb_get_device_descriptor "libusb_device *dev" "libusb_device_descriptor *desc"
@@ -519,6 +544,21 @@ libusb_free_container_id_descriptor function.
.Fn libusb_free_container_id_descriptor "struct libusb_container_id_descriptor *container_id"
This function is NULL safe and frees a parsed container ID descriptor given by
.Fa container_id .
+.Pp
+.Ft int
+.Fn libusb_get_platform_descriptor "struct libusb_context *ctx" "struct libusb_bos_dev_capability_descriptor *dev_cap" "struct libusb_platform_descriptor **platform_descriptor"
+This function parses the platform descriptor from the descriptor given by
+.Fa dev_cap
+and stores a pointer to the parsed descriptor into
+.Fa platform_descriptor .
+Returns zero on success and a LIBUSB_ERROR code on failure.
+On success the parsed platform descriptor must be freed using the
+libusb_free_platform_descriptor function.
+.Pp
+.Ft void
+.Fn libusb_free_platform_descriptor "struct libusb_platform_descriptor *platform_descriptor"
+This function is NULL safe and frees a parsed platform descriptor given by
+.Fa platform_descriptor .
.Sh USB ASYNCHRONOUS I/O
.Ft struct libusb_transfer *
.Fn libusb_alloc_transfer "int iso_packets"
@@ -717,6 +757,14 @@ another thread is already doing so.
Must be called with the event lock held.
.Pp
.Ft int
+.Fn libusb_pollfds_handle_timeouts "libusb_context *ctx"
+This function determines whether applications maintaining libusb events using
+.Fn libusb_get_pollfds
+are responsible for handling timeout events themselves.
+Returns 1 if libusb handles the timeout internally, 0 if the application
+needs to set a dedicated timer to handle it.
+.Pp
+.Ft int
.Fn libusb_get_next_timeout "libusb_context *ctx" "struct timeval *tv"
Determine the next internal timeout that libusb needs to handle.
Returns 0
@@ -775,6 +823,17 @@ argument can be either of LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED or LIBUSB_HOTPLUG_
.Ft void
.Fn libusb_hotplug_deregister_callback "libusb_context *ctx" "libusb_hotplug_callback_handle handle"
This function unregisters a hotplug filter.
+.Pp
+.Ft void
+.Fn libusb_free_pollfds "const struct libusb_pollfd **pollfds"
+This function releases the memory storage in
+.Fa pollfds ,
+and is safe to call when the argument is NULL.
+.Pp void *
+.Fn libusb_hotplug_get_user_data "struct libusb_context *ctx" "libusb_hotplug_callback_handle callback_handle"
+This function returns the user data from the opaque
+.Fa callback_handle ,
+or returns NULL if no matching handle is found.
.Sh LIBUSB VERSION 0.1 COMPATIBILITY
The library is also compliant with LibUSB version 0.1.12.
.Pp
diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h
index 6fb1c19fad13..623b56fb273b 100644
--- a/lib/libusb/libusb.h
+++ b/lib/libusb/libusb.h
@@ -66,6 +66,7 @@ enum libusb_class_code {
LIBUSB_CLASS_PERSONAL_HEALTHCARE = 15,
LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc,
LIBUSB_CLASS_WIRELESS = 0xe0,
+ LIBUSB_CLASS_MISCELLANEOUS = 0xef,
LIBUSB_CLASS_APPLICATION = 0xfe,
LIBUSB_CLASS_VENDOR_SPEC = 0xff,
};
@@ -106,6 +107,7 @@ enum libusb_device_capability_type {
#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7
#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10
#define LIBUSB_BT_CONTAINER_ID_SIZE 20
+#define LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE 20
#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f
#define LIBUSB_ENDPOINT_DIR_MASK 0x80
@@ -122,6 +124,7 @@ enum libusb_transfer_type {
LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1,
LIBUSB_TRANSFER_TYPE_BULK = 2,
LIBUSB_TRANSFER_TYPE_INTERRUPT = 3,
+ LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4,
};
enum libusb_standard_request {
@@ -171,11 +174,23 @@ enum libusb_iso_usage_type {
LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2,
};
+enum libusb_usb_2_0_extension_attributes {
+ LIBUSB_BM_LPM_SUPPORT = 0x2,
+};
+
+enum libusb_supported_speed {
+ LIBUSB_LOW_SPEED_OPERATION = (1 << 0),
+ LIBUSB_FULL_SPEED_OPERATION = (1 << 1),
+ LIBUSB_HIGH_SPEED_OPERATION = (1 << 2),
+ LIBUSB_SUPER_SPEED_OPERATION = (1 << 3),
+};
+
enum libusb_bos_type {
LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1,
LIBUSB_BT_USB_2_0_EXTENSION = 2,
LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 3,
LIBUSB_BT_CONTAINER_ID = 4,
+ LIBUSB_BT_PLATFORM_DESCRIPTOR = 5,
};
enum libusb_capability {
@@ -433,6 +448,15 @@ typedef struct libusb_container_id_descriptor {
uint8_t ContainerID[16];
} libusb_container_id_descriptor __aligned(sizeof(void *));
+typedef struct libusb_platform_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t bReserved;
+ uint8_t PlatformCapabilityUUID[16];
+ uint8_t CapabilityData[];
+} libusb_platform_descriptor __aligned(sizeof(void *));
+
typedef struct libusb_control_setup {
uint8_t bmRequestType;
uint8_t bRequest;
@@ -494,6 +518,7 @@ int libusb_get_max_packet_size(libusb_device * dev, uint8_t endpoint);
int libusb_get_max_iso_packet_size(libusb_device * dev, uint8_t endpoint);
libusb_device *libusb_ref_device(libusb_device * dev);
void libusb_unref_device(libusb_device * dev);
+int libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle);
int libusb_open(libusb_device * dev, libusb_device_handle ** devh);
libusb_device_handle *libusb_open_device_with_vid_pid(libusb_context * ctx, uint16_t vendor_id, uint16_t product_id);
void libusb_close(libusb_device_handle * devh);
@@ -513,6 +538,9 @@ int libusb_detach_kernel_driver(libusb_device_handle * devh, int interface);
int libusb_attach_kernel_driver(libusb_device_handle * devh, int interface);
int libusb_set_auto_detach_kernel_driver(libusb_device_handle *dev, int enable);
int libusb_set_interface_alt_setting(libusb_device_handle * devh, int interface_number, int alternate_setting);
+unsigned char *libusb_dev_mem_alloc(libusb_device_handle *devh);
+int libusb_dev_mem_free(libusb_device_handle *devh, unsigned char *buffer,
+ size_t size);
/* USB Descriptors */
@@ -537,6 +565,8 @@ int libusb_get_ss_usb_device_capability_descriptor(struct libusb_context *ctx, s
void libusb_free_ss_usb_device_capability_descriptor(struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_capability);
int libusb_get_container_id_descriptor(struct libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_container_id_descriptor **container_id);
void libusb_free_container_id_descriptor(struct libusb_container_id_descriptor *container_id);
+int libusb_get_platform_descriptor(libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_platform_descriptor **platform_descriptor);
+void libusb_free_platform_descriptor(struct libusb_platform_descriptor *platform_descriptor);
/* Asynchronous device I/O */
@@ -552,6 +582,7 @@ struct libusb_control_setup *libusb_control_transfer_get_setup(struct libusb_tra
void libusb_fill_control_setup(uint8_t *buf, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength);
void libusb_fill_control_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t *buf, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, int length, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
+void libusb_fill_bulk_stream_transfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, uint32_t stream_id, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout);
void libusb_fill_interrupt_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, int length, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
void libusb_fill_iso_transfer(struct libusb_transfer *transfer, libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf, int length, int npacket, libusb_transfer_cb_fn callback, void *user_data, uint32_t timeout);
@@ -571,9 +602,11 @@ int libusb_handle_events_completed(libusb_context * ctx, int *completed);
int libusb_handle_events_timeout(libusb_context * ctx, struct timeval *tv);
int libusb_handle_events(libusb_context * ctx);
int libusb_handle_events_locked(libusb_context * ctx, struct timeval *tv);
+int libusb_pollfds_handle_timeouts(libusb_context *ctx);
int libusb_get_next_timeout(libusb_context * ctx, struct timeval *tv);
void libusb_set_pollfd_notifiers(libusb_context * ctx, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, void *user_data);
-const struct libusb_pollfd **libusb_get_pollfds(libusb_context * ctx);
+const struct libusb_pollfd **libusb_get_pollfds(libusb_context *ctx);
+void libusb_free_pollfds(const struct libusb_pollfd **pollfds);
/* Synchronous device I/O */
@@ -593,6 +626,8 @@ typedef int (*libusb_hotplug_callback_fn)(libusb_context *ctx,
int libusb_hotplug_register_callback(libusb_context *ctx, libusb_hotplug_event events, libusb_hotplug_flag flags, int vendor_id, int product_id, int dev_class, libusb_hotplug_callback_fn cb_fn, void *user_data, libusb_hotplug_callback_handle *handle);
void libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle handle);
+void *libusb_hotplug_get_user_data(struct libusb_context *ctx,
+ libusb_hotplug_callback_handle callback_handle);
/* Streams support */
diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c
index 6f1ca877fc28..e226def0b7b6 100644
--- a/lib/libusb/libusb10.c
+++ b/lib/libusb/libusb10.c
@@ -1530,6 +1530,7 @@ found:
libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy);
break;
case LIBUSB_TRANSFER_TYPE_BULK:
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy);
break;
@@ -1904,3 +1905,23 @@ libusb_setlocale(const char *locale)
return (LIBUSB_ERROR_INVALID_PARAM);
}
+
+unsigned char *
+libusb_dev_mem_alloc(libusb_device_handle *devh)
+{
+ return (NULL);
+}
+
+int
+libusb_dev_mem_free(libusb_device_handle *devh, unsigned char *buffer,
+ size_t size)
+{
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
+}
+
+int
+libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev,
+ libusb_device_handle **dev_handle)
+{
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
+}
diff --git a/lib/libusb/libusb10_desc.c b/lib/libusb/libusb10_desc.c
index 5f4c46740688..7da5c84f4ad2 100644
--- a/lib/libusb/libusb10_desc.c
+++ b/lib/libusb/libusb10_desc.c
@@ -711,6 +711,55 @@ void
libusb_free_container_id_descriptor(
struct libusb_container_id_descriptor *container_id)
{
-
free(container_id);
}
+
+int
+libusb_get_platform_descriptor(libusb_context *ctx,
+ struct libusb_bos_dev_capability_descriptor *bos_cap,
+ struct libusb_platform_descriptor **pd)
+{
+ struct libusb_platform_descriptor *desc;
+ uint8_t *cap_data;
+
+ if (bos_cap == NULL ||
+ bos_cap->bDescriptorType != LIBUSB_BT_PLATFORM_DESCRIPTOR ||
+ pd == NULL)
+ return (LIBUSB_ERROR_INVALID_PARAM);
+
+ if (bos_cap->bLength < LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE)
+ return (LIBUSB_ERROR_IO);
+
+ cap_data = bos_cap->dev_capability_data;
+ desc = calloc(1, bos_cap->bLength);
+ if (desc == NULL)
+ return (LIBUSB_ERROR_NO_MEM);
+
+ desc->bLength = bos_cap->bLength;
+ desc->bDescriptorType = LIBUSB_BT_PLATFORM_DESCRIPTOR;
+ desc->bDevCapabilityType = bos_cap->bDevCapabilityType;
+ desc->bReserved = cap_data[0];
+ memcpy(desc->PlatformCapabilityUUID, cap_data + 1,
+ sizeof(desc->PlatformCapabilityUUID));
+
+ /*
+ * UUID (16 bytes) + bReserved
+ */
+ cap_data += sizeof(desc->PlatformCapabilityUUID) + 1;
+ /*
+ * UUID (16 bytes) + bReserved + bLength + bDescriptortype +
+ * bDevCapabilitytype
+ */
+ memcpy(desc->CapabilityData, cap_data,
+ bos_cap->bLength - (sizeof(desc->PlatformCapabilityUUID) + 4));
+ *pd = desc;
+
+ return (LIBUSB_SUCCESS);
+}
+
+void
+libusb_free_platform_descriptor(
+ struct libusb_platform_descriptor *platform_descriptor)
+{
+ free(platform_descriptor);
+}
diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c
index 369539d4512e..9c46d4926bfa 100644
--- a/lib/libusb/libusb10_hotplug.c
+++ b/lib/libusb/libusb10_hotplug.c
@@ -414,3 +414,21 @@ void libusb_hotplug_deregister_callback(libusb_context *ctx,
free(handle);
}
+
+void *
+libusb_hotplug_get_user_data(struct libusb_context *ctx,
+ libusb_hotplug_callback_handle callback_handle)
+{
+ libusb_hotplug_callback_handle handle;
+
+ ctx = GET_CONTEXT(ctx);
+
+ HOTPLUG_LOCK(ctx);
+ TAILQ_FOREACH(handle, &ctx->hotplug_cbh, entry) {
+ if (handle == callback_handle)
+ break;
+ }
+ HOTPLUG_UNLOCK(ctx);
+
+ return (handle);
+}
diff --git a/lib/libusb/libusb10_io.c b/lib/libusb/libusb10_io.c
index dd541b09caa6..2047712e9e39 100644
--- a/lib/libusb/libusb10_io.c
+++ b/lib/libusb/libusb10_io.c
@@ -422,6 +422,12 @@ libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv)
return (0);
}
+int
+libusb_pollfds_handle_timeouts(libusb_context *ctx)
+{
+ return (1);
+}
+
void
libusb_set_pollfd_notifiers(libusb_context *ctx,
libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
@@ -781,6 +787,19 @@ libusb_fill_interrupt_transfer(struct libusb_transfer *transfer,
}
void
+libusb_fill_bulk_stream_transfer(struct libusb_transfer *transfer,
+ libusb_device_handle *dev_handle, unsigned char endpoint,
+ uint32_t stream_id, unsigned char *buffer, int length,
+ libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
+{
+ libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer,
+ length, callback, user_data, timeout);
+ transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
+
+ libusb_transfer_set_stream_id(transfer, stream_id);
+}
+
+void
libusb_fill_iso_transfer(struct libusb_transfer *transfer,
libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf,
int length, int npacket, libusb_transfer_cb_fn callback,
@@ -842,3 +861,12 @@ libusb_transfer_get_stream_id(struct libusb_transfer *transfer)
/* get stream ID */
return (sxfer->stream_id);
}
+
+void
+libusb_free_pollfds(const struct libusb_pollfd **pollfds)
+{
+ if (pollfds == NULL)
+ return;
+
+ free(pollfds);
+}
diff --git a/lib/libutil++/Makefile b/lib/libutil++/Makefile
new file mode 100644
index 000000000000..2e7a614df800
--- /dev/null
+++ b/lib/libutil++/Makefile
@@ -0,0 +1,23 @@
+LIB_CXX= util++
+INTERNALLIB= true
+SHLIB_MAJOR= 1
+SRCS= stringf.cc
+
+MAN+= freebsd::FILE_up.3 \
+ freebsd::addrinfo_up.3 \
+ freebsd::fd_up.3 \
+ freebsd::malloc_up.3 \
+ freebsd::nvlist_up.3 \
+ freebsd::pidfile.3 \
+ freebsd::stringf.3
+
+.for page in ${MAN}
+MANSRC.${page}= ${page:S/:/_/g}
+.endfor
+
+.include <src.opts.mk>
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.lib.mk>
diff --git a/lib/libutil++/freebsd__FILE_up.3 b/lib/libutil++/freebsd__FILE_up.3
new file mode 100644
index 000000000000..ea63b1233b43
--- /dev/null
+++ b/lib/libutil++/freebsd__FILE_up.3
@@ -0,0 +1,41 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2025 Chelsio Communications, Inc.
+.\" Written by: John Baldwin <jhb@FreeBSD.org>
+.\"
+.Dd July 31, 2025
+.Dt FREEBSD::FILE_UP 3
+.Os
+.Sh NAME
+.Nm freebsd::FILE_up
+.Nd std::unique_ptr specialization for stdio FILE objects
+.Sh LIBRARY
+.Lb libutil++
+.Sh SYNOPSIS
+.In libutil++.hh
+.Ft using FILE_up = std::unique_ptr<FILE, fclose_deleter>;
+.Sh DESCRIPTION
+This class is a specialization of
+.Vt std::unique_ptr
+for stdio
+.Vt FILE
+objects.
+When a
+.Vt FILE
+object managed by an instance of this class is disposed,
+.Xr fclose 3
+is invoked to dispose of the
+.Vt FILE
+object.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+freebsd::FILE_up fp(fopen("foo.txt", "w"));
+if (!fp)
+ err(1, "fopen");
+fprintf(fp.get(), "hello\n");
+// `fp' is implicitly closed on destruction
+.Ed
+.Sh SEE ALSO
+.Xr fclose 3 ,
+.Xr fopen 3
diff --git a/lib/libutil++/freebsd__addrinfo_up.3 b/lib/libutil++/freebsd__addrinfo_up.3
new file mode 100644
index 000000000000..4845a76bfb61
--- /dev/null
+++ b/lib/libutil++/freebsd__addrinfo_up.3
@@ -0,0 +1,45 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2025 Chelsio Communications, Inc.
+.\" Written by: John Baldwin <jhb@FreeBSD.org>
+.\"
+.Dd July 31, 2025
+.Dt FREEBSD::ADDRINFO_UP 3
+.Os
+.Sh NAME
+.Nm freebsd::addrinfo_up
+.Nd std::unique_ptr specialization for lists of socket addresses
+.Sh LIBRARY
+.Lb libutil++
+.Sh SYNOPSIS
+.In libutil++.hh
+.Ft using addrinfo_up = std::unique_ptr<addrinfo, freeaddrinfo_deleter>;
+.Sh DESCRIPTION
+This class is a specialization of
+.Vt std::unique_ptr
+for socket addresses returned by
+.Xr getaddrinfo 3 .
+When a list of socket addresses managed by an instance of this class is
+disposed,
+.Xr freeaddrinfo 3
+is invoked to dispose of the list.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+freebsd::addrinfo_up
+resolve_address(const char *address, const char *port)
+{
+ struct addrinfo hints, *ai;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(address, port, &hints, &ai);
+ if (error != 0)
+ return {};
+ return freebsd::addrinfo_up(ai);
+}
+.Ed
+.Sh SEE ALSO
+.Xr getaddrinfo 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 <jhb@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++/freebsd__malloc_up.3 b/lib/libutil++/freebsd__malloc_up.3
new file mode 100644
index 000000000000..b18e7854213a
--- /dev/null
+++ b/lib/libutil++/freebsd__malloc_up.3
@@ -0,0 +1,50 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2025 Chelsio Communications, Inc.
+.\" Written by: John Baldwin <jhb@FreeBSD.org>
+.\"
+.Dd July 31, 2025
+.Dt FREEBSD::MALLOC_UP 3
+.Os
+.Sh NAME
+.Nm freebsd::malloc_up
+.Nd std::unique_ptr specialization for objects allocated via malloc
+.Sh LIBRARY
+.Lb libutil++
+.Sh SYNOPSIS
+.In libutil++.hh
+.Ft using malloc_up = std::unique_ptr<T, free_deleter<T>>;
+.Sh DESCRIPTION
+This class is a specialization of
+.Vt std::unique_ptr
+which invokes
+.Xr free 3
+instead of
+.Fn delete
+when an object is disposed.
+While explicit calls to
+.Xr malloc 3
+should be avoided in C++ code,
+this class can be useful to manage an object allocated by an existing API
+which uses
+.Xr malloc 3
+internally such as
+.Xr scandir 3 .
+Note that the type of the underlying object must be used as the first
+template argument similar to std::unique_ptr.
+.Sh EXAMPLES
+This example uses
+.Xr strdup 3
+for simplicity,
+but new C++ code should generally not use
+.Xr strdup 3 :
+.Bd -literal -offset indent
+freebsd::malloc_up<char> my_string(strdup("foo"));
+// `mystring' is implicitly freed on destruction
+.Ed
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr malloc 3 ,
+.Xr scandir 3 ,
+.Xr strdup 3
diff --git a/lib/libutil++/freebsd__nvlist_up.3 b/lib/libutil++/freebsd__nvlist_up.3
new file mode 100644
index 000000000000..43f76cf3ead3
--- /dev/null
+++ b/lib/libutil++/freebsd__nvlist_up.3
@@ -0,0 +1,37 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2025 Chelsio Communications, Inc.
+.\" Written by: John Baldwin <jhb@FreeBSD.org>
+.\"
+.Dd July 31, 2025
+.Dt FREEBSD::NVLIST_UP 3
+.Os
+.Sh NAME
+.Nm freebsd::nvlist_up
+.Nd std::unique_ptr specialization for name/value pairs
+.Sh LIBRARY
+.Lb libutil++
+.Sh SYNOPSIS
+.In libutil++.hh
+.Ft using nvlist_up = std::unique_ptr<nvlist, nvlist_deleter>;
+.Sh DESCRIPTION
+This class is a specialization of
+.Vt std::unique_ptr
+for
+.Vt nvlist_t
+objects.
+When an
+.Vt nvlist_t
+object managed by an instance of this class is disposed,
+.Xr nvlist_destroy 3
+is invoked to dispose of the object.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+freebsd::nvlist_up nvl(nvlist_create(0));
+nvlist_add_number(nvl.get(), "answer", 42);
+nvlist_add_bool(nvl.get(), "valid", true);
+// `nvl' is implicitly destroyed
+.Ed
+.Sh SEE ALSO
+.Xr nvlist_destroy 3
diff --git a/lib/libutil++/freebsd__pidfile.3 b/lib/libutil++/freebsd__pidfile.3
new file mode 100644
index 000000000000..fb67253f5c02
--- /dev/null
+++ b/lib/libutil++/freebsd__pidfile.3
@@ -0,0 +1,110 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2025 Chelsio Communications, Inc.
+.\" Written by: John Baldwin <jhb@FreeBSD.org>
+.\"
+.Dd July 31, 2025
+.Dt FREEBSD::STRINGF 3
+.Os
+.Sh NAME
+.Nm freebsd::pidfile
+.Nd own a PID file handle
+.Sh LIBRARY
+.Lb libutil++
+.Sh SYNOPSIS
+.In libutil++.hh
+.Pp
+.Vt class freebsd::pidfile
+{
+.Bd -ragged -offset indent
+.Fn pidfile
+.Fn pidfile "struct pidfh *pfh"
+.Fn pidfile "pidfile &&other"
+.Fn ~pidfile
+.Ft struct pidfh *
+.Fn release
+.Ft void
+.Fn reset "struct pidfh *newpfh = nullptr"
+.Ft int
+.Fn write
+.Ft int
+.Fn close
+.Ft int
+.Fn fileno
+.Ft "pidfile &"
+.Fn operator= "pidfile &&other"
+.Ft "pidfile &"
+.Fn operator= "struct pidfh *pfh"
+.Fn "explicit operator bool"
+.Ed
+};
+.Sh DESCRIPTION
+Each instance of this class owns a PID file handle created by
+.Xr pidfile_open 3 .
+This class is patterned on std::unique_ptr;
+however,
+rather than exporting the raw pointer via a
+.Fn get
+method,
+this class provides wrapper methods for each of the other
+.Xr pidfile 3
+functions.
+The currently-owned PID file is removed by invoking
+.Xr pidfile_remove 3
+when an instance of this class is destroyed.
+The currently-owned PID file is also removed if it is replaced by the
+.Fn reset
+method or assignment operators.
+.Pp
+The
+.Fn release
+method relinquishes ownership of the current PID file handle and returns the
+value of the previously-owned PID file handle.
+.Pp
+The
+.Fn write
+method writes out the PID of the current process to the PID file via
+.Xr pidfile_write 3 .
+.Pp
+The
+.Fn close
+method closes the current PID file without removing it via
+.Xr pidfile_close 3 .
+If the close succeeds, the PID file handle is no longer valid.
+.Pp
+The
+.Fn fileno
+method returns the underlying file descriptor for the current PID file via
+.Xr pidfile_fileno 3 .
+.Pp
+The explicit
+.Vt bool
+conversion operator permits testing the validity of an object.
+The operator returns true if the instance owns a valid PID file handle.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+int
+main()
+{
+ freebsd::pidfile pf(pidfile_open("/var/run/daemon.pid",
+ 0600, NULL));
+ if (!pf)
+ err(1, "pidfile_open");
+
+ if (daemon(0, 0) == -1) {
+ warn("daemon");
+ return 1;
+ }
+
+ pf->write();
+
+ for (;;) {
+ /* Do Work */
+ }
+
+ return 0;
+}
+.Ed
+.Sh SEE ALSO
+.Xr pidfile 3
diff --git a/lib/libutil++/freebsd__stringf.3 b/lib/libutil++/freebsd__stringf.3
new file mode 100644
index 000000000000..341fedef4343
--- /dev/null
+++ b/lib/libutil++/freebsd__stringf.3
@@ -0,0 +1,48 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2025 Chelsio Communications, Inc.
+.\" Written by: John Baldwin <jhb@FreeBSD.org>
+.\"
+.Dd July 31, 2025
+.Dt FREEBSD::STRINGF 3
+.Os
+.Sh NAME
+.Nm freebsd::stringf
+.Nd build a std::string using stdio formatting
+.Sh LIBRARY
+.Lb libutil++
+.Sh SYNOPSIS
+.In libutil++.hh
+.Ft std::string
+.Fn freebsd::stringf "const char *fmt" "..."
+.Ft std::string
+.Fn freebsd::stringf "const char *fmt" "va_list ap"
+.Sh DESCRIPTION
+These functions construct a
+.Vt std::string
+object containing a formatted string.
+The output of the string is dictated by the
+.Fa fmt
+argument and additional arguments using the same conventions documented in
+.Xr printf 3 .
+The first form provides functionality similar to
+.Xr asprintf 3
+and the second form is similar to
+.Xr vasprintf 3 .
+.Sh RETURN VALUES
+These functions return a std::string object.
+.Sh EXCEPTIONS
+These functions may throw one of the following exceptions:
+.Bl -tag -width Er
+.It Bq Er std::bad_alloc
+Failed to allocate memory.
+.It Bq Er std::length_error
+The result would exceeed the maximum possible string size.
+.El
+.Sh EXAMPLES
+.Bd -literal -offset indent
+std::string s = freebsd::stringf("hello %s", "world");
+.Ed
+.Sh SEE ALSO
+.Xr asprintf 3
diff --git a/lib/libutil++/libutil++.hh b/lib/libutil++/libutil++.hh
new file mode 100644
index 000000000000..60e6b3fc5fde
--- /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__ */
diff --git a/lib/libutil++/stringf.cc b/lib/libutil++/stringf.cc
new file mode 100644
index 000000000000..8c24167d70ac
--- /dev/null
+++ b/lib/libutil++/stringf.cc
@@ -0,0 +1,57 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <cstdarg>
+#include <cstdio>
+#include <string>
+
+#include "libutil++.hh"
+
+static int
+stringf_write(void *cookie, const char *buf, int len)
+{
+ std::string *str = reinterpret_cast<std::string *>(cookie);
+ try {
+ str->append(buf, len);
+ } catch (std::bad_alloc) {
+ errno = ENOMEM;
+ return (-1);
+ } catch (std::length_error) {
+ errno = EFBIG;
+ return (-1);
+ }
+ return (len);
+}
+
+std::string
+freebsd::stringf(const char *fmt, va_list ap)
+{
+ std::string str;
+ freebsd::FILE_up fp(fwopen(reinterpret_cast<void *>(&str),
+ stringf_write));
+
+ vfprintf(fp.get(), fmt, ap);
+
+ if (ferror(fp.get()))
+ throw std::bad_alloc();
+ fp.reset(nullptr);
+
+ return str;
+}
+
+std::string
+freebsd::stringf(const char *fmt, ...)
+{
+ std::va_list ap;
+ std::string str;
+
+ va_start(ap, fmt);
+ str = freebsd::stringf(fmt, ap);
+ va_end(ap);
+
+ return str;
+}
diff --git a/lib/libutil++/tests/Makefile b/lib/libutil++/tests/Makefile
new file mode 100644
index 000000000000..e7720d122f36
--- /dev/null
+++ b/lib/libutil++/tests/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+ATF_TESTS_CXX+= pidfile_test
+ATF_TESTS_CXX+= stringf_test
+ATF_TESTS_CXX+= up_test
+
+CFLAGS+= -I${SRCTOP}/lib/libutil++
+LIBADD+= util++
+
+LIBADD.pidfile_test+= util
+
+.include <bsd.test.mk>
diff --git a/lib/libutil++/tests/pidfile_test.cc b/lib/libutil++/tests/pidfile_test.cc
new file mode 100644
index 000000000000..067f10e8fab8
--- /dev/null
+++ b/lib/libutil++/tests/pidfile_test.cc
@@ -0,0 +1,44 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <atf-c++.hpp>
+#include <sys/stat.h>
+#include <libutil.h>
+
+#include <libutil++.hh>
+
+ATF_TEST_CASE_WITHOUT_HEAD(basic);
+ATF_TEST_CASE_BODY(basic)
+{
+ pid_t other;
+ struct pidfh *pfh = pidfile_open("test_pidfile", 0600, &other);
+ ATF_REQUIRE(pfh != nullptr);
+ ATF_REQUIRE(pidfile_fileno(pfh) >= 0);
+
+ struct stat sb;
+ ATF_REQUIRE(fstat(pidfile_fileno(pfh), &sb) == 0);
+ ATF_REQUIRE_EQ(0, sb.st_size);
+
+ freebsd::pidfile pf(pfh);
+ ATF_REQUIRE_EQ(pidfile_fileno(pfh), pf.fileno());
+
+ ATF_REQUIRE(pf.write() == 0);
+
+ ATF_REQUIRE(fstat(pf.fileno(), &sb) == 0);
+ ATF_REQUIRE(sb.st_size > 0);
+
+ ATF_REQUIRE(pf.close() == 0);
+ ATF_REQUIRE(pf.fileno() == -1);
+ ATF_REQUIRE_EQ(EDOOFUS, errno);
+
+ ATF_REQUIRE(unlink("test_pidfile") == 0);
+}
+
+ATF_INIT_TEST_CASES(tcs)
+{
+ ATF_ADD_TEST_CASE(tcs, basic);
+}
diff --git a/lib/libutil++/tests/stringf_test.cc b/lib/libutil++/tests/stringf_test.cc
new file mode 100644
index 000000000000..5b8ef4ad54a9
--- /dev/null
+++ b/lib/libutil++/tests/stringf_test.cc
@@ -0,0 +1,52 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <atf-c++.hpp>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <libutil++.hh>
+
+ATF_TEST_CASE_WITHOUT_HEAD(basic);
+ATF_TEST_CASE_BODY(basic)
+{
+ ATF_REQUIRE_EQ("foo", freebsd::stringf("foo"));
+ ATF_REQUIRE_EQ("bar", freebsd::stringf("%s", "bar"));
+ ATF_REQUIRE_EQ("42", freebsd::stringf("%u", 42));
+ ATF_REQUIRE_EQ("0xdeadbeef", freebsd::stringf("%#x", 0xdeadbeef));
+ ATF_REQUIRE_EQ("", freebsd::stringf(""));
+ ATF_REQUIRE_EQ("this is a test", freebsd::stringf("this %s test",
+ "is a"));
+}
+
+static std::string
+stringv(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ std::string str = freebsd::stringf(fmt, ap);
+ va_end(ap);
+ return (str);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(va_list);
+ATF_TEST_CASE_BODY(va_list)
+{
+ ATF_REQUIRE_EQ("foo", stringv("foo"));
+ ATF_REQUIRE_EQ("bar", stringv("%s", "bar"));
+ ATF_REQUIRE_EQ("42", stringv("%u", 42));
+ ATF_REQUIRE_EQ("0xdeadbeef", stringv("%#x", 0xdeadbeef));
+ ATF_REQUIRE_EQ("", stringv(""));
+ ATF_REQUIRE_EQ("this is a test", stringv("this %s test", "is a"));
+}
+
+ATF_INIT_TEST_CASES(tcs)
+{
+ ATF_ADD_TEST_CASE(tcs, basic);
+ ATF_ADD_TEST_CASE(tcs, va_list);
+}
diff --git a/lib/libutil++/tests/up_test.cc b/lib/libutil++/tests/up_test.cc
new file mode 100644
index 000000000000..3f344054c334
--- /dev/null
+++ b/lib/libutil++/tests/up_test.cc
@@ -0,0 +1,33 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <atf-c++.hpp>
+#include <libutil.h>
+
+#include <libutil++.hh>
+
+ATF_TEST_CASE_WITHOUT_HEAD(FILE_up);
+ATF_TEST_CASE_BODY(FILE_up)
+{
+ FILE *fp = fopen("/dev/null", "r");
+ ATF_REQUIRE(fp != NULL);
+ ATF_REQUIRE(fileno(fp) != -1);
+
+ freebsd::FILE_up f(fp);
+ ATF_REQUIRE_EQ(fileno(fp), fileno(f.get()));
+
+ f.reset();
+ ATF_REQUIRE_EQ(f.get(), nullptr);
+
+ ATF_REQUIRE_EQ(-1, fileno(fp));
+ ATF_REQUIRE_EQ(EBADF, errno);
+}
+
+ATF_INIT_TEST_CASES(tcs)
+{
+ ATF_ADD_TEST_CASE(tcs, FILE_up);
+}
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index 0639745d08fc..f6251c093345 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -7,9 +7,9 @@ PACKAGE= runtime
.PATH: ${SRCTOP}/lib/libc/gen # for pw_scan.c
LIB= util
-SHLIB_MAJOR= 9
+SHLIB_MAJOR= 10
-SRCS= _secure_path.c auth.c cpuset.c expand_number.c flopen.c fparseln.c \
+SRCS= _secure_path.c cpuset.c expand_number.c flopen.c fparseln.c \
ftime.c getlocalbase.c gr_util.c \
hexdump.c humanize_number.c kinfo_getfile.c \
kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c \
@@ -29,73 +29,125 @@ CFLAGS+= -DINET6
CFLAGS+= -I${.CURDIR} -I${SRCTOP}/lib/libc/gen/
-MAN+= cpuset.3 expand_number.3 flopen.3 fparseln.3 ftime.3 getlocalbase.3 \
- hexdump.3 humanize_number.3 kinfo_getallproc.3 kinfo_getfile.3 \
- kinfo_getproc.3 kinfo_getvmmap.3 kinfo_getvmobject.3 kld.3 \
- login_auth.3 login_cap.3 \
- login_class.3 login_ok.3 login_times.3 login_tty.3 mntopts.3 \
- pidfile.3 \
- property.3 pty.3 quotafile.3 realhostname.3 realhostname_sa.3 \
- _secure_path.3 trimdomain.3 uucplock.3 pw_util.3
-MAN+= login.conf.5
+VERSION_DEF= ${SRCTOP}/lib/libc/Versions.def
+SYMBOL_MAPS= ${.CURDIR}/Symbol.map
+
+MAN+= cpuset.3
+MLINKS+=cpuset.3 cpuset_parselist.3
+MLINKS+=cpuset.3 domainset_parselist.3
+MAN+= expand_number.3
+MAN+= flopen.3
MLINKS+=flopen.3 flopenat.3
-MLINKS+=kld.3 kld_isloaded.3 kld.3 kld_load.3
-MLINKS+=login_auth.3 auth_cat.3 login_auth.3 auth_checknologin.3
-MLINKS+=login_cap.3 login_close.3 login_cap.3 login_getcapbool.3 \
- login_cap.3 login_getcaplist.3 login_cap.3 login_getcapnum.3 \
- login_cap.3 login_getcapsize.3 login_cap.3 login_getcapstr.3 \
- login_cap.3 login_getcaptime.3 login_cap.3 login_getclass.3 \
- login_cap.3 login_getclassbyname.3 login_cap.3 login_getpath.3 \
- login_cap.3 login_getpwclass.3 login_cap.3 login_getstyle.3 \
- login_cap.3 login_getuserclass.3 login_cap.3 login_setcryptfmt.3
-MLINKS+=login_class.3 setclasscontext.3 login_class.3 setclassenvironment.3 \
- login_class.3 setclassresources.3 login_class.3 setusercontext.3
-MLINKS+=login_ok.3 auth_hostok.3 login_ok.3 auth_timeok.3 \
- login_ok.3 auth_ttyok.3
-MLINKS+=login_times.3 in_lt.3 login_times.3 in_ltm.3 \
- login_times.3 in_ltms.3 \
- login_times.3 in_lts.3 \
- login_times.3 parse_lt.3
-MLINKS+=mntopts.3 getmntopts.3 \
- mntopts.3 getmntpoint.3 \
- mntopts.3 chkdoreload.3 \
- mntopts.3 build_iovec.3 \
- mntopts.3 build_iovec_argf.3 \
- mntopts.3 free_iovec.3 \
- mntopts.3 checkpath.3 \
- mntopts.3 rmslashes.3
-MLINKS+=pidfile.3 pidfile_close.3 \
- pidfile.3 pidfile_fileno.3 \
- pidfile.3 pidfile_open.3 \
- pidfile.3 pidfile_remove.3 \
- pidfile.3 pidfile_write.3
-MLINKS+=property.3 property_find.3 property.3 properties_free.3
+MAN+= fparseln.3
+MAN+= ftime.3
+MAN+= getlocalbase.3
+MAN+= hexdump.3
+MAN+= humanize_number.3
+MAN+= kinfo_getallproc.3
+MAN+= kinfo_getfile.3
+MAN+= kinfo_getproc.3
+MAN+= kinfo_getvmmap.3
+MAN+= kinfo_getvmobject.3
+MAN+= kld.3
+MLINKS+=kld.3 kld_isloaded.3
+MLINKS+=kld.3 kld_load.3
+MAN+= login_auth.3
+MLINKS+=login_auth.3 auth_cat.3
+MLINKS+=login_auth.3 auth_checknologin.3
+MAN+= login_cap.3
+MLINKS+=login_cap.3 login_close.3
+MLINKS+=login_cap.3 login_getcapbool.3
+MLINKS+=login_cap.3 login_getcapenum.3
+MLINKS+=login_cap.3 login_getcaplist.3
+MLINKS+=login_cap.3 login_getcapnum.3
+MLINKS+=login_cap.3 login_getcapsize.3
+MLINKS+=login_cap.3 login_getcapstr.3
+MLINKS+=login_cap.3 login_getcaptime.3
+MLINKS+=login_cap.3 login_getclass.3
+MLINKS+=login_cap.3 login_getclassbyname.3
+MLINKS+=login_cap.3 login_getpath.3
+MLINKS+=login_cap.3 login_getpwclass.3
+MLINKS+=login_cap.3 login_getstyle.3
+MLINKS+=login_cap.3 login_getuserclass.3
+MLINKS+=login_cap.3 login_setcryptfmt.3
+MAN+= login_class.3
+MLINKS+=login_class.3 setclasscontext.3
+MLINKS+=login_class.3 setclasscpumask.3
+MLINKS+=login_class.3 setclassenvironment.3
+MLINKS+=login_class.3 setclassresources.3
+MLINKS+=login_class.3 setusercontext.3
+MAN+= login_ok.3
+MLINKS+=login_ok.3 auth_hostok.3
+MLINKS+=login_ok.3 auth_timeok.3
+MLINKS+=login_ok.3 auth_ttyok.3
+MAN+= login_times.3
+MLINKS+=login_times.3 in_lt.3
+MLINKS+=login_times.3 in_ltm.3
+MLINKS+=login_times.3 in_ltms.3
+MLINKS+=login_times.3 in_lts.3
+MLINKS+=login_times.3 parse_lt.3
+MAN+= login_tty.3
+MAN+= mntopts.3
+MLINKS+=mntopts.3 build_iovec.3
+MLINKS+=mntopts.3 build_iovec_argf.3
+MLINKS+=mntopts.3 checkpath.3
+MLINKS+=mntopts.3 chkdoreload.3
+MLINKS+=mntopts.3 free_iovec.3
+MLINKS+=mntopts.3 getmntopts.3
+MLINKS+=mntopts.3 getmntpoint.3
+MLINKS+=mntopts.3 rmslashes.3
+MAN+= pidfile.3
+MLINKS+=pidfile.3 pidfile_close.3
+MLINKS+=pidfile.3 pidfile_fileno.3
+MLINKS+=pidfile.3 pidfile_open.3
+MLINKS+=pidfile.3 pidfile_remove.3
+MLINKS+=pidfile.3 pidfile_signal.3
+MLINKS+=pidfile.3 pidfile_write.3
+MAN+= property.3
+MLINKS+=property.3 property_find.3
+MLINKS+=property.3 properties_free.3
MLINKS+=property.3 properties_read.3
-MLINKS+=pty.3 forkpty.3 pty.3 openpty.3
-MLINKS+=quotafile.3 quota_close.3 \
- quotafile.3 quota_fsname.3 \
- quotafile.3 quota_open.3 \
- quotafile.3 quota_qfname.3 \
- quotafile.3 quota_read.3 \
- quotafile.3 quota_statfs.3 \
- quotafile.3 quota_write_limits.3 \
- quotafile.3 quota_write_usage.3
-MLINKS+=uucplock.3 uu_lock.3 uucplock.3 uu_lock_txfr.3 \
- uucplock.3 uu_lockerr.3 uucplock.3 uu_unlock.3
-MLINKS+=pw_util.3 pw_copy.3 \
- pw_util.3 pw_dup.3 \
- pw_util.3 pw_edit.3 \
- pw_util.3 pw_equal.3 \
- pw_util.3 pw_fini.3 \
- pw_util.3 pw_init.3 \
- pw_util.3 pw_make.3 \
- pw_util.3 pw_make_v7.3 \
- pw_util.3 pw_mkdb.3 \
- pw_util.3 pw_lock.3 \
- pw_util.3 pw_scan.3 \
- pw_util.3 pw_tempname.3 \
- pw_util.3 pw_tmp.3
-MLINKS+=cpuset.3 cpuset_parselist.3
+MAN+= pty.3
+MLINKS+=pty.3 forkpty.3
+MLINKS+=pty.3 openpty.3
+MAN+= pw_util.3
+MLINKS+=pw_util.3 pw_copy.3
+MLINKS+=pw_util.3 pw_dup.3
+MLINKS+=pw_util.3 pw_edit.3
+MLINKS+=pw_util.3 pw_equal.3
+MLINKS+=pw_util.3 pw_fini.3
+MLINKS+=pw_util.3 pw_init.3
+MLINKS+=pw_util.3 pw_initpwd.3
+MLINKS+=pw_util.3 pw_make.3
+MLINKS+=pw_util.3 pw_make_v7.3
+MLINKS+=pw_util.3 pw_mkdb.3
+MLINKS+=pw_util.3 pw_lock.3
+MLINKS+=pw_util.3 pw_scan.3
+MLINKS+=pw_util.3 pw_tempname.3
+MLINKS+=pw_util.3 pw_tmp.3
+MAN+= quotafile.3
+MLINKS+=quotafile.3 quota_check_path.3
+MLINKS+=quotafile.3 quota_close.3
+MLINKS+=quotafile.3 quota_convert.3
+MLINKS+=quotafile.3 quota_fsname.3
+MLINKS+=quotafile.3 quota_maxid.3
+MLINKS+=quotafile.3 quota_off.3
+MLINKS+=quotafile.3 quota_on.3
+MLINKS+=quotafile.3 quota_open.3
+MLINKS+=quotafile.3 quota_qfname.3
+MLINKS+=quotafile.3 quota_read.3
+MLINKS+=quotafile.3 quota_write_limits.3
+MLINKS+=quotafile.3 quota_write_usage.3
+MAN+= realhostname.3
+MAN+= realhostname_sa.3
+MAN+= _secure_path.3
+MAN+= trimdomain.3
+MAN+= uucplock.3
+MLINKS+=uucplock.3 uu_lock.3
+MLINKS+=uucplock.3 uu_lock_txfr.3
+MLINKS+=uucplock.3 uu_lockerr.3
+MLINKS+=uucplock.3 uu_unlock.3
+MAN+= login.conf.5
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/lib/libutil/Symbol.map b/lib/libutil/Symbol.map
new file mode 100644
index 000000000000..2b28456f4406
--- /dev/null
+++ b/lib/libutil/Symbol.map
@@ -0,0 +1,135 @@
+FBSD_1.8 {
+ _secure_path;
+ auth_cat;
+ auth_checknologin;
+ auth_hostok;
+ auth_timeok;
+ auth_ttyok;
+ build_iovec_argf;
+ build_iovec;
+ checkpath_allow_file;
+ checkpath;
+ chkdoreload;
+ cpuset_parselist;
+ domainset_parselist;
+ expand_number;
+ expand_unsigned;
+ flopen;
+ flopenat;
+ forkpty;
+ fparseln;
+ free_iovec;
+ ftime;
+ getlocalbase;
+ getmnt_silent;
+ getmntopts;
+ getmntpoint;
+ gr_add;
+ gr_copy;
+ gr_dup;
+ gr_equal;
+ gr_fini;
+ gr_init;
+ gr_lock;
+ gr_make;
+ gr_mkdb;
+ gr_scan;
+ gr_tmp;
+ hexdump;
+ humanize_number;
+ in_lt;
+ in_ltm;
+ in_ltms;
+ in_lts;
+ kinfo_getallproc;
+ kinfo_getfile;
+ kinfo_getproc;
+ kinfo_getswapvmobject;
+ kinfo_getvmmap;
+ kinfo_getvmobject;
+ kld_isloaded;
+ kld_load;
+ login_close;
+ login_getcapbool;
+ login_getcapenum;
+ login_getcaplist;
+ login_getcapnum;
+ login_getcapsize;
+ login_getcapstr;
+ login_getcaptime;
+ login_getclass;
+ login_getclassbyname;
+ login_getpath;
+ login_getpwclass;
+ login_getstyle;
+ login_getuserclass;
+ login_hostok;
+ login_setcryptfmt;
+ login_str2inlist;
+ login_strinlist;
+ login_timelist;
+ login_tty;
+ login_ttyok;
+ openpty;
+ parse_lt;
+ pidfile_close;
+ pidfile_fileno;
+ pidfile_open;
+ pidfile_remove;
+ pidfile_signal;
+ pidfile_write;
+ properties_free;
+ properties_read;
+ property_find;
+ pw_copy;
+ pw_dup;
+ pw_edit;
+ pw_equal;
+ pw_fini;
+ pw_init;
+ pw_initpwd;
+ pw_lock;
+ pw_make_v7;
+ pw_make;
+ pw_mkdb;
+ pw_scan;
+ pw_tempname;
+ pw_tmp;
+ quota_check_path;
+ quota_close;
+ quota_convert;
+ quota_fsname;
+ quota_maxid;
+ quota_off;
+ quota_on;
+ quota_open;
+ quota_qfname;
+ quota_read;
+ quota_write_limits;
+ quota_write_usage;
+ realhostname_sa;
+ realhostname;
+ rmslashes;
+ setclasscontext;
+ setclasscpumask;
+ setclassenvironment;
+ setclassresources;
+ setusercontext;
+ trimdomain;
+ uu_lock_txfr;
+ uu_lock;
+ uu_lockerr;
+ uu_unlock;
+
+ /*
+ * login_setcryptfmt() uses crypt_set_format() from libcrypt. To
+ * avoid forcing a hard dependency on libcrypt, we provide a weak
+ * stub. Applications that use login_setcryptfmt() should link
+ * with libcrypt, whose crypt_set_format() will override the stub.
+ */
+ crypt_set_format;
+};
+
+FBSDprivate_1.0 {
+ __pw_initpwd;
+};
diff --git a/lib/libutil/auth.c b/lib/libutil/auth.c
deleted file mode 100644
index 3414fc8e26e7..000000000000
--- a/lib/libutil/auth.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Simple authentication database handling code.
- *
- * Copyright (c) 1998
- * Jordan Hubbard. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer,
- * verbatim and that no modifications are made prior to this
- * point in the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#include <stdlib.h>
-
-#include <libutil.h>
-
-char *
-auth_getval(const char *name)
-{
-
- (void)name;
- return (NULL);
-}
diff --git a/lib/libutil/cpuset.3 b/lib/libutil/cpuset.3
index be29d5309ef0..47dffd209ee6 100644
--- a/lib/libutil/cpuset.3
+++ b/lib/libutil/cpuset.3
@@ -22,21 +22,22 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 31, 2017
+.Dd June 24, 2025
.Dt CPUSET 3
.Os
.Sh NAME
-.Nm cpuset_parselist
-.Nd utility functions for
-.Xr cpuset 2
-handling
+.Nm cpuset_parselist ,
+.Nm domainset_parselist
+.Nd utility functions for cpuset(2) handling
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In sys/cpuset.h
.In libutil.h
.Ft int
-.Fn cpuset_parselist "const char *cpu-list" "cpuset_t *mask"
+.Fn cpuset_parselist "const char *cpu_list" "cpuset_t *mask"
+.Ft int
+.Fn domainset_parselist "const char *domain_policy" "domainset_t *domain_mask" "int *policyp"
.Sh DESCRIPTION
The
.Fn cpuset_parselist
@@ -52,6 +53,27 @@ numbers.
A special list of
.Dq all
may be specified in which case the list includes all CPUs from the root set.
+.Pp
+The
+.Fn domainset_parselist
+function parses a
+.Xr domainset 9
+memory domain allocation policy
+specified by
+.Va domain_policy
+filling the
+.Va domain_mask
+and the
+.Va policyp .
+A valid
+.Va domain_policy
+is formatted as
+.Ar policy:domain-list .
+See the
+.Ar -n
+flag in
+.Xr cpuset 1
+for a list of valid domain policies.
.Sh RETURN VALUES
Return values can be the following
.Bl -tag -width Er
@@ -60,19 +82,30 @@ The parsing was successful
.It Dv CPUSET_PARSE_ERROR
The
.Va cpu-list
+or
+.Va domain-policy
format is invalid
.It Dv CPUSET_PARSE_GETAFFINITY
The
.Xr cpuset_getaffinity 2
call has failed
.It Dv CPUSET_PARSE_INVALID_CPU
-The number of supported CPUs has been exceeded.
+The number of supported CPUs or NUMA domains has been exceeded.
The maximum number being
-.Va CPU_SETSIZE .
+.Va CPU_SETSIZE
+and
+.Va DOMAINSET_SETSIZE
+respectively.
+.It Dv CPUSET_PARSE_GETDOMAIN
+The
+.Xr cpuset_getdomain 2
+call has failed
.El
.Sh SEE ALSO
.Xr cpuset 1 ,
.Xr cpuset 2 ,
-.Xr cpuset 9
+.Xr numa 4 ,
+.Xr cpuset 9 ,
+.Xr domainset 9
.Sh AUTHORS
.An Jeffrey Roberson Aq Mt jeff@FreeBSD.org
diff --git a/lib/libutil/cpuset.c b/lib/libutil/cpuset.c
index 3c374bfa6cac..d4840af7e175 100644
--- a/lib/libutil/cpuset.c
+++ b/lib/libutil/cpuset.c
@@ -27,34 +27,48 @@
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+#define _WANT_FREEBSD_BITSET
+
#include <sys/types.h>
#include <sys/cpuset.h>
+#include <sys/domainset.h>
#include <stdlib.h>
#include <string.h>
#include <libutil.h>
#include <ctype.h>
-int
-cpuset_parselist(const char *list, cpuset_t *mask)
+struct numa_policy {
+ const char *name;
+ int policy;
+};
+
+static const struct numa_policy policies[] = {
+ { "round-robin", DOMAINSET_POLICY_ROUNDROBIN },
+ { "rr", DOMAINSET_POLICY_ROUNDROBIN },
+ { "first-touch", DOMAINSET_POLICY_FIRSTTOUCH },
+ { "ft", DOMAINSET_POLICY_FIRSTTOUCH },
+ { "prefer", DOMAINSET_POLICY_PREFER },
+ { "interleave", DOMAINSET_POLICY_INTERLEAVE},
+ { "il", DOMAINSET_POLICY_INTERLEAVE},
+ { NULL, DOMAINSET_POLICY_INVALID }
+};
+
+static int
+parselist(const char *list, struct bitset *mask, int size)
{
enum { NONE, NUM, DASH } state;
int lastnum;
int curnum;
const char *l;
- if (strcasecmp(list, "all") == 0) {
- if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1,
- sizeof(*mask), mask) != 0)
- return (CPUSET_PARSE_GETAFFINITY);
- return (CPUSET_PARSE_OK);
- }
state = NONE;
curnum = lastnum = 0;
for (l = list; *l != '\0';) {
if (isdigit(*l)) {
curnum = atoi(l);
- if (curnum > CPU_SETSIZE)
+ if (curnum >= size)
return (CPUSET_PARSE_INVALID_CPU);
while (isdigit(*l))
l++;
@@ -65,7 +79,7 @@ cpuset_parselist(const char *list, cpuset_t *mask)
break;
case DASH:
for (; lastnum <= curnum; lastnum++)
- CPU_SET(lastnum, mask);
+ BIT_SET(size, lastnum, mask);
state = NONE;
break;
case NUM:
@@ -80,7 +94,7 @@ cpuset_parselist(const char *list, cpuset_t *mask)
case NONE:
break;
case NUM:
- CPU_SET(curnum, mask);
+ BIT_SET(size, curnum, mask);
state = NONE;
break;
case DASH:
@@ -102,7 +116,7 @@ cpuset_parselist(const char *list, cpuset_t *mask)
case NONE:
break;
case NUM:
- CPU_SET(curnum, mask);
+ BIT_SET(size, curnum, mask);
break;
case DASH:
goto parserr;
@@ -111,3 +125,63 @@ cpuset_parselist(const char *list, cpuset_t *mask)
parserr:
return (CPUSET_PARSE_ERROR);
}
+
+/*
+ * permissively parse policy:domain list
+ * allow:
+ * round-robin:0-4 explicit
+ * round-robin:all explicit root domains
+ * 0-4 implicit root policy
+ * round-robin implicit root domains
+ * all explicit root domains and implicit policy
+ */
+int
+domainset_parselist(const char *list, domainset_t *mask, int *policyp)
+{
+ domainset_t rootmask;
+ const struct numa_policy *policy;
+ const char *l;
+ int p;
+
+ /*
+ * Use the rootset's policy as the default for unspecified policies.
+ */
+ if (cpuset_getdomain(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1,
+ sizeof(rootmask), &rootmask, &p) != 0)
+ return (CPUSET_PARSE_GETDOMAIN);
+
+ if (list == NULL || strcasecmp(list, "all") == 0 || *list == '\0') {
+ *policyp = p;
+ DOMAINSET_COPY(&rootmask, mask);
+ return (CPUSET_PARSE_OK);
+ }
+
+ l = list;
+ for (policy = &policies[0]; policy->name != NULL; policy++) {
+ if (strncasecmp(l, policy->name, strlen(policy->name)) == 0) {
+ p = policy->policy;
+ l += strlen(policy->name);
+ if (*l != ':' && *l != '\0')
+ return (CPUSET_PARSE_ERROR);
+ if (*l == ':')
+ l++;
+ break;
+ }
+ }
+ *policyp = p;
+
+ return (parselist(l, (struct bitset *)mask, DOMAINSET_SETSIZE));
+}
+
+int
+cpuset_parselist(const char *list, cpuset_t *mask)
+{
+ if (strcasecmp(list, "all") == 0) {
+ if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1,
+ sizeof(*mask), mask) != 0)
+ return (CPUSET_PARSE_GETAFFINITY);
+ return (CPUSET_PARSE_OK);
+ }
+
+ return (parselist(list, (struct bitset *)mask, CPU_SETSIZE));
+}
diff --git a/lib/libutil/expand_number.3 b/lib/libutil/expand_number.3
index 3609b1ad3939..b1833cedf406 100644
--- a/lib/libutil/expand_number.3
+++ b/lib/libutil/expand_number.3
@@ -1,5 +1,6 @@
.\" Copyright (c) 2007 Eric Anderson <anderson@FreeBSD.org>
.\" Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+.\" Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -23,43 +24,65 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 13, 2023
+.Dd August 6, 2025
.Dt EXPAND_NUMBER 3
.Os
.Sh NAME
-.Nm expand_number
-.Nd format a number from human readable form
+.Nm expand_number ,
+.Nm expand_unsigned
+.Nd parse a number from human readable form
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In libutil.h
.Ft int
.Fo expand_number
+.Fa "const char *buf" "int64_t *num"
+.Fc
+.Ft int
+.Fo expand_unsigned
.Fa "const char *buf" "uint64_t *num"
.Fc
.Sh DESCRIPTION
The
.Fn expand_number
-function parses the
+function parses the number in the string pointed to by its
.Fa buf
-string and stores a unsigned 64-bit quantity at
-.Fa *num .
+argument and stores the number it represents as a signed 64-bit
+quantity in the location pointed to by its
+.Fa *num
+argument.
.Pp
The
-.Fn expand_number
-function
-is case-insensitive and
-follows the SI power of two convention.
+.Fn expand_unsigned
+function is similar to
+.Fn expand_number ,
+but accepts only positive numbers in the range
+.Bq 0, Ns Dv UINT64_MAX .
+.Pp
+Both functions interpret the input
+.Dq -0
+as 0.
+.Pp
+The input string must consist of a decimal number, optionally preceded
+by a
+.Sq +
+or
+.Sq -
+sign, and optionally followed, without intervening whitespace, by a
+suffix indicating a power-of-two multiplier to apply.
+Any amount of whitespace at the beginning of the string will be
+ignored.
.Pp
-The suffixes are:
+Recognized suffixes are:
.Bl -column "Suffix" "Description" "1000000000000000000" -offset indent
.It Sy "Suffix" Ta Sy "Description" Ta Sy "Multiplier"
-.It Li K Ta No kilo Ta 1024
-.It Li M Ta No mega Ta 1048576
-.It Li G Ta No giga Ta 1073741824
-.It Li T Ta No tera Ta 1099511627776
-.It Li P Ta No peta Ta 1125899906842624
-.It Li E Ta No exa Ta 1152921504606846976
+.It Li K Ta No kilo Ta 1,024
+.It Li M Ta No mega Ta 1,048,576
+.It Li G Ta No giga Ta 1,073,741,824
+.It Li T Ta No tera Ta 1,099,511,627,776
+.It Li P Ta No peta Ta 1,125,899,906,842,624
+.It Li E Ta No exa Ta 1,152,921,504,606,846,976
.El
.Pp
For historical reasons, the
@@ -68,21 +91,44 @@ function accepts and ignores a single
.Dq B
suffix at the end of the
.Fa buf
-string.
+string (i.e.
+.Dq 5b
+is interpreted as 5, and
+.Dq 5kb
+is interpreted as 5,120).
However, the usage of this suffix is discouraged.
+.Pp
+For backward compatibility reasons, if the compiler supports generic
+selection, a macro is provided which automatically replaces calls to
+.Fn expand_number
+with calls to
+.Fn expand_unsigned
+if the type of the actual
+.Va num
+argument is compatible with
+.Vt uint64_t * .
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
The
.Fn expand_number
-function will fail if:
+and
+.Fn expand_unsigned
+functions will fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
-The given string contains no digits.
+The given string does not contain a valid number.
.It Bq Er EINVAL
-An unrecognized suffix was given.
+An unrecognized suffix was encountered.
.It Bq Er ERANGE
-Result doesn't fit into 64 bits.
+The given string represents a number which does not fit into an
+.Vt int64_t
+(for
+.Fn expand_number )
+or
+.Vt uint64_t
+(for
+.Fn expand_unsigned ) .
.El
.Sh SEE ALSO
.Xr humanize_number 3
@@ -91,3 +137,17 @@ The
.Fn expand_number
function first appeared in
.Fx 6.3 .
+The original implementation did not handle negative numbers correctly,
+and it was switched to taking a
+.Vt uint64_t *
+and accepting only positive numbers in
+.Fx 9.0 .
+The
+.Fn expand_unsigned
+function was added,
+and
+.Fn expand_number
+switched back to
+.Vt int64_t * ,
+in
+.Fx 15.0 .
diff --git a/lib/libutil/expand_number.c b/lib/libutil/expand_number.c
index fc2ea8e8b17c..a3313ba39d98 100644
--- a/lib/libutil/expand_number.c
+++ b/lib/libutil/expand_number.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2007 Eric Anderson <anderson@FreeBSD.org>
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,79 +29,159 @@
*/
#include <sys/types.h>
+
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <libutil.h>
+#include <stdbool.h>
#include <stdint.h>
-int
-expand_number(const char *buf, uint64_t *num)
+static int
+expand_impl(const char *buf, uint64_t *num, bool *neg)
{
char *endptr;
- uintmax_t umaxval;
- uint64_t number;
- unsigned shift;
+ uintmax_t number;
+ unsigned int shift;
int serrno;
+ /*
+ * Skip whitespace and optional sign.
+ */
+ while (isspace((unsigned char)*buf))
+ buf++;
+ if (*buf == '-') {
+ *neg = true;
+ buf++;
+ } else {
+ *neg = false;
+ if (*buf == '+')
+ buf++;
+ }
+
+ /*
+ * The next character should be the first digit of the number. If
+ * we don't enforce this ourselves, strtoumax() will allow further
+ * whitespace and a (second?) sign.
+ */
+ if (!isdigit((unsigned char)*buf)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
serrno = errno;
errno = 0;
- umaxval = strtoumax(buf, &endptr, 0);
- if (umaxval > UINT64_MAX)
- errno = ERANGE;
+ number = strtoumax(buf, &endptr, 0);
if (errno != 0)
return (-1);
errno = serrno;
- number = umaxval;
switch (tolower((unsigned char)*endptr)) {
case 'e':
shift = 60;
+ endptr++;
break;
case 'p':
shift = 50;
+ endptr++;
break;
case 't':
shift = 40;
+ endptr++;
break;
case 'g':
shift = 30;
+ endptr++;
break;
case 'm':
shift = 20;
+ endptr++;
break;
case 'k':
shift = 10;
+ endptr++;
break;
- case 'b':
- shift = 0;
- break;
- case '\0': /* No unit. */
- *num = number;
- return (0);
default:
- /* Unrecognized unit. */
- errno = EINVAL;
- return (-1);
+ shift = 0;
}
/*
* Treat 'b' as an ignored suffix for all unit except 'b',
* otherwise there should be no remaining character(s).
*/
- endptr++;
- if (shift != 0 && tolower((unsigned char)*endptr) == 'b')
+ if (tolower((unsigned char)*endptr) == 'b')
endptr++;
if (*endptr != '\0') {
errno = EINVAL;
return (-1);
}
+ /*
+ * Apply the shift and check for overflow.
+ */
if ((number << shift) >> shift != number) {
/* Overflow */
errno = ERANGE;
return (-1);
}
- *num = number << shift;
+ number <<= shift;
+
+ *num = number;
+ return (0);
+}
+
+int
+(expand_number)(const char *buf, int64_t *num)
+{
+ uint64_t number;
+ bool neg;
+
+ /*
+ * Parse the number.
+ */
+ if (expand_impl(buf, &number, &neg) != 0)
+ return (-1);
+
+ /*
+ * Apply the sign and check for overflow.
+ */
+ if (neg) {
+ if (number > 0x8000000000000000LLU /* -INT64_MIN */) {
+ errno = ERANGE;
+ return (-1);
+ }
+ *num = -number;
+ } else {
+ if (number > INT64_MAX) {
+ errno = ERANGE;
+ return (-1);
+ }
+ *num = number;
+ }
+
+ return (0);
+}
+
+int
+expand_unsigned(const char *buf, uint64_t *num)
+{
+ uint64_t number;
+ bool neg;
+
+ /*
+ * Parse the number.
+ */
+ if (expand_impl(buf, &number, &neg) != 0)
+ return (-1);
+
+ /*
+ * Negative numbers are out of range.
+ */
+ if (neg && number > 0) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ *num = number;
return (0);
}
diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
index 919855184caf..9b5b2abe7f09 100644
--- a/lib/libutil/libutil.h
+++ b/lib/libutil/libutil.h
@@ -86,10 +86,17 @@ struct termios;
struct winsize;
__BEGIN_DECLS
-char *auth_getval(const char *_name);
void clean_environment(const char * const *_white,
const char * const *_more_white);
-int expand_number(const char *_buf, uint64_t *_num);
+int expand_number(const char *_buf, int64_t *_num);
+int expand_unsigned(const char *_buf, uint64_t *_num);
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
+ __has_extension(c_generic_selections)
+#define expand_number(_buf, _num) \
+ _Generic((_num), \
+ uint64_t *: expand_unsigned, \
+ default: expand_number)((_buf), (_num))
+#endif
int extattr_namespace_to_string(int _attrnamespace, char **_string);
int extattr_string_to_namespace(const char *_string, int *_attrnamespace);
int flopen(const char *_path, int _flags, ...);
@@ -213,7 +220,13 @@ int cpuset_parselist(const char *list, cpuset_t *mask);
#define CPUSET_PARSE_OK 0
#define CPUSET_PARSE_GETAFFINITY -1
#define CPUSET_PARSE_ERROR -2
-#define CPUSET_PARSE_INVALID_CPU -3
+#define CPUSET_PARSE_OUT_OF_RANGE -3
+#define CPUSET_PARSE_GETDOMAIN -4
+#define CPUSET_PARSE_INVALID_CPU CPUSET_PARSE_OUT_OF_RANGE /* backwards compat */
+#endif
+
+#ifdef _SYS_DOMAINSET_H_
+int domainset_parselist(const char *list, domainset_t *mask, int *policyp);
#endif
__END_DECLS
diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5
index d43fdfb761f3..942f3ecd2661 100644
--- a/lib/libutil/login.conf.5
+++ b/lib/libutil/login.conf.5
@@ -17,7 +17,7 @@
.\" 5. Modifications may be freely made to this file providing the above
.\" conditions are met.
.\"
-.Dd June 28, 2023
+.Dd September 25, 2025
.Dt LOGIN.CONF 5
.Os
.Sh NAME
@@ -380,14 +380,15 @@ If
is specified, then logins are only allowed during the periods given.
If
.Em times.deny
-is specified, then logins are denied during the periods given, regardless of whether
-one of the periods specified in
+is specified, then logins are denied during the periods given,
+regardless of whether one of the periods specified in
.Em times.allow
applies.
.Pp
Note that
.Xr login 1
-enforces only that the actual login falls within periods allowed by these entries.
+enforces only that the actual login falls within periods allowed by
+these entries.
Further enforcement over the life of a session requires a separate daemon to
monitor transitions from an allowed period to a non-allowed one.
.Pp
@@ -495,7 +496,7 @@ lists.
.Xr pam 3 ,
.Xr passwd 5 ,
.Xr ttys 5 ,
-.Xr ftpd 8 ,
+.Xr ftpd 8 Pq Pa ports/ftp/freebsd-ftpd ,
.Xr pam_passwdqc 8
.Sh HISTORY
The file
diff --git a/lib/libutil/login_auth.3 b/lib/libutil/login_auth.3
index fafe43b906e6..dd5ba3e01265 100644
--- a/lib/libutil/login_auth.3
+++ b/lib/libutil/login_auth.3
@@ -58,8 +58,8 @@
.\" .Ft int
.\" .Fn auth_timesok "login_cap_t *lc" "time_t now"
.Sh DESCRIPTION
-This set of functions support the login class authorisation style interface provided
-by
+This set of functions support the login class authorisation style
+interface provided by
.Xr login.conf 5 .
.\" .Sh RETURN VALUES
.Sh SEE ALSO
diff --git a/lib/libutil/login_cap.3 b/lib/libutil/login_cap.3
index 86142c3b19f9..48af0e3c9c46 100644
--- a/lib/libutil/login_cap.3
+++ b/lib/libutil/login_cap.3
@@ -31,6 +31,7 @@
.Nm login_getcaptime ,
.Nm login_getclass ,
.Nm login_getclassbyname ,
+.Nm login_getpath ,
.Nm login_getpwclass ,
.Nm login_getstyle ,
.Nm login_getuserclass ,
diff --git a/lib/libutil/mntopts.3 b/lib/libutil/mntopts.3
index 35f6d476fcec..28e5a02442c2 100644
--- a/lib/libutil/mntopts.3
+++ b/lib/libutil/mntopts.3
@@ -342,9 +342,9 @@ By default
.Va getmnt_silent
is zero.
.Sh SEE ALSO
+.Xr nmount 2 ,
.Xr err 3 ,
-.Xr mount 8 ,
-.Xr nmount 8
+.Xr mount 8
.Sh HISTORY
The
.Fn getmntopts
@@ -358,7 +358,7 @@ The
and
.Fn rmslashes
functions were added with
-.Xr nmount 8
+.Xr nmount 2
in
.Fx 5.0 .
The
@@ -368,7 +368,9 @@ and
functions were added in
.Fx 13.2 .
.Pp
-Historically, these functions were found in getmntopts.c in the sources for the
+Historically, these functions were found in
+.Pa getmntopts.c
+in the source code of the
.Xr mount 8
program.
As of
diff --git a/lib/libutil/mntopts.c b/lib/libutil/mntopts.c
index 1d9347e3108a..4a064a086fd5 100644
--- a/lib/libutil/mntopts.c
+++ b/lib/libutil/mntopts.c
@@ -145,6 +145,18 @@ checkpath_allow_file(const char *path, char *resolved)
return (0);
}
+static char *
+prependdevtopath(const char *path, char *buf, u_long buflen)
+{
+ u_long len;
+
+ if ((len = strlen(_PATH_DEV) + strlen(path) + 1) > buflen)
+ return NULL;
+ strncpy(buf, _PATH_DEV, len);
+ strncat(buf, path, len - sizeof(_PATH_DEV));
+ return (buf);
+}
+
/*
* Get the mount point information for name. Name may be mount point name
* or device name (with or without /dev/ preprended).
@@ -153,19 +165,27 @@ struct statfs *
getmntpoint(const char *name)
{
struct stat devstat, mntdevstat;
- char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
- char *ddevname;
+ char *devname;
struct statfs *mntbuf, *statfsp;
- int i, mntsize, isdev;
- u_long len;
+ int i, len, isdev, mntsize, mntfromnamesize;
+ char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
+ u_long devlen;
- if (stat(name, &devstat) != 0)
+ devlen = sizeof(device);
+ /*
+ * Note that stat(NULL, &statbuf) returns -1 (EBADF) which will
+ * cause us to return NULL if prependdevtopath() returns NULL.
+ */
+ if (stat(name, &devstat) != 0 &&
+ (name[0] != '/' &&
+ stat(prependdevtopath(name, device, devlen), &devstat) != 0))
return (NULL);
if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
isdev = 1;
else
isdev = 0;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+ mntfromnamesize = sizeof(statfsp->f_mntfromname);
for (i = 0; i < mntsize; i++) {
statfsp = &mntbuf[i];
if (isdev == 0) {
@@ -173,18 +193,20 @@ getmntpoint(const char *name)
continue;
return (statfsp);
}
- ddevname = statfsp->f_mntfromname;
- if (*ddevname != '/') {
- if ((len = strlen(_PATH_DEV) + strlen(ddevname) + 1) >
- sizeof(statfsp->f_mntfromname) ||
- len > sizeof(device))
+ devname = statfsp->f_mntfromname;
+ if (*devname == '/') {
+ if (stat(devname, &mntdevstat) != 0)
+ continue;
+ } else {
+ devname = prependdevtopath(devname, device, devlen);
+ if (devname == NULL ||
+ (len = strlen(devname)) > mntfromnamesize)
+ continue;
+ if (stat(devname, &mntdevstat) != 0)
continue;
- strncpy(device, _PATH_DEV, len);
- strncat(device, ddevname, len);
- if (stat(device, &mntdevstat) == 0)
- strncpy(statfsp->f_mntfromname, device, len);
+ strncpy(statfsp->f_mntfromname, devname, len);
}
- if (stat(ddevname, &mntdevstat) == 0 &&
+ if (S_ISCHR(mntdevstat.st_mode) &&
mntdevstat.st_rdev == devstat.st_rdev)
return (statfsp);
}
diff --git a/lib/libutil/pidfile.3 b/lib/libutil/pidfile.3
index c4786736d28f..d28d5ed8eccb 100644
--- a/lib/libutil/pidfile.3
+++ b/lib/libutil/pidfile.3
@@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 10, 2020
+.Dd August 2, 2025
.Dt PIDFILE 3
.Os
.Sh NAME
.Nm pidfile_open ,
.Nm pidfile_write ,
.Nm pidfile_close ,
-.Nm pidfile_remove
+.Nm pidfile_remove ,
+.Nm pidfile_fileno ,
+.Nm pidfile_signal
.Nd "library for PID files handling"
.Sh LIBRARY
.Lb libutil
@@ -45,6 +47,8 @@
.Fn pidfile_remove "struct pidfh *pfh"
.Ft int
.Fn pidfile_fileno "struct pidfh *pfh"
+.Ft int
+.Fn pidfile_signal "const char *path" "int sig" "pid_t *pidptr"
.Sh DESCRIPTION
The
.Nm pidfile
@@ -101,6 +105,26 @@ function closes and removes a pidfile.
The
.Fn pidfile_fileno
function returns the file descriptor for the open pidfile.
+.Pp
+The
+.Fn pidfile_signal
+function looks for the pidfile specified by
+.Va path ,
+and if it exists and is locked, sends the signal specified by
+.Va sig
+to the PID it contains.
+If
+.Va pidptr
+is not
+.Dv NULL ,
+the PID that was found in the pidfile is stored in the location it
+points to.
+Note that calling
+.Fn pidfile_signal
+with
+.Va sig
+set to zero is an effective way to verify the existence of a pidfile
+and of the process that owns it.
.Sh RETURN VALUES
The
.Fn pidfile_open
@@ -125,6 +149,13 @@ and sets
if a NULL
.Vt pidfh
is specified, or if the pidfile is no longer open.
+.Pp
+The
+.Fn pidfile_signal
+function returns 0 if it successfully signaled a process, and an
+appropriate
+.Va errno
+value otherwise.
.Sh EXAMPLES
The following example shows in which order these functions should be used.
Note that it is safe to pass
@@ -132,7 +163,7 @@ Note that it is safe to pass
to
.Fn pidfile_write ,
.Fn pidfile_remove ,
-.Fn pidfile_close
+.Fn pidfile_close ,
and
.Fn pidfile_fileno
functions.
@@ -280,7 +311,28 @@ Improper function use.
Probably called not from the process which used
.Fn pidfile_open .
.El
+.Pp
+The
+.Fn pidfile_signal
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er ENOENT
+The pidfile does not exist, or exists but is not locked.
+.It Bq Er EDOM
+The pidfile contains a negative number.
+.El
+.Pp
+The
+.Fn pidfile_signal
+function may also fail and return any of the
+.Va errno
+values specified for the
+.Fn pidfile_read
+function and the
+.Xr kill 2
+system call.
.Sh SEE ALSO
+.Xr kill 2 ,
.Xr open 2 ,
.Xr daemon 3 ,
.Xr flopen 3
@@ -288,11 +340,19 @@ Probably called not from the process which used
The functions
.Fn pidfile_open ,
.Fn pidfile_write ,
-.Fn pidfile_close
+.Fn pidfile_close ,
and
.Fn pidfile_remove
first appeared in
.Fx 5.5 .
+The
+.Fn pidfile_fileno
+function was added in
+.Fx 9.1 .
+The
+.Fn pidfile_signal
+function was added in
+.Fx 14.0 .
.Sh AUTHORS
.An -nosplit
The
diff --git a/lib/libutil/pw_util.3 b/lib/libutil/pw_util.3
index ed05818cd16a..a6bb71600441 100644
--- a/lib/libutil/pw_util.3
+++ b/lib/libutil/pw_util.3
@@ -31,6 +31,7 @@
.Nm pw_edit ,
.Nm pw_equal ,
.Nm pw_fini ,
+.Nm pw_initpwd ,
.Nm pw_init ,
.Nm pw_make ,
.Nm pw_make_v7 ,
diff --git a/lib/libutil/tests/expand_number_test.c b/lib/libutil/tests/expand_number_test.c
index 6bf3ff082ee4..9bd339298575 100644
--- a/lib/libutil/tests/expand_number_test.c
+++ b/lib/libutil/tests/expand_number_test.c
@@ -1,7 +1,8 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2023 Google LLC
+ * Copyright (c) 2019 John Baldwin <jhb@FreeBSD.org>
+ * Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,60 +26,269 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
+#include <atf-c.h>
#include <errno.h>
#include <libutil.h>
+#include <stdint.h>
-#include <atf-c.h>
+static void
+require_success(const char *str, int64_t exp_val)
+{
+ int64_t val;
+
+ ATF_REQUIRE_MSG(expand_number(str, &val) == 0,
+ "Failed to parse '%s': %m", str);
+ ATF_REQUIRE_MSG(val == exp_val,
+ "String '%s' parsed as %jd instead of expected %jd", str,
+ (intmax_t)val, (intmax_t)exp_val);
+}
-ATF_TC_WITHOUT_HEAD(positivetests);
-ATF_TC_BODY(positivetests, tc)
+static void
+require_error(const char *str, int exp_errno)
{
- int retval;
- uint64_t num;
+ int64_t val;
+
+ ATF_REQUIRE_MSG(expand_number(str, &val) == -1,
+ "String '%s' parsed as %jd instead of error", str, (intmax_t)val);
+ ATF_REQUIRE_MSG(errno == exp_errno,
+ "String '%s' failed with %d instead of expected %d", str, errno,
+ exp_errno);
+}
+
+ATF_TC_WITHOUT_HEAD(expand_number__ok);
+ATF_TC_BODY(expand_number__ok, tp)
+{
+ /* Bare numbers. */
+ require_success("-0", 0);
+ require_success(" 0", 0);
+ require_success("+0", 0);
+ require_success("-1", -1);
+ require_success(" 1", 1);
+ require_success("+1", 1);
+ require_success("-10", -10);
+ require_success(" 10", 10);
+ require_success("+10", 10);
+
+ /* Uppercase suffixes. */
+ require_success("1B", 1);
+ require_success("1K", 1LL << 10);
+ require_success("1M", 1LL << 20);
+ require_success("1G", 1LL << 30);
+ require_success("1T", 1LL << 40);
+ require_success("1P", 1LL << 50);
+ require_success("1E", 1LL << 60);
+
+ /* Lowercase suffixes. */
+ require_success("2b", 2);
+ require_success("2k", 2LL << 10);
+ require_success("2m", 2LL << 20);
+ require_success("2g", 2LL << 30);
+ require_success("2t", 2LL << 40);
+ require_success("2p", 2LL << 50);
+ require_success("2e", 2LL << 60);
+
+ /* Suffixes with a trailing 'b'. */
+ require_success("3KB", 3LL << 10);
+ require_success("3MB", 3LL << 20);
+ require_success("3GB", 3LL << 30);
+ require_success("3TB", 3LL << 40);
+ require_success("3PB", 3LL << 50);
+ require_success("3EB", 3LL << 60);
+
+ /* Negative numbers. */
+ require_success("-1", -1);
+ require_success("-10", -10);
+ require_success("-1B", -1);
+ require_success("-1K", -(1LL << 10));
+ require_success("-1M", -(1LL << 20));
+ require_success("-1G", -(1LL << 30));
+ require_success("-1T", -(1LL << 40));
+ require_success("-1P", -(1LL << 50));
+ require_success("-1E", -(1LL << 60));
+ require_success("-2b", -2);
+ require_success("-2k", -(2LL << 10));
+ require_success("-2m", -(2LL << 20));
+ require_success("-2g", -(2LL << 30));
+ require_success("-2t", -(2LL << 40));
+ require_success("-2p", -(2LL << 50));
+ require_success("-2e", -(2LL << 60));
+ require_success("-3KB", -(3LL << 10));
+ require_success("-3MB", -(3LL << 20));
+ require_success("-3GB", -(3LL << 30));
+ require_success("-3TB", -(3LL << 40));
+ require_success("-3PB", -(3LL << 50));
+ require_success("-3EB", -(3LL << 60));
+
+ /* Maximum values. */
+ require_success("7E", 7LL << 60);
+ require_success("8191P", 8191LL << 50);
+ require_success("8388607T", 8388607LL << 40);
+ require_success("8589934591G", 8589934591LL << 30);
+ require_success("8796093022207M", 8796093022207LL << 20);
+ require_success("9007199254740991K", 9007199254740991LL << 10);
+ require_success("9223372036854775807", INT64_MAX);
+
+ /* Minimum values. */
+ require_success("-7E", -(7LL << 60));
+ require_success("-8191P", -(8191LL << 50));
+ require_success("-8388607T", -(8388607LL << 40));
+ require_success("-8589934591G", -(8589934591LL << 30));
+ require_success("-8796093022207M", -(8796093022207LL << 20));
+ require_success("-9007199254740991K", -(9007199254740991LL << 10));
+ require_success("-9223372036854775808", INT64_MIN);
+}
+
+ATF_TC_WITHOUT_HEAD(expand_number__bad);
+ATF_TC_BODY(expand_number__bad, tp)
+{
+ /* No digits. */
+ require_error("", EINVAL);
+ require_error("b", EINVAL);
+ require_error("k", EINVAL);
+ require_error("m", EINVAL);
+ require_error("g", EINVAL);
+ require_error("t", EINVAL);
+ require_error("p", EINVAL);
+ require_error("e", EINVAL);
+ require_error("-", EINVAL);
+ require_error("-b", EINVAL);
+ require_error("-k", EINVAL);
+ require_error("-m", EINVAL);
+ require_error("-g", EINVAL);
+ require_error("-t", EINVAL);
+ require_error("-p", EINVAL);
+ require_error("-e", EINVAL);
+
+ require_error("not_a_number", EINVAL);
+
+ /* Invalid suffixes. */
+ require_error("1a", EINVAL);
+ require_error("1c", EINVAL);
+ require_error("1d", EINVAL);
+ require_error("1f", EINVAL);
+ require_error("1h", EINVAL);
+ require_error("1i", EINVAL);
+ require_error("1j", EINVAL);
+ require_error("1l", EINVAL);
+ require_error("1n", EINVAL);
+ require_error("1o", EINVAL);
+ require_error("1q", EINVAL);
+ require_error("1r", EINVAL);
+ require_error("1s", EINVAL);
+ require_error("1u", EINVAL);
+ require_error("1v", EINVAL);
+ require_error("1w", EINVAL);
+ require_error("1x", EINVAL);
+ require_error("1y", EINVAL);
+ require_error("1z", EINVAL);
+
+ /* Trailing garbage. */
+ require_error("1K foo", EINVAL);
+ require_error("1Mfoo", EINVAL);
+
+ /* Overflow. */
+ require_error("8E", ERANGE);
+ require_error("8192P", ERANGE);
+ require_error("8388608T", ERANGE);
+ require_error("8589934592G", ERANGE);
+ require_error("8796093022208M", ERANGE);
+ require_error("9007199254740992K", ERANGE);
+ require_error("9223372036854775808", ERANGE);
+
+ /* Multiple signs */
+ require_error("--1", EINVAL);
+ require_error("-+1", EINVAL);
+ require_error("+-1", EINVAL);
+ require_error("++1", EINVAL);
-#define positive_tc(string, value) \
- do { \
- ATF_CHECK_ERRNO(0, (retval = expand_number((string), &num)) == 0); \
- ATF_CHECK_EQ(retval, 0); \
- ATF_CHECK_EQ(num, (value)); \
- } while (0)
-
- positive_tc("123456", 123456);
- positive_tc("123456b", 123456);
- positive_tc("1k", 1024);
- positive_tc("1kb", 1024);
- positive_tc("1K", 1024);
- positive_tc("1KB", 1024);
- positive_tc("1m", 1048576);
- positive_tc("1M", 1048576);
- positive_tc("1g", 1073741824);
- positive_tc("1G", 1073741824);
- positive_tc("1t", 1099511627776);
- positive_tc("1T", 1099511627776);
- positive_tc("1p", 1125899906842624);
- positive_tc("1P", 1125899906842624);
- positive_tc("1e", 1152921504606846976);
- positive_tc("1E", 1152921504606846976);
- positive_tc("15E", 17293822569102704640ULL);
+ /* Whitespace after the sign */
+ require_error(" - 1", EINVAL);
+ require_error(" + 1", EINVAL);
}
-ATF_TC_WITHOUT_HEAD(negativetests);
-ATF_TC_BODY(negativetests, tc)
+ATF_TC_WITHOUT_HEAD(expand_unsigned);
+ATF_TC_BODY(expand_unsigned, tp)
{
+ static struct tc {
+ const char *str;
+ uint64_t num;
+ int error;
+ } tcs[] = {
+ { "0", 0, 0 },
+ { "+0", 0, 0 },
+ { "-0", 0, 0 },
+ { "1", 1, 0 },
+ { "+1", 1, 0 },
+ { "-1", 0, ERANGE },
+ { "18446744073709551615", UINT64_MAX, 0 },
+ { "+18446744073709551615", UINT64_MAX, 0 },
+ { "-18446744073709551615", 0, ERANGE },
+ { 0 },
+ };
+ struct tc *tc;
uint64_t num;
+ int error, ret;
- ATF_CHECK_ERRNO(EINVAL, expand_number("", &num));
- ATF_CHECK_ERRNO(EINVAL, expand_number("x", &num));
- ATF_CHECK_ERRNO(EINVAL, expand_number("1bb", &num));
- ATF_CHECK_ERRNO(EINVAL, expand_number("1x", &num));
- ATF_CHECK_ERRNO(EINVAL, expand_number("1kx", &num));
- ATF_CHECK_ERRNO(ERANGE, expand_number("16E", &num));
+ for (tc = tcs; tc->str != NULL; tc++) {
+ ret = expand_number(tc->str, &num);
+ error = errno;
+ if (tc->error == 0) {
+ ATF_REQUIRE_EQ_MSG(0, ret,
+ "%s ret = %d", tc->str, ret);
+ ATF_REQUIRE_EQ_MSG(tc->num, num,
+ "%s num = %ju", tc->str, (uintmax_t)num);
+ } else {
+ ATF_REQUIRE_EQ_MSG(-1, ret,
+ "%s ret = %d", tc->str, ret);
+ ATF_REQUIRE_EQ_MSG(tc->error, error,
+ "%s errno = %d", tc->str, error);
+ }
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(expand_generic);
+ATF_TC_BODY(expand_generic, tp)
+{
+ uint64_t uint64;
+ int64_t int64;
+#ifdef __LP64__
+ size_t size;
+#endif
+ off_t off;
+
+ ATF_REQUIRE_EQ(0, expand_number("18446744073709551615", &uint64));
+ ATF_REQUIRE_EQ(UINT64_MAX, uint64);
+ ATF_REQUIRE_EQ(-1, expand_number("-1", &uint64));
+ ATF_REQUIRE_EQ(ERANGE, errno);
+
+ ATF_REQUIRE_EQ(0, expand_number("9223372036854775807", &int64));
+ ATF_REQUIRE_EQ(INT64_MAX, int64);
+ ATF_REQUIRE_EQ(-1, expand_number("9223372036854775808", &int64));
+ ATF_REQUIRE_EQ(ERANGE, errno);
+ ATF_REQUIRE_EQ(0, expand_number("-9223372036854775808", &int64));
+ ATF_REQUIRE_EQ(INT64_MIN, int64);
+
+#ifdef __LP64__
+ ATF_REQUIRE_EQ(0, expand_number("18446744073709551615", &size));
+ ATF_REQUIRE_EQ(UINT64_MAX, size);
+ ATF_REQUIRE_EQ(-1, expand_number("-1", &size));
+ ATF_REQUIRE_EQ(ERANGE, errno);
+#endif
+
+ ATF_REQUIRE_EQ(0, expand_number("9223372036854775807", &off));
+ ATF_REQUIRE_EQ(INT64_MAX, off);
+ ATF_REQUIRE_EQ(-1, expand_number("9223372036854775808", &off));
+ ATF_REQUIRE_EQ(ERANGE, errno);
+ ATF_REQUIRE_EQ(0, expand_number("-9223372036854775808", &off));
+ ATF_REQUIRE_EQ(INT64_MIN, off);
}
ATF_TP_ADD_TCS(tp)
{
- ATF_TP_ADD_TC(tp, positivetests);
- ATF_TP_ADD_TC(tp, negativetests);
+ ATF_TP_ADD_TC(tp, expand_number__ok);
+ ATF_TP_ADD_TC(tp, expand_number__bad);
+ ATF_TP_ADD_TC(tp, expand_unsigned);
+ ATF_TP_ADD_TC(tp, expand_generic);
+
return (atf_no_error());
}
diff --git a/lib/libutil/uucplock.3 b/lib/libutil/uucplock.3
index dd19d0311b4e..ee8c9f6bb995 100644
--- a/lib/libutil/uucplock.3
+++ b/lib/libutil/uucplock.3
@@ -28,6 +28,7 @@
.Os
.Sh NAME
.Nm uu_lock ,
+.Nm uu_lock_txfr ,
.Nm uu_unlock ,
.Nm uu_lockerr
.Nd acquire and release control of a serial device
diff --git a/lib/libvmmapi/Makefile b/lib/libvmmapi/Makefile
index 1866c8fa5e7c..6dd0deeaa9c0 100644
--- a/lib/libvmmapi/Makefile
+++ b/lib/libvmmapi/Makefile
@@ -1,6 +1,6 @@
PACKAGE=lib${LIB}
LIB= vmmapi
-SHLIB_MAJOR= 6
+SHLIB_MAJOR= 7
SRCS= vmmapi.c
INCS= vmmapi.h
diff --git a/lib/libvmmapi/internal.h b/lib/libvmmapi/internal.h
index aa7b1d8e6a93..4afe1cab3460 100644
--- a/lib/libvmmapi/internal.h
+++ b/lib/libvmmapi/internal.h
@@ -8,12 +8,7 @@
#define __VMMAPI_INTERNAL_H__
#include <sys/types.h>
-
-enum {
- VM_MEMSEG_LOW,
- VM_MEMSEG_HIGH,
- VM_MEMSEG_COUNT,
-};
+#include <dev/vmm/vmm_mem.h>
struct vmctx {
int fd; /* device file descriptor */
@@ -21,7 +16,9 @@ struct vmctx {
struct {
vm_paddr_t base;
vm_size_t size;
- } memsegs[VM_MEMSEG_COUNT];
+ } memsegs[VM_MAX_MEMSEGS];
+ size_t lowmem_size;
+ size_t highmem_size;
int memflags;
char *baseaddr;
char *name;
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
index a1a5d56ff8a2..77f0f8f5c581 100644
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -28,13 +28,14 @@
#include <sys/param.h>
#include <sys/capsicum.h>
+#include <sys/cpuset.h>
+#include <sys/domainset.h>
#include <sys/sysctl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/linker.h>
#include <sys/module.h>
#include <sys/_iovec.h>
-#include <sys/cpuset.h>
#include <capsicum_helpers.h>
#include <err.h>
@@ -322,8 +323,8 @@ vm_get_guestmem_from_ctx(struct vmctx *ctx, char **guest_baseaddr,
{
*guest_baseaddr = ctx->baseaddr;
- *lowmem_size = ctx->memsegs[VM_MEMSEG_LOW].size;
- *highmem_size = ctx->memsegs[VM_MEMSEG_HIGH].size;
+ *lowmem_size = ctx->lowmem_size;
+ *highmem_size = ctx->highmem_size;
return (0);
}
@@ -379,7 +380,8 @@ cmpseg(size_t len, const char *str, size_t len2, const char *str2)
}
static int
-vm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name)
+vm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name,
+ int ds_policy, domainset_t *ds_mask, size_t ds_size)
{
struct vm_memseg memseg;
size_t n;
@@ -407,6 +409,13 @@ vm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name)
bzero(&memseg, sizeof(struct vm_memseg));
memseg.segid = segid;
memseg.len = len;
+ if (ds_mask == NULL) {
+ memseg.ds_policy = DOMAINSET_POLICY_INVALID;
+ } else {
+ memseg.ds_policy = ds_policy;
+ memseg.ds_mask = ds_mask;
+ memseg.ds_mask_size = ds_size;
+ }
if (name != NULL) {
n = strlcpy(memseg.name, name, sizeof(memseg.name));
if (n >= sizeof(memseg.name)) {
@@ -442,13 +451,14 @@ vm_get_memseg(struct vmctx *ctx, int segid, size_t *lenp, char *namebuf,
}
static int
-setup_memory_segment(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char *base)
+map_memory_segment(struct vmctx *ctx, int segid, vm_paddr_t gpa, size_t len,
+ size_t segoff, char *base)
{
char *ptr;
int error, flags;
/* Map 'len' bytes starting at 'gpa' in the guest address space */
- error = vm_mmap_memseg(ctx, gpa, VM_SYSMEM, gpa, len, PROT_ALL);
+ error = vm_mmap_memseg(ctx, gpa, segid, segoff, len, PROT_ALL);
if (error)
return (error);
@@ -464,65 +474,136 @@ setup_memory_segment(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char *base)
return (0);
}
+/*
+ * Allocates and maps virtual machine memory segments according
+ * to the NUMA topology specified by the 'doms' array.
+ *
+ * The domains are laid out sequentially in the guest's physical address space.
+ * The [VM_LOWMEM_LIMIT, VM_HIGHMEM_BASE) address range is skipped and
+ * left unmapped.
+ */
int
-vm_setup_memory(struct vmctx *ctx, size_t memsize, enum vm_mmap_style vms)
+vm_setup_memory_domains(struct vmctx *ctx, enum vm_mmap_style vms,
+ struct vm_mem_domain *doms, int ndoms)
{
- size_t objsize, len;
- vm_paddr_t gpa;
+ size_t low_len, len, totalsize;
+ struct vm_mem_domain *dom;
+ struct vm_memseg memseg;
char *baseaddr, *ptr;
- int error;
+ int error, i, segid;
+ vm_paddr_t gpa;
+ /* Sanity checks. */
assert(vms == VM_MMAP_ALL);
-
- /*
- * If 'memsize' cannot fit entirely in the 'lowmem' segment then create
- * another 'highmem' segment above VM_HIGHMEM_BASE for the remainder.
- */
- if (memsize > VM_LOWMEM_LIMIT) {
- ctx->memsegs[VM_MEMSEG_LOW].size = VM_LOWMEM_LIMIT;
- ctx->memsegs[VM_MEMSEG_HIGH].size = memsize - VM_LOWMEM_LIMIT;
- objsize = VM_HIGHMEM_BASE + ctx->memsegs[VM_MEMSEG_HIGH].size;
- } else {
- ctx->memsegs[VM_MEMSEG_LOW].size = memsize;
- ctx->memsegs[VM_MEMSEG_HIGH].size = 0;
- objsize = memsize;
+ if (doms == NULL || ndoms <= 0 || ndoms > VM_MAXMEMDOM) {
+ errno = EINVAL;
+ return (-1);
}
- error = vm_alloc_memseg(ctx, VM_SYSMEM, objsize, NULL);
- if (error)
- return (error);
+ /* Calculate total memory size. */
+ totalsize = 0;
+ for (i = 0; i < ndoms; i++)
+ totalsize += doms[i].size;
+
+ if (totalsize > VM_LOWMEM_LIMIT)
+ totalsize = VM_HIGHMEM_BASE + (totalsize - VM_LOWMEM_LIMIT);
/*
* Stake out a contiguous region covering the guest physical memory
* and the adjoining guard regions.
*/
- len = VM_MMAP_GUARD_SIZE + objsize + VM_MMAP_GUARD_SIZE;
+ len = VM_MMAP_GUARD_SIZE + totalsize + VM_MMAP_GUARD_SIZE;
ptr = mmap(NULL, len, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1, 0);
if (ptr == MAP_FAILED)
return (-1);
-
baseaddr = ptr + VM_MMAP_GUARD_SIZE;
- if (ctx->memsegs[VM_MEMSEG_HIGH].size > 0) {
- gpa = VM_HIGHMEM_BASE;
- len = ctx->memsegs[VM_MEMSEG_HIGH].size;
- error = setup_memory_segment(ctx, gpa, len, baseaddr);
- if (error)
- return (error);
- }
- if (ctx->memsegs[VM_MEMSEG_LOW].size > 0) {
- gpa = 0;
- len = ctx->memsegs[VM_MEMSEG_LOW].size;
- error = setup_memory_segment(ctx, gpa, len, baseaddr);
- if (error)
- return (error);
- }
+ /*
+ * Allocate and map memory segments for the virtual machine.
+ */
+ gpa = VM_LOWMEM_LIMIT > 0 ? 0 : VM_HIGHMEM_BASE;
+ ctx->lowmem_size = 0;
+ ctx->highmem_size = 0;
+ for (i = 0; i < ndoms; i++) {
+ segid = VM_SYSMEM + i;
+ dom = &doms[i];
+
+ /*
+ * Check if the memory segment already exists.
+ * If 'ndoms' is greater than one, refuse to proceed if the
+ * memseg already exists. If only one domain was requested, use
+ * the existing segment to preserve the behaviour of the previous
+ * implementation.
+ *
+ * Splitting existing memory segments is tedious and
+ * error-prone, which is why we don't support NUMA
+ * domains for bhyveload(8)-loaded VMs.
+ */
+ error = vm_get_memseg(ctx, segid, &len, memseg.name,
+ sizeof(memseg.name));
+ if (error == 0 && len != 0) {
+ if (ndoms != 1) {
+ errno = EEXIST;
+ return (-1);
+ } else
+ doms[0].size = len;
+ } else {
+ error = vm_alloc_memseg(ctx, segid, dom->size, NULL,
+ dom->ds_policy, dom->ds_mask, dom->ds_size);
+ if (error)
+ return (error);
+ }
+ /*
+ * If a domain is split by VM_LOWMEM_LIMIT then break
+ * its segment mapping into two parts, one below VM_LOWMEM_LIMIT
+ * and one above VM_HIGHMEM_BASE.
+ */
+ if (gpa <= VM_LOWMEM_LIMIT &&
+ gpa + dom->size > VM_LOWMEM_LIMIT) {
+ low_len = VM_LOWMEM_LIMIT - gpa;
+ error = map_memory_segment(ctx, segid, gpa, low_len, 0,
+ baseaddr);
+ if (error)
+ return (error);
+ ctx->lowmem_size = VM_LOWMEM_LIMIT;
+ /* Map the remainder. */
+ gpa = VM_HIGHMEM_BASE;
+ len = dom->size - low_len;
+ error = map_memory_segment(ctx, segid, gpa, len,
+ low_len, baseaddr);
+ if (error)
+ return (error);
+ } else {
+ len = dom->size;
+ error = map_memory_segment(ctx, segid, gpa, len, 0,
+ baseaddr);
+ if (error)
+ return (error);
+ }
+ if (gpa <= VM_LOWMEM_LIMIT)
+ ctx->lowmem_size += len;
+ else
+ ctx->highmem_size += len;
+ gpa += len;
+ }
ctx->baseaddr = baseaddr;
return (0);
}
+int
+vm_setup_memory(struct vmctx *ctx, size_t memsize, enum vm_mmap_style vms)
+{
+ struct vm_mem_domain dom0;
+
+ memset(&dom0, 0, sizeof(dom0));
+ dom0.ds_policy = DOMAINSET_POLICY_INVALID;
+ dom0.size = memsize;
+
+ return (vm_setup_memory_domains(ctx, vms, &dom0, 1));
+}
+
/*
* Returns a non-NULL pointer if [gaddr, gaddr+len) is entirely contained in
* the lowmem or highmem regions.
@@ -535,13 +616,13 @@ vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
{
vm_size_t lowsize, highsize;
- lowsize = ctx->memsegs[VM_MEMSEG_LOW].size;
+ lowsize = ctx->lowmem_size;
if (lowsize > 0) {
if (gaddr < lowsize && len <= lowsize && gaddr + len <= lowsize)
return (ctx->baseaddr + gaddr);
}
- highsize = ctx->memsegs[VM_MEMSEG_HIGH].size;
+ highsize = ctx->highmem_size;
if (highsize > 0 && gaddr >= VM_HIGHMEM_BASE) {
if (gaddr < VM_HIGHMEM_BASE + highsize && len <= highsize &&
gaddr + len <= VM_HIGHMEM_BASE + highsize)
@@ -559,12 +640,12 @@ vm_rev_map_gpa(struct vmctx *ctx, void *addr)
offaddr = (char *)addr - ctx->baseaddr;
- lowsize = ctx->memsegs[VM_MEMSEG_LOW].size;
+ lowsize = ctx->lowmem_size;
if (lowsize > 0)
if (offaddr <= lowsize)
return (offaddr);
- highsize = ctx->memsegs[VM_MEMSEG_HIGH].size;
+ highsize = ctx->highmem_size;
if (highsize > 0)
if (offaddr >= VM_HIGHMEM_BASE &&
offaddr < VM_HIGHMEM_BASE + highsize)
@@ -583,8 +664,7 @@ vm_get_name(struct vmctx *ctx)
size_t
vm_get_lowmem_size(struct vmctx *ctx)
{
-
- return (ctx->memsegs[VM_MEMSEG_LOW].size);
+ return (ctx->lowmem_size);
}
vm_paddr_t
@@ -597,8 +677,7 @@ vm_get_highmem_base(struct vmctx *ctx __unused)
size_t
vm_get_highmem_size(struct vmctx *ctx)
{
-
- return (ctx->memsegs[VM_MEMSEG_HIGH].size);
+ return (ctx->highmem_size);
}
void *
@@ -616,7 +695,7 @@ vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len)
goto done;
}
- error = vm_alloc_memseg(ctx, segid, len, name);
+ error = vm_alloc_memseg(ctx, segid, len, name, 0, NULL, 0);
if (error)
goto done;
diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
index 440064ad13cb..b637c45d1eff 100644
--- a/lib/libvmmapi/vmmapi.h
+++ b/lib/libvmmapi/vmmapi.h
@@ -40,7 +40,7 @@
* API version for out-of-tree consumers like grub-bhyve for making compile
* time decisions.
*/
-#define VMMAPI_VERSION 0200 /* 2 digit major followed by 2 digit minor */
+#define VMMAPI_VERSION 0300 /* 2 digit major followed by 2 digit minor */
struct iovec;
struct vcpu;
@@ -64,16 +64,12 @@ enum vm_mmap_style {
#define VM_MEM_F_INCORE 0x01 /* include guest memory in core file */
#define VM_MEM_F_WIRED 0x02 /* guest memory is wired */
-/*
- * Identifiers for memory segments:
- * - vm_setup_memory() uses VM_SYSMEM for the system memory segment.
- * - the remaining identifiers can be used to create devmem segments.
- */
-enum {
- VM_SYSMEM,
- VM_BOOTROM,
- VM_FRAMEBUFFER,
- VM_PCIROM,
+/* Memory size and allocation policy for a single NUMA domain. */
+struct vm_mem_domain {
+ size_t size;
+ int ds_policy;
+ domainset_t *ds_mask;
+ size_t ds_size;
};
__BEGIN_DECLS
@@ -127,7 +123,9 @@ struct vcpu *vm_vcpu_open(struct vmctx *ctx, int vcpuid);
void vm_vcpu_close(struct vcpu *vcpu);
int vcpu_id(struct vcpu *vcpu);
int vm_parse_memsize(const char *optarg, size_t *memsize);
-int vm_setup_memory(struct vmctx *ctx, size_t len, enum vm_mmap_style s);
+int vm_setup_memory(struct vmctx *ctx, size_t len, enum vm_mmap_style s);
+int vm_setup_memory_domains(struct vmctx *ctx, enum vm_mmap_style s,
+ struct vm_mem_domain *doms, int ndoms);
void *vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len);
/* inverse operation to vm_map_gpa - extract guest address from host pointer */
vm_paddr_t vm_rev_map_gpa(struct vmctx *ctx, void *addr);
diff --git a/lib/libxo/tests/encoder/Makefile b/lib/libxo/tests/encoder/Makefile
index 7522328b0818..02634b971ace 100644
--- a/lib/libxo/tests/encoder/Makefile
+++ b/lib/libxo/tests/encoder/Makefile
@@ -1,4 +1,5 @@
PACKAGE= tests
+NO_DEV_PACKAGE=
LIBXOSRC= ${SRCTOP}/contrib/libxo
diff --git a/lib/liby/Makefile b/lib/liby/Makefile
index 93f72ee440f8..ace8f8457d22 100644
--- a/lib/liby/Makefile
+++ b/lib/liby/Makefile
@@ -1,4 +1,4 @@
-PACKAGE=lib${LIB}
+PACKAGE=toolchain
LIB= y
SRCS= main.c yyerror.c
NO_PIC=
diff --git a/lib/msun/bsdsrc/b_tgamma.c b/lib/msun/bsdsrc/b_tgamma.c
index 8369477c18b7..a7e97bc777c3 100644
--- a/lib/msun/bsdsrc/b_tgamma.c
+++ b/lib/msun/bsdsrc/b_tgamma.c
@@ -259,7 +259,7 @@ small_gam(double x)
static double
smaller_gam(double x)
{
- double d, rhi, rlo, t, xhi, xlo;
+ double d, t, xhi, xlo;
struct Double r;
if (x < x0 + left) {
diff --git a/lib/msun/src/e_fmod.c b/lib/msun/src/e_fmod.c
index 77afd116c658..ced9cce33aa0 100644
--- a/lib/msun/src/e_fmod.c
+++ b/lib/msun/src/e_fmod.c
@@ -26,14 +26,14 @@ static const double one = 1.0, Zero[] = {0.0, -0.0,};
double
fmod(double x, double y)
{
- int32_t n,hx,hy,hz,ix,iy,sx,i;
- u_int32_t lx,ly,lz;
+ int32_t hx, hy, hz, ix, iy, n, sx;
+ u_int32_t lx, ly, lz;
EXTRACT_WORDS(hx,lx,x);
EXTRACT_WORDS(hy,ly,y);
sx = hx&0x80000000; /* sign of x */
- hx ^=sx; /* |x| */
- hy &= 0x7fffffff; /* |y| */
+ hx ^= sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
/* purge off exception values */
if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */
@@ -46,22 +46,16 @@ fmod(double x, double y)
}
/* determine ix = ilogb(x) */
- if(hx<0x00100000) { /* subnormal x */
- if(hx==0) {
- for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
- } else {
- for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
- }
- } else ix = (hx>>20)-1023;
+ if(hx<0x00100000)
+ ix = subnormal_ilogb(hx, lx);
+ else
+ ix = (hx>>20)-1023;
/* determine iy = ilogb(y) */
- if(hy<0x00100000) { /* subnormal y */
- if(hy==0) {
- for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
- } else {
- for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
- }
- } else iy = (hy>>20)-1023;
+ if(hy<0x00100000)
+ iy = subnormal_ilogb(hy, ly);
+ else
+ iy = (hy>>20)-1023;
/* set up {hx,lx}, {hy,ly} and align y to x */
if(ix >= -1022)
diff --git a/lib/msun/src/e_fmodf.c b/lib/msun/src/e_fmodf.c
index a7d1a0c22acd..ada969db44c7 100644
--- a/lib/msun/src/e_fmodf.c
+++ b/lib/msun/src/e_fmodf.c
@@ -27,7 +27,7 @@ static const float one = 1.0, Zero[] = {0.0, -0.0,};
float
fmodf(float x, float y)
{
- int32_t n,hx,hy,hz,ix,iy,sx,i;
+ int32_t hx, hy, hz, ix, iy, n, sx;
GET_FLOAT_WORD(hx,x);
GET_FLOAT_WORD(hy,y);
@@ -44,14 +44,16 @@ fmodf(float x, float y)
return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/
/* determine ix = ilogb(x) */
- if(hx<0x00800000) { /* subnormal x */
- for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
- } else ix = (hx>>23)-127;
+ if(hx<0x00800000)
+ ix = subnormal_ilogbf(hx);
+ else
+ ix = (hx>>23)-127;
/* determine iy = ilogb(y) */
- if(hy<0x00800000) { /* subnormal y */
- for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
- } else iy = (hy>>23)-127;
+ if(hy<0x00800000)
+ iy = subnormal_ilogbf(hy);
+ else
+ iy = (hy>>23)-127;
/* set up {hx,lx}, {hy,ly} and align y to x */
if(ix >= -126)
diff --git a/lib/msun/src/e_remainder.c b/lib/msun/src/e_remainder.c
index a5fb7141d01a..cc6cd320073e 100644
--- a/lib/msun/src/e_remainder.c
+++ b/lib/msun/src/e_remainder.c
@@ -64,8 +64,8 @@ remainder(double x, double p)
if(x>=p_half) x -= p;
}
}
- GET_HIGH_WORD(hx,x);
- if ((hx&0x7fffffff)==0) hx = 0;
+ EXTRACT_WORDS(hx, lx, x);
+ if (((hx&0x7fffffff)|lx) == 0) hx = 0;
SET_HIGH_WORD(x,hx^sx);
return x;
}
diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h
index 1595f902846c..fbd84e246ca7 100644
--- a/lib/msun/src/math_private.h
+++ b/lib/msun/src/math_private.h
@@ -739,6 +739,41 @@ irintl(long double x)
(ar) = (x) - (ai); \
} while (0)
+/*
+ * For a subnormal double entity split into high and low parts, compute ilogb.
+ */
+static inline int32_t
+subnormal_ilogb(int32_t hi, int32_t lo)
+{
+ int32_t j;
+ uint32_t i;
+
+ j = -1022;
+ if (hi == 0) {
+ j -= 21;
+ i = (uint32_t)lo;
+ } else
+ i = (uint32_t)hi << 11;
+
+ for (; i < 0x7fffffff; i <<= 1) j -= 1;
+
+ return (j);
+}
+
+/*
+ * For a subnormal float entity represented as an int32_t, compute ilogb.
+ */
+static inline int32_t
+subnormal_ilogbf(int32_t hx)
+{
+ int32_t j;
+ uint32_t i;
+ i = (uint32_t) hx << 8;
+ for (j = -126; i < 0x7fffffff; i <<= 1) j -=1;
+
+ return (j);
+}
+
#ifdef DEBUG
#if defined(__amd64__) || defined(__i386__)
#define breakpoint() asm("int $3")
diff --git a/lib/msun/src/s_ccosh.c b/lib/msun/src/s_ccosh.c
index 3d46c993c6f1..14a8931742dc 100644
--- a/lib/msun/src/s_ccosh.c
+++ b/lib/msun/src/s_ccosh.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * Copyright (c) 2005-2025 Bruce D. Evans and Steven G. Kargl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,7 @@ static const double huge = 0x1p1023;
double complex
ccosh(double complex z)
{
- double x, y, h;
+ double c, h, s, x, y;
int32_t hx, hy, ix, iy, lx, ly;
x = creal(z);
@@ -64,14 +64,16 @@ ccosh(double complex z)
if (ix < 0x7ff00000 && iy < 0x7ff00000) {
if ((iy | ly) == 0)
return (CMPLX(cosh(x), x * y));
+
+ sincos(y, &s, &c);
if (ix < 0x40360000) /* |x| < 22: normal case */
- return (CMPLX(cosh(x) * cos(y), sinh(x) * sin(y)));
+ return (CMPLX(cosh(x) * c, sinh(x) * s));
/* |x| >= 22, so cosh(x) ~= exp(|x|) */
if (ix < 0x40862e42) {
/* x < 710: exp(|x|) won't overflow */
- h = exp(fabs(x)) * 0.5;
- return (CMPLX(h * cos(y), copysign(h, x) * sin(y)));
+ h = exp(fabs(x)) / 2;
+ return (CMPLX(h * c, copysign(h, x) * s));
} else if (ix < 0x4096bbaa) {
/* x < 1455: scale to avoid overflow */
z = __ldexp_cexp(CMPLX(fabs(x), y), -1);
@@ -79,7 +81,7 @@ ccosh(double complex z)
} else {
/* x >= 1455: the result always overflows */
h = huge * x;
- return (CMPLX(h * h * cos(y), h * sin(y)));
+ return (CMPLX(h * h * c, h * s));
}
}
@@ -129,7 +131,9 @@ ccosh(double complex z)
if (ix == 0x7ff00000 && lx == 0) {
if (iy >= 0x7ff00000)
return (CMPLX(INFINITY, x * (y - y)));
- return (CMPLX(INFINITY * cos(y), x * sin(y)));
+
+ sincos(y, &s, &c);
+ return (CMPLX(INFINITY * c, x * s));
}
/*
@@ -154,3 +158,8 @@ ccos(double complex z)
/* ccos(z) = ccosh(I * z) */
return (ccosh(CMPLX(-cimag(z), creal(z))));
}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(ccosh, ccoshl);
+__weak_reference(ccos, ccosl);
+#endif
diff --git a/lib/msun/src/s_ccoshf.c b/lib/msun/src/s_ccoshf.c
index aeb2dec23677..fa41fdf4c4ea 100644
--- a/lib/msun/src/s_ccoshf.c
+++ b/lib/msun/src/s_ccoshf.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * Copyright (c) 2005-2025 Bruce D. Evans and Steven G. Kargl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@ static const float huge = 0x1p127;
float complex
ccoshf(float complex z)
{
- float x, y, h;
+ float c, h, s, x, y;
int32_t hx, hy, ix, iy;
x = crealf(z);
@@ -55,14 +55,16 @@ ccoshf(float complex z)
if (ix < 0x7f800000 && iy < 0x7f800000) {
if (iy == 0)
return (CMPLXF(coshf(x), x * y));
+
+ sincosf(y, &s, &c);
if (ix < 0x41100000) /* |x| < 9: normal case */
- return (CMPLXF(coshf(x) * cosf(y), sinhf(x) * sinf(y)));
+ return (CMPLXF(coshf(x) * c, sinhf(x) * s));
/* |x| >= 9, so cosh(x) ~= exp(|x|) */
if (ix < 0x42b17218) {
/* x < 88.7: expf(|x|) won't overflow */
- h = expf(fabsf(x)) * 0.5F;
- return (CMPLXF(h * cosf(y), copysignf(h, x) * sinf(y)));
+ h = expf(fabsf(x)) / 2;
+ return (CMPLXF(h * c, copysignf(h, x) * s));
} else if (ix < 0x4340b1e7) {
/* x < 192.7: scale to avoid overflow */
z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1);
@@ -70,7 +72,7 @@ ccoshf(float complex z)
} else {
/* x >= 192.7: the result always overflows */
h = huge * x;
- return (CMPLXF(h * h * cosf(y), h * sinf(y)));
+ return (CMPLXF(h * h * c, h * s));
}
}
@@ -86,7 +88,9 @@ ccoshf(float complex z)
if (ix == 0x7f800000) {
if (iy >= 0x7f800000)
return (CMPLXF(INFINITY, x * (y - y)));
- return (CMPLXF(INFINITY * cosf(y), x * sinf(y)));
+
+ sincosf(y, &s, &c);
+ return (CMPLXF(INFINITY * c, x * s));
}
return (CMPLXF(((long double)x * x) * (y - y),
diff --git a/lib/msun/src/s_cpow.c b/lib/msun/src/s_cpow.c
index b887db51aa2a..2c20a8f3b48b 100644
--- a/lib/msun/src/s_cpow.c
+++ b/lib/msun/src/s_cpow.c
@@ -58,7 +58,10 @@ cpow(double complex a, double complex z)
y = cimag (z);
absa = cabs (a);
if (absa == 0.0) {
- return (CMPLX(0.0, 0.0));
+ if (x == 0 && y == 0)
+ return (CMPLX(1., 0.));
+ else
+ return (CMPLX(0., 0.));
}
arga = carg (a);
r = pow (absa, x);
diff --git a/lib/msun/src/s_cpowf.c b/lib/msun/src/s_cpowf.c
index 144291079f97..b8bdbd9cb07b 100644
--- a/lib/msun/src/s_cpowf.c
+++ b/lib/msun/src/s_cpowf.c
@@ -57,7 +57,10 @@ cpowf(float complex a, float complex z)
y = cimagf(z);
absa = cabsf (a);
if (absa == 0.0f) {
- return (CMPLXF(0.0f, 0.0f));
+ if (x == 0 && y == 0)
+ return (CMPLXF(1.f, 0.f));
+ else
+ return (CMPLXF(0.f, 0.f));
}
arga = cargf (a);
r = powf (absa, x);
diff --git a/lib/msun/src/s_cpowl.c b/lib/msun/src/s_cpowl.c
index 39797cadcfcb..efbe4936895f 100644
--- a/lib/msun/src/s_cpowl.c
+++ b/lib/msun/src/s_cpowl.c
@@ -57,7 +57,10 @@ cpowl(long double complex a, long double complex z)
y = cimagl(z);
absa = cabsl(a);
if (absa == 0.0L) {
- return (CMPLXL(0.0L, 0.0L));
+ if (x == 0 && y == 0)
+ return (CMPLXL(1.L, 0.L));
+ else
+ return (CMPLXL(0.L, 0.L));
}
arga = cargl(a);
r = powl(absa, x);
diff --git a/lib/msun/src/s_csinh.c b/lib/msun/src/s_csinh.c
index e7ed10e7d885..11c2ec345094 100644
--- a/lib/msun/src/s_csinh.c
+++ b/lib/msun/src/s_csinh.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * Copyright (c) 2005-2025 Bruce D. Evans and Steven G. Kargl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,7 @@ static const double huge = 0x1p1023;
double complex
csinh(double complex z)
{
- double x, y, h;
+ double c, h, s, x, y;
int32_t hx, hy, ix, iy, lx, ly;
x = creal(z);
@@ -64,14 +64,16 @@ csinh(double complex z)
if (ix < 0x7ff00000 && iy < 0x7ff00000) {
if ((iy | ly) == 0)
return (CMPLX(sinh(x), y));
+
+ sincos(y, &s, &c);
if (ix < 0x40360000) /* |x| < 22: normal case */
- return (CMPLX(sinh(x) * cos(y), cosh(x) * sin(y)));
+ return (CMPLX(sinh(x) * c, cosh(x) * s));
/* |x| >= 22, so cosh(x) ~= exp(|x|) */
if (ix < 0x40862e42) {
/* x < 710: exp(|x|) won't overflow */
- h = exp(fabs(x)) * 0.5;
- return (CMPLX(copysign(h, x) * cos(y), h * sin(y)));
+ h = exp(fabs(x)) / 2;
+ return (CMPLX(copysign(h, x) * c, h * s));
} else if (ix < 0x4096bbaa) {
/* x < 1455: scale to avoid overflow */
z = __ldexp_cexp(CMPLX(fabs(x), y), -1);
@@ -79,7 +81,7 @@ csinh(double complex z)
} else {
/* x >= 1455: the result always overflows */
h = huge * x;
- return (CMPLX(h * cos(y), h * h * sin(y)));
+ return (CMPLX(h * c, h * h * s));
}
}
@@ -128,7 +130,9 @@ csinh(double complex z)
if (ix == 0x7ff00000 && lx == 0) {
if (iy >= 0x7ff00000)
return (CMPLX(x, y - y));
- return (CMPLX(x * cos(y), INFINITY * sin(y)));
+
+ sincos(y, &s, &c);
+ return (CMPLX(x * c, INFINITY * s));
}
/*
@@ -154,3 +158,8 @@ csin(double complex z)
z = csinh(CMPLX(cimag(z), creal(z)));
return (CMPLX(cimag(z), creal(z)));
}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(csinh, csinhl);
+__weak_reference(csin, csinl);
+#endif
diff --git a/lib/msun/src/s_csinhf.c b/lib/msun/src/s_csinhf.c
index c4392755c482..fcfc011a2484 100644
--- a/lib/msun/src/s_csinhf.c
+++ b/lib/msun/src/s_csinhf.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * Copyright (c) 2005-2025 Bruce D. Evans and Steven G. Kargl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@ static const float huge = 0x1p127;
float complex
csinhf(float complex z)
{
- float x, y, h;
+ float c, h, s, x, y;
int32_t hx, hy, ix, iy;
x = crealf(z);
@@ -55,14 +55,16 @@ csinhf(float complex z)
if (ix < 0x7f800000 && iy < 0x7f800000) {
if (iy == 0)
return (CMPLXF(sinhf(x), y));
+
+ sincosf(y, &s, &c);
if (ix < 0x41100000) /* |x| < 9: normal case */
- return (CMPLXF(sinhf(x) * cosf(y), coshf(x) * sinf(y)));
+ return (CMPLXF(sinhf(x) * c, coshf(x) * s));
/* |x| >= 9, so cosh(x) ~= exp(|x|) */
if (ix < 0x42b17218) {
/* x < 88.7: expf(|x|) won't overflow */
- h = expf(fabsf(x)) * 0.5F;
- return (CMPLXF(copysignf(h, x) * cosf(y), h * sinf(y)));
+ h = expf(fabsf(x)) / 2;
+ return (CMPLXF(copysignf(h, x) * c, h * s));
} else if (ix < 0x4340b1e7) {
/* x < 192.7: scale to avoid overflow */
z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1);
@@ -70,7 +72,7 @@ csinhf(float complex z)
} else {
/* x >= 192.7: the result always overflows */
h = huge * x;
- return (CMPLXF(h * cosf(y), h * h * sinf(y)));
+ return (CMPLXF(h * c, h * h * s));
}
}
@@ -86,7 +88,9 @@ csinhf(float complex z)
if (ix == 0x7f800000) {
if (iy >= 0x7f800000)
return (CMPLXF(x, y - y));
- return (CMPLXF(x * cosf(y), INFINITY * sinf(y)));
+
+ sincosf(y, &s, &c);
+ return (CMPLXF(x * c, INFINITY * s));
}
return (CMPLXF(((long double)x + x) * (y - y),
diff --git a/lib/msun/src/s_ilogb.c b/lib/msun/src/s_ilogb.c
index 27e0bbb8735b..aa707d51d7b7 100644
--- a/lib/msun/src/s_ilogb.c
+++ b/lib/msun/src/s_ilogb.c
@@ -21,21 +21,18 @@
#include "math.h"
#include "math_private.h"
- int ilogb(double x)
+int
+ilogb(double x)
{
- int32_t hx,lx,ix;
+ int32_t hx, ix, lx;
EXTRACT_WORDS(hx,lx,x);
hx &= 0x7fffffff;
if(hx<0x00100000) {
if((hx|lx)==0)
return FP_ILOGB0;
- else /* subnormal x */
- if(hx==0) {
- for (ix = -1043; lx>0; lx<<=1) ix -=1;
- } else {
- for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1;
- }
+ else
+ ix = subnormal_ilogb(hx, lx);
return ix;
}
else if (hx<0x7ff00000) return (hx>>20)-1023;
diff --git a/lib/msun/src/s_ilogbf.c b/lib/msun/src/s_ilogbf.c
index e0f8fee26ac8..5195e2331af3 100644
--- a/lib/msun/src/s_ilogbf.c
+++ b/lib/msun/src/s_ilogbf.c
@@ -18,7 +18,8 @@
#include "math.h"
#include "math_private.h"
- int ilogbf(float x)
+int
+ilogbf(float x)
{
int32_t hx,ix;
@@ -28,7 +29,7 @@
if(hx==0)
return FP_ILOGB0;
else /* subnormal x */
- for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
+ ix = subnormal_ilogbf(hx);
return ix;
}
else if (hx<0x7f800000) return (hx>>23)-127;
diff --git a/lib/msun/src/s_remquo.c b/lib/msun/src/s_remquo.c
index 206d2903cd86..b26b5619f3ad 100644
--- a/lib/msun/src/s_remquo.c
+++ b/lib/msun/src/s_remquo.c
@@ -4,7 +4,7 @@
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
+ * software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
@@ -27,7 +27,7 @@ static const double Zero[] = {0.0, -0.0,};
double
remquo(double x, double y, int *quo)
{
- int32_t n,hx,hy,hz,ix,iy,sx,i;
+ int32_t hx,hy,hz,ix,iy,n,sx;
u_int32_t lx,ly,lz,q,sxy;
EXTRACT_WORDS(hx,lx,x);
@@ -53,25 +53,19 @@ remquo(double x, double y, int *quo)
}
/* determine ix = ilogb(x) */
- if(hx<0x00100000) { /* subnormal x */
- if(hx==0) {
- for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
- } else {
- for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
- }
- } else ix = (hx>>20)-1023;
+ if(hx<0x00100000)
+ ix = subnormal_ilogb(hx, lx);
+ else
+ ix = (hx>>20)-1023;
/* determine iy = ilogb(y) */
- if(hy<0x00100000) { /* subnormal y */
- if(hy==0) {
- for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
- } else {
- for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
- }
- } else iy = (hy>>20)-1023;
+ if(hy<0x00100000)
+ iy = subnormal_ilogb(hy, ly);
+ else
+ iy = (hy>>20)-1023;
/* set up {hx,lx}, {hy,ly} and align y to x */
- if(ix >= -1022)
+ if(ix >= -1022)
hx = 0x00100000|(0x000fffff&hx);
else { /* subnormal x, shift x to normal */
n = -1022-ix;
@@ -83,7 +77,7 @@ remquo(double x, double y, int *quo)
lx = 0;
}
}
- if(iy >= -1022)
+ if(iy >= -1022)
hy = 0x00100000|(0x000fffff&hy);
else { /* subnormal y, shift y to normal */
n = -1022-iy;
diff --git a/lib/msun/src/s_remquof.c b/lib/msun/src/s_remquof.c
index 9cd148586796..e4adb8321559 100644
--- a/lib/msun/src/s_remquof.c
+++ b/lib/msun/src/s_remquof.c
@@ -25,7 +25,7 @@ static const float Zero[] = {0.0, -0.0,};
float
remquof(float x, float y, int *quo)
{
- int32_t n,hx,hy,hz,ix,iy,sx,i;
+ int32_t hx, hy, hz, ix, iy, n, sx;
u_int32_t q,sxy;
GET_FLOAT_WORD(hx,x);
@@ -47,14 +47,16 @@ remquof(float x, float y, int *quo)
}
/* determine ix = ilogb(x) */
- if(hx<0x00800000) { /* subnormal x */
- for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
- } else ix = (hx>>23)-127;
+ if(hx<0x00800000)
+ ix = subnormal_ilogbf(hx);
+ else
+ ix = (hx>>23)-127;
/* determine iy = ilogb(y) */
- if(hy<0x00800000) { /* subnormal y */
- for (iy = -126,i=(hy<<8); i>0; i<<=1) iy -=1;
- } else iy = (hy>>23)-127;
+ if(hy<0x00800000)
+ iy = subnormal_ilogbf(hy);
+ else
+ iy = (hy>>23)-127;
/* set up {hx,lx}, {hy,ly} and align y to x */
if(ix >= -126)
diff --git a/lib/ncurses/Makefile.inc b/lib/ncurses/Makefile.inc
index f2ed84e2e38f..e14867696834 100644
--- a/lib/ncurses/Makefile.inc
+++ b/lib/ncurses/Makefile.inc
@@ -1,5 +1,7 @@
# This is to include src/lib/Makefile.inc
+PACKAGE?= ncurses
+LIB_PACKAGE=
WARNS?= 3
.include "../Makefile.inc"
diff --git a/lib/ncurses/form/Makefile b/lib/ncurses/form/Makefile
index d4774a5f51a8..7d8963b05ae8 100644
--- a/lib/ncurses/form/Makefile
+++ b/lib/ncurses/form/Makefile
@@ -3,7 +3,6 @@
SRCDIR= ${NCURSES_DIR}/form
-PACKAGE= clibs
LIB= formw
SHLIB_MAJOR= 6
diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile
index 512a452ad6d0..b60760281b39 100644
--- a/lib/ncurses/ncurses/Makefile
+++ b/lib/ncurses/ncurses/Makefile
@@ -1,4 +1,3 @@
-PACKAGE= clibs
SHLIBDIR?= /lib
.include <src.opts.mk>
diff --git a/lib/ncurses/panel/Makefile b/lib/ncurses/panel/Makefile
index a51129df42e3..dfb478aa5f5b 100644
--- a/lib/ncurses/panel/Makefile
+++ b/lib/ncurses/panel/Makefile
@@ -3,7 +3,6 @@
SRCDIR= ${NCURSES_DIR}/panel
-PACKAGE= clibs
LIB= panelw
SHLIB_MAJOR= 6
diff --git a/lib/ncurses/tinfo/Makefile b/lib/ncurses/tinfo/Makefile
index 920bd6e5559c..8f01557edaee 100644
--- a/lib/ncurses/tinfo/Makefile
+++ b/lib/ncurses/tinfo/Makefile
@@ -1,4 +1,3 @@
-PACKAGE= clibs
SHLIBDIR?= /lib
.include <src.opts.mk>
@@ -259,10 +258,18 @@ term.h: MKterm.h.awk edit_cfg.sh Caps Caps-ncurses
sh ${NCURSES_DIR}/include/edit_cfg.sh ${NCURSES_CFG_H} $@.new
mv -f $@.new $@
+# Avoid hard-coding absolute source paths if requested.
+.if ${MK_REPRODUCIBLE_BUILD} != "no"
+NCURSES_SRCTOP=/usr/src
+.else
+NCURSES_SRCTOP=${SRCTOP}
+.endif
+
curses.h: curses.head MKkey_defs.sh Caps Caps-ncurses
cat curses.head > $@.new
AWK=${AWK} _POSIX2_VERSION=199209 sh ${NCURSES_DIR}/include/MKkey_defs.sh \
${NCURSES_DIR}/include/Caps ${NCURSES_DIR}/include/Caps-ncurses >> $@.new
+ sed -i '' 's|${SRCTOP}|${NCURSES_SRCTOP}|g' $@.new
cat ${NCURSES_DIR}/include/curses.wide >> $@.new
cat ${NCURSES_DIR}/include/curses.tail >> $@.new
mv -f $@.new $@
@@ -387,6 +394,7 @@ unctrl.h: unctrl.h.in
terminfo.5: MKterminfo.sh terminfo.head Caps
sh ${NCURSES_DIR}/man/MKterminfo.sh ${NCURSES_DIR}/man/terminfo.head \
${NCURSES_DIR}/include/Caps ${NCURSES_DIR}/man/terminfo.tail >$@
+ sed -i '' 's|${SRCTOP}|${NCURSES_SRCTOP}|g' $@
CLEANFILES+= terminfo.5
diff --git a/lib/nss_tacplus/Makefile b/lib/nss_tacplus/Makefile
index f39788cfbdea..c85297a7dbaa 100644
--- a/lib/nss_tacplus/Makefile
+++ b/lib/nss_tacplus/Makefile
@@ -1,9 +1,9 @@
LIB= nss_tacplus
-SRCS= ${LIB}.8
+SRCS= ${LIB}.c
SHLIB_MAJOR= 1
SHLIB_NAME= ${LIB}.so.${SHLIB_MAJOR}
LIBADD= tacplus
-MK_INSTALLIB= no
+MK_INSTALLLIB= no
MAN= ${LIB}.8
.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/Makefile b/lib/virtual_oss/Makefile
new file mode 100644
index 000000000000..dc83edd4b980
--- /dev/null
+++ b/lib/virtual_oss/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+SHLIBDIR?= ${LIBDIR}/virtual_oss
+
+SUBDIR+= null \
+ oss
+
+.include "Makefile.inc"
+.include <bsd.subdir.mk>
diff --git a/lib/virtual_oss/Makefile.inc b/lib/virtual_oss/Makefile.inc
new file mode 100644
index 000000000000..877465a5c548
--- /dev/null
+++ b/lib/virtual_oss/Makefile.inc
@@ -0,0 +1,5 @@
+PACKAGE= sound
+
+.include "../Makefile.inc"
+
+LDFLAGS+= -L${.OBJDIR:H:H}/libsamplerate
diff --git a/lib/virtual_oss/bt/Makefile b/lib/virtual_oss/bt/Makefile
new file mode 100644
index 000000000000..15413b7a1f1e
--- /dev/null
+++ b/lib/virtual_oss/bt/Makefile
@@ -0,0 +1,19 @@
+SHLIB_NAME= voss_bt.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= bt.c \
+ avdtp.c \
+ sbc_encode.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate
+LDFLAGS+= -lbluetooth -lsdp
+LIBADD= samplerate
+
+.if defined(HAVE_LIBAV)
+CFLAGS+= -I${LOCALBASE:U/usr/local}/include -DHAVE_LIBAV
+LDFLAGS+= -L${LOCALBASE:U/usr/local}/lib \
+ -lavdevice -lavutil -lavcodec -lavformat
+.endif
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/bt/avdtp.c b/lib/virtual_oss/bt/avdtp.c
new file mode 100644
index 000000000000..82ed0fb942b6
--- /dev/null
+++ b/lib/virtual_oss/bt/avdtp.c
@@ -0,0 +1,720 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2015-2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ * Copyright (c) 2016-2019 Hans Petter Selasky <hps@selasky.org>
+ * Copyright (c) 2019 Google LLC, written by Richard Kralovic <riso@google.com>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "avdtp_signal.h"
+#include "bt.h"
+
+#define DPRINTF(...) printf("backend_bt: " __VA_ARGS__)
+
+struct avdtpGetPacketInfo {
+ uint8_t buffer_data[512];
+ uint16_t buffer_len;
+ uint8_t trans;
+ uint8_t signalID;
+};
+
+static int avdtpAutoConfig(struct bt_config *);
+
+/* Return received message type if success, < 0 if failure. */
+static int
+avdtpGetPacket(int fd, struct avdtpGetPacketInfo *info)
+{
+ uint8_t *pos = info->buffer_data;
+ uint8_t *end = info->buffer_data + sizeof(info->buffer_data);
+ uint8_t message_type;
+ int len;
+
+ memset(info, 0, sizeof(*info));
+
+ /* Handle fragmented packets */
+ for (int remaining = 1; remaining > 0; --remaining) {
+ len = read(fd, pos, end - pos);
+
+ if (len < AVDTP_LEN_SUCCESS)
+ return (-1);
+ if (len == (int)(end - pos))
+ return (-1); /* buffer too small */
+
+ uint8_t trans = (pos[0] & TRANSACTIONLABEL) >> TRANSACTIONLABEL_S;
+ uint8_t packet_type = (pos[0] & PACKETTYPE) >> PACKETTYPE_S;
+ uint8_t current_message_type = (info->buffer_data[0] & MESSAGETYPE);
+ uint8_t shift;
+ if (pos == info->buffer_data) {
+ info->trans = trans;
+ message_type = current_message_type;
+ if (packet_type == singlePacket) {
+ info->signalID = (pos[1] & SIGNALID_MASK);
+ shift = 2;
+ } else {
+ if (packet_type != startPacket)
+ return (-1);
+ remaining = pos[1];
+ info->signalID = (pos[2] & SIGNALID_MASK);
+ shift = 3;
+ }
+ } else {
+ if (info->trans != trans ||
+ message_type != current_message_type ||
+ (remaining == 1 && packet_type != endPacket) ||
+ (remaining > 1 && packet_type != continuePacket)) {
+ return (-1);
+ }
+ shift = 1;
+ }
+ memmove(pos, pos + shift, len);
+ pos += len;
+ }
+ info->buffer_len = pos - info->buffer_data;
+ return (message_type);
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpSendPacket(int fd, uint8_t command, uint8_t trans, uint8_t type,
+ uint8_t * data0, int datasize0, uint8_t * data1,
+ int datasize1)
+{
+ struct iovec iov[3];
+ uint8_t header[2];
+ int retval;
+
+ /* fill out command header */
+ header[0] = (trans << 4) | (type & 3);
+ if (command != 0)
+ header[1] = command & 0x3f;
+ else
+ header[1] = 3;
+
+ iov[0].iov_base = header;
+ iov[0].iov_len = 2;
+ iov[1].iov_base = data0;
+ iov[1].iov_len = datasize0;
+ iov[2].iov_base = data1;
+ iov[2].iov_len = datasize1;
+
+ retval = writev(fd, iov, 3);
+ if (retval != (2 + datasize0 + datasize1))
+ return (-EINVAL);
+ else
+ return (0);
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpSendSyncCommand(int fd, struct avdtpGetPacketInfo *info,
+ uint8_t command, uint8_t type, uint8_t * data0,
+ int datasize0, uint8_t * data1, int datasize1)
+{
+ static uint8_t transLabel;
+ uint8_t trans;
+ int retval;
+
+ alarm(8); /* set timeout */
+
+ trans = (transLabel++) & 0xF;
+
+ retval = avdtpSendPacket(fd, command, trans, type,
+ data0, datasize0, data1, datasize1);
+ if (retval)
+ goto done;
+retry:
+ switch (avdtpGetPacket(fd, info)) {
+ case RESPONSEACCEPT:
+ if (info->trans != trans)
+ goto retry;
+ retval = 0;
+ break;
+ case RESPONSEREJECT:
+ if (info->trans != trans)
+ goto retry;
+ retval = -EINVAL;
+ break;
+ case COMMAND:
+ retval = avdtpSendReject(fd, info->trans, info->signalID);
+ if (retval == 0)
+ goto retry;
+ break;
+ default:
+ retval = -ENXIO;
+ break;
+ }
+done:
+ alarm(0); /* clear timeout */
+
+ return (retval);
+}
+
+/*
+ * Variant for acceptor role: We support any frequency, blocks, bands, and
+ * allocation. Returns 0 on success, < 0 on failure.
+ */
+static int
+avdtpSendCapabilitiesResponseSBCForACP(int fd, int trans)
+{
+ uint8_t data[10];
+
+ data[0] = mediaTransport;
+ data[1] = 0;
+ data[2] = mediaCodec;
+ data[3] = 0x6;
+ data[4] = mediaTypeAudio;
+ data[5] = SBC_CODEC_ID;
+ data[6] =
+ (1 << (3 - MODE_STEREO)) |
+ (1 << (3 - MODE_JOINT)) |
+ (1 << (3 - MODE_DUAL)) |
+ (1 << (3 - MODE_MONO)) |
+ (1 << (7 - FREQ_44_1K)) |
+ (1 << (7 - FREQ_48K)) |
+ (1 << (7 - FREQ_32K)) |
+ (1 << (7 - FREQ_16K));
+ data[7] =
+ (1 << (7 - BLOCKS_4)) |
+ (1 << (7 - BLOCKS_8)) |
+ (1 << (7 - BLOCKS_12)) |
+ (1 << (7 - BLOCKS_16)) |
+ (1 << (3 - BANDS_4)) |
+ (1 << (3 - BANDS_8)) | (1 << ALLOC_LOUDNESS) | (1 << ALLOC_SNR);
+ data[8] = MIN_BITPOOL;
+ data[9] = DEFAULT_MAXBPOOL;
+
+ return (avdtpSendPacket(fd, AVDTP_GET_CAPABILITIES, trans,
+ RESPONSEACCEPT, data, sizeof(data), NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSendAccept(int fd, uint8_t trans, uint8_t myCommand)
+{
+ return (avdtpSendPacket(fd, myCommand, trans, RESPONSEACCEPT,
+ NULL, 0, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSendReject(int fd, uint8_t trans, uint8_t myCommand)
+{
+ uint8_t value = 0;
+
+ return (avdtpSendPacket(fd, myCommand, trans, RESPONSEREJECT,
+ &value, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSendDiscResponseAudio(int fd, uint8_t trans,
+ uint8_t mySep, uint8_t is_sink)
+{
+ uint8_t data[2];
+
+ data[0] = mySep << 2;
+ data[1] = mediaTypeAudio << 4 | (is_sink ? (1 << 3) : 0);
+
+ return (avdtpSendPacket(fd, AVDTP_DISCOVER, trans, RESPONSEACCEPT,
+ data, 2, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpDiscoverAndConfig(struct bt_config *cfg, bool isSink)
+{
+ struct avdtpGetPacketInfo info;
+ uint16_t offset;
+ uint8_t chmode = cfg->chmode;
+ uint8_t aacMode1 = cfg->aacMode1;
+ uint8_t aacMode2 = cfg->aacMode2;
+ int retval;
+
+ retval = avdtpSendSyncCommand(cfg->hc, &info, AVDTP_DISCOVER, 0,
+ NULL, 0, NULL, 0);
+ if (retval)
+ return (retval);
+
+ retval = -EBUSY;
+ for (offset = 0; offset + 2 <= info.buffer_len; offset += 2) {
+ cfg->sep = info.buffer_data[offset] >> 2;
+ cfg->media_Type = info.buffer_data[offset + 1] >> 4;
+ cfg->chmode = chmode;
+ cfg->aacMode1 = aacMode1;
+ cfg->aacMode2 = aacMode2;
+ if (info.buffer_data[offset] & DISCOVER_SEP_IN_USE)
+ continue;
+ if (info.buffer_data[offset + 1] & DISCOVER_IS_SINK) {
+ if (!isSink)
+ continue;
+ } else {
+ if (isSink)
+ continue;
+ }
+ /* try to configure SBC */
+ retval = avdtpAutoConfig(cfg);
+ if (retval == 0)
+ return (0);
+ }
+ return (retval);
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpGetCapabilities(int fd, uint8_t sep, struct avdtpGetPacketInfo *info)
+{
+ uint8_t address = (sep << 2);
+
+ return (avdtpSendSyncCommand(fd, info,
+ AVDTP_GET_CAPABILITIES, 0, &address, 1,
+ NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSetConfiguration(int fd, uint8_t sep, uint8_t * data, int datasize)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t configAddresses[2];
+
+ configAddresses[0] = sep << 2;
+ configAddresses[1] = INTSEP << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_SET_CONFIGURATION, 0,
+ configAddresses, 2, data, datasize));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpOpen(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_OPEN, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpStart(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_START, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpClose(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_CLOSE, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpSuspend(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_SUSPEND, 0,
+ &address, 1, NULL, 0));
+}
+
+/* Returns 0 on success, < 0 on failure. */
+int
+avdtpAbort(int fd, uint8_t sep)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t address = sep << 2;
+
+ return (avdtpSendSyncCommand(fd, &info, AVDTP_ABORT, 0,
+ &address, 1, NULL, 0));
+}
+
+static int
+avdtpAutoConfig(struct bt_config *cfg)
+{
+ struct avdtpGetPacketInfo info;
+ uint8_t freqmode;
+ uint8_t blk_len_sb_alloc;
+ uint8_t availFreqMode = 0;
+ uint8_t availConfig = 0;
+ uint8_t supBitpoolMin = 0;
+ uint8_t supBitpoolMax = 0;
+ uint8_t aacMode1 = 0;
+ uint8_t aacMode2 = 0;
+#ifdef HAVE_LIBAV
+ uint8_t aacBitrate3 = 0;
+ uint8_t aacBitrate4 = 0;
+ uint8_t aacBitrate5 = 0;
+#endif
+ int retval;
+ int i;
+
+ retval = avdtpGetCapabilities(cfg->hc, cfg->sep, &info);
+ if (retval) {
+ DPRINTF("Cannot get capabilities\n");
+ return (retval);
+ }
+retry:
+ for (i = 0; (i + 1) < info.buffer_len;) {
+#if 0
+ DPRINTF("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ info.buffer_data[i + 0],
+ info.buffer_data[i + 1],
+ info.buffer_data[i + 2],
+ info.buffer_data[i + 3],
+ info.buffer_data[i + 4], info.buffer_data[i + 5]);
+#endif
+ if (i + 2 + info.buffer_data[i + 1] > info.buffer_len)
+ break;
+ switch (info.buffer_data[i]) {
+ case mediaTransport:
+ break;
+ case mediaCodec:
+ if (info.buffer_data[i + 1] < 2)
+ break;
+ /* check codec */
+ switch (info.buffer_data[i + 3]) {
+ case 0: /* SBC */
+ if (info.buffer_data[i + 1] < 6)
+ break;
+ availFreqMode = info.buffer_data[i + 4];
+ availConfig = info.buffer_data[i + 5];
+ supBitpoolMin = info.buffer_data[i + 6];
+ supBitpoolMax = info.buffer_data[i + 7];
+ break;
+ case 2: /* MPEG2/4 AAC */
+ if (info.buffer_data[i + 1] < 8)
+ break;
+ aacMode1 = info.buffer_data[i + 5];
+ aacMode2 = info.buffer_data[i + 6];
+#ifdef HAVE_LIBAV
+ aacBitrate3 = info.buffer_data[i + 7];
+ aacBitrate4 = info.buffer_data[i + 8];
+ aacBitrate5 = info.buffer_data[i + 9];
+#endif
+ break;
+ default:
+ break;
+ }
+ }
+ /* jump to next information element */
+ i += 2 + info.buffer_data[i + 1];
+ }
+ aacMode1 &= cfg->aacMode1;
+ aacMode2 &= cfg->aacMode2;
+
+ /* Try AAC first */
+ if (aacMode1 == cfg->aacMode1 && aacMode2 == cfg->aacMode2) {
+#ifdef HAVE_LIBAV
+ uint8_t config[12] = { mediaTransport, 0x0, mediaCodec,
+ 0x8, 0x0, 0x02, 0x80, aacMode1, aacMode2, aacBitrate3,
+ aacBitrate4, aacBitrate5
+ };
+
+ if (avdtpSetConfiguration
+ (cfg->hc, cfg->sep, config, sizeof(config)) == 0) {
+ cfg->codec = CODEC_AAC;
+ return (0);
+ }
+#endif
+ }
+ /* Try SBC second */
+ if (cfg->freq == FREQ_UNDEFINED)
+ goto auto_config_failed;
+
+ freqmode = (1 << (3 - cfg->freq + 4)) | (1 << (3 - cfg->chmode));
+
+ if ((availFreqMode & freqmode) != freqmode) {
+ DPRINTF("No frequency and mode match\n");
+ goto auto_config_failed;
+ }
+ for (i = 0; i != 4; i++) {
+ blk_len_sb_alloc = (1 << (i + 4)) |
+ (1 << (1 - cfg->bands + 2)) | (1 << cfg->allocm);
+
+ if ((availConfig & blk_len_sb_alloc) == blk_len_sb_alloc)
+ break;
+ }
+ if (i == 4) {
+ DPRINTF("No bands available\n");
+ goto auto_config_failed;
+ }
+ cfg->blocks = (3 - i);
+
+ if (cfg->allocm == ALLOC_SNR)
+ supBitpoolMax &= ~1;
+
+ if (cfg->chmode == MODE_DUAL || cfg->chmode == MODE_MONO)
+ supBitpoolMax /= 2;
+
+ if (cfg->bands == BANDS_4)
+ supBitpoolMax /= 2;
+
+ if (supBitpoolMax > cfg->bitpool)
+ supBitpoolMax = cfg->bitpool;
+ else
+ cfg->bitpool = supBitpoolMax;
+
+ do {
+ uint8_t config[10] = { mediaTransport, 0x0, mediaCodec, 0x6,
+ 0x0, 0x0, freqmode, blk_len_sb_alloc, supBitpoolMin,
+ supBitpoolMax
+ };
+
+ if (avdtpSetConfiguration
+ (cfg->hc, cfg->sep, config, sizeof(config)) == 0) {
+ cfg->codec = CODEC_SBC;
+ return (0);
+ }
+ } while (0);
+
+auto_config_failed:
+ if (cfg->chmode == MODE_STEREO) {
+ cfg->chmode = MODE_MONO;
+ cfg->aacMode2 ^= 0x0C;
+ goto retry;
+ }
+ return (-EINVAL);
+}
+
+void
+avdtpACPFree(struct bt_config *cfg)
+{
+ if (cfg->handle.sbc_enc) {
+ free(cfg->handle.sbc_enc);
+ cfg->handle.sbc_enc = NULL;
+ }
+}
+
+/* Returns 0 on success, < 0 on failure. */
+static int
+avdtpParseSBCConfig(uint8_t * data, struct bt_config *cfg)
+{
+ if (data[0] & (1 << (7 - FREQ_48K))) {
+ cfg->freq = FREQ_48K;
+ } else if (data[0] & (1 << (7 - FREQ_44_1K))) {
+ cfg->freq = FREQ_44_1K;
+ } else if (data[0] & (1 << (7 - FREQ_32K))) {
+ cfg->freq = FREQ_32K;
+ } else if (data[0] & (1 << (7 - FREQ_16K))) {
+ cfg->freq = FREQ_16K;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[0] & (1 << (3 - MODE_STEREO))) {
+ cfg->chmode = MODE_STEREO;
+ } else if (data[0] & (1 << (3 - MODE_JOINT))) {
+ cfg->chmode = MODE_JOINT;
+ } else if (data[0] & (1 << (3 - MODE_DUAL))) {
+ cfg->chmode = MODE_DUAL;
+ } else if (data[0] & (1 << (3 - MODE_MONO))) {
+ cfg->chmode = MODE_MONO;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[1] & (1 << (7 - BLOCKS_16))) {
+ cfg->blocks = BLOCKS_16;
+ } else if (data[1] & (1 << (7 - BLOCKS_12))) {
+ cfg->blocks = BLOCKS_12;
+ } else if (data[1] & (1 << (7 - BLOCKS_8))) {
+ cfg->blocks = BLOCKS_8;
+ } else if (data[1] & (1 << (7 - BLOCKS_4))) {
+ cfg->blocks = BLOCKS_4;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[1] & (1 << (3 - BANDS_8))) {
+ cfg->bands = BANDS_8;
+ } else if (data[1] & (1 << (3 - BANDS_4))) {
+ cfg->bands = BANDS_4;
+ } else {
+ return -EINVAL;
+ }
+
+ if (data[1] & (1 << ALLOC_LOUDNESS)) {
+ cfg->allocm = ALLOC_LOUDNESS;
+ } else if (data[1] & (1 << ALLOC_SNR)) {
+ cfg->allocm = ALLOC_SNR;
+ } else {
+ return -EINVAL;
+ }
+ cfg->bitpool = data[3];
+ return 0;
+}
+
+int
+avdtpACPHandlePacket(struct bt_config *cfg)
+{
+ struct avdtpGetPacketInfo info;
+ int retval;
+
+ if (avdtpGetPacket(cfg->hc, &info) != COMMAND)
+ return (-ENXIO);
+
+ switch (info.signalID) {
+ case AVDTP_DISCOVER:
+ retval =
+ avdtpSendDiscResponseAudio(cfg->hc, info.trans, ACPSEP, 1);
+ if (!retval)
+ retval = AVDTP_DISCOVER;
+ break;
+ case AVDTP_GET_CAPABILITIES:
+ retval =
+ avdtpSendCapabilitiesResponseSBCForACP(cfg->hc, info.trans);
+ if (!retval)
+ retval = AVDTP_GET_CAPABILITIES;
+ break;
+ case AVDTP_SET_CONFIGURATION:
+ if (cfg->acceptor_state != acpInitial)
+ goto err;
+ cfg->sep = info.buffer_data[1] >> 2;
+ int is_configured = 0;
+ for (int i = 2; (i + 1) < info.buffer_len;) {
+ if (i + 2 + info.buffer_data[i + 1] > info.buffer_len)
+ break;
+ switch (info.buffer_data[i]) {
+ case mediaTransport:
+ break;
+ case mediaCodec:
+ if (info.buffer_data[i + 1] < 2)
+ break;
+ /* check codec */
+ switch (info.buffer_data[i + 3]) {
+ case 0: /* SBC */
+ if (info.buffer_data[i + 1] < 6)
+ break;
+ retval =
+ avdtpParseSBCConfig(info.buffer_data + i + 4, cfg);
+ if (retval)
+ return retval;
+ is_configured = 1;
+ break;
+ case 2: /* MPEG2/4 AAC */
+ /* TODO: Add support */
+ default:
+ break;
+ }
+ }
+ /* jump to next information element */
+ i += 2 + info.buffer_data[i + 1];
+ }
+ if (!is_configured)
+ goto err;
+
+ retval =
+ avdtpSendAccept(cfg->hc, info.trans, AVDTP_SET_CONFIGURATION);
+ if (retval)
+ return (retval);
+
+ /* TODO: Handle other codecs */
+ if (cfg->handle.sbc_enc == NULL) {
+ cfg->handle.sbc_enc = malloc(sizeof(*cfg->handle.sbc_enc));
+ if (cfg->handle.sbc_enc == NULL)
+ return (-ENOMEM);
+ }
+ memset(cfg->handle.sbc_enc, 0, sizeof(*cfg->handle.sbc_enc));
+
+ retval = AVDTP_SET_CONFIGURATION;
+ cfg->acceptor_state = acpConfigurationSet;
+ break;
+ case AVDTP_OPEN:
+ if (cfg->acceptor_state != acpConfigurationSet)
+ goto err;
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return (retval);
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamOpened;
+ break;
+ case AVDTP_START:
+ if (cfg->acceptor_state != acpStreamOpened &&
+ cfg->acceptor_state != acpStreamSuspended) {
+ goto err;
+ }
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return retval;
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamStarted;
+ break;
+ case AVDTP_CLOSE:
+ if (cfg->acceptor_state != acpStreamOpened &&
+ cfg->acceptor_state != acpStreamStarted &&
+ cfg->acceptor_state != acpStreamSuspended) {
+ goto err;
+ }
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return (retval);
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamClosed;
+ break;
+ case AVDTP_SUSPEND:
+ if (cfg->acceptor_state != acpStreamOpened &&
+ cfg->acceptor_state != acpStreamStarted) {
+ goto err;
+ }
+ retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID);
+ if (retval)
+ return (retval);
+ retval = info.signalID;
+ cfg->acceptor_state = acpStreamSuspended;
+ break;
+ case AVDTP_GET_CONFIGURATION:
+ case AVDTP_RECONFIGURE:
+ case AVDTP_ABORT:
+ /* TODO: Implement this. */
+ default:
+err:
+ avdtpSendReject(cfg->hc, info.trans, info.signalID);
+ return (-ENXIO);
+ }
+ return (retval);
+}
diff --git a/lib/virtual_oss/bt/avdtp_signal.h b/lib/virtual_oss/bt/avdtp_signal.h
new file mode 100644
index 000000000000..a46cc6dd9dcf
--- /dev/null
+++ b/lib/virtual_oss/bt/avdtp_signal.h
@@ -0,0 +1,139 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _AVDTP_SIGNAL_H_
+#define _AVDTP_SIGNAL_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Our endpoint. */
+#define INTSEP 8
+#define ACPSEP 8
+
+/* AVDTP signals. */
+
+#define AVDTP_DISCOVER 0x01
+#define AVDTP_GET_CAPABILITIES 0x02
+#define AVDTP_SET_CONFIGURATION 0x03
+#define AVDTP_GET_CONFIGURATION 0x04
+#define AVDTP_RECONFIGURE 0x05
+#define AVDTP_OPEN 0x06
+#define AVDTP_START 0x07
+#define AVDTP_CLOSE 0x08
+#define AVDTP_SUSPEND 0x09
+#define AVDTP_ABORT 0x0a
+#define AVDTP_SECUURITY_CONTROL 0x0b
+
+/* Signal Command & Response Header Masks. */
+
+#define TRANSACTIONLABEL 0xf0
+#define TRANSACTIONLABEL_S 4
+#define SIGNALID_MASK 0x3f
+#define PACKETTYPE 0x0c
+#define PACKETTYPE_S 0x02
+#define MESSAGETYPE 0x03
+#define SIGNALIDENTIFIER 0x3f
+#define DISCOVER_SEP_IN_USE 0x02
+#define DISCOVER_IS_SINK 0x08
+
+/* Packet Types */
+#define singlePacket 0x0
+#define startPacket 0x1
+#define continuePacket 0x2
+#define endPacket 0x3
+
+/* Message Types */
+#define COMMAND 0x0
+#define RESPONSEACCEPT 0x2
+#define RESPONSEREJECT 0x3
+
+/* Response general error/success lengths */
+#define AVDTP_LEN_SUCCESS 2
+#define AVDTP_LEN_ERROR 3
+
+/* Error codes */
+#define BAD_HEADER_FORMAT 0x01
+#define BAD_LENGTH 0x11
+#define BAD_ACP_SEID 0x12
+#define SEP_IN_USE 0x13
+#define SEP_NOT_IN_USE 0x14
+#define BAD_SERV_CATAGORY 0x17
+#define BAD_PAYLOAD_FORMAT 0x18
+#define NOT_SUPPORTED_COMMAND 0x19
+#define INVALID_CAPABILITIES 0x1a
+
+#define BAD_RECOVERY_TYPE 0x22
+#define BAD_MEDIA_TRANSPORT_FORMAT 0x23
+#define BAD_RECOVERY_FORMAT 0x25
+#define BAD_ROHC_FORMAT 0x26
+#define BAD_CP_FORMAT 0x27
+#define BAD_MULTIPLEXING_FORMAT 0x28
+#define UNSUPPORTED_CONFIGURATION 0x29
+#define BAD_STATE 0x31
+
+/* Service Capabilities Field. */
+#define mediaTransport 0x1
+#define reporting 0x2
+#define recovery 0x3
+#define contentProtection 0x4
+#define headerCompression 0x5
+#define multiplexing 0x6
+#define mediaCodec 0x7
+
+/* Media Codec Capabilities */
+#define mediaCodecSbc 0x00
+#define mediaCodecMpeg1 0x01
+#define mediaCodecMpeg2 0x02
+
+#define SBC_CODEC_ID 0x0
+#define mediaTypeAudio 0x0
+
+struct bt_config;
+
+int avdtpSendAccept(int, uint8_t, uint8_t);
+int avdtpSendReject(int, uint8_t, uint8_t);
+int avdtpSendDiscResponseAudio(int, uint8_t, uint8_t, uint8_t);
+int avdtpDiscoverAndConfig(struct bt_config *, bool);
+int avdtpSetConfiguration(int, uint8_t, uint8_t *, int);
+int avdtpOpen(int, uint8_t);
+int avdtpStart(int, uint8_t);
+int avdtpClose(int, uint8_t);
+int avdtpSuspend(int, uint8_t);
+int avdtpAbort(int, uint8_t);
+
+/* Return < 0 if error, processed signal otherwise. */
+int avdtpACPHandlePacket(struct bt_config *cfg);
+/* Free state allocated in avdtpACPHandlePacket(), if any. */
+void avdtpACPFree(struct bt_config *cfg);
+
+#endif /* _AVDTP_SIGNAL_H_ */
diff --git a/lib/virtual_oss/bt/bt.c b/lib/virtual_oss/bt/bt.c
new file mode 100644
index 000000000000..57f000b067d5
--- /dev/null
+++ b/lib/virtual_oss/bt/bt.c
@@ -0,0 +1,1061 @@
+/*-
+ * Copyright (c) 2015-2019 Hans Petter Selasky
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ * Copyright (c) 2006 Itronix Inc
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/filio.h>
+#include <sys/soundcard.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <sdp.h>
+
+#include "backend.h"
+#include "int.h"
+
+#include "avdtp_signal.h"
+#include "bt.h"
+
+#define DPRINTF(...) printf("backend_bt: " __VA_ARGS__)
+
+struct l2cap_info {
+ bdaddr_t laddr;
+ bdaddr_t raddr;
+};
+
+static struct bt_config bt_play_cfg;
+static struct bt_config bt_rec_cfg;
+
+int
+bt_receive(struct bt_config *cfg, void *ptr, int len, int use_delay)
+{
+ struct sbc_header *phdr = (struct sbc_header *)cfg->mtu_data;
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ uint8_t *tmp = ptr;
+ int old_len = len;
+ int delta;
+ int err;
+
+ /* wait for service interval, if any */
+ if (use_delay)
+ virtual_oss_wait();
+
+ switch (cfg->blocks) {
+ case BLOCKS_4:
+ sbc->blocks = 4;
+ break;
+ case BLOCKS_8:
+ sbc->blocks = 8;
+ break;
+ case BLOCKS_12:
+ sbc->blocks = 12;
+ break;
+ default:
+ sbc->blocks = 16;
+ break;
+ }
+
+ switch (cfg->bands) {
+ case BANDS_4:
+ sbc->bands = 4;
+ break;
+ default:
+ sbc->bands = 8;
+ break;
+ }
+
+ if (cfg->chmode != MODE_MONO) {
+ sbc->channels = 2;
+ } else {
+ sbc->channels = 1;
+ }
+
+ while (1) {
+ delta = len & ~1;
+ if (delta > (int)(2 * sbc->rem_len))
+ delta = (2 * sbc->rem_len);
+
+ /* copy out samples, if any */
+ memcpy(tmp, (char *)sbc->music_data + sbc->rem_off, delta);
+ tmp += delta;
+ len -= delta;
+ sbc->rem_off += delta / 2;
+ sbc->rem_len -= delta / 2;
+ if (len == 0)
+ break;
+
+ if (sbc->rem_len == 0 &&
+ sbc->rem_data_frames != 0) {
+ err = sbc_decode_frame(cfg, sbc->rem_data_len * 8);
+ sbc->rem_data_frames--;
+ sbc->rem_data_ptr += err;
+ sbc->rem_data_len -= err;
+ continue;
+ }
+ /* TODO: Support fragmented SBC frames */
+ err = read(cfg->fd, cfg->mtu_data, cfg->mtu);
+
+ if (err == 0) {
+ break;
+ } else if (err < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ break;
+ else
+ return (-1); /* disconnected */
+ }
+
+ /* verify RTP header */
+ if (err < (int)sizeof(*phdr) || phdr->id != 0x80)
+ continue;
+
+ sbc->rem_data_frames = phdr->numFrames;
+ sbc->rem_data_ptr = (uint8_t *)(phdr + 1);
+ sbc->rem_data_len = err - sizeof(*phdr);
+ }
+ return (old_len - len);
+}
+
+static int
+bt_set_format(int *format)
+{
+ int value;
+
+ value = *format & AFMT_S16_NE;
+ if (value != 0) {
+ *format = value;
+ return (0);
+ }
+ return (-1);
+}
+
+static void
+bt_close(struct voss_backend *pbe)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ if (cfg->hc > 0) {
+ avdtpAbort(cfg->hc, cfg->sep);
+ avdtpClose(cfg->hc, cfg->sep);
+ close(cfg->hc);
+ cfg->hc = -1;
+ }
+ if (cfg->fd > 0) {
+ close(cfg->fd);
+ cfg->fd = -1;
+ }
+}
+
+static void
+bt_play_close(struct voss_backend *pbe)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ if (cfg->handle.sbc_enc == NULL)
+ break;
+ free(cfg->handle.sbc_enc);
+ cfg->handle.sbc_enc = NULL;
+ break;
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ if (cfg->handle.av.context == NULL)
+ break;
+ av_free(cfg->rem_in_data);
+ av_frame_free(&cfg->handle.av.frame);
+ avcodec_close(cfg->handle.av.context);
+ avformat_free_context(cfg->handle.av.format);
+ cfg->handle.av.context = NULL;
+ break;
+#endif
+ default:
+ break;
+ }
+ return (bt_close(pbe));
+}
+
+static void
+bt_rec_close(struct voss_backend *pbe)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ break;
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ break;
+#endif
+
+ default:
+ break;
+ }
+ return (bt_close(pbe));
+}
+
+static const uint32_t bt_attrs[] = {
+ SDP_ATTR_RANGE(SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
+ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
+};
+
+#define BT_NUM_VALUES 32
+#define BT_BUF_SIZE 32
+
+static int
+bt_find_psm(const uint8_t *start, const uint8_t *end)
+{
+ uint32_t type;
+ uint32_t len;
+ int protover = 0;
+ int psm = -1;
+
+ if ((end - start) < 2)
+ return (-1);
+
+ SDP_GET8(type, start);
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, start);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, start);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, start);
+ break;
+
+ default:
+ return (-1);
+ }
+
+ while (start < end) {
+ SDP_GET8(type, start);
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, start);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, start);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, start);
+ break;
+
+ default:
+ return (-1);
+ }
+ /* check range */
+ if (len > (uint32_t)(end - start))
+ break;
+
+ if (len >= 6) {
+ const uint8_t *ptr = start;
+
+ SDP_GET8(type, ptr);
+ if (type == SDP_DATA_UUID16) {
+ uint16_t temp;
+
+ SDP_GET16(temp, ptr);
+ switch (temp) {
+ case SDP_UUID_PROTOCOL_L2CAP:
+ SDP_GET8(type, ptr);
+ SDP_GET16(psm, ptr);
+ break;
+ case SDP_UUID_PROTOCOL_AVDTP:
+ SDP_GET8(type, ptr);
+ SDP_GET16(protover, ptr);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ start += len;
+
+ if (protover >= 0x0100 && psm > -1)
+ return (htole16(psm));
+ }
+ return (-1);
+}
+
+static int
+bt_query(struct l2cap_info *info, uint16_t service_class)
+{
+ sdp_attr_t values[BT_NUM_VALUES];
+ uint8_t buffer[BT_NUM_VALUES][BT_BUF_SIZE];
+ void *ss;
+ int psm = -1;
+ int n;
+
+ memset(buffer, 0, sizeof(buffer));
+ memset(values, 0, sizeof(values));
+
+ ss = sdp_open(&info->laddr, &info->raddr);
+ if (ss == NULL || sdp_error(ss) != 0) {
+ DPRINTF("Could not open SDP\n");
+ sdp_close(ss);
+ return (psm);
+ }
+ /* Initialize attribute values array */
+ for (n = 0; n != BT_NUM_VALUES; n++) {
+ values[n].flags = SDP_ATTR_INVALID;
+ values[n].vlen = BT_BUF_SIZE;
+ values[n].value = buffer[n];
+ }
+
+ /* Do SDP Service Search Attribute Request */
+ n = sdp_search(ss, 1, &service_class, 1, bt_attrs, BT_NUM_VALUES, values);
+ if (n != 0) {
+ DPRINTF("SDP search failed\n");
+ goto done;
+ }
+ /* Print attributes values */
+ for (n = 0; n != BT_NUM_VALUES; n++) {
+ if (values[n].flags != SDP_ATTR_OK)
+ break;
+ if (values[n].attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST)
+ continue;
+ psm = bt_find_psm(values[n].value, values[n].value + values[n].vlen);
+ if (psm > -1)
+ break;
+ }
+done:
+ sdp_close(ss);
+ return (psm);
+}
+
+static int
+bt_open(struct voss_backend *pbe __unused, const char *devname, int samplerate,
+ int bufsize __unused, int *pchannels, int *pformat, struct bt_config *cfg,
+ int service_class, int isSink)
+{
+ struct sockaddr_l2cap addr;
+ struct l2cap_info info;
+ socklen_t mtusize = sizeof(uint16_t);
+ int tmpbitpool;
+ int l2cap_psm;
+ int temp;
+
+ memset(&info, 0, sizeof(info));
+
+ if (strstr(devname, "/dev/bluetooth/") != devname) {
+ printf("Invalid device name '%s'", devname);
+ goto error;
+ }
+ /* skip prefix */
+ devname += sizeof("/dev/bluetooth/") - 1;
+
+ if (!bt_aton(devname, &info.raddr)) {
+ struct hostent *he = NULL;
+
+ if ((he = bt_gethostbyname(devname)) == NULL) {
+ DPRINTF("Could not get host by name\n");
+ goto error;
+ }
+ bdaddr_copy(&info.raddr, (bdaddr_t *)he->h_addr);
+ }
+ switch (samplerate) {
+ case 8000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x80;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 11025:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x40;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 12000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x20;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 16000:
+ cfg->freq = FREQ_16K;
+ cfg->aacMode1 = 0x10;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 22050:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x08;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 24000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0x04;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 32000:
+ cfg->freq = FREQ_32K;
+ cfg->aacMode1 = 0x02;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 44100:
+ cfg->freq = FREQ_44_1K;
+ cfg->aacMode1 = 0x01;
+ cfg->aacMode2 = 0x0C;
+ break;
+ case 48000:
+ cfg->freq = FREQ_48K;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x8C;
+ break;
+ case 64000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x4C;
+ break;
+ case 88200:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x2C;
+ break;
+ case 96000:
+ cfg->freq = FREQ_UNDEFINED;
+ cfg->aacMode1 = 0;
+ cfg->aacMode2 = 0x1C;
+ break;
+ default:
+ DPRINTF("Invalid samplerate %d", samplerate);
+ goto error;
+ }
+ cfg->bands = BANDS_8;
+ cfg->bitpool = 0;
+
+ switch (*pchannels) {
+ case 1:
+ cfg->aacMode2 &= 0xF8;
+ cfg->chmode = MODE_MONO;
+ break;
+ default:
+ cfg->aacMode2 &= 0xF4;
+ cfg->chmode = MODE_STEREO;
+ break;
+ }
+
+ cfg->allocm = ALLOC_LOUDNESS;
+
+ if (cfg->chmode == MODE_MONO || cfg->chmode == MODE_DUAL)
+ tmpbitpool = 16;
+ else
+ tmpbitpool = 32;
+
+ if (cfg->bands == BANDS_8)
+ tmpbitpool *= 8;
+ else
+ tmpbitpool *= 4;
+
+ if (tmpbitpool > DEFAULT_MAXBPOOL)
+ tmpbitpool = DEFAULT_MAXBPOOL;
+
+ cfg->bitpool = tmpbitpool;
+
+ if (bt_set_format(pformat)) {
+ DPRINTF("Unsupported sample format\n");
+ goto error;
+ }
+ l2cap_psm = bt_query(&info, service_class);
+ DPRINTF("PSM=0x%02x\n", l2cap_psm);
+ if (l2cap_psm < 0) {
+ DPRINTF("PSM not found\n");
+ goto error;
+ }
+ cfg->hc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
+ if (cfg->hc < 0) {
+ DPRINTF("Could not create BT socket\n");
+ goto error;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.l2cap_len = sizeof(addr);
+ addr.l2cap_family = AF_BLUETOOTH;
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr);
+
+ if (bind(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not bind to HC\n");
+ goto error;
+ }
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr);
+ addr.l2cap_psm = l2cap_psm;
+ if (connect(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not connect to HC: %d\n", errno);
+ goto error;
+ }
+ if (avdtpDiscoverAndConfig(cfg, isSink)) {
+ DPRINTF("DISCOVER FAILED\n");
+ goto error;
+ }
+ if (avdtpOpen(cfg->hc, cfg->sep)) {
+ DPRINTF("OPEN FAILED\n");
+ goto error;
+ }
+ cfg->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
+ if (cfg->fd < 0) {
+ DPRINTF("Could not create BT socket\n");
+ goto error;
+ }
+ memset(&addr, 0, sizeof(addr));
+
+ addr.l2cap_len = sizeof(addr);
+ addr.l2cap_family = AF_BLUETOOTH;
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr);
+
+ if (bind(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not bind\n");
+ goto error;
+ }
+ bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr);
+ addr.l2cap_psm = l2cap_psm;
+ if (connect(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ DPRINTF("Could not connect: %d\n", errno);
+ goto error;
+ }
+ if (isSink) {
+ if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_OMTU, &cfg->mtu, &mtusize) == -1) {
+ DPRINTF("Could not get MTU\n");
+ goto error;
+ }
+ temp = cfg->mtu * 16;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDBUF, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set send buffer size\n");
+ goto error;
+ }
+ temp = cfg->mtu;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDLOWAT, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set low water mark\n");
+ goto error;
+ }
+ } else {
+ if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_IMTU, &cfg->mtu, &mtusize) == -1) {
+ DPRINTF("Could not get MTU\n");
+ goto error;
+ }
+ temp = cfg->mtu * 16;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVBUF, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set receive buffer size\n");
+ goto error;
+ }
+ temp = 1;
+ if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVLOWAT, &temp, sizeof(temp)) == -1) {
+ DPRINTF("Could not set low water mark\n");
+ goto error;
+ }
+ temp = 1;
+ if (ioctl(cfg->fd, FIONBIO, &temp) == -1) {
+ DPRINTF("Could not set non-blocking I/O for receive direction\n");
+ goto error;
+ }
+ }
+
+ if (avdtpStart(cfg->hc, cfg->sep)) {
+ DPRINTF("START FAILED\n");
+ goto error;
+ }
+ switch (cfg->chmode) {
+ case MODE_MONO:
+ *pchannels = 1;
+ break;
+ default:
+ *pchannels = 2;
+ break;
+ }
+ return (0);
+
+error:
+ if (cfg->hc > 0) {
+ close(cfg->hc);
+ cfg->hc = -1;
+ }
+ if (cfg->fd > 0) {
+ close(cfg->fd);
+ cfg->fd = -1;
+ }
+ return (-1);
+}
+
+static void
+bt_init_cfg(struct bt_config *cfg)
+{
+ memset(cfg, 0, sizeof(*cfg));
+}
+
+static int
+bt_rec_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ struct bt_config *cfg = pbe->arg;
+ int retval;
+
+ bt_init_cfg(cfg);
+
+ retval = bt_open(pbe, devname, samplerate, bufsize, pchannels, pformat,
+ cfg, SDP_SERVICE_CLASS_AUDIO_SOURCE, 0);
+ if (retval != 0)
+ return (retval);
+ return (0);
+}
+
+static int
+bt_play_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ struct bt_config *cfg = pbe->arg;
+ int retval;
+
+ bt_init_cfg(cfg);
+
+ retval = bt_open(pbe, devname, samplerate, bufsize, pchannels, pformat,
+ cfg, SDP_SERVICE_CLASS_AUDIO_SINK, 1);
+ if (retval != 0)
+ return (retval);
+
+ /* setup codec */
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ cfg->handle.sbc_enc =
+ malloc(sizeof(*cfg->handle.sbc_enc));
+ if (cfg->handle.sbc_enc == NULL)
+ return (-1);
+ memset(cfg->handle.sbc_enc, 0, sizeof(*cfg->handle.sbc_enc));
+ break;
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ cfg->handle.av.codec = __DECONST(AVCodec *,
+ avcodec_find_encoder_by_name("aac"));
+ if (cfg->handle.av.codec == NULL) {
+ DPRINTF("Codec AAC encoder not found\n");
+ goto av_error_0;
+ }
+ cfg->handle.av.format = avformat_alloc_context();
+ if (cfg->handle.av.format == NULL) {
+ DPRINTF("Could not allocate format context\n");
+ goto av_error_0;
+ }
+ cfg->handle.av.format->oformat =
+ av_guess_format("latm", NULL, NULL);
+ if (cfg->handle.av.format->oformat == NULL) {
+ DPRINTF("Could not guess output format\n");
+ goto av_error_1;
+ }
+ cfg->handle.av.stream = avformat_new_stream(
+ cfg->handle.av.format, cfg->handle.av.codec);
+
+ if (cfg->handle.av.stream == NULL) {
+ DPRINTF("Could not create new stream\n");
+ goto av_error_1;
+ }
+ cfg->handle.av.context = avcodec_alloc_context3(cfg->handle.av.codec);
+ if (cfg->handle.av.context == NULL) {
+ DPRINTF("Could not allocate audio context\n");
+ goto av_error_1;
+ }
+ /*avcodec_get_context_defaults3(cfg->handle.av.context,*/
+ /*cfg->handle.av.codec);*/
+
+ cfg->handle.av.context->bit_rate = 128000;
+ cfg->handle.av.context->sample_fmt = AV_SAMPLE_FMT_FLTP;
+ cfg->handle.av.context->sample_rate = samplerate;
+ switch (*pchannels) {
+ case 1:
+ cfg->handle.av.context->ch_layout = *(AVChannelLayout *)AV_CH_LAYOUT_MONO;
+ break;
+ default:
+ cfg->handle.av.context->ch_layout = *(AVChannelLayout *)AV_CH_LAYOUT_STEREO;
+ break;
+ }
+
+ cfg->handle.av.context->profile = FF_PROFILE_AAC_LOW;
+ if (1) {
+ AVDictionary *opts = NULL;
+
+ av_dict_set(&opts, "strict", "-2", 0);
+ av_dict_set_int(&opts, "latm", 1, 0);
+
+ if (avcodec_open2(cfg->handle.av.context,
+ cfg->handle.av.codec, &opts) < 0) {
+ av_dict_free(&opts);
+
+ DPRINTF("Could not open codec\n");
+ goto av_error_1;
+ }
+ av_dict_free(&opts);
+ }
+ cfg->handle.av.frame = av_frame_alloc();
+ if (cfg->handle.av.frame == NULL) {
+ DPRINTF("Could not allocate audio frame\n");
+ goto av_error_2;
+ }
+ cfg->handle.av.frame->nb_samples = cfg->handle.av.context->frame_size;
+ cfg->handle.av.frame->format = cfg->handle.av.context->sample_fmt;
+ cfg->handle.av.frame->ch_layout = cfg->handle.av.context->ch_layout;
+ cfg->rem_in_size = av_samples_get_buffer_size(NULL,
+ cfg->handle.av.context->ch_layout.nb_channels,
+ cfg->handle.av.context->frame_size,
+ cfg->handle.av.context->sample_fmt, 0);
+
+ cfg->rem_in_data = av_malloc(cfg->rem_in_size);
+ if (cfg->rem_in_data == NULL) {
+ DPRINTF("Could not allocate %u bytes sample buffer\n",
+ (unsigned)cfg->rem_in_size);
+ goto av_error_3;
+ }
+ retval = avcodec_fill_audio_frame(cfg->handle.av.frame,
+ cfg->handle.av.context->ch_layout.nb_channels,
+ cfg->handle.av.context->sample_fmt,
+ cfg->rem_in_data, cfg->rem_in_size, 0);
+ if (retval < 0) {
+ DPRINTF("Could not setup audio frame\n");
+ goto av_error_4;
+ }
+ break;
+av_error_4:
+ av_free(cfg->rem_in_data);
+av_error_3:
+ av_frame_free(&cfg->handle.av.frame);
+av_error_2:
+ avcodec_close(cfg->handle.av.context);
+av_error_1:
+ avformat_free_context(cfg->handle.av.format);
+ cfg->handle.av.context = NULL;
+av_error_0:
+ bt_close(pbe);
+ return (-1);
+#endif
+ default:
+ bt_close(pbe);
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+bt_rec_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (bt_receive(pbe->arg, ptr, len, 1));
+}
+
+static int
+bt_play_sbc_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct bt_config *cfg = pbe->arg;
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ int rem_size = 1;
+ int old_len = len;
+ int err = 0;
+
+ switch (cfg->blocks) {
+ case BLOCKS_4:
+ sbc->blocks = 4;
+ rem_size *= 4;
+ break;
+ case BLOCKS_8:
+ sbc->blocks = 8;
+ rem_size *= 8;
+ break;
+ case BLOCKS_12:
+ sbc->blocks = 12;
+ rem_size *= 12;
+ break;
+ default:
+ sbc->blocks = 16;
+ rem_size *= 16;
+ break;
+ }
+
+ switch (cfg->bands) {
+ case BANDS_4:
+ rem_size *= 4;
+ sbc->bands = 4;
+ break;
+ default:
+ rem_size *= 8;
+ sbc->bands = 8;
+ break;
+ }
+
+ /* store number of samples per frame */
+ sbc->framesamples = rem_size;
+
+ if (cfg->chmode != MODE_MONO) {
+ rem_size *= 2;
+ sbc->channels = 2;
+ } else {
+ sbc->channels = 1;
+ }
+
+ rem_size *= 2; /* 16-bit samples */
+
+ while (len > 0) {
+ int delta = len;
+
+ if (delta > (int)(rem_size - sbc->rem_len))
+ delta = (int)(rem_size - sbc->rem_len);
+
+ /* copy in samples */
+ memcpy((char *)sbc->music_data + sbc->rem_len, ptr, delta);
+
+ ptr = (char *)ptr + delta;
+ len -= delta;
+ sbc->rem_len += delta;
+
+ /* check if buffer is full */
+ if ((int)sbc->rem_len == rem_size) {
+ struct sbc_header *phdr = (struct sbc_header *)cfg->mtu_data;
+ uint32_t pkt_len;
+ uint32_t rem;
+
+ if (cfg->chmode == MODE_MONO)
+ sbc->channels = 1;
+ else
+ sbc->channels = 2;
+
+ pkt_len = sbc_encode_frame(cfg);
+
+ retry:
+ if (cfg->mtu_offset == 0) {
+ phdr->id = 0x80; /* RTP v2 */
+ phdr->id2 = 0x60; /* payload type 96. */
+ phdr->seqnumMSB = (uint8_t)(cfg->mtu_seqnumber >> 8);
+ phdr->seqnumLSB = (uint8_t)(cfg->mtu_seqnumber);
+ phdr->ts3 = (uint8_t)(cfg->mtu_timestamp >> 24);
+ phdr->ts2 = (uint8_t)(cfg->mtu_timestamp >> 16);
+ phdr->ts1 = (uint8_t)(cfg->mtu_timestamp >> 8);
+ phdr->ts0 = (uint8_t)(cfg->mtu_timestamp);
+ phdr->reserved0 = 0x01;
+ phdr->numFrames = 0;
+
+ cfg->mtu_seqnumber++;
+ cfg->mtu_offset += sizeof(*phdr);
+ }
+ /* compute bytes left */
+ rem = cfg->mtu - cfg->mtu_offset;
+
+ if (phdr->numFrames == 255 || rem < pkt_len) {
+ int xlen;
+
+ if (phdr->numFrames == 0)
+ return (-1);
+ do {
+ xlen = write(cfg->fd, cfg->mtu_data, cfg->mtu_offset);
+ } while (xlen < 0 && errno == EAGAIN);
+
+ if (xlen < 0)
+ return (-1);
+
+ cfg->mtu_offset = 0;
+ goto retry;
+ }
+ memcpy(cfg->mtu_data + cfg->mtu_offset, sbc->data, pkt_len);
+ memset(sbc->data, 0, pkt_len);
+ cfg->mtu_offset += pkt_len;
+ cfg->mtu_timestamp += sbc->framesamples;
+ phdr->numFrames++;
+
+ sbc->rem_len = 0;
+ }
+ }
+ if (err == 0)
+ return (old_len);
+ return (err);
+}
+
+#ifdef HAVE_LIBAV
+static int
+bt_play_aac_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct bt_config *cfg = pbe->arg;
+ struct aac_header {
+ uint8_t id;
+ uint8_t id2;
+ uint8_t seqnumMSB;
+ uint8_t seqnumLSB;
+ uint8_t ts3;
+ uint8_t ts2;
+ uint8_t ts1;
+ uint8_t ts0;
+ uint8_t sync3;
+ uint8_t sync2;
+ uint8_t sync1;
+ uint8_t sync0;
+ uint8_t fixed[8];
+ };
+ int old_len = len;
+ int err = 0;
+
+ while (len > 0) {
+ int delta = len;
+ int rem;
+
+ if (delta > (int)(cfg->rem_in_size - cfg->rem_in_len))
+ delta = (int)(cfg->rem_in_size - cfg->rem_in_len);
+
+ memcpy(cfg->rem_in_data + cfg->rem_in_len, ptr, delta);
+
+ ptr = (char *)ptr + delta;
+ len -= delta;
+ cfg->rem_in_len += delta;
+
+ /* check if buffer is full */
+ if (cfg->rem_in_len == cfg->rem_in_size) {
+ struct aac_header *phdr = (struct aac_header *)cfg->mtu_data;
+ AVPacket *pkt;
+ uint8_t *pkt_buf;
+ int pkt_len;
+
+ pkt = av_packet_alloc();
+ err = avcodec_send_frame(cfg->handle.av.context,
+ cfg->handle.av.frame);
+ if (err < 0) {
+ DPRINTF("Error encoding audio frame\n");
+ return (-1);
+ }
+ phdr->id = 0x80;/* RTP v2 */
+ phdr->id2 = 0x60; /* payload type 96. */
+ phdr->seqnumMSB = (uint8_t)(cfg->mtu_seqnumber >> 8);
+ phdr->seqnumLSB = (uint8_t)(cfg->mtu_seqnumber);
+ phdr->ts3 = (uint8_t)(cfg->mtu_timestamp >> 24);
+ phdr->ts2 = (uint8_t)(cfg->mtu_timestamp >> 16);
+ phdr->ts1 = (uint8_t)(cfg->mtu_timestamp >> 8);
+ phdr->ts0 = (uint8_t)(cfg->mtu_timestamp);
+ phdr->sync3 = 0;
+ phdr->sync2 = 0;
+ phdr->sync1 = 0;
+ phdr->sync0 = 0;
+ phdr->fixed[0] = 0xfc;
+ phdr->fixed[1] = 0x00;
+ phdr->fixed[2] = 0x00;
+ phdr->fixed[3] = 0xb0;
+ phdr->fixed[4] = 0x90;
+ phdr->fixed[5] = 0x80;
+ phdr->fixed[6] = 0x03;
+ phdr->fixed[7] = 0x00;
+
+ cfg->mtu_seqnumber++;
+ cfg->mtu_offset = sizeof(*phdr);
+
+ /* compute bytes left */
+ rem = cfg->mtu - cfg->mtu_offset;
+
+ if (avio_open_dyn_buf(&cfg->handle.av.format->pb) == 0) {
+ static int once = 0;
+
+ if (!once++)
+ (void)avformat_write_header(cfg->handle.av.format, NULL);
+ av_write_frame(cfg->handle.av.format, pkt);
+ av_packet_unref(pkt);
+ pkt_len = avio_close_dyn_buf(cfg->handle.av.format->pb, &pkt_buf);
+ if (rem < pkt_len)
+ DPRINTF("Out of buffer space\n");
+ if (pkt_len >= 3 && rem >= pkt_len) {
+ int xlen;
+
+ memcpy(cfg->mtu_data + cfg->mtu_offset, pkt_buf + 3, pkt_len - 3);
+
+ av_free(pkt_buf);
+
+ cfg->mtu_offset += pkt_len - 3;
+ if (cfg->chmode != MODE_MONO)
+ cfg->mtu_timestamp += cfg->rem_in_size / 4;
+ else
+ cfg->mtu_timestamp += cfg->rem_in_size / 2;
+ do {
+ xlen = write(cfg->fd, cfg->mtu_data, cfg->mtu_offset);
+ } while (xlen < 0 && errno == EAGAIN);
+
+ if (xlen < 0)
+ return (-1);
+ } else {
+ av_free(pkt_buf);
+ }
+ } else {
+ av_packet_unref(pkt);
+ }
+ /* reset remaining length */
+ cfg->rem_in_len = 0;
+ }
+ }
+ if (err == 0)
+ return (old_len);
+ return (err);
+}
+
+#endif
+
+static int
+bt_play_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct bt_config *cfg = pbe->arg;
+
+ switch (cfg->codec) {
+ case CODEC_SBC:
+ return (bt_play_sbc_transfer(pbe, ptr, len));
+#ifdef HAVE_LIBAV
+ case CODEC_AAC:
+ return (bt_play_aac_transfer(pbe, ptr, len));
+#endif
+ default:
+ return (-1);
+ }
+}
+
+static void
+bt_rec_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ *pdelay = -1;
+}
+
+static void
+bt_play_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ /* TODO */
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_bt_rec = {
+ .open = bt_rec_open,
+ .close = bt_rec_close,
+ .transfer = bt_rec_transfer,
+ .delay = bt_rec_delay,
+ .arg = &bt_rec_cfg,
+};
+
+struct voss_backend voss_backend_bt_play = {
+ .open = bt_play_open,
+ .close = bt_play_close,
+ .transfer = bt_play_transfer,
+ .delay = bt_play_delay,
+ .arg = &bt_play_cfg,
+};
diff --git a/lib/virtual_oss/bt/bt.h b/lib/virtual_oss/bt/bt.h
new file mode 100644
index 000000000000..2abdb9eb021a
--- /dev/null
+++ b/lib/virtual_oss/bt/bt.h
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 2015 Hans Petter Selasky
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BACKEND_BT_H_
+#define _BACKEND_BT_H_
+
+#ifdef HAVE_LIBAV
+#include <libavformat/avformat.h>
+#include <libavcodec/avcodec.h>
+#include <libavutil/opt.h>
+#endif
+
+#include "sbc_encode.h"
+
+struct bt_config {
+ uint8_t sep; /* SEID of the peer */
+ uint8_t media_Type;
+ uint8_t chmode;
+#define MODE_STEREO 2
+#define MODE_JOINT 3
+#define MODE_DUAL 1
+#define MODE_MONO 0
+ uint8_t allocm;
+#define ALLOC_LOUDNESS 0
+#define ALLOC_SNR 1
+ uint8_t bitpool;
+ uint8_t bands;
+#define BANDS_4 0
+#define BANDS_8 1
+ uint8_t blocks;
+#define BLOCKS_4 0
+#define BLOCKS_8 1
+#define BLOCKS_12 2
+#define BLOCKS_16 3
+ uint8_t freq;
+#define FREQ_UNDEFINED 255
+#define FREQ_16K 0
+#define FREQ_32K 1
+#define FREQ_44_1K 2
+#define FREQ_48K 3
+ uint16_t mtu;
+ uint8_t codec;
+#define CODEC_SBC 0x00
+#define CODEC_AAC 0x02
+ uint8_t aacMode1;
+ uint8_t aacMode2;
+
+ /* transcoding handle(s) */
+ union {
+#ifdef HAVE_LIBAV
+ struct {
+ AVCodec *codec;
+ AVCodecContext *context;
+ AVFormatContext *format;
+ AVFrame *frame;
+ AVStream *stream;
+ } av;
+#endif
+ struct sbc_encode *sbc_enc;
+ } handle;
+
+ /* audio input buffer */
+ uint32_t rem_in_len;
+ uint32_t rem_in_size;
+ uint8_t *rem_in_data;
+
+ /* data transport */
+ uint32_t mtu_seqnumber;
+ uint32_t mtu_timestamp;
+ uint32_t mtu_offset;
+
+ /* bluetooth file handles */
+ int fd;
+ int hc;
+
+ /* scratch buffer */
+ uint8_t mtu_data[65536];
+
+ /* acceptor state */
+ int8_t acceptor_state;
+#define acpInitial 1
+#define acpConfigurationSet 2
+#define acpStreamOpened 3
+#define acpStreamStarted 4
+#define acpStreamSuspended 5
+#define acpStreamClosed 6
+};
+
+size_t sbc_encode_frame(struct bt_config *);
+size_t sbc_decode_frame(struct bt_config *, int);
+
+int bt_receive(struct bt_config *cfg, void *ptr, int len, int use_delay);
+
+#endif /* _BACKEND_BT_H_ */
diff --git a/lib/virtual_oss/bt/cosdata-gen/Makefile b/lib/virtual_oss/bt/cosdata-gen/Makefile
new file mode 100644
index 000000000000..d08e263f32b5
--- /dev/null
+++ b/lib/virtual_oss/bt/cosdata-gen/Makefile
@@ -0,0 +1,12 @@
+# $NetBSD$
+
+WARNS?= 3
+
+PROG= cosdata
+SRCS= cosdata.c
+MAN=
+
+DPADD+= ${LIBMATH}
+LDADD+= -lm
+
+.include <bsd.prog.mk>
diff --git a/lib/virtual_oss/bt/cosdata-gen/cosdata.c b/lib/virtual_oss/bt/cosdata-gen/cosdata.c
new file mode 100644
index 000000000000..b8409cbd0216
--- /dev/null
+++ b/lib/virtual_oss/bt/cosdata-gen/cosdata.c
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2015 - 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ * All rights reserved.
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
+
+static const double sbc8_coeffs[] = {
+ 0.00000000e+00, 1.56575398e-04, 3.43256425e-04, 5.54620202e-04,
+ 8.23919506e-04, 1.13992507e-03, 1.47640169e-03, 1.78371725e-03,
+ 2.01182542e-03, 2.10371989e-03, 1.99454554e-03, 1.61656283e-03,
+ 9.02154502e-04, -1.78805361e-04, -1.64973098e-03, -3.49717454e-03,
+ 5.65949473e-03, 8.02941163e-03, 1.04584443e-02, 1.27472335e-02,
+ 1.46525263e-02, 1.59045603e-02, 1.62208471e-02, 1.53184106e-02,
+ 1.29371806e-02, 8.85757540e-03, 2.92408442e-03, -4.91578024e-03,
+ -1.46404076e-02, -2.61098752e-02, -3.90751381e-02, -5.31873032e-02,
+ 6.79989431e-02, 8.29847578e-02, 9.75753918e-02, 1.11196689e-01,
+ 1.23264548e-01, 1.33264415e-01, 1.40753505e-01, 1.45389847e-01,
+ 1.46955068e-01, 1.45389847e-01, 1.40753505e-01, 1.33264415e-01,
+ 1.23264548e-01, 1.11196689e-01, 9.75753918e-02, 8.29847578e-02,
+ -6.79989431e-02, -5.31873032e-02, -3.90751381e-02, -2.61098752e-02,
+ -1.46404076e-02, -4.91578024e-03, 2.92408442e-03, 8.85757540e-03,
+ 1.29371806e-02, 1.53184106e-02, 1.62208471e-02, 1.59045603e-02,
+ 1.46525263e-02, 1.27472335e-02, 1.04584443e-02, 8.02941163e-03,
+ -5.65949473e-03, -3.49717454e-03, -1.64973098e-03, -1.78805361e-04,
+ 9.02154502e-04, 1.61656283e-03, 1.99454554e-03, 2.10371989e-03,
+ 2.01182542e-03, 1.78371725e-03, 1.47640169e-03, 1.13992507e-03,
+ 8.23919506e-04, 5.54620202e-04, 3.43256425e-04, 1.56575398e-04,
+};
+
+static const double sbc4_coeffs[] = {
+ 0.00000000e+00, 5.36548976e-04, 1.49188357e-03, 2.73370904e-03,
+ 3.83720193e-03, 3.89205149e-03, 1.86581691e-03, -3.06012286e-03,
+ 1.09137620e-02, 2.04385087e-02, 2.88757392e-02, 3.21939290e-02,
+ 2.58767811e-02, 6.13245186e-03, -2.88217274e-02, -7.76463494e-02,
+ 1.35593274e-01, 1.94987841e-01, 2.46636662e-01, 2.81828203e-01,
+ 2.94315332e-01, 2.81828203e-01, 2.46636662e-01, 1.94987841e-01,
+ -1.35593274e-01, -7.76463494e-02, -2.88217274e-02, 6.13245186e-03,
+ 2.58767811e-02, 3.21939290e-02, 2.88757392e-02, 2.04385087e-02,
+ -1.09137620e-02, -3.06012286e-03, 1.86581691e-03, 3.89205149e-03,
+ 3.83720193e-03, 2.73370904e-03, 1.49188357e-03, 5.36548976e-04,
+};
+
+#define AC(x) (int)(sizeof(x) / sizeof((x)[0]))
+
+int
+main(int argc, char **argv)
+{
+ float S[8][16];
+ int i;
+ int k;
+ int count = 0;
+
+ printf("/* sbc_coeffs.h - Automatically generated by cosdata.c. */\n"
+ "\n");
+
+ printf("static const float sbc_coeffs8[] = {\n ");
+ for (k = 0; k < AC(sbc8_coeffs); k++) {
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ printf("%0.12ff, ", (float)sbc8_coeffs[k]);
+ count++;
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float sbc_coeffs4[] = {\n ");
+ for (k = 0; k < AC(sbc4_coeffs); k++) {
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ printf("%0.12ff, ", (float)sbc4_coeffs[k]);
+ count++;
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdata8[8][16] = {\n ");
+ for (i = 0; i < 8; i++) {
+ for (k = 0; k < 16; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k - 4) * (M_PI / 8.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 15)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdata4[4][8] = {\n ");
+ for (i = 0; i < 4; i++) {
+ for (k = 0; k < 8; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k - 2) * (M_PI / 4.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 7)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdecdata8[8][16] = {\n ");
+ for (i = 0; i < 8; i++) {
+ for (k = 0; k < 16; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k + 4) * (M_PI / 8.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 15)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ count = 0;
+ printf("static const float cosdecdata4[4][8] = {\n ");
+ for (i = 0; i < 4; i++) {
+ for (k = 0; k < 8; k++) {
+ S[i][k] = cosf((float)((i + 0.5) * (k + 2) * (M_PI / 4.0)));
+
+ if ((count % 8) == 0 && count != 0)
+ printf("\n ");
+ if (k == 0)
+ printf("{ ");
+ printf("%0.12ff, ", S[i][k]);
+ if (k == 7)
+ printf("},");
+ count++;
+ }
+ }
+ printf("\n};\n");
+
+ return (0);
+}
diff --git a/lib/virtual_oss/bt/sbc_coeffs.h b/lib/virtual_oss/bt/sbc_coeffs.h
new file mode 100644
index 000000000000..b9428033d50b
--- /dev/null
+++ b/lib/virtual_oss/bt/sbc_coeffs.h
@@ -0,0 +1,69 @@
+/* sbc_coeffs.h - Automatically generated by cosdata.c. */
+
+static const float sbc_coeffs8[] = {
+ 0.000000000000f, 0.000156575392f, 0.000343256426f, 0.000554620230f, 0.000823919487f, 0.001139925094f, 0.001476401696f, 0.001783717307f,
+ 0.002011825331f, 0.002103719860f, 0.001994545572f, 0.001616562833f, 0.000902154483f, -0.000178805363f, -0.001649730955f, -0.003497174475f,
+ 0.005659494549f, 0.008029411547f, 0.010458444245f, 0.012747233734f, 0.014652526006f, 0.015904560685f, 0.016220847145f, 0.015318410471f,
+ 0.012937180698f, 0.008857575245f, 0.002924084431f, -0.004915780388f, -0.014640407637f, -0.026109876111f, -0.039075139910f, -0.053187303245f,
+ 0.067998945713f, 0.082984760404f, 0.097575388849f, 0.111196689308f, 0.123264551163f, 0.133264422417f, 0.140753507614f, 0.145389840007f,
+ 0.146955072880f, 0.145389840007f, 0.140753507614f, 0.133264422417f, 0.123264551163f, 0.111196689308f, 0.097575388849f, 0.082984760404f,
+ -0.067998945713f, -0.053187303245f, -0.039075139910f, -0.026109876111f, -0.014640407637f, -0.004915780388f, 0.002924084431f, 0.008857575245f,
+ 0.012937180698f, 0.015318410471f, 0.016220847145f, 0.015904560685f, 0.014652526006f, 0.012747233734f, 0.010458444245f, 0.008029411547f,
+ -0.005659494549f, -0.003497174475f, -0.001649730955f, -0.000178805363f, 0.000902154483f, 0.001616562833f, 0.001994545572f, 0.002103719860f,
+ 0.002011825331f, 0.001783717307f, 0.001476401696f, 0.001139925094f, 0.000823919487f, 0.000554620230f, 0.000343256426f, 0.000156575392f,
+};
+static const float sbc_coeffs4[] = {
+ 0.000000000000f, 0.000536548963f, 0.001491883537f, 0.002733709058f, 0.003837201977f, 0.003892051522f, 0.001865816885f, -0.003060122952f,
+ 0.010913762264f, 0.020438509062f, 0.028875738382f, 0.032193928957f, 0.025876780972f, 0.006132451817f, -0.028821727261f, -0.077646352351f,
+ 0.135593280196f, 0.194987848401f, 0.246636658907f, 0.281828194857f, 0.294315338135f, 0.281828194857f, 0.246636658907f, 0.194987848401f,
+ -0.135593280196f, -0.077646352351f, -0.028821727261f, 0.006132451817f, 0.025876780972f, 0.032193928957f, 0.028875738382f, 0.020438509062f,
+ -0.010913762264f, -0.003060122952f, 0.001865816885f, 0.003892051522f, 0.003837201977f, 0.002733709058f, 0.001491883537f, 0.000536548963f,
+};
+static const float cosdata8[8][16] = {
+ { 0.707106769085f, 0.831469595432f, 0.923879504204f, 0.980785250664f, 1.000000000000f, 0.980785250664f, 0.923879504204f, 0.831469595432f,
+ 0.707106769085f, 0.555570244789f, 0.382683426142f, 0.195090353489f, -0.000000043711f, -0.195090323687f, -0.382683396339f, -0.555570185184f, },
+ { -0.707106769085f, -0.195090323687f, 0.382683426142f, 0.831469595432f, 1.000000000000f, 0.831469595432f, 0.382683426142f, -0.195090323687f,
+ -0.707106769085f, -0.980785310268f, -0.923879504204f, -0.555570423603f, 0.000000011925f, 0.555570065975f, 0.923879563808f, 0.980785310268f, },
+ { -0.707106828690f, -0.980785310268f, -0.382683396339f, 0.555570244789f, 1.000000000000f, 0.555570244789f, -0.382683396339f, -0.980785310268f,
+ -0.707106828690f, 0.195090413094f, 0.923879563808f, 0.831469655037f, 0.000000139071f, -0.831469774246f, -0.923879444599f, -0.195090219378f, },
+ { 0.707106649876f, -0.555570423603f, -0.923879504204f, 0.195090353489f, 1.000000000000f, 0.195090353489f, -0.923879504204f, -0.555570423603f,
+ 0.707106649876f, 0.831469655037f, -0.382683008909f, -0.980785369873f, -0.000000290067f, 0.980785250664f, 0.382683545351f, -0.831469595432f, },
+ { 0.707106769085f, 0.555570065975f, -0.923879504204f, -0.195090323687f, 1.000000000000f, -0.195090323687f, -0.923879504204f, 0.555570065975f,
+ 0.707106769085f, -0.831469774246f, -0.382683843374f, 0.980785250664f, -0.000000035775f, -0.980785250664f, 0.382683902979f, 0.831469714642f, },
+ { -0.707106590271f, 0.980785310268f, -0.382683575153f, -0.555570185184f, 1.000000000000f, -0.555570185184f, -0.382683575153f, 0.980785310268f,
+ -0.707106590271f, -0.195090219378f, 0.923879683018f, -0.831469595432f, -0.000000592058f, 0.831469714642f, -0.923879623413f, 0.195090919733f, },
+ { -0.707106530666f, 0.195090532303f, 0.382683604956f, -0.831469655037f, 1.000000000000f, -0.831469655037f, 0.382683604956f, 0.195090532303f,
+ -0.707106530666f, 0.980785310268f, -0.923879384995f, 0.555569529533f, -0.000000687457f, -0.555570006371f, 0.923879563808f, -0.980785191059f, },
+ { 0.707106828690f, -0.831469774246f, 0.923879563808f, -0.980785310268f, 1.000000000000f, -0.980785310268f, 0.923879563808f, -0.831469774246f,
+ 0.707106828690f, -0.555570065975f, 0.382683902979f, -0.195089668036f, 0.000000059624f, 0.195089548826f, -0.382683813572f, 0.555569946766f, },
+};
+static const float cosdata4[4][8] = {
+ { 0.707106769085f, 0.923879504204f, 1.000000000000f, 0.923879504204f, 0.707106769085f, 0.382683426142f, -0.000000043711f, -0.382683396339f, },
+ { -0.707106769085f, 0.382683426142f, 1.000000000000f, 0.382683426142f, -0.707106769085f, -0.923879504204f, 0.000000011925f, 0.923879563808f, },
+ { -0.707106828690f, -0.382683396339f, 1.000000000000f, -0.382683396339f, -0.707106828690f, 0.923879563808f, 0.000000139071f, -0.923879444599f, },
+ { 0.707106649876f, -0.923879504204f, 1.000000000000f, -0.923879504204f, 0.707106649876f, -0.382683008909f, -0.000000290067f, 0.382683545351f, },
+};
+static const float cosdecdata8[8][16] = {
+ { 0.707106769085f, 0.555570244789f, 0.382683426142f, 0.195090353489f, -0.000000043711f, -0.195090323687f, -0.382683396339f, -0.555570185184f,
+ -0.707106769085f, -0.831469655037f, -0.923879504204f, -0.980785310268f, -1.000000000000f, -0.980785310268f, -0.923879504204f, -0.831469535828f, },
+ { -0.707106769085f, -0.980785310268f, -0.923879504204f, -0.555570423603f, 0.000000011925f, 0.555570065975f, 0.923879563808f, 0.980785310268f,
+ 0.707106769085f, 0.195090532303f, -0.382683008909f, -0.831469774246f, -1.000000000000f, -0.831469714642f, -0.382683843374f, 0.195090577006f, },
+ { -0.707106828690f, 0.195090413094f, 0.923879563808f, 0.831469655037f, 0.000000139071f, -0.831469774246f, -0.923879444599f, -0.195090219378f,
+ 0.707106828690f, 0.980785310268f, 0.382683545351f, -0.555570065975f, -1.000000000000f, -0.555570542812f, 0.382683902979f, 0.980785191059f, },
+ { 0.707106649876f, 0.831469655037f, -0.382683008909f, -0.980785369873f, -0.000000290067f, 0.980785250664f, 0.382683545351f, -0.831469595432f,
+ -0.707107424736f, 0.555569529533f, 0.923879802227f, -0.195089668036f, -1.000000000000f, -0.195090815425f, 0.923879384995f, 0.555570483208f, },
+ { 0.707106769085f, -0.831469774246f, -0.382683843374f, 0.980785250664f, -0.000000035775f, -0.980785250664f, 0.382683902979f, 0.831469714642f,
+ -0.707106173038f, -0.555570006371f, 0.923879384995f, 0.195089548826f, -1.000000000000f, 0.195089697838f, 0.923879325390f, -0.555570125580f, },
+ { -0.707106590271f, -0.195090219378f, 0.923879683018f, -0.831469595432f, -0.000000592058f, 0.831469714642f, -0.923879623413f, 0.195090919733f,
+ 0.707107424736f, -0.980785191059f, 0.382683366537f, 0.555569946766f, -1.000000000000f, 0.555571198463f, 0.382683783770f, -0.980785667896f, },
+ { -0.707106530666f, 0.980785310268f, -0.923879384995f, 0.555569529533f, -0.000000687457f, -0.555570006371f, 0.923879563808f, -0.980785191059f,
+ 0.707106173038f, -0.195089071989f, -0.382684975863f, 0.831468641758f, -1.000000000000f, 0.831470131874f, -0.382683992386f, -0.195090129972f, },
+ { 0.707106828690f, -0.555570065975f, 0.382683902979f, -0.195089668036f, 0.000000059624f, 0.195089548826f, -0.382683813572f, 0.555569946766f,
+ -0.707106053829f, 0.831468641758f, -0.923880040646f, 0.980785369873f, -1.000000000000f, 0.980785429478f, -0.923880159855f, 0.831468760967f, },
+};
+static const float cosdecdata4[4][8] = {
+ { 0.707106769085f, 0.382683426142f, -0.000000043711f, -0.382683396339f, -0.707106769085f, -0.923879504204f, -1.000000000000f, -0.923879504204f, },
+ { -0.707106769085f, -0.923879504204f, 0.000000011925f, 0.923879563808f, 0.707106769085f, -0.382683008909f, -1.000000000000f, -0.382683843374f, },
+ { -0.707106828690f, 0.923879563808f, 0.000000139071f, -0.923879444599f, 0.707106828690f, 0.382683545351f, -1.000000000000f, 0.382683902979f, },
+ { 0.707106649876f, -0.382683008909f, -0.000000290067f, 0.382683545351f, -0.707107424736f, 0.923879802227f, -1.000000000000f, 0.923879384995f, },
+};
diff --git a/lib/virtual_oss/bt/sbc_encode.c b/lib/virtual_oss/bt/sbc_encode.c
new file mode 100644
index 000000000000..153f2e69e76e
--- /dev/null
+++ b/lib/virtual_oss/bt/sbc_encode.c
@@ -0,0 +1,701 @@
+/*-
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "sbc_coeffs.h"
+#include "bt.h"
+
+#define SYNCWORD 0x9c
+#define ABS(x) (((x) < 0) ? -(x) : (x))
+#define BIT30 (1U << 30)
+#define BM(x) ((1LL << (x)) - 1LL)
+
+/* Loudness offset allocations. */
+static const int loudnessoffset8[4][8] = {
+ {-2, 0, 0, 0, 0, 0, 0, 1},
+ {-3, 0, 0, 0, 0, 0, 1, 2},
+ {-4, 0, 0, 0, 0, 0, 1, 2},
+ {-4, 0, 0, 0, 0, 0, 1, 2},
+};
+
+static const int loudnessoffset4[4][4] = {
+ {-1, 0, 0, 0},
+ {-2, 0, 0, 1},
+ {-2, 0, 0, 1},
+ {-2, 0, 0, 1},
+};
+
+static uint8_t
+calc_scalefactors_joint(struct sbc_encode *sbc)
+{
+ float sb_j[16][2];
+ uint32_t x;
+ uint32_t y;
+ uint8_t block;
+ uint8_t joint;
+ uint8_t sb;
+ uint8_t lz;
+
+ joint = 0;
+ for (sb = 0; sb != sbc->bands - 1; sb++) {
+ for (block = 0; block < sbc->blocks; block++) {
+ sb_j[block][0] = (sbc->samples[block][0][sb] +
+ sbc->samples[block][1][sb]) / 2.0f;
+ sb_j[block][1] = (sbc->samples[block][0][sb] -
+ sbc->samples[block][1][sb]) / 2.0f;
+ }
+
+ x = 1 << 15;
+ y = 1 << 15;
+ for (block = 0; block < sbc->blocks; block++) {
+ x |= (uint32_t)ABS(sb_j[block][0]);
+ y |= (uint32_t)ABS(sb_j[block][1]);
+ }
+
+ lz = 1;
+ while (!(x & BIT30)) {
+ lz++;
+ x <<= 1;
+ }
+ x = 16 - lz;
+
+ lz = 1;
+ while (!(y & BIT30)) {
+ lz++;
+ y <<= 1;
+ }
+ y = 16 - lz;
+
+ if ((sbc->scalefactor[0][sb] + sbc->scalefactor[1][sb]) > x + y) {
+ joint |= 1 << (sbc->bands - sb - 1);
+ sbc->scalefactor[0][sb] = x;
+ sbc->scalefactor[1][sb] = y;
+ for (block = 0; block < sbc->blocks; block++) {
+ sbc->samples[block][0][sb] = sb_j[block][0];
+ sbc->samples[block][1][sb] = sb_j[block][1];
+ }
+ }
+ }
+ return (joint);
+}
+
+static void
+calc_scalefactors(struct sbc_encode *sbc)
+{
+ uint8_t block;
+ uint8_t ch;
+ uint8_t sb;
+
+ for (ch = 0; ch != sbc->channels; ch++) {
+ for (sb = 0; sb != sbc->bands; sb++) {
+ uint32_t x = 1 << 15;
+ uint8_t lx = 1;
+
+ for (block = 0; block != sbc->blocks; block++)
+ x |= (uint32_t)ABS(sbc->samples[block][ch][sb]);
+
+ while (!(x & BIT30)) {
+ lx++;
+ x <<= 1;
+ }
+ sbc->scalefactor[ch][sb] = 16 - lx;
+ }
+ }
+}
+
+static void
+calc_bitneed(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ int32_t bitneed[2][8];
+ int32_t max_bitneed, bitcount;
+ int32_t slicecount, bitslice;
+ int32_t loudness;
+ int ch, sb, start_chan = 0;
+
+ if (cfg->chmode == MODE_DUAL)
+ sbc->channels = 1;
+
+next_chan:
+ max_bitneed = 0;
+ bitcount = 0;
+ slicecount = 0;
+
+ if (cfg->allocm == ALLOC_SNR) {
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ bitneed[ch][sb] = sbc->scalefactor[ch][sb];
+
+ if (bitneed[ch][sb] > max_bitneed)
+ max_bitneed = bitneed[ch][sb];
+ }
+ }
+ } else {
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->scalefactor[ch][sb] == 0) {
+ bitneed[ch][sb] = -5;
+ } else {
+ if (sbc->bands == 8) {
+ loudness = sbc->scalefactor[ch][sb] -
+ loudnessoffset8[cfg->freq][sb];
+ } else {
+ loudness = sbc->scalefactor[ch][sb] -
+ loudnessoffset4[cfg->freq][sb];
+ }
+ if (loudness > 0)
+ bitneed[ch][sb] = loudness / 2;
+ else
+ bitneed[ch][sb] = loudness;
+ }
+ if (bitneed[ch][sb] > max_bitneed)
+ max_bitneed = bitneed[ch][sb];
+ }
+ }
+ }
+
+ slicecount = bitcount = 0;
+ bitslice = max_bitneed + 1;
+ do {
+ bitslice--;
+ bitcount += slicecount;
+ slicecount = 0;
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if ((bitneed[ch][sb] > bitslice + 1) &&
+ (bitneed[ch][sb] < bitslice + 16))
+ slicecount++;
+ else if (bitneed[ch][sb] == bitslice + 1)
+ slicecount += 2;
+ }
+ }
+ } while (bitcount + slicecount < cfg->bitpool);
+
+ /* check if exactly one more fits */
+ if (bitcount + slicecount == cfg->bitpool) {
+ bitcount += slicecount;
+ bitslice--;
+ }
+ for (ch = start_chan; ch < sbc->channels; ch++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (bitneed[ch][sb] < bitslice + 2) {
+ sbc->bits[ch][sb] = 0;
+ } else {
+ sbc->bits[ch][sb] = bitneed[ch][sb] - bitslice;
+ if (sbc->bits[ch][sb] > 16)
+ sbc->bits[ch][sb] = 16;
+ }
+ }
+ }
+
+ if (cfg->chmode == MODE_DUAL)
+ ch = start_chan;
+ else
+ ch = 0;
+ sb = 0;
+ while (bitcount < cfg->bitpool && sb < sbc->bands) {
+ if ((sbc->bits[ch][sb] >= 2) && (sbc->bits[ch][sb] < 16)) {
+ sbc->bits[ch][sb]++;
+ bitcount++;
+ } else if ((bitneed[ch][sb] == bitslice + 1) &&
+ (cfg->bitpool > bitcount + 1)) {
+ sbc->bits[ch][sb] = 2;
+ bitcount += 2;
+ }
+ if (sbc->channels == 1 || start_chan == 1)
+ sb++;
+ else if (ch == 1) {
+ ch = 0;
+ sb++;
+ } else
+ ch = 1;
+ }
+
+ if (cfg->chmode == MODE_DUAL)
+ ch = start_chan;
+ else
+ ch = 0;
+ sb = 0;
+ while (bitcount < cfg->bitpool && sb < sbc->bands) {
+ if (sbc->bits[ch][sb] < 16) {
+ sbc->bits[ch][sb]++;
+ bitcount++;
+ }
+ if (sbc->channels == 1 || start_chan == 1)
+ sb++;
+ else if (ch == 1) {
+ ch = 0;
+ sb++;
+ } else
+ ch = 1;
+ }
+
+ if (cfg->chmode == MODE_DUAL && start_chan == 0) {
+ start_chan = 1;
+ sbc->channels = 2;
+ goto next_chan;
+ }
+}
+
+static void
+sbc_store_bits_crc(struct sbc_encode *sbc, uint32_t numbits, uint32_t value)
+{
+ uint32_t off = sbc->bitoffset;
+
+ while (numbits-- && off != sbc->maxoffset) {
+ if (value & (1 << numbits)) {
+ sbc->data[off / 8] |= 1 << ((7 - off) & 7);
+ sbc->crc ^= 0x80;
+ }
+ sbc->crc *= 2;
+ if (sbc->crc & 0x100)
+ sbc->crc ^= 0x11d; /* CRC-8 polynomial */
+
+ off++;
+ }
+ sbc->bitoffset = off;
+}
+
+static int
+sbc_encode(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ const int16_t *input = sbc->music_data;
+ float delta[2][8];
+ float levels[2][8];
+ float mask[2][8];
+ float S;
+ float *X;
+ float Z[80];
+ float Y[80];
+ float audioout;
+ int16_t left[8];
+ int16_t right[8];
+ int16_t *data;
+ int numsamples;
+ int i;
+ int k;
+ int block;
+ int chan;
+ int sb;
+
+ for (block = 0; block < sbc->blocks; block++) {
+
+ for (i = 0; i < sbc->bands; i++) {
+ left[i] = *input++;
+ if (sbc->channels == 2)
+ right[i] = *input++;
+ }
+
+ for (chan = 0; chan < sbc->channels; chan++) {
+
+ /* select right or left channel */
+ if (chan == 0) {
+ X = sbc->left;
+ data = left;
+ } else {
+ X = sbc->right;
+ data = right;
+ }
+
+ /* shift up old data */
+ for (i = (sbc->bands * 10) - 1; i > sbc->bands - 1; i--)
+ X[i] = X[i - sbc->bands];
+ k = 0;
+ for (i = sbc->bands - 1; i >= 0; i--)
+ X[i] = data[k++];
+ for (i = 0; i < sbc->bands * 10; i++) {
+ if (sbc->bands == 8)
+ Z[i] = sbc_coeffs8[i] * X[i];
+ else
+ Z[i] = sbc_coeffs4[i] * X[i];
+ }
+ for (i = 0; i < sbc->bands * 2; i++) {
+ Y[i] = 0;
+ for (k = 0; k < 5; k++)
+ Y[i] += Z[i + k * sbc->bands * 2];
+ }
+ for (i = 0; i < sbc->bands; i++) {
+ S = 0;
+ for (k = 0; k < sbc->bands * 2; k++) {
+ if (sbc->bands == 8) {
+ S += cosdata8[i][k] * Y[k];
+ } else {
+ S += cosdata4[i][k] * Y[k];
+ }
+ }
+ sbc->samples[block][chan][i] = S * (1 << 15);
+ }
+ }
+ }
+
+ calc_scalefactors(sbc);
+
+ if (cfg->chmode == MODE_JOINT)
+ sbc->join = calc_scalefactors_joint(sbc);
+ else
+ sbc->join = 0;
+
+ calc_bitneed(cfg);
+
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0)
+ continue;
+ mask[chan][sb] = BM(sbc->bits[chan][sb]);
+ levels[chan][sb] = mask[chan][sb] *
+ (1LL << (15 - sbc->scalefactor[chan][sb]));
+ delta[chan][sb] =
+ (1LL << (sbc->scalefactor[chan][sb] + 16));
+ }
+ }
+
+ numsamples = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0)
+ continue;
+ audioout = (levels[chan][sb] *
+ (delta[chan][sb] + sbc->samples[block][chan][sb]));
+ audioout /= (1LL << 32);
+
+ audioout = roundf(audioout);
+
+ /* range check */
+ if (audioout > mask[chan][sb])
+ audioout = mask[chan][sb];
+
+ sbc->output[numsamples++] = audioout;
+ }
+ }
+ }
+ return (numsamples);
+}
+
+static void
+sbc_decode(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ float delta[2][8];
+ float levels[2][8];
+ float audioout;
+ float *X;
+ float *V;
+ float left[160];
+ float right[160];
+ float U[160];
+ float W[160];
+ float S[8];
+ int position;
+ int block;
+ int chan;
+ int sb;
+ int i;
+ int k;
+
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ levels[chan][sb] = (1 << sbc->bits[chan][sb]) - 1;
+ delta[chan][sb] = (1 << sbc->scalefactor[chan][sb]);
+ }
+ }
+
+ i = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0) {
+ audioout = 0;
+ } else {
+ audioout =
+ ((((sbc->output[i] * 2.0f) + 1.0f) * delta[chan][sb]) /
+ levels[chan][sb]) - delta[chan][sb];
+ }
+ sbc->output[i++] = audioout;
+ }
+ }
+ }
+
+ if (cfg->chmode == MODE_JOINT) {
+ i = 0;
+ while (i < (sbc->blocks * sbc->bands * sbc->channels)) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->join & (1 << (sbc->bands - sb - 1))) {
+ audioout = sbc->output[i];
+ sbc->output[i] = (2.0f * sbc->output[i]) +
+ (2.0f * sbc->output[i + sbc->bands]);
+ sbc->output[i + sbc->bands] =
+ (2.0f * audioout) -
+ (2.0f * sbc->output[i + sbc->bands]);
+ sbc->output[i] /= 2.0f;
+ sbc->output[i + sbc->bands] /= 2.0f;
+ }
+ i++;
+ }
+ i += sbc->bands;
+ }
+ }
+ position = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ /* select right or left channel */
+ if (chan == 0) {
+ X = left;
+ V = sbc->left;
+ } else {
+ X = right;
+ V = sbc->right;
+ }
+ for (i = 0; i < sbc->bands; i++)
+ S[i] = sbc->output[position++];
+
+ for (i = (sbc->bands * 20) - 1; i >= (sbc->bands * 2); i--)
+ V[i] = V[i - (sbc->bands * 2)];
+ for (k = 0; k < sbc->bands * 2; k++) {
+ float vk = 0;
+ for (i = 0; i < sbc->bands; i++) {
+ if (sbc->bands == 8) {
+ vk += cosdecdata8[i][k] * S[i];
+ } else {
+ vk += cosdecdata4[i][k] * S[i];
+ }
+ }
+ V[k] = vk;
+ }
+ for (i = 0; i <= 4; i++) {
+ for (k = 0; k < sbc->bands; k++) {
+ U[(i * sbc->bands * 2) + k] =
+ V[(i * sbc->bands * 4) + k];
+ U[(i * sbc->bands
+ * 2) + sbc->bands + k] =
+ V[(i * sbc->bands * 4) +
+ (sbc->bands * 3) + k];
+ }
+ }
+ for (i = 0; i < sbc->bands * 10; i++) {
+ if (sbc->bands == 4) {
+ W[i] = U[i] * (sbc_coeffs4[i] * -4.0f);
+ } else if (sbc->bands == 8) {
+ W[i] = U[i] * (sbc_coeffs8[i] * -8.0f);
+ } else {
+ W[i] = 0;
+ }
+ }
+
+ for (k = 0; k < sbc->bands; k++) {
+ unsigned int offset = k + (block * sbc->bands);
+
+ X[offset] = 0;
+ for (i = 0; i < 10; i++) {
+ X[offset] += W[k + (i * sbc->bands)];
+ }
+
+ if (X[offset] > 32767.0)
+ X[offset] = 32767.0;
+ else if (X[offset] < -32767.0)
+ X[offset] = -32767.0;
+ }
+ }
+ }
+
+ for (i = 0, k = 0; k != (sbc->blocks * sbc->bands); k++) {
+ sbc->music_data[i++] = left[k];
+ if (sbc->channels == 2)
+ sbc->music_data[i++] = right[k];
+ }
+}
+
+size_t
+sbc_encode_frame(struct bt_config *cfg)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ uint8_t config;
+ uint8_t block;
+ uint8_t chan;
+ uint8_t sb;
+ uint8_t j;
+ uint8_t i;
+
+ config = (cfg->freq << 6) | (cfg->blocks << 4) |
+ (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands;
+
+ sbc_encode(cfg);
+
+ /* set initial CRC */
+ sbc->crc = 0x5e;
+
+ /* reset data position and size */
+ sbc->bitoffset = 0;
+ sbc->maxoffset = sizeof(sbc->data) * 8;
+
+ sbc_store_bits_crc(sbc, 8, SYNCWORD);
+ sbc_store_bits_crc(sbc, 8, config);
+ sbc_store_bits_crc(sbc, 8, cfg->bitpool);
+
+ /* skip 8-bit CRC */
+ sbc->bitoffset += 8;
+
+ if (cfg->chmode == MODE_JOINT) {
+ if (sbc->bands == 8)
+ sbc_store_bits_crc(sbc, 8, sbc->join);
+ else if (sbc->bands == 4)
+ sbc_store_bits_crc(sbc, 4, sbc->join);
+ }
+ for (i = 0; i < sbc->channels; i++) {
+ for (j = 0; j < sbc->bands; j++)
+ sbc_store_bits_crc(sbc, 4, sbc->scalefactor[i][j]);
+ }
+
+ /* store 8-bit CRC */
+ sbc->data[3] = (sbc->crc & 0xFF);
+
+ i = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0)
+ continue;
+
+ sbc_store_bits_crc(sbc, sbc->bits[chan][sb], sbc->output[i++]);
+ }
+ }
+ }
+ return ((sbc->bitoffset + 7) / 8);
+}
+
+static uint32_t
+sbc_load_bits_crc(struct sbc_encode *sbc, uint32_t numbits)
+{
+ uint32_t off = sbc->bitoffset;
+ uint32_t value = 0;
+
+ while (numbits-- && off != sbc->maxoffset) {
+ if (sbc->rem_data_ptr[off / 8] & (1 << ((7 - off) & 7))) {
+ value |= (1 << numbits);
+ sbc->crc ^= 0x80;
+ }
+ sbc->crc *= 2;
+ if (sbc->crc & 0x100)
+ sbc->crc ^= 0x11d; /* CRC-8 polynomial */
+
+ off++;
+ }
+ sbc->bitoffset = off;
+ return (value);
+}
+
+size_t
+sbc_decode_frame(struct bt_config *cfg, int bits)
+{
+ struct sbc_encode *sbc = cfg->handle.sbc_enc;
+ uint8_t config;
+ uint8_t block;
+ uint8_t chan;
+ uint8_t sb;
+ uint8_t j;
+ uint8_t i;
+
+ sbc->rem_off = 0;
+ sbc->rem_len = 0;
+
+ config = (cfg->freq << 6) | (cfg->blocks << 4) |
+ (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands;
+
+ /* set initial CRC */
+ sbc->crc = 0x5e;
+
+ /* reset data position and size */
+ sbc->bitoffset = 0;
+ sbc->maxoffset = bits;
+
+ /* verify SBC header */
+ if (sbc->maxoffset < (8 * 4))
+ return (0);
+ if (sbc_load_bits_crc(sbc, 8) != SYNCWORD)
+ return (0);
+ if (sbc_load_bits_crc(sbc, 8) != config)
+ return (0);
+ cfg->bitpool = sbc_load_bits_crc(sbc, 8);
+
+ (void)sbc_load_bits_crc(sbc, 8);/* CRC */
+
+ if (cfg->chmode == MODE_JOINT) {
+ if (sbc->bands == 8)
+ sbc->join = sbc_load_bits_crc(sbc, 8);
+ else if (sbc->bands == 4)
+ sbc->join = sbc_load_bits_crc(sbc, 4);
+ else
+ sbc->join = 0;
+ } else {
+ sbc->join = 0;
+ }
+
+ for (i = 0; i < sbc->channels; i++) {
+ for (j = 0; j < sbc->bands; j++)
+ sbc->scalefactor[i][j] = sbc_load_bits_crc(sbc, 4);
+ }
+
+ calc_bitneed(cfg);
+
+ i = 0;
+ for (block = 0; block < sbc->blocks; block++) {
+ for (chan = 0; chan < sbc->channels; chan++) {
+ for (sb = 0; sb < sbc->bands; sb++) {
+ if (sbc->bits[chan][sb] == 0) {
+ i++;
+ continue;
+ }
+ sbc->output[i++] =
+ sbc_load_bits_crc(sbc, sbc->bits[chan][sb]);
+ }
+ }
+ }
+
+ sbc_decode(cfg);
+
+ sbc->rem_off = 0;
+ sbc->rem_len = sbc->blocks * sbc->channels * sbc->bands;
+
+ return ((sbc->bitoffset + 7) / 8);
+}
diff --git a/lib/virtual_oss/bt/sbc_encode.h b/lib/virtual_oss/bt/sbc_encode.h
new file mode 100644
index 000000000000..71f8460a242e
--- /dev/null
+++ b/lib/virtual_oss/bt/sbc_encode.h
@@ -0,0 +1,82 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ *
+ * This software is dedicated to the memory of -
+ * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
+ *
+ * Barry was a man who loved his music.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SBC_ENCODE_H_
+#define _SBC_ENCODE_H_
+
+#define MIN_BITPOOL 2
+#define DEFAULT_MAXBPOOL 250
+
+/*
+ * SBC header format
+ */
+struct sbc_header {
+ uint8_t id;
+ uint8_t id2;
+ uint8_t seqnumMSB;
+ uint8_t seqnumLSB;
+ uint8_t ts3;
+ uint8_t ts2;
+ uint8_t ts1;
+ uint8_t ts0;
+ uint8_t reserved3;
+ uint8_t reserved2;
+ uint8_t reserved1;
+ uint8_t reserved0;
+ uint8_t numFrames;
+};
+
+struct sbc_encode {
+ int16_t music_data[256];
+ uint8_t data[1024];
+ uint8_t *rem_data_ptr;
+ int rem_data_len;
+ int rem_data_frames;
+ int bits[2][8];
+ float output[256];
+ float left[160];
+ float right[160];
+ float samples[16][2][8];
+ uint32_t rem_len;
+ uint32_t rem_off;
+ uint32_t bitoffset;
+ uint32_t maxoffset;
+ uint32_t crc;
+ uint16_t framesamples;
+ uint8_t scalefactor[2][8];
+ uint8_t channels;
+ uint8_t bands;
+ uint8_t blocks;
+ uint8_t join;
+};
+
+#endif /* _SBC_ENCODE_H_ */
diff --git a/lib/virtual_oss/null/Makefile b/lib/virtual_oss/null/Makefile
new file mode 100644
index 000000000000..ec5c2d40f665
--- /dev/null
+++ b/lib/virtual_oss/null/Makefile
@@ -0,0 +1,10 @@
+SHLIB_NAME= voss_null.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= null.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate
+LIBADD= samplerate
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/null/null.c b/lib/virtual_oss/null/null.c
new file mode 100644
index 000000000000..149c6e3e8c6a
--- /dev/null
+++ b/lib/virtual_oss/null/null.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2015-2022 Hans Petter Selasky
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/filio.h>
+#include <sys/soundcard.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <time.h>
+
+#include "backend.h"
+#include "int.h"
+
+static void
+null_close(struct voss_backend *pbe __unused)
+{
+}
+
+static int
+null_open(struct voss_backend *pbe __unused, const char *devname __unused,
+ int samplerate __unused, int bufsize __unused, int *pchannels __unused,
+ int *pformat)
+{
+ int value[3];
+ int i;
+
+ value[0] = *pformat & VPREFERRED_SNE_AFMT;
+ value[1] = *pformat & VPREFERRED_SLE_AFMT;
+ value[2] = *pformat & VPREFERRED_SBE_AFMT;
+
+ for (i = 0; i != 3; i++) {
+ if (value[i] == 0)
+ continue;
+ *pformat = value[i];
+ return (0);
+ }
+ return (-1);
+}
+
+static int
+null_rec_transfer(struct voss_backend *pbe __unused, void *ptr, int len)
+{
+
+ if (voss_has_synchronization == 0)
+ virtual_oss_wait();
+ memset(ptr, 0, len);
+ return (len);
+}
+
+static int
+null_play_transfer(struct voss_backend *pbe __unused, void *ptr __unused,
+ int len)
+{
+ return (len);
+}
+
+static void
+null_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_null_rec = {
+ .open = null_open,
+ .close = null_close,
+ .transfer = null_rec_transfer,
+ .delay = null_delay,
+};
+
+struct voss_backend voss_backend_null_play = {
+ .open = null_open,
+ .close = null_close,
+ .transfer = null_play_transfer,
+ .delay = null_delay,
+};
diff --git a/lib/virtual_oss/oss/Makefile b/lib/virtual_oss/oss/Makefile
new file mode 100644
index 000000000000..257d7f0c0bae
--- /dev/null
+++ b/lib/virtual_oss/oss/Makefile
@@ -0,0 +1,10 @@
+SHLIB_NAME= voss_oss.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= oss.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate
+LIBADD= samplerate
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/oss/oss.c b/lib/virtual_oss/oss/oss.c
new file mode 100644
index 000000000000..b4779f9108d9
--- /dev/null
+++ b/lib/virtual_oss/oss/oss.c
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 2015-2019 Hans Petter Selasky
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/filio.h>
+#include <sys/soundcard.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <poll.h>
+
+#include "backend.h"
+#include "int.h"
+
+static int
+oss_set_format(int fd, int *format)
+{
+ int value[6];
+ int error;
+ int fmt;
+ int i;
+
+ value[0] = *format & VPREFERRED_SNE_AFMT;
+ value[1] = *format & VPREFERRED_UNE_AFMT;
+ value[2] = *format & VPREFERRED_SLE_AFMT;
+ value[3] = *format & VPREFERRED_SBE_AFMT;
+ value[4] = *format & VPREFERRED_ULE_AFMT;
+ value[5] = *format & VPREFERRED_UBE_AFMT;
+
+ for (i = 0; i != 6; i++) {
+ fmt = value[i];
+ if (fmt == 0)
+ continue;
+ error = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
+ /* make sure we got the format we asked for */
+ if (error == 0 && fmt == value[i]) {
+ *format = fmt;
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+static void
+oss_close(struct voss_backend *pbe)
+{
+ if (pbe->fd > -1) {
+ close(pbe->fd);
+ pbe->fd = -1;
+ }
+}
+
+static int
+oss_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat, int attr, int fionbio)
+{
+ int temp;
+ int err;
+
+ pbe->fd = open(devname, attr);
+ if (pbe->fd < 0) {
+ warn("Could not open DSP device '%s'", devname);
+ return (-1);
+ }
+ err = ioctl(pbe->fd, FIONBIO, &fionbio);
+ if (err < 0) {
+ warn("Could not set blocking mode on DSP");
+ goto error;
+ }
+ err = oss_set_format(pbe->fd, pformat);
+ if (err < 0) {
+ warn("Could not set sample format 0x%08x", *pformat);
+ goto error;
+ }
+ temp = *pchannels;
+ bufsize /= temp; /* get buffer size per channel */
+ do {
+ err = ioctl(pbe->fd, SOUND_PCM_WRITE_CHANNELS, &temp);
+ } while (err < 0 && --temp > 0);
+
+ err = ioctl(pbe->fd, SOUND_PCM_READ_CHANNELS, &temp);
+ if (err < 0 || temp <= 0 || temp > *pchannels) {
+ warn("Could not set DSP channels: %d / %d", temp, *pchannels);
+ goto error;
+ }
+ *pchannels = temp;
+
+ temp = samplerate;
+ err = ioctl(pbe->fd, SNDCTL_DSP_SPEED, &temp);
+ if (err < 0 || temp != samplerate) {
+ warn("Could not set sample rate to %d / %d Hz", temp, samplerate);
+ goto error;
+ }
+
+ temp = bufsize * (*pchannels);
+ err = ioctl(pbe->fd, SNDCTL_DSP_SETBLKSIZE, &temp);
+ if (err < 0) {
+ warn("Could not set block size to %d", temp);
+ goto error;
+ }
+ return (0);
+error:
+ close(pbe->fd);
+ pbe->fd = -1;
+ return (-1);
+}
+
+static int
+oss_rec_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ return (oss_open(pbe, devname, samplerate, bufsize, pchannels, pformat, O_RDONLY, 0));
+}
+
+static int
+oss_play_open(struct voss_backend *pbe, const char *devname, int samplerate,
+ int bufsize, int *pchannels, int *pformat)
+{
+ bufsize *= 4; /* XXX allow extra space for jitter */
+ return (oss_open(pbe, devname, samplerate, bufsize, pchannels, pformat, O_WRONLY, 0));
+}
+
+static int
+oss_rec_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ struct pollfd fds = { .fd = pbe->fd, .events = POLLIN | POLLRDNORM };
+ int err;
+
+ /* wait at maximum 2 seconds for data, else something is wrong */
+ err = poll(&fds, 1, 2000);
+ if (err < 1)
+ return (-1);
+ return (read(pbe->fd, ptr, len));
+}
+
+static int
+oss_play_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (write(pbe->fd, ptr, len));
+}
+
+static void
+oss_rec_delay(struct voss_backend *pbe, int *pdelay)
+{
+ if (ioctl(pbe->fd, FIONREAD, pdelay) != 0)
+ *pdelay = -1;
+}
+
+static void
+oss_play_delay(struct voss_backend *pbe, int *pdelay)
+{
+ if (voss_has_synchronization != 0 ||
+ ioctl(pbe->fd, SNDCTL_DSP_GETODELAY, pdelay) != 0)
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_oss_rec = {
+ .open = oss_rec_open,
+ .close = oss_close,
+ .transfer = oss_rec_transfer,
+ .delay = oss_rec_delay,
+ .fd = -1,
+};
+
+struct voss_backend voss_backend_oss_play = {
+ .open = oss_play_open,
+ .close = oss_close,
+ .transfer = oss_play_transfer,
+ .delay = oss_play_delay,
+ .fd = -1,
+};
diff --git a/lib/virtual_oss/sndio/Makefile b/lib/virtual_oss/sndio/Makefile
new file mode 100644
index 000000000000..9b5af63a3246
--- /dev/null
+++ b/lib/virtual_oss/sndio/Makefile
@@ -0,0 +1,12 @@
+SHLIB_NAME= voss_sndio.so
+SHLIBDIR= ${LIBDIR}/virtual_oss
+
+SRCS= sndio.c
+
+CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \
+ -I${SRCTOP}/contrib/libsamplerate \
+ -I${LOCALBASE:U/usr/local}/include
+LDFLAGS+= -L${LOCALBASE:U/usr/local}/lib -lsndio
+LIBADD= samplerate
+
+.include <bsd.lib.mk>
diff --git a/lib/virtual_oss/sndio/sndio.c b/lib/virtual_oss/sndio/sndio.c
new file mode 100644
index 000000000000..2d1a3411049b
--- /dev/null
+++ b/lib/virtual_oss/sndio/sndio.c
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 2021 Tim Creech <tcreech@tcreech.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/soundcard.h>
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sndio.h>
+
+#include "backend.h"
+#include "int.h"
+
+static struct sio_hdl *
+get_sio_hdl(struct voss_backend *pbe)
+{
+ if (pbe)
+ return (pbe->arg);
+
+ return (NULL);
+}
+
+static void
+sndio_close(struct voss_backend *pbe)
+{
+ if (!pbe)
+ return;
+
+ if (get_sio_hdl(pbe))
+ sio_close(get_sio_hdl(pbe));
+}
+
+static int
+sndio_get_signedness(int *fmt)
+{
+ int s_fmt = *fmt & (VPREFERRED_SLE_AFMT | VPREFERRED_SBE_AFMT);
+
+ if (s_fmt) {
+ *fmt = s_fmt;
+ return (1);
+ }
+ *fmt = *fmt & (VPREFERRED_ULE_AFMT | VPREFERRED_UBE_AFMT);
+ return (0);
+}
+
+static int
+sndio_get_endianness_is_le(int *fmt)
+{
+ int le_fmt = *fmt & (VPREFERRED_SLE_AFMT | VPREFERRED_ULE_AFMT);
+
+ if (le_fmt) {
+ *fmt = le_fmt;
+ return (1);
+ }
+ *fmt = *fmt & (VPREFERRED_SBE_AFMT | VPREFERRED_UBE_AFMT);
+ return (0);
+}
+
+static int
+sndio_get_bits(int *fmt)
+{
+ if (*fmt & AFMT_16BIT)
+ return (16);
+ if (*fmt & AFMT_24BIT)
+ return (24);
+ if (*fmt & AFMT_32BIT)
+ return (32);
+ if (*fmt & AFMT_8BIT)
+ return (8);
+ return (-1);
+ /* TODO AFMT_BIT */
+}
+
+static int
+sndio_open(struct voss_backend *pbe, const char *devname,
+ int samplerate, int bufsize, int *pchannels, int *pformat, int direction)
+{
+ const char *sndio_name = devname + strlen("/dev/sndio/");
+
+ int sig = sndio_get_signedness(pformat);
+ int le = sndio_get_endianness_is_le(pformat);
+ int bits = sndio_get_bits(pformat);
+
+ if (bits == -1) {
+ warn("unsupported format precision");
+ return (-1);
+ }
+
+ struct sio_hdl *hdl = sio_open(sndio_name, direction, 0);
+
+ if (hdl == 0) {
+ warn("sndio: failed to open device");
+ return (-1);
+ }
+
+ struct sio_par par;
+
+ sio_initpar(&par);
+ par.pchan = *pchannels;
+ par.sig = sig;
+ par.bits = bits;
+ par.bps = SIO_BPS(bits);
+ par.le = le;
+ par.rate = samplerate;
+ par.appbufsz = bufsize;
+ par.xrun = SIO_SYNC;
+ if (!sio_setpar(hdl, &par))
+ errx(1, "internal error, sio_setpar() failed");
+ if (!sio_getpar(hdl, &par))
+ errx(1, "internal error, sio_getpar() failed");
+ if ((int)par.pchan != *pchannels)
+ errx(1, "couldn't set number of channels");
+ if ((int)par.sig != sig || (int)par.bits != bits || (int)par.le != le)
+ errx(1, "couldn't set format");
+ if ((int)par.bits != bits)
+ errx(1, "couldn't set precision");
+ if ((int)par.rate < samplerate * 995 / 1000 ||
+ (int)par.rate > samplerate * 1005 / 1000)
+ errx(1, "couldn't set rate");
+ if (par.xrun != SIO_SYNC)
+ errx(1, "couldn't set xun policy");
+
+ /* Save the device handle with the backend */
+ pbe->arg = hdl;
+
+ /* Start the device. */
+ if (!sio_start(hdl))
+ errx(1, "couldn't start device");
+
+ return (0);
+}
+
+static int
+sndio_open_play(struct voss_backend *pbe, const char *devname,
+ int samplerate, int bufsize, int *pchannels, int *pformat)
+{
+ return (sndio_open(pbe, devname, samplerate, bufsize, pchannels, pformat, SIO_PLAY));
+}
+
+static int
+sndio_open_rec(struct voss_backend *pbe, const char *devname,
+ int samplerate, int bufsize, int *pchannels, int *pformat)
+{
+ return (sndio_open(pbe, devname, samplerate, bufsize, pchannels, pformat, SIO_REC));
+}
+
+static int
+sndio_play_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (sio_write(get_sio_hdl(pbe), ptr, len));
+}
+
+static int
+sndio_rec_transfer(struct voss_backend *pbe, void *ptr, int len)
+{
+ return (sio_read(get_sio_hdl(pbe), ptr, len));
+}
+
+static void
+sndio_delay(struct voss_backend *pbe __unused, int *pdelay)
+{
+ *pdelay = -1;
+}
+
+struct voss_backend voss_backend_sndio_rec = {
+ .open = sndio_open_rec,
+ .close = sndio_close,
+ .transfer = sndio_rec_transfer,
+ .delay = sndio_delay,
+ .fd = -1,
+};
+
+struct voss_backend voss_backend_sndio_play = {
+ .open = sndio_open_play,
+ .close = sndio_close,
+ .transfer = sndio_play_transfer,
+ .delay = sndio_delay,
+ .fd = -1,
+};