diff options
Diffstat (limited to 'lib')
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, +}; |