Compare commits

...

56 Commits

Author SHA1 Message Date
Guillem Jover
84acf21568 Release libbsd 0.11.6 2022-03-30 23:09:35 +02:00
WANG Xuerui
15200ec7ac Add LoongArch support to nlist()
Closes: !13
Signed-off-by: WANG Xuerui <git@xen0n.name>
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2022-03-30 23:03:56 +02:00
Guillem Jover
f7465b93ec man: Document when functions were added to musl in libbsd(7)
The explicit_bzero(3) and reallocarray(3) functions are also present on
musl libc, mention it in the superseded section.
2022-03-30 22:58:47 +02:00
Guilherme Janczak
e5ed5fdd62 Remove arc4random() OpenBSD support
The arc4random() support for OpenBSD does not build. The intention was
to include any portability code so that the library could be easily
ported to such systems, but it makes little sense to build it on OpenBSD
where most of the functionality will be already present, or the software
would have been ported anyway.

[guillem@hadrons.org: Reword commit message to add rationale. ]

Closes: !15
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2022-03-30 22:55:56 +02:00
Duncan Overbruck
abb1a6b1a7 build: Add alpine to CI for tests with musl libc
Closes: !18
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2022-01-29 15:03:08 +01:00
Guillem Jover
c9ff83687c test: Import explicit_bzero and strtonum test cases from OpenBSD
- Remove trailing spaces.
- Declare file-scope functions and variables static.
- Declare functions with a proper prototype.
- Do not mix declarations and code for C90 conformance.
- Do not compare size_t and ssize_t variables.
2022-01-29 14:54:24 +01:00
Guillem Jover
62e67bb49e build: Sort test programs in .gitignore 2022-01-29 14:52:39 +01:00
Duncan Overbruck
87b1307040 test: Add fpurge() test case using open_memstream(3) FILE
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2022-01-29 14:10:55 +01:00
Duncan Overbruck
ba3c46b30f fpurge: Make it work with non fd based FILEs
Streams opened with for example open_memstream(3) will have no associated
file descriptor, and fileno(3) will fail.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2022-01-26 04:42:09 +01:00
Duncan Overbruck
091097e062 test: Remove static FILE declaration from fpurge test
This does not work with libcs that do not declare the structure
in a header file, like musl. And gets in the way of supporting
non-fd based streams.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2022-01-26 04:39:42 +01:00
Guillem Jover
5f9608c775 Release libbsd 0.11.5 2022-01-25 01:48:29 +01:00
Guillem Jover
eef07993c9 Revert "build: Add missing proctitle unit test program"
This reverts commit beafad2657.

This test was already handled later on as part of the BUILD_LIBBSD_CTOR
conditional. Adding it to the unconditional set made the build fail when
the system does not have GNU .init_array section support.

Closes: #9
Analysis-by: Duncan Overbruck <mail@duncano.de>
2022-01-25 01:41:14 +01:00
Guillem Jover
c6d589bc71 Document how to build from git and from a tarball release
Closes: #8
2022-01-23 21:09:05 +01:00
Guillem Jover
2975d809a0 build: Check for objdump explicitly
We should not assume that something will implicitly check for this tool,
as we need it ourselves, and this is an internal implementation detail
of right now libtool.

Fixes: commit f11ab67223
2022-01-23 20:52:26 +01:00
Sam James
f11ab67223 build: Respect $(OBJDUMP)
We already search for it in `./configure` so let's respect
the result of that search.

This helps with cross-compilation and any other cases
where one might want to choose a different toolchain.

Closes: !16
Bug: https://bugs.gentoo.org/831863
Signed-off-by: Sam James <sam@gentoo.org>
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2022-01-23 18:42:01 +01:00
Guillem Jover
54796231c7 Release libbsd 0.11.4 2022-01-22 22:41:51 +01:00
Guillem Jover
7aed0edf73 man: Add missing comma in .Dd for tree(3)
Reported-by: Thorsten Glaser <tg@mirbsd.de>
2021-12-02 00:35:40 +01:00
Guillem Jover
fafcc397ac man: Update tree(3) man page from OpenBSD
This man page has a BSD-3-clause-author license instead of the old
BSD-4-clause license.
2021-12-01 04:17:11 +01:00
Guillem Jover
48107fc8c4 build: Clarify link-time warnings
Mention the involved function instead of stating an implicit "this
function". Mention libbsd when proposing using an alternative libmd
to make the context clear.
2021-12-01 04:17:11 +01:00
Guillem Jover
e7cf8c5785 Switch md5 compatibility logic back to direct linking
When using the recent dlsym() based wrapper, we are not requiring any
symbol from libmd, as we resolve those dynamically at run-time. We were
ending up linking against libmd because in another part of the code we
require (depending on the architecture) the SHA512 functions for the
getentropy() local implementation. But that function might be provided
by the system libc on some systems, which means we end up not linking
against libmd at all.

To solve this we go back to the previous simpler solution of linking
directly, which had the main drawback of then making programs fail to
link when not specifying -lmd (on platforms that need it). And then
switch the .so link point from a symlink to a linker script, so that we
can inject the -lmd library as-needed. This is similar to what glibc is
doing.

Fixes: commit 31f034e386
2021-12-01 04:14:35 +01:00
Guillem Jover
25d35625eb build: Split libmd dependency due to MD5 functions from SHA requirements
To be able to rework the md5 deprecation logic, we need to detangle when
we depend on libmd due to requiring MD5 functions, which might be
otherwise provided by libc, or when we require SHA functions for the
internal getentropy() implementation.
2021-11-28 22:40:58 +01:00
Guillem Jover
500b3080a2 build: Add new libbsd_symver_weak() macro
We will use it for the reworked md5 deprecation logic.
2021-11-28 22:34:59 +01:00
Guillem Jover
1eba406021 test: Check that strdup() does not fail
Warned-by: gcc
2021-11-27 23:42:37 +01:00
Guillem Jover
8ad7570c20 getentropy: Add missing prototype for BSD variant
Warned-by: gcc
2021-11-27 23:42:37 +01:00
Guillem Jover
43a8270317 nlist: Remove condition which is always true
The nlist() function is limited to handle ELF binaries of the same class
as size as the size_t of the architecture built.

In addition the SIZE_T_MAX macro is BSD specific, and was falling back
to the wrong constant on most 64-bit non-BSD systems.

Warned-by: gcc
2021-11-27 23:36:34 +01:00
Guillem Jover
6a71b24b63 build: Append __ after __attribute and __typeof keywords
Be consistent with other usages in the code base.
2021-11-27 22:53:32 +01:00
Guillem Jover
7389fe8d24 build: Ignore backup files 2021-11-27 06:54:49 +01:00
Victor Westerhuis
2716dfd0b7 test: Explicitly mark symbols as used
Because some of the symbols are not otherwise referenced, GCC would like
to remove them.

Closes: !14
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-11-27 06:52:17 +01:00
Victor Westerhuis
54f8745657 build: Enable .init_array support when building with LTO
Because these symbols are not otherwise referenced, GCC would like
to remove them.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-11-27 06:51:02 +01:00
Guillem Jover
428be9e030 man: Fix .Nx macro usage
Its arguments are used as version numbers, so we need continue the
content on the next line.
2021-11-27 05:06:14 +01:00
Alexander Miller
c7a5d780ae build: Allow building with -flto on gcc-10 and newer
Global asm statements (like .symver directives) do not work reliably
in gcc with link time optimization. Use the symver attribute introduced
with gcc-10 to set symbol versions instead, if available.

[guillem@hadrons.org:
 - Simplify by using __has_attribute fallback from <sys/cdefs.h>.
 - Coding style changes. ]

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-11-27 05:06:14 +01:00
Guillem Jover
1808d64b77 test: Fix pipe_feed() to allow checking fprintf format strings
Warned-by: gcc -W
2021-11-27 05:06:14 +01:00
Guillem Jover
beafad2657 build: Add missing proctitle unit test program 2021-11-27 05:06:14 +01:00
Guillem Jover
6145b56178 test: Do not pass NULL as the first funopen() argument
Warned-by: gcc -W
2021-11-27 05:06:14 +01:00
Guillem Jover
731b0a7739 build: Detect sed at configure time
Check whether sed is available and use the implementation matching the
requirements via the SED variable.
2021-11-27 05:06:14 +01:00
Guillem Jover
50b50a4330 vis: Add prototypes for strnvis() and strnunvis() variants
Warned-by: gcc
2021-11-27 05:06:14 +01:00
Guillem Jover
25e88f6479 test: Cast literal strings to (char *) on n_name assignment
The member is declared as n_name so we cannot directly assign a literal
string constant.

Warned-by: gcc
2021-11-27 05:06:14 +01:00
Guillem Jover
04a8fb2469 Add missing prototypes to functions
Warned-by: gcc
2021-11-27 05:06:14 +01:00
Guillem Jover
4f68a88f55 build: Add compiler warnings support
Detect as many warnings as possible during configure and enable them
if the user did not supply any, so that any such problem can be spotted
and fixed.
2021-11-27 05:06:14 +01:00
Guillem Jover
8f59221c4f nlist: Remove repeated shadowing variable declaration
Warned-by: gcc
2021-02-28 05:30:37 +01:00
Guillem Jover
72a82ee262 getentropy: Fix function cast for getauxval()
Warned-by: gcc
2021-02-28 05:30:37 +01:00
Guillem Jover
3c305f2873 test: Add proper prototypes for main() function
Warned-by: gcc
2021-02-28 05:30:31 +01:00
Guillem Jover
25278891d8 Mark local functions as static
Warned-by: gcc
2021-02-28 05:30:25 +01:00
Guillem Jover
e35d9141dc Add link-time warnings to MD5 wrapper functions
Let's get the word out that these functions are deprecated and should be
switched away from.
2021-02-28 05:28:57 +01:00
Guillem Jover
4feda87049 Require a semicolon for libbsd_link_warning() macro
Remove the semicolon in the macro definition to force adding one on the
call sites, to make the code look like an actual function.
2021-02-28 05:28:57 +01:00
Guillem Jover
d563a17430 man: Call the libbsd-ctor library by its name instead of bsd-ctor 2021-02-28 05:28:57 +01:00
Guillem Jover
785cf9d1e9 man: Fix pkg-config(1) references in libbsd(7) man page 2021-02-28 05:28:57 +01:00
Guillem Jover
15bd284b29 build: Add code coverage support in the GitLab CI 2021-02-28 05:28:49 +01:00
Guillem Jover
a9fc285988 build: Use apt-get instead of apt in the GitLab CI
The former is to be used programmatically, while the latter is intended
for interactive use.
2021-02-28 05:27:35 +01:00
Guillem Jover
c0d86a6412 build: Add a Libs.private field to overlay pkg-config file
We need to list all internal libraries there so that we can statically
link.

Fixes: commit 2374f409de
2021-02-09 08:36:01 +01:00
Guillem Jover
1fb25b7dca Release libbsd 0.11.3 2021-02-09 06:23:38 +01:00
Guillem Jover
31f034e386 Switch libmd wrapper to use dlsym()
Switch from the previous versioned symbol implementation which required
users to also link against the message digest provider explicitly, or
they would fail to find the symbols, to an implementation that loads
the symbols from the linked library providing the functions using
dlsym(), thus preserving backwards compatibility.
2021-02-09 06:23:38 +01:00
Guillem Jover
2374f409de build: Add a Libs.private field to pkg-config file
We need to list all internal libraries there so that we can statically
link.
2021-02-09 06:23:38 +01:00
Guillem Jover
a4e0db2b97 build: Use a single variable to track libraries to link against
Using various variables means we have to keep these in sync in various
places. Just use a single variable that we can use anywhere where this
is needed.
2021-02-09 06:23:38 +01:00
Guillem Jover
43d34c9d3b build: Fix message digest library checks
They were not failing when not finding the SHA-2 functions and
were hardcoding -lmd regardless of what library had been found.
2021-02-09 06:23:38 +01:00
Guillem Jover
1c3ff61699 Use uintptr_t and size_t instead of __-prefixed types in <sys/cdefs.h>
The __-prefixed types cannot be assumed to be defined. Use the standard
types instead.

Closes: #6
2021-02-09 06:23:27 +01:00
47 changed files with 908 additions and 338 deletions

5
.gitignore vendored
View File

@@ -1,4 +1,5 @@
ChangeLog
*~
*.pc
*.la
*.lo
@@ -7,6 +8,8 @@ ChangeLog
*.a
*.log
*.trs
*.gcda
*.gcno
.dirstamp
.deps/
.libs/
@@ -17,6 +20,6 @@ autom4te.cache/
build-aux/
configure
config.*
format.ld
libtool
m4/
stamp-h1

View File

@@ -1,9 +1,37 @@
image: debian:buster
test:
before_script:
- apt update -qq
- apt install -qq -y --no-install-recommends git gcc make autoconf automake libtool libmd-dev
.unit-tests:
script:
- ./autogen && ./configure
- make check
.coverage:
script:
- ./autogen && ./configure --disable-static
- make check CFLAGS="--coverage -O0 -ggdb" LDFLAGS="--coverage -O0 -ggdb"
- gcovr -s -e test/
.debian:
image: debian:buster
stage: test
before_script:
- apt-get update -qq
- apt-get install -qq -y --no-install-recommends
git gcc make autoconf automake libtool libmd-dev gcovr
.alpine:
image: alpine:latest
stage: test
before_script:
- apk add --no-cache git gcc make autoconf automake libtool
bsd-compat-headers linux-headers libmd-dev musl-dev gcovr
unit-tests:debian:
extends: [.debian, .unit-tests]
coverage:debian:
extends: [.debian, .coverage]
unit-tests:alpine:
extends: [.alpine, .unit-tests]
coverage:alpine:
extends: [.alpine, .coverage]

View File

@@ -3,12 +3,11 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Files:
*
Copyright:
Copyright © 2004-2006, 2008-2021 Guillem Jover <guillem@hadrons.org>
Copyright © 2004-2006, 2008-2022 Guillem Jover <guillem@hadrons.org>
License: BSD-3-clause
Files:
man/arc4random.3bsd
man/tree.3bsd
Copyright:
Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
All rights reserved.
@@ -348,6 +347,7 @@ License: BSD-2-clause-verbatim
Files:
include/bsd/sys/tree.h
man/fparseln.3bsd
man/tree.3bsd
src/fparseln.c
Copyright:
Copyright © 1997 Christos Zoulas.
@@ -364,7 +364,6 @@ Files:
man/strtonum.3bsd
src/arc4random.c
src/arc4random_linux.h
src/arc4random_openbsd.h
src/arc4random_uniform.c
src/arc4random_unix.h
src/arc4random_win.h
@@ -383,6 +382,8 @@ Files:
src/recallocarray.c
src/strlcat.c
src/strlcpy.c
test/explicit_bzero.c
test/strtonum.c
Copyright:
Copyright © 2004 Ted Unangst and Todd Miller
All rights reserved.
@@ -391,6 +392,7 @@ Copyright:
Copyright © 1998, 2000-2002, 2004-2005, 2007, 2010, 2012-2015
Todd C. Miller <Todd.Miller@courtesan.com>
Copyright © 2004 Ted Unangst
Copyright © 2004 Otto Moerbeek <otto@drijf.net>
Copyright © 2008 Damien Miller <djm@openbsd.org>
Copyright © 2008, 2010-2011, 2016-2017 Otto Moerbeek <otto@drijf.net>
Copyright © 2013 Markus Friedl <markus@openbsd.org>
@@ -398,6 +400,7 @@ Copyright:
Copyright © 2014 Brent Cook <bcook@openbsd.org>
Copyright © 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
Copyright © 2014 Theo de Raadt <deraadt@openbsd.org>
Copyright © 2014 Google Inc.
Copyright © 2015 Michael Felt <aixtools@gmail.com>
Copyright © 2015 Guillem Jover <guillem@hadrons.org>
License: ISC

32
README
View File

@@ -37,3 +37,35 @@ The master repository can be browsed at:
and cloned from:
<https://anongit.freedesktop.org/git/libbsd>
Building from git source
------------------------
To prepare the libbsd source tree from git before starting the build process
some required software needs to be installed:
GNU autoconf >= 2.67
GNU automake >= 1.9
GNU libtool >= 2.0
After installing the needed software, and running the following command on
the git tree:
$ ./autogen
the source should be roughly equivalent to the distributed tar source.
Building from tar source
------------------------
The minimum software required to configure and build dpkg from a tarball is:
C89 compiler
make
The following software might be required depending on the system:
libmd (whenever the libc does not provide the needed digest functions)
The build process is done by running the usual «./configure; make». To
see all available configuration options please run «./configure --help».

View File

@@ -13,7 +13,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
LIBBSD_ABI_MAJOR=0
LIBBSD_ABI_MINOR=11
LIBBSD_ABI_PATCH=2
LIBBSD_ABI_PATCH=6
LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH"
AC_SUBST([LIBBSD_ABI])
@@ -47,14 +47,52 @@ AM_CONDITIONAL([HAVE_LINKER_VERSION_SCRIPT],
[test "x$libbsd_cv_version_script" = "xyes"])
# Checks for programs.
AC_CHECK_TOOL([OBJDUMP], [objdump])
AC_PROG_CC
AC_PROG_SED
AC_PROG_INSTALL
AC_PROG_LN_S
# Set default compiler variables
if test "$user_CFLAGS" = unset && test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter"
fi
AS_IF([test "$user_CFLAGS" = unset], [
LIBBSD_CHECK_COMPILER_FLAG([-Wall])
LIBBSD_CHECK_COMPILER_FLAG([-Wextra])
LIBBSD_CHECK_COMPILER_FLAG([-Wbad-function-cast])
LIBBSD_CHECK_COMPILER_FLAG([-Wc99-c11-compat])
LIBBSD_CHECK_COMPILER_FLAG([-Wcast-align])
LIBBSD_CHECK_COMPILER_FLAG([-Wdeclaration-after-statement])
LIBBSD_CHECK_COMPILER_FLAG([-Wdocumentation])
LIBBSD_CHECK_COMPILER_FLAG([-Wduplicated-branches])
LIBBSD_CHECK_COMPILER_FLAG([-Wduplicated-cond])
LIBBSD_CHECK_COMPILER_FLAG([-Wformat -Wformat-security])
LIBBSD_CHECK_COMPILER_FLAG([-Wformat=2])
LIBBSD_CHECK_COMPILER_FLAG([-Winit-self])
LIBBSD_CHECK_COMPILER_FLAG([-Wlogical-not-parentheses])
LIBBSD_CHECK_COMPILER_FLAG([-Wlogical-op])
LIBBSD_CHECK_COMPILER_FLAG([-Wmissing-declarations])
LIBBSD_CHECK_COMPILER_FLAG([-Wmissing-format-attribute])
LIBBSD_CHECK_COMPILER_FLAG([-Wmissing-prototypes])
LIBBSD_CHECK_COMPILER_FLAG([-Wnested-externs])
LIBBSD_CHECK_COMPILER_FLAG([-Wno-missing-field-initializers])
LIBBSD_CHECK_COMPILER_FLAG([-Wno-nonnull-compare])
LIBBSD_CHECK_COMPILER_FLAG([-Wno-tautological-constant-out-of-range-compare])
LIBBSD_CHECK_COMPILER_FLAG([-Wno-unused-parameter])
LIBBSD_CHECK_COMPILER_FLAG([-Wnull-dereference])
LIBBSD_CHECK_COMPILER_FLAG([-Wold-style-definition])
LIBBSD_CHECK_COMPILER_FLAG([-Wpointer-arith])
LIBBSD_CHECK_COMPILER_FLAG([-Wregister])
LIBBSD_CHECK_COMPILER_FLAG([-Wrestrict])
LIBBSD_CHECK_COMPILER_FLAG([-Wshadow])
LIBBSD_CHECK_COMPILER_FLAG([-Wshift-negative-value])
LIBBSD_CHECK_COMPILER_FLAG([-Wsizeof-array-argument])
LIBBSD_CHECK_COMPILER_FLAG([-Wstrict-prototypes])
LIBBSD_CHECK_COMPILER_FLAG([-Wswitch-bool])
LIBBSD_CHECK_COMPILER_FLAG([-Wvla])
LIBBSD_CHECK_COMPILER_FLAG([-Wwrite-strings])
CFLAGS="$CFLAGS $LIBBSD_COMPILER_FLAGS"
])
# Checks for libraries.
AC_CHECK_LIB([testu01], [unif01_CreateExternGenBits],
@@ -65,15 +103,25 @@ AM_CONDITIONAL([HAVE_LIBTESTU01],
saved_LIBS="$LIBS"
AC_SEARCH_LIBS([MD5Update], [md], [
AC_SEARCH_LIBS([SHA512Update], [md], [
MD_LIBS="-lmd"
AS_IF([test "x$ac_cv_search_MD5Update" != "xnone required"], [
MD5_LIBS="$MD5_LIBS $ac_cv_search_MD5Update"
need_transparent_libmd=yes
])
], [
AC_MSG_ERROR([cannot find required message digest functions in libc or libmd])
AC_MSG_ERROR([cannot find required MD5 functions in libc or libmd])
])
AC_SEARCH_LIBS([SHA512Update], [md], [
AS_IF([test "x$ac_cv_search_SHA512Update" != "xnone required"], [
LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_SHA512Update"
])
], [
AC_MSG_ERROR([cannot find required SHA-2 functions in libc or libmd])
])
AC_SUBST([MD_LIBS])
LIBS="$saved_LIBS"
AM_CONDITIONAL([NEED_TRANSPARENT_LIBMD],
[test "x$need_transparent_libmd" = "xyes"])
is_windows=no
AS_CASE([$host_os],
[*-gnu*], [
@@ -81,10 +129,9 @@ AS_CASE([$host_os],
saved_LIBS="$LIBS"
AC_SEARCH_LIBS([clock_gettime], [rt], [
AS_IF([test "x$ac_cv_search_clock_gettime" != "xnone required"], [
CLOCK_GETTIME_LIBS="$ac_cv_search_clock_gettime"
LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_clock_gettime"
])
])
AC_SUBST([CLOCK_GETTIME_LIBS])
LIBS="$saved_LIBS"
],
[*-musl*], [
@@ -126,7 +173,7 @@ AC_CACHE_CHECK(
[[
static int rc = 1;
static void init(int argc) { if (argc == 1) rc = 0; }
void (*init_func)(int argc) __attribute__((__section__(".init_array"))) = init;
void (*init_func)(int argc) __attribute__((__section__(".init_array"), __used__)) = init;
int main() { return rc; }
]]
)],
@@ -192,8 +239,7 @@ AC_LINK_IFELSE(
[AC_DEFINE([HAVE___REGISTER_ATFORK], [1],
[Define to 1 if you have __register_atfork])
AC_MSG_RESULT([yes])],
[ARC4RANDOM_ATFORK_LIBS="-pthread"
AC_SUBST([ARC4RANDOM_ATFORK_LIBS])
[LIBBSD_LIBS="$LIBBSD_LIBS -pthread"
AC_MSG_RESULT([no])
])
@@ -202,6 +248,9 @@ AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
pstat_getproc sysconf])
AM_CONDITIONAL([HAVE_GETENTROPY], [test "x$ac_cv_func_getentropy" = "xtrue"])
AC_SUBST([MD5_LIBS])
AC_SUBST([LIBBSD_LIBS])
AC_CONFIG_FILES([
Makefile
include/Makefile

View File

@@ -187,10 +187,10 @@
# else
# ifndef __cplusplus
# define __offsetof(type, field) \
((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field))
((size_t)(uintptr_t)((const volatile void *)&((type *)0)->field))
# else
# define __offsetof(type, field) \
(__offsetof__ (reinterpret_cast <__size_t> \
(__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<type *> (0)->field))))
# endif
@@ -243,15 +243,15 @@
#endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var))
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
#endif
#ifndef __DEVOLATILE
#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var))
#define __DEVOLATILE(type, var) ((type)(uintptr_t)(volatile void *)(var))
#endif
#ifndef __DEQUALIFY
#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var))
#define __DEQUALIFY(type, var) ((type)(uintptr_t)(const volatile void *)(var))
#endif
#endif

2
m4/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.m4
!libbsd*.m4

24
m4/libbsd-compiler.m4 Normal file
View File

@@ -0,0 +1,24 @@
# Copyright © 2021 Guillem Jover <guillem@hadrons.org>
# LIBBSD_CHECK_COMPILER_FLAG
# -------------------------
AC_DEFUN([LIBBSD_CHECK_COMPILER_FLAG], [
AS_VAR_PUSHDEF([libbsd_varname_cache], [libbsd_cv_cflags_$1])
AC_CACHE_CHECK([whether $CC accepts $1], [libbsd_varname_cache], [
m4_define([libbsd_check_flag], m4_bpatsubst([$1], [^-Wno-], [-W]))
AS_VAR_COPY([libbsd_save_CFLAGS], [CFLAGS])
AS_VAR_SET([CFLAGS], ["-Werror libbsd_check_flag"])
AC_COMPILE_IFELSE([
AC_LANG_SOURCE([[]])
], [
AS_VAR_SET([libbsd_varname_cache], [yes])
], [
AS_VAR_SET([libbsd_varname_cache], [no])
])
AS_VAR_COPY([CFLAGS], [libbsd_save_CFLAGS])
])
AS_VAR_IF([libbsd_varname_cache], [yes], [
AS_VAR_APPEND([LIBBSD_COMPILER_FLAGS], [" $1"])
])
AS_VAR_POPDEF([libbsd_varname_cache])
])

View File

@@ -11,7 +11,7 @@ CLEANFILES = \
SED_MD5_SUBST = -e 's/mdX/md5/g' -e 's/mdY/md4/g' -e 's/MDX/MD5/g'
md5.3bsd: $(srcdir)/mdX.3bsd
$(AM_V_GEN) sed $(SED_MD5_SUBST) $< > $@
$(AM_V_GEN) $(SED) $(SED_MD5_SUBST) $< > $@
dist_man_MANS = \
LIST_CLASS_ENTRY.3bsd \

View File

@@ -1,6 +1,6 @@
.\" libbsd man page
.\"
.\" Copyright © 2017-2018 Guillem Jover <guillem@hadrons.org>
.\" Copyright © 2017-2022 Guillem Jover <guillem@hadrons.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -24,7 +24,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 21, 2018
.Dd Mar 30, 2022
.Dt LIBBSD 7
.Os
.Sh NAME
@@ -42,7 +42,7 @@ The library can be used in an overlay mode, which is the preferred way, so
that the code is portable and requires no modification to the original BSD
code.
This can be done easily with the
.Xr pkg-config 3
.Xr pkg-config 1
library named
.Pa libbsd-overlay .
Or by adding the system-specific include directory with the
@@ -64,7 +64,7 @@ this is less portable as it makes using
mandatory and it will not work on BSD-based systems, and requires
modifying original BSD code.
This can be done with the
.Xr pkg-config 3
.Xr pkg-config 1
library named
.Pa libbsd .
The includes in this case should be namespaced with
@@ -73,13 +73,13 @@ such as
.In bsd/unistd.h .
.Pp
The package also provides a
.Pa bsd-ctor
.Nm libbsd-ctor
static library that can be used to inject automatic constructors into a
program so that the
.Fn setproctitle_init 3
function gets invoked automatically at startup time.
This can be done with the
.Xr pkg-config 3
.Xr pkg-config 1
library named
.Pa libbsd-ctor .
.Sh HEADERS
@@ -160,7 +160,8 @@ functions and is now more widespread.
Define
.Dv LIBBSD_NETBSD_VIS
to switch to the
.Nx one now.
.Nx
one now.
Define
.Dv LIBBSD_OPENBSD_VIS
to keep using the
@@ -229,11 +230,15 @@ companion library, so it is advised to switch to use that directly instead.
.It Fn explicit_bzero 3
This function is provided by
.Nm glibc
2.25.
2.25, and
.Nm musl
1.1.20.
.It Fn reallocarray 3
This function is provided by
.Nm glibc
2.26.
2.26, and
.Nm musl
1.2.2.
.El
.Sh SEE ALSO
.Xr arc4random 3bsd ,

View File

@@ -1,36 +1,29 @@
.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $
.\"
.\" Copyright 2002 Niels Provos <provos@citi.umich.edu>
.\" 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.
.\" 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Niels Provos.
.\" 4. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" 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 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.
.\"
.\" $FreeBSD$
.\"
.Dd December 27, 2007
.\" $OpenBSD: tree.3,v 1.30 2019/05/10 13:13:14 florian Exp $
.\"/*
.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu>
.\" * 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.
.\" * 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 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.
.\" */
.Dd May 10, 2019
.Dt TREE 3bsd
.Os
.Sh NAME
@@ -70,7 +63,9 @@
.Nm RB_RIGHT ,
.Nm RB_PARENT ,
.Nm RB_FOREACH ,
.Nm RB_FOREACH_SAFE ,
.Nm RB_FOREACH_REVERSE ,
.Nm RB_FOREACH_REVERSE_SAFE ,
.Nm RB_INIT ,
.Nm RB_INSERT ,
.Nm RB_REMOVE
@@ -84,88 +79,92 @@
(See
.Xr libbsd 7
for include usage.)
.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP
.Fn SPLAY_GENERATE NAME TYPE FIELD CMP
.Fn SPLAY_ENTRY TYPE
.Fn SPLAY_HEAD HEADNAME TYPE
.Pp
.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP"
.Fn SPLAY_ENTRY "TYPE"
.Fn SPLAY_HEAD "HEADNAME" "TYPE"
.Ft "struct TYPE *"
.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
.Fn SPLAY_ROOT "SPLAY_HEAD *head"
.Ft bool
.Ft "int"
.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
.Ft "struct TYPE *"
.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn SPLAY_MIN NAME "SPLAY_HEAD *head"
.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head"
.Ft "struct TYPE *"
.Fn SPLAY_MAX NAME "SPLAY_HEAD *head"
.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head"
.Ft "struct TYPE *"
.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm"
.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME"
.Ft "struct TYPE *"
.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME"
.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head"
.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head"
.Ft void
.Fn SPLAY_INIT "SPLAY_HEAD *head"
.Ft "struct TYPE *"
.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm"
.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
.Fn RB_GENERATE NAME TYPE FIELD CMP
.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
.Fn RB_ENTRY TYPE
.Fn RB_HEAD HEADNAME TYPE
.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Pp
.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_PROTOTYPE_STATIC "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_GENERATE_STATIC "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_ENTRY "TYPE"
.Fn RB_HEAD "HEADNAME" "TYPE"
.Fn RB_INITIALIZER "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_ROOT "RB_HEAD *head"
.Ft "bool"
.Ft "int"
.Fn RB_EMPTY "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm"
.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm"
.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_MIN NAME "RB_HEAD *head"
.Fn RB_MIN "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_MAX NAME "RB_HEAD *head"
.Fn RB_MAX "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm"
.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm"
.Fn RB_NFIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *"
.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *"
.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head"
.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head"
.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head"
.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head"
.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
.Ft void
.Fn RB_INIT "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm"
.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm"
.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Sh DESCRIPTION
These macros define data structures for different types of trees:
splay trees and red-black trees.
.Pp
In the macro definitions,
.Fa TYPE
is the name tag of a user defined structure that must contain a field of type
.Vt SPLAY_ENTRY ,
is the name tag of a user defined structure that must contain a field named
.Fa FIELD ,
of type
.Li SPLAY_ENTRY
or
.Vt RB_ENTRY ,
named
.Fa ENTRYNAME .
.Li RB_ENTRY .
The argument
.Fa HEADNAME
is the name tag of a user defined structure that must be declared
using the macros
.Fn SPLAY_HEAD ,
.Fn SPLAY_HEAD
or
.Fn RB_HEAD .
The argument
@@ -173,46 +172,38 @@ The argument
has to be a unique name prefix for every tree that is defined.
.Pp
The function prototypes are declared with
.Fn SPLAY_PROTOTYPE ,
.Fn RB_PROTOTYPE ,
.Li SPLAY_PROTOTYPE ,
.Li RB_PROTOTYPE ,
or
.Fn RB_PROTOTYPE_STATIC .
.Li RB_PROTOTYPE_STATIC .
The function bodies are generated with
.Fn SPLAY_GENERATE ,
.Fn RB_GENERATE ,
.Li SPLAY_GENERATE ,
.Li RB_GENERATE ,
or
.Fn RB_GENERATE_STATIC .
.Li RB_GENERATE_STATIC .
See the examples below for further explanation of how these macros are used.
.Sh SPLAY TREES
A splay tree is a self-organizing data structure.
Every operation on the tree causes a splay to happen.
The splay moves the requested
node to the root of the tree and partly rebalances it.
The splay moves the requested node to the root of the tree and partly
rebalances it.
.Pp
This has the benefit that request locality causes faster lookups as
the requested nodes move to the top of the tree.
On the other hand, every lookup causes memory writes.
.Pp
The Balance Theorem bounds the total access time for
.Ar m
operations and
.Ar n
inserts on an initially empty tree as
.Fn O "\*[lp]m + n\*[rp]lg n" .
The
amortized cost for a sequence of
.Ar m
accesses to a splay tree is
.Fn O "lg n" .
The Balance Theorem bounds the total access time for m operations
and n inserts on an initially empty tree as O((m + n)lg n).
The amortized cost for a sequence of m accesses to a splay tree is O(lg n).
.Pp
A splay tree is headed by a structure defined by the
.Fn SPLAY_HEAD
macro.
A
.Fa SPLAY_HEAD
structure is declared as follows:
.Bd -ragged -offset indent
.Fn SPLAY_HEAD HEADNAME TYPE
.Va head ;
.Bd -literal -offset indent
SPLAY_HEAD(HEADNAME, TYPE) head;
.Ed
.Pp
where
@@ -251,16 +242,15 @@ macro, but should be used only once.
Finally,
the
.Fa CMP
argument is the name of a function used to compare tree nodes
argument is the name of a function used to compare trees' nodes
with each other.
The function takes two arguments of type
.Vt "struct TYPE *" .
.Fa "struct TYPE *" .
If the first argument is smaller than the second, the function returns a
value smaller than zero.
If they are equal, the function returns zero.
Otherwise, it should return a value greater than zero.
The compare
function defines the order of the tree elements.
The compare function defines the order of the tree elements.
.Pp
The
.Fn SPLAY_INIT
@@ -270,11 +260,8 @@ macro initializes the tree referenced by
The splay tree can also be initialized statically by using the
.Fn SPLAY_INITIALIZER
macro like this:
.Bd -ragged -offset indent
.Fn SPLAY_HEAD HEADNAME TYPE
.Va head
=
.Fn SPLAY_INITIALIZER &head ;
.Bd -literal -offset indent
SPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(&head);
.Ed
.Pp
The
@@ -282,6 +269,11 @@ The
macro inserts the new element
.Fa elm
into the tree.
Upon success,
.Va NULL
is returned.
If a matching element already exists in the tree, the insertion is
aborted, and a pointer to the existing element is returned.
.Pp
The
.Fn SPLAY_REMOVE
@@ -289,6 +281,11 @@ macro removes the element
.Fa elm
from the tree pointed by
.Fa head .
Upon success, a pointer to the removed element is returned.
.Va NULL
is returned if
.Fa elm
is not present in the tree.
.Pp
The
.Fn SPLAY_FIND
@@ -296,7 +293,7 @@ macro can be used to find a particular element in the tree.
.Bd -literal -offset indent
struct TYPE find, *res;
find.key = 30;
res = SPLAY_FIND(NAME, head, &find);
res = SPLAY_FIND(NAME, &head, &find);
.Ed
.Pp
The
@@ -313,8 +310,8 @@ for (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np))
Or, for simplicity, one can use the
.Fn SPLAY_FOREACH
macro:
.Bd -ragged -offset indent
.Fn SPLAY_FOREACH np NAME head
.Bd -literal -offset indent
SPLAY_FOREACH(np, NAME, &head)
.Ed
.Pp
The
@@ -324,29 +321,28 @@ macro should be used to check whether a splay tree is empty.
A red-black tree is a binary search tree with the node color as an
extra attribute.
It fulfills a set of conditions:
.Bl -enum -offset indent
.Pp
.Bl -enum -compact -offset indent
.It
Every search path from the root to a leaf consists of the same number of
black nodes.
every search path from the root to a leaf consists of the same number of
black nodes,
.It
Each red node (except for the root) has a black parent.
each red node (except for the root) has a black parent,
.It
Each leaf node is black.
each leaf node is black.
.El
.Pp
Every operation on a red-black tree is bounded as
.Fn O "lg n" .
The maximum height of a red-black tree is
.Fn 2lg "n + 1" .
Every operation on a red-black tree is bounded as O(lg n).
The maximum height of a red-black tree is 2lg (n+1).
.Pp
A red-black tree is headed by a structure defined by the
.Fn RB_HEAD
macro.
A
.Fa RB_HEAD
structure is declared as follows:
.Bd -ragged -offset indent
.Fn RB_HEAD HEADNAME TYPE
.Va head ;
.Bd -literal -offset indent
RB_HEAD(HEADNAME, TYPE) head;
.Ed
.Pp
where
@@ -364,7 +360,7 @@ their prototypes need to be declared with the
.Fn RB_PROTOTYPE
or
.Fn RB_PROTOTYPE_STATIC
macro,
macros,
where
.Fa NAME
is a unique identifier for this particular tree.
@@ -381,7 +377,7 @@ The function bodies are generated with the
.Fn RB_GENERATE
or
.Fn RB_GENERATE_STATIC
macro.
macros.
These macros take the same arguments as the
.Fn RB_PROTOTYPE
and
@@ -391,16 +387,15 @@ macros, but should be used only once.
Finally,
the
.Fa CMP
argument is the name of a function used to compare tree nodes
argument is the name of a function used to compare trees' nodes
with each other.
The function takes two arguments of type
.Vt "struct TYPE *" .
.Fa "struct TYPE *" .
If the first argument is smaller than the second, the function returns a
value smaller than zero.
If they are equal, the function returns zero.
Otherwise, it should return a value greater than zero.
The compare
function defines the order of the tree elements.
The compare function defines the order of the tree elements.
.Pp
The
.Fn RB_INIT
@@ -410,11 +405,8 @@ macro initializes the tree referenced by
The red-black tree can also be initialized statically by using the
.Fn RB_INITIALIZER
macro like this:
.Bd -ragged -offset indent
.Fn RB_HEAD HEADNAME TYPE
.Va head
=
.Fn RB_INITIALIZER &head ;
.Bd -literal -offset indent
RB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(&head);
.Ed
.Pp
The
@@ -422,6 +414,11 @@ The
macro inserts the new element
.Fa elm
into the tree.
Upon success,
.Va NULL
is returned.
If a matching element already exists in the tree, the insertion is
aborted, and a pointer to the existing element is returned.
.Pp
The
.Fn RB_REMOVE
@@ -429,16 +426,24 @@ macro removes the element
.Fa elm
from the tree pointed by
.Fa head .
.Fn RB_REMOVE
returns
.Fa elm .
.Pp
The
.Fn RB_FIND
and
.Fn RB_NFIND
macros can be used to find a particular element in the tree.
.Fn RB_FIND
finds the node with the same key as
.Fa elm .
.Fn RB_NFIND
finds the first node greater than or equal to the search key.
.Bd -literal -offset indent
struct TYPE find, *res;
find.key = 30;
res = RB_FIND(NAME, head, &find);
res = RB_FIND(NAME, &head, &find);
.Ed
.Pp
The
@@ -449,26 +454,119 @@ The
and
.Fn RB_PREV
macros can be used to traverse the tree:
.Pp
.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))"
.Bd -literal -offset indent
for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))
.Ed
.Pp
Or, for simplicity, one can use the
.Fn RB_FOREACH
or
.Fn RB_FOREACH_REVERSE
macro:
.Bd -ragged -offset indent
.Fn RB_FOREACH np NAME head
macros:
.Bd -literal -offset indent
RB_FOREACH(np, NAME, &head)
.Ed
.Pp
The macros
.Fn RB_FOREACH_SAFE
and
.Fn RB_FOREACH_REVERSE_SAFE
traverse the tree referenced by head
in a forward or reverse direction respectively,
assigning each element in turn to np.
However, unlike their unsafe counterparts,
they permit both the removal of np
as well as freeing it from within the loop safely
without interfering with the traversal.
.Pp
The
.Fn RB_EMPTY
macro should be used to check whether a red-black tree is empty.
.Sh EXAMPLES
The following example demonstrates how to declare a red-black tree
holding integers.
Values are inserted into it and the contents of the tree are printed
in order.
Lastly, the internal structure of the tree is printed.
.Bd -literal -offset 3n
#include <sys/tree.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
struct node {
RB_ENTRY(node) entry;
int i;
};
int intcmp(struct node *, struct node *);
void print_tree(struct node *);
int
intcmp(struct node *e1, struct node *e2)
{
return (e1->i < e2->i ? -1 : e1->i > e2->i);
}
RB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
RB_PROTOTYPE(inttree, node, entry, intcmp)
RB_GENERATE(inttree, node, entry, intcmp)
int testdata[] = {
20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18,
7, 11, 14
};
void
print_tree(struct node *n)
{
struct node *left, *right;
if (n == NULL) {
printf("nil");
return;
}
left = RB_LEFT(n, entry);
right = RB_RIGHT(n, entry);
if (left == NULL && right == NULL)
printf("%d", n->i);
else {
printf("%d(", n->i);
print_tree(left);
printf(",");
print_tree(right);
printf(")");
}
}
int
main(void)
{
int i;
struct node *n;
for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
if ((n = malloc(sizeof(struct node))) == NULL)
err(1, NULL);
n->i = testdata[i];
RB_INSERT(inttree, &head, n);
}
RB_FOREACH(n, inttree, &head) {
printf("%d\en", n->i);
}
print_tree(RB_ROOT(&head));
printf("\en");
return (0);
}
.Ed
.Sh SEE ALSO
.Xr queue 3bsd
.Sh NOTES
Trying to free a tree in the following way is a common error:
.Bd -literal -offset indent
SPLAY_FOREACH(var, NAME, head) {
SPLAY_REMOVE(NAME, head, var);
SPLAY_FOREACH(var, NAME, &head) {
SPLAY_REMOVE(NAME, &head, var);
free(var);
}
free(head);
@@ -476,36 +574,17 @@ free(head);
.Pp
Since
.Va var
is freed, the
is free'd, the
.Fn FOREACH
macro refers to a pointer that may have been reallocated already.
Proper code needs a second variable.
.Bd -literal -offset indent
for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) {
nxt = SPLAY_NEXT(NAME, head, var);
SPLAY_REMOVE(NAME, head, var);
for (var = SPLAY_MIN(NAME, &head); var != NULL; var = nxt) {
nxt = SPLAY_NEXT(NAME, &head, var);
SPLAY_REMOVE(NAME, &head, var);
free(var);
}
.Ed
.Pp
Both
.Fn RB_INSERT
and
.Fn SPLAY_INSERT
return
.Dv NULL
if the element was inserted in the tree successfully, otherwise they
return a pointer to the element with the colliding key.
.Pp
Accordingly,
.Fn RB_REMOVE
and
.Fn SPLAY_REMOVE
return the pointer to the removed element otherwise they return
.Dv NULL
to indicate an error.
.Sh SEE ALSO
.Xr queue 3bsd
.Sh AUTHORS
The author of the tree macros is
.An Niels Provos .

View File

@@ -25,6 +25,7 @@ libbsd_la_included_sources = \
getentropy_win.c \
$(nil)
CLEANFILES =
EXTRA_DIST = \
libbsd.map \
libbsd.pc.in \
@@ -52,9 +53,8 @@ libbsd_la_DEPENDENCIES = \
$(libbsd_la_included_sources) \
libbsd.map
libbsd_la_LIBADD = \
$(MD_LIBS) \
$(CLOCK_GETTIME_LIBS) \
$(ARC4RANDOM_ATFORK_LIBS) \
$(MD5_LIBS) \
$(LIBBSD_LIBS) \
$(nil)
libbsd_la_LDFLAGS = \
-version-number $(LIBBSD_ABI)
@@ -66,7 +66,6 @@ libbsd_la_SOURCES = \
arc4random.c \
arc4random.h \
arc4random_linux.h \
arc4random_openbsd.h \
arc4random_uniform.c \
arc4random_unix.h \
arc4random_win.h \
@@ -126,22 +125,51 @@ libbsd_la_SOURCES += \
$(nil)
endif
if NEED_TRANSPARENT_LIBMD
CLEANFILES += \
format.ld \
# EOL
endif
libbsd_ctor_a_SOURCES = \
setproctitle_ctor.c \
$(nil)
if NEED_TRANSPARENT_LIBMD
TRANSPARENT_LIBMD_DEPENDS = format.ld
format.ld:
$(CC) -shared -nostdlib -nostartfiles -x assembler /dev/null -o $@.so
$(OBJDUMP) -f $@.so | sed -n 's/.*file format \(.*\)/OUTPUT_FORMAT(\1)/;T;p' > $@
rm -f $@.so
endif
runtimelibdir = $(libdir)
install-exec-hook:
install-exec-hook: $(TRANSPARENT_LIBMD_DEPENDS)
if [ "$(libdir)" != "$(runtimelibdir)" ]; then \
$(MKDIR_P) $(DESTDIR)$(runtimelibdir); \
mv $(DESTDIR)$(libdir)/libbsd*.so.* \
$(DESTDIR)$(runtimelibdir)/; \
fi
if NEED_TRANSPARENT_LIBMD
# The "GNU ld script" magic is required so that GNU ldconfig does not complain
# about an unknown format file.
soname=`readlink $(DESTDIR)$(libdir)/libbsd.so`; \
$(RM) $(DESTDIR)$(libdir)/libbsd.so; \
(echo '/* GNU ld script'; \
echo ' * The MD5 functions are provided by the libmd library. */'; \
cat format.ld; \
echo "GROUP($(runtimelibdir)/$$soname AS_NEEDED($(MD5_LIBS)))"; \
)>$(DESTDIR)$(libdir)/libbsd.so
else
if [ "$(libdir)" != "$(runtimelibdir)" ]; then \
soname=`readlink $(DESTDIR)$(libdir)/libbsd.so`; \
sorelprefix=`echo $(libdir) | sed -r -e 's:(^/)?[^/]+:..:g'`; \
sorelprefix=`echo $(libdir) | $(SED) -r -e 's:(^/)?[^/]+:..:g'`; \
ln -sf $$sorelprefix$(runtimelibdir)/$$soname \
$(DESTDIR)$(libdir)/libbsd.so; \
fi
endif
uninstall-hook:
rm -f $(DESTDIR)$(runtimelibdir)/libbsd*.so*

View File

@@ -32,9 +32,7 @@
int
getentropy(void *buf, size_t len);
#if defined(__OpenBSD__)
#include "arc4random_openbsd.h"
#elif defined(__linux__)
#if defined(__linux__)
#include "arc4random_linux.h"
#elif defined(_WIN32)
#include "arc4random_win.h"

View File

@@ -1,61 +0,0 @@
/* $OpenBSD: arc4random.h,v 1.3 2014/07/20 20:51:13 bcook Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.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.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <signal.h>
#include "thread_private.h"
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
struct {
struct _rs rs;
struct _rsx rsx;
} *p;
if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if (minherit(p, sizeof(*p), MAP_INHERIT_ZERO) == -1) {
munmap(p, sizeof(*p));
return (-1);
}
*rsp = &p->rs;
*rsxp = &p->rsx;
return (0);
}
static inline void
_rs_forkdetect(void)
{
}

View File

@@ -79,7 +79,7 @@ sys_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags)
* Close all file descriptors greater than or equal to lowfd.
* This is the expensive (fallback) method.
*/
void
static void
closefrom_fallback(int lowfd)
{
long fd, maxfd;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
/* $OpenBSD: explicit_bzero.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
/*
* Public domain.
* Written by Matthew Dempsky.
@@ -6,6 +6,9 @@
#include <string.h>
__attribute__((__weak__)) void
__explicit_bzero_hook(void *, size_t);
__attribute__((__weak__)) void
__explicit_bzero_hook(void *buf, size_t len)
{

View File

@@ -76,8 +76,8 @@ fgetln(FILE *stream, size_t *len)
}
}
libbsd_link_warning(fgetln,
"This function cannot be safely ported, use getline(3) "
"instead, as it is supported by GNU and POSIX.1-2008.")
"The fgetln() function cannot be safely ported, use getline(3) "
"instead, as it is supported by GNU and POSIX.1-2008.");
#else
#error "Function fgetln() needs to be ported."
#endif

View File

@@ -88,5 +88,5 @@ fgetwln(FILE *stream, size_t *lenp)
return wused ? fb->wbuf : NULL;
}
libbsd_link_warning(fgetwln,
"This function cannot be safely ported, use fgetwc(3) "
"instead, as it is supported by C99 and POSIX.1-2001.")
"The fgetwln() function cannot be safely ported, use fgetwc(3) "
"instead, as it is supported by C99 and POSIX.1-2001.");

View File

@@ -32,7 +32,7 @@
int
fpurge(FILE *fp)
{
if (fp == NULL || fileno(fp) < 0) {
if (fp == NULL) {
errno = EBADF;
return EOF;
}

View File

@@ -26,6 +26,8 @@
#include <errno.h>
#include <stddef.h>
int getentropy(void *buf, size_t len);
/*
* Derived from lib/libc/gen/arc4random.c from FreeBSD.
*/

View File

@@ -520,17 +520,17 @@ getentropy_fallback(void *buf, size_t len)
#ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */
p = (char *) getauxval(AT_RANDOM);
p = (char *) ((intptr_t) getauxval(AT_RANDOM));
if (p)
HR(p, 16);
#endif
#ifdef AT_SYSINFO_EHDR
p = (char *) getauxval(AT_SYSINFO_EHDR);
p = (char *) ((intptr_t) getauxval(AT_SYSINFO_EHDR));
if (p)
HR(p, pgs);
#endif
#ifdef AT_BASE
p = (char *) getauxval(AT_BASE);
p = (char *) ((intptr_t) getauxval(AT_BASE));
if (p)
HD(p);
#endif

View File

@@ -8,4 +8,5 @@ Description: Utility functions from BSD systems (overlay)
Version: @VERSION@
URL: https://libbsd.freedesktop.org/
Libs: -L${libdir} -lbsd
Libs.private: @LIBBSD_LIBS@ @MD5_LIBS@
Cflags: -isystem ${includedir}/bsd -DLIBBSD_OVERLAY

View File

@@ -8,4 +8,5 @@ Description: Utility functions from BSD systems
Version: @VERSION@
URL: https://libbsd.freedesktop.org/
Libs: -L${libdir} -lbsd
Libs.private: @LIBBSD_LIBS@ @MD5_LIBS@
Cflags: -I${includedir}

View File

@@ -124,6 +124,16 @@
#define ELF_TARG_CLASS ELFCLASS64
#define ELF_TARG_DATA ELFDATA2LSB
#elif defined(__loongarch__)
#define ELF_TARG_MACH EM_LOONGARCH
#if defined(__loongarch64)
#define ELF_TARG_CLASS ELFCLASS64
#else
#error Unsupported ELF class
#endif
#define ELF_TARG_DATA ELFDATA2LSB
#elif defined(__m32r__)
#define ELF_TARG_MACH EM_M32R

View File

@@ -27,21 +27,44 @@
#ifndef LIBBSD_LOCAL_LINK_H
#define LIBBSD_LOCAL_LINK_H
#include <sys/cdefs.h>
#define libbsd_link_warning(symbol, msg) \
static const char libbsd_emit_link_warning_##symbol[] \
__attribute__((__used__,__section__(".gnu.warning." #symbol))) = msg;
__attribute__((__used__,__section__(".gnu.warning." #symbol))) = msg
#ifdef __ELF__
# if __has_attribute(symver)
/* The symver attribute is supported since gcc 10.x. */
#define libbsd_symver_default(alias, symbol, version) \
extern __typeof__(symbol) symbol \
__attribute__((__symver__(#alias "@@" #version)))
#define libbsd_symver_variant(alias, symbol, version) \
extern __typeof__(symbol) symbol \
__attribute__((__symver__(#alias "@" #version)))
#define libbsd_symver_weak(alias, symbol, version) \
extern __typeof__(symbol) symbol \
__attribute__((__symver__(#alias "@" #version), __weak__))
# else
#define libbsd_symver_default(alias, symbol, version) \
__asm__(".symver " #symbol "," #alias "@@" #version)
#define libbsd_symver_variant(alias, symbol, version) \
__asm__(".symver " #symbol "," #alias "@" #version)
#define libbsd_symver_weak(alias, symbol, version) \
libbsd_symver_variant(alias, symbol, version); \
extern __typeof__(symbol) alias \
__attribute__((__weak__))
# endif
#else
#define libbsd_symver_default(alias, symbol, version) \
extern __typeof(symbol) alias __attribute__((__alias__(#symbol)))
extern __typeof__(symbol) alias __attribute__((__alias__(#symbol)))
#define libbsd_symver_variant(alias, symbol, version)
#define libbsd_symver_weak(alias, symbol, version)
#endif
#endif

View File

@@ -27,65 +27,94 @@
#include <md5.h>
#include "local-link.h"
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
void
bsd_MD5Init(MD5_CTX *context)
libbsd_MD5Init(MD5_CTX *context)
{
MD5Init(context);
}
libbsd_symver_variant(MD5Init, bsd_MD5Init, LIBBSD_0.0);
libbsd_link_warning(MD5Init,
"The MD5Init() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5Init, libbsd_MD5Init, LIBBSD_0.0);
void
bsd_MD5Update(MD5_CTX *context, const uint8_t *data, size_t len)
libbsd_MD5Update(MD5_CTX *context, const uint8_t *data, size_t len)
{
MD5Update(context, data, len);
}
libbsd_symver_variant(MD5Update, bsd_MD5Update, LIBBSD_0.0);
libbsd_link_warning(MD5Update,
"The MD5Update() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5Update, libbsd_MD5Update, LIBBSD_0.0);
void
bsd_MD5Pad(MD5_CTX *context)
libbsd_MD5Pad(MD5_CTX *context)
{
MD5Pad(context);
}
libbsd_symver_variant(MD5Pad, bsd_MD5Pad, LIBBSD_0.0);
libbsd_link_warning(MD5Pad,
"The MD5Pad() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5Pad, libbsd_MD5Pad, LIBBSD_0.0);
void
bsd_MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
libbsd_MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
{
MD5Final(digest, context);
}
libbsd_symver_variant(MD5Final, bsd_MD5Final, LIBBSD_0.0);
libbsd_link_warning(MD5Final,
"The MD5Final() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5Final, libbsd_MD5Final, LIBBSD_0.0);
void
bsd_MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
libbsd_MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
{
MD5Transform(state, block);
}
libbsd_symver_variant(MD5Transform, bsd_MD5Transform, LIBBSD_0.0);
libbsd_link_warning(MD5Transform,
"The MD5Transform() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5Transform, libbsd_MD5Transform, LIBBSD_0.0);
char *
bsd_MD5End(MD5_CTX *context, char *buf)
libbsd_MD5End(MD5_CTX *context, char *buf)
{
return MD5End(context, buf);
}
libbsd_symver_variant(MD5End, bsd_MD5End, LIBBSD_0.0);
libbsd_link_warning(MD5End,
"The MD5End() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5End, libbsd_MD5End, LIBBSD_0.0);
char *
bsd_MD5File(const char *filename, char *buf)
libbsd_MD5File(const char *filename, char *buf)
{
return MD5File(filename, buf);
}
libbsd_symver_variant(MD5File, bsd_MD5File, LIBBSD_0.0);
libbsd_link_warning(MD5File,
"The MD5File() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5File, libbsd_MD5File, LIBBSD_0.0);
char *
bsd_MD5FileChunk(const char *filename, char *buf, off_t offset, off_t length)
libbsd_MD5FileChunk(const char *filename, char *buf, off_t offset, off_t length)
{
return MD5FileChunk(filename, buf, offset, length);
}
libbsd_symver_variant(MD5FileChunk, bsd_MD5FileChunk, LIBBSD_0.0);
libbsd_link_warning(MD5FileChunk,
"The MD5FileChunk() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5FileChunk, libbsd_MD5FileChunk, LIBBSD_0.0);
char *
bsd_MD5Data(const uint8_t *data, size_t len, char *buf)
libbsd_MD5Data(const uint8_t *data, size_t len, char *buf)
{
return MD5Data(data, len, buf);
}
libbsd_symver_variant(MD5Data, bsd_MD5Data, LIBBSD_0.0);
libbsd_link_warning(MD5Data,
"The MD5Data() function in libbsd is a deprecated wrapper, "
"use libmd instead.");
libbsd_symver_weak(MD5Data, libbsd_MD5Data, LIBBSD_0.0);

View File

@@ -43,10 +43,6 @@
#include "local-elf.h"
#ifndef SIZE_T_MAX
#define SIZE_T_MAX 0xffffffffU
#endif
/* Note: This function is used by libkvm0, so we need to export it.
* It is not declared in the include files though. */
int __fdnlist(int, struct nlist *);
@@ -153,7 +149,7 @@ __fdnlist(int fd, struct nlist *list)
shdr_size = ehdr.e_shentsize * ehdr.e_shnum;
/* Make sure it's not too big to mmap */
if (shdr_size > SIZE_T_MAX || shdr_size > st.st_size) {
if (shdr_size > st.st_size) {
errno = EFBIG;
return (-1);
}
@@ -186,7 +182,7 @@ __fdnlist(int fd, struct nlist *list)
}
/* Check for files too large to mmap. */
if (symstrsize > SIZE_T_MAX || symstrsize > st.st_size) {
if (symstrsize > st.st_size) {
errno = EFBIG;
goto done;
}
@@ -239,7 +235,6 @@ __fdnlist(int fd, struct nlist *list)
for (s = sbuf; cc > 0 && nent > 0; ++s, cc -= sizeof(*s)) {
char *name;
Elf_Word size;
struct nlist *p;
name = strtab + s->st_name;
if (name[0] == '\0')

View File

@@ -222,6 +222,10 @@ setproctitle_init(int argc, char *argv[], char *envp[])
#define SPT_MAXTITLE 255
#endif
__printflike(1, 2)
void
setproctitle_impl(const char *fmt, ...);
void
setproctitle_impl(const char *fmt, ...)
{

View File

@@ -49,4 +49,4 @@
* move them from .ctors to .init_array.
*/
void (*libbsd_init_func)(int argc, char *argv[], char *envp[])
__attribute__((__section__(".init_array"))) = setproctitle_init;
__attribute__((__section__(".init_array"), __used__)) = setproctitle_init;

View File

@@ -564,12 +564,16 @@ strunvis(char *dst, const char *src)
* NetBSD: 2012, strnunvis(char *dst, size_t dlen, const char *src);
*/
ssize_t
strnunvis_openbsd(char *, const char *, size_t);
ssize_t
strnunvis_openbsd(char *dst, const char *src, size_t dlen)
{
return strnunvisx(dst, dlen, src, 0);
}
libbsd_symver_default(strnunvis, strnunvis_openbsd, LIBBSD_0.2);
int
strnunvis_netbsd(char *, size_t, const char *);
int
strnunvis_netbsd(char *dst, size_t dlen, const char *src)
{

View File

@@ -733,12 +733,16 @@ strvis(char *mbdst, const char *mbsrc, int flags)
* NetBSD: 2012, strnvis(char *dst, size_t dlen, const char *src, int flag);
*/
int
strnvis_openbsd(char *, const char *, size_t, int);
int
strnvis_openbsd(char *mbdst, const char *mbsrc, size_t dlen, int flags)
{
return istrsenvisxl(mbdst, &dlen, mbsrc, flags, "", NULL);
}
libbsd_symver_default(strnvis, strnvis_openbsd, LIBBSD_0.2);
int
strnvis_netbsd(char *, size_t, const char *, int);
int
strnvis_netbsd(char *mbdst, size_t dlen, const char *mbsrc, int flags)
{

6
test/.gitignore vendored
View File

@@ -2,23 +2,25 @@ arc4random
bzero
closefrom
endian
explicit_bzero
fgetln
funopen
fparseln
fpurge
funopen
headers-overlay-gen.c
headers-system-gen.c
humanize
md5
nlist
overlay
proctitle-init
proctitle
proctitle-init
progname
pwcache
setmode
strl
strmode
strnstr
strtonum
vis
vis-openbsd

View File

@@ -34,6 +34,7 @@ check_PROGRAMS = \
bzero \
closefrom \
endian \
explicit_bzero \
humanize \
fgetln \
funopen \
@@ -48,12 +49,11 @@ check_PROGRAMS = \
strl \
strmode \
strnstr \
strtonum \
vis \
vis-openbsd \
$(nil)
md5_LDADD = $(LDADD) $(MD_LIBS)
if HAVE_LIBTESTU01
arc4random_LDADD = $(LDADD) $(TESTU01_LIBS)
@@ -70,6 +70,11 @@ proctitle_LDFLAGS = \
check_PROGRAMS += proctitle
endif
if NEED_TRANSPARENT_LIBMD
# On the installed system this is handled via the ld script.
md5_LDADD = $(LDADD) $(MD5_LIBS)
endif
fgetln_SOURCES = test-stream.c test-stream.h fgetln.c
fgetln_CFLAGS = -Wno-deprecated-declarations
fparseln_SOURCES = test-stream.c test-stream.h fparseln.c

View File

@@ -28,7 +28,7 @@
#include <string.h>
int
main()
main(int argc, char *argv[])
{
unsigned char array[40];
size_t i;

View File

@@ -31,7 +31,7 @@
#include <stdio.h>
int
main()
main(int argc, char *argv[])
{
int i;
int fd;

View File

@@ -30,7 +30,7 @@
#include <string.h>
int
main()
main(int argc, char *argv[])
{
unsigned char decstream[] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,

214
test/explicit_bzero.c Normal file
View File

@@ -0,0 +1,214 @@
/* $OpenBSD: explicit_bzero.c,v 1.7 2021/03/27 11:17:58 bcook Exp $ */
/*
* Copyright (c) 2014 Google Inc.
*
* 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.
*/
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define ASSERT_EQ(a, b) assert((a) == (b))
#define ASSERT_NE(a, b) assert((a) != (b))
#define ASSERT_GE(a, b) assert((a) >= (b))
/* 128 bits of random data. */
static const char secret[16] = {
0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c,
0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96,
};
enum {
SECRETCOUNT = 64,
SECRETBYTES = SECRETCOUNT * sizeof(secret)
};
/*
* As of glibc 2.34, when _GNU_SOURCE is defined, SIGSTKSZ is no longer
* constant on Linux. SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ).
*/
static char *altstack;
#define ALTSTACK_SIZE (SIGSTKSZ + SECRETBYTES)
static void
setup_stack(void)
{
const stack_t sigstk = {
.ss_sp = altstack = calloc(1, ALTSTACK_SIZE),
.ss_size = ALTSTACK_SIZE
};
ASSERT_NE(NULL, altstack);
ASSERT_EQ(0, sigaltstack(&sigstk, NULL));
}
static void
cleanup_stack(void)
{
free(altstack);
}
static void
assert_on_stack(void)
{
stack_t cursigstk;
ASSERT_EQ(0, sigaltstack(NULL, &cursigstk));
ASSERT_EQ(SS_ONSTACK, cursigstk.ss_flags & (SS_DISABLE|SS_ONSTACK));
}
static void
call_on_stack(void (*fn)(int))
{
/*
* This is a bit more complicated than strictly necessary, but
* it ensures we don't have any flaky test failures due to
* inherited signal masks/actions/etc.
*
* On systems where SA_ONSTACK is not supported, this could
* alternatively be implemented using makecontext() or
* pthread_attr_setstack().
*/
const struct sigaction sigact = {
.sa_handler = fn,
.sa_flags = SA_ONSTACK,
};
struct sigaction oldsigact;
sigset_t sigset, oldsigset;
/* First, block all signals. */
ASSERT_EQ(0, sigemptyset(&sigset));
ASSERT_EQ(0, sigfillset(&sigset));
ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset, &oldsigset));
/* Next setup the signal handler for SIGUSR1. */
ASSERT_EQ(0, sigaction(SIGUSR1, &sigact, &oldsigact));
/* Raise SIGUSR1 and momentarily unblock it to run the handler. */
ASSERT_EQ(0, raise(SIGUSR1));
ASSERT_EQ(0, sigdelset(&sigset, SIGUSR1));
ASSERT_EQ(-1, sigsuspend(&sigset));
ASSERT_EQ(EINTR, errno);
/* Restore the original signal action, stack, and mask. */
ASSERT_EQ(0, sigaction(SIGUSR1, &oldsigact, NULL));
ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &oldsigset, NULL));
}
static void
populate_secret(char *buf, ssize_t len)
{
int i, fds[2];
ASSERT_EQ(0, pipe(fds));
for (i = 0; i < SECRETCOUNT; i++)
ASSERT_EQ(sizeof(secret), write(fds[1], secret, sizeof(secret)));
ASSERT_EQ(0, close(fds[1]));
ASSERT_EQ(len, read(fds[0], buf, len));
ASSERT_EQ(0, close(fds[0]));
}
static int
count_secrets(const char *buf)
{
int res = 0;
size_t i;
for (i = 0; i < SECRETCOUNT; i++) {
if (memcmp(buf + i * sizeof(secret), secret,
sizeof(secret)) == 0)
res += 1;
}
return (res);
}
static char *
test_without_bzero(void)
{
char buf[SECRETBYTES];
char *res;
assert_on_stack();
populate_secret(buf, sizeof(buf));
res = memmem(altstack, ALTSTACK_SIZE, buf, sizeof(buf));
ASSERT_NE(NULL, res);
return (res);
}
static char *
test_with_bzero(void)
{
char buf[SECRETBYTES];
char *res;
assert_on_stack();
populate_secret(buf, sizeof(buf));
res = memmem(altstack, ALTSTACK_SIZE, buf, sizeof(buf));
ASSERT_NE(NULL, res);
explicit_bzero(buf, sizeof(buf));
return (res);
}
static void
do_test_without_bzero(int signo)
{
char *buf = test_without_bzero();
ASSERT_GE(count_secrets(buf), 1);
}
static void
do_test_with_bzero(int signo)
{
char *buf = test_with_bzero();
ASSERT_EQ(count_secrets(buf), 0);
}
int
main(int argc, char **argv)
{
setup_stack();
/*
* Solaris and OS X clobber the signal stack after returning to the
* normal stack, so we need to inspect altstack while we're still
* running on it. Unfortunately, this means we risk clobbering the
* buffer ourselves.
*
* To minimize this risk, test_with{,out}_bzero() are responsible for
* locating the offset of their buf variable within altstack, and
* and returning that address. Then we can simply memcmp() repeatedly
* to count how many instances of secret we found.
*/
/*
* First, test that if we *don't* call explicit_bzero, that we
* *are* able to find at least one instance of the secret data still
* on the stack. This sanity checks that call_on_stack() and
* populate_secret() work as intended.
*/
memset(altstack, 0, ALTSTACK_SIZE);
call_on_stack(do_test_without_bzero);
/*
* Now test with a call to explicit_bzero() and check that we
* *don't* find any instances of the secret data.
*/
memset(altstack, 0, ALTSTACK_SIZE);
call_on_stack(do_test_with_bzero);
cleanup_stack();
return (0);
}

View File

@@ -75,7 +75,7 @@ test_fgetln_single(void)
size_t len;
int i;
fp = pipe_feed("%s", (const void **)data_ascii, DATA_LINES);
fp = pipe_feed(PIPE_DATA_ASCII, (const void **)data_ascii, DATA_LINES);
for (i = 0; i < DATA_LINES; i++) {
char *str = fgetln(fp, &len);
@@ -96,13 +96,14 @@ test_fgetln_multi(void)
char *str;
str = strdup("A\n");
assert(str);
str[0] += i;
files[i].line_alloc = str;
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = str;
files[i].lines[1] = str;
files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
files[i].fp = pipe_feed(PIPE_DATA_ASCII, files[i].lines, LINE_COUNT);
}
for (l = 0; l < LINE_COUNT; l++) {
@@ -139,7 +140,7 @@ test_fgetwln_single(void)
size_t len;
int i;
fp = pipe_feed("%ls", (const void **)data_wide, DATA_LINES);
fp = pipe_feed(PIPE_DATA_WIDE, (const void **)data_wide, DATA_LINES);
for (i = 0; i < DATA_LINES; i++) {
wchar_t *wstr;
@@ -168,7 +169,7 @@ test_fgetwln_multi(void)
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = wstr;
files[i].lines[1] = wstr;
files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);
files[i].fp = pipe_feed(PIPE_DATA_WIDE, files[i].lines, LINE_COUNT);
}
for (l = 0; l < LINE_COUNT; l++) {

View File

@@ -68,7 +68,7 @@ test_fparseln(const char **data_expect, int flags)
FILE *fp;
size_t i, len, lineno = 0;
fp = pipe_feed("%s", (const void **)data_test, TEST_LINES);
fp = pipe_feed(PIPE_DATA_ASCII, (const void **)data_test, TEST_LINES);
for (i = 0; i < EXPECT_LINES; i++) {
char *str = fparseln(fp, &len, &lineno, NULL, flags);

View File

@@ -25,24 +25,33 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main()
main(int argc, char *argv[])
{
static FILE fp_bad;
FILE *fp;
char *buf = NULL;
size_t bufsz = 0;
if (fpurge(NULL) == 0)
return 1;
if (fpurge(&fp_bad) == 0)
return 1;
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
fclose(fp);
fp = open_memstream(&buf, &bufsz);
fputs("World", fp);
if (fpurge(fp) < 0)
return 1;
fflush(fp);
if (bufsz != 0)
return 1;
free(buf);
return 0;
}

View File

@@ -37,7 +37,7 @@ struct test_cookie {
int index;
};
int
static int
test_readfn(void *cookie, char *buf, int size)
{
struct test_cookie *tc = cookie;
@@ -56,7 +56,7 @@ test_readfn(void *cookie, char *buf, int size)
return size;
}
int
static int
test_writefn(void *cookie, const char *buf, int size)
{
struct test_cookie *tc = cookie;
@@ -75,7 +75,7 @@ test_writefn(void *cookie, const char *buf, int size)
return size;
}
off_t
static off_t
test_seekfn(void *cookie, off_t offset, int whence)
{
struct test_cookie *tc = cookie;
@@ -95,7 +95,7 @@ test_seekfn(void *cookie, off_t offset, int whence)
return tc->index;
}
int
static int
test_closefn(void *cookie)
{
struct test_cookie *tc = cookie;
@@ -114,7 +114,7 @@ main(int argc, char **argv)
size_t i;
/* Test invalid hooks. */
fp = funopen(&tc, NULL, NULL, NULL, NULL);
fp = funopen(NULL, NULL, NULL, NULL, NULL);
assert(fp == NULL);
assert(errno == EINVAL);

View File

@@ -28,7 +28,7 @@
#include <md5.h>
#include <string.h>
void
static void
test_md5(const char *digest, const char *string)
{
char result[MD5_DIGEST_STRING_LENGTH];
@@ -37,7 +37,7 @@ test_md5(const char *digest, const char *string)
}
int
main()
main(int argc, char *argv[])
{
test_md5("d41d8cd98f00b204e9800998ecf8427e", "");
test_md5("900150983cd24fb0d6963f7d28e17f72", "abc");

View File

@@ -39,11 +39,11 @@ extern int data_pub_uninit[2048];
extern int *data_pub_ptr;
int *data_pub_ptr = &data_prv_init;
int data_pub_init = 10;
int data_pub_uninit[2048];
int data_pub_init __attribute__((__used__)) = 10;
int data_pub_uninit[2048] __attribute__((__used__));
extern int
func_pub(void);
func_pub(void) __attribute__((__used__)) ;
int
func_pub(void)
@@ -55,11 +55,11 @@ int
main(int argc, char **argv)
{
struct nlist nl[] = {
{ .n_un.n_name = "main" },
{ .n_un.n_name = "func_pub" },
{ .n_un.n_name = "data_pub_uninit" },
{ .n_un.n_name = "data_pub_init" },
{ .n_un.n_name = "data_prv_init" },
{ .n_un.n_name = (char *)"main" },
{ .n_un.n_name = (char *)"func_pub" },
{ .n_un.n_name = (char *)"data_pub_uninit" },
{ .n_un.n_name = (char *)"data_pub_init" },
{ .n_un.n_name = (char *)"data_prv_init" },
{ .n_un.n_name = NULL },
};
int rc;

View File

@@ -45,7 +45,7 @@
#include <unistd.h>
int
main()
main(int argc, char *argv[])
{
/* Test that we do not get partial definitions. */
fflush(stdout);

64
test/strtonum.c Normal file
View File

@@ -0,0 +1,64 @@
/* $OpenBSD: strtonumtest.c,v 1.1 2004/08/03 20:38:36 otto Exp $ */
/*
* Copyright (c) 2004 Otto Moerbeek <otto@drijf.net>
*
* 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.
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
static int fail;
static void
test(const char *p, long long lb, long long ub, int ok)
{
long long val;
const char *q;
val = strtonum(p, lb, ub, &q);
if (ok && q != NULL) {
fprintf(stderr, "%s [%lld-%lld] ", p, lb, ub);
fprintf(stderr, "NUMBER NOT ACCEPTED %s\n", q);
fail = 1;
} else if (!ok && q == NULL) {
fprintf(stderr, "%s [%lld-%lld] %lld ", p, lb, ub, val);
fprintf(stderr, "NUMBER ACCEPTED\n");
fail = 1;
}
}
int main(int argc, char *argv[])
{
test("1", 0, 10, 1);
test("0", -2, 5, 1);
test("0", 2, 5, 0);
test("0", 2, LLONG_MAX, 0);
test("-2", 0, LLONG_MAX, 0);
test("0", -5, LLONG_MAX, 1);
test("-3", -3, LLONG_MAX, 1);
test("-9223372036854775808", LLONG_MIN, LLONG_MAX, 1);
test("9223372036854775807", LLONG_MIN, LLONG_MAX, 1);
test("-9223372036854775809", LLONG_MIN, LLONG_MAX, 0);
test("9223372036854775808", LLONG_MIN, LLONG_MAX, 0);
test("1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0);
test("-1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0);
test("-2", 10, -1, 0);
test("-2", -10, -1, 1);
test("-20", -10, -1, 0);
test("20", -10, -1, 0);
return (fail);
}

View File

@@ -27,12 +27,13 @@
#include <sys/wait.h>
#include <assert.h>
#include <unistd.h>
#include <wchar.h>
#include <stdio.h>
#include "test-stream.h"
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
pipe_feed(enum pipe_data_mode mode, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
@@ -56,7 +57,10 @@ pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
rc = fprintf(fp, fmt, buf[line]);
if (mode == PIPE_DATA_ASCII)
rc = fprintf(fp, "%s", (const char *)buf[line]);
else
rc = fprintf(fp, "%ls", (const wchar_t *)buf[line]);
assert(rc >= 0);
}

View File

@@ -29,8 +29,13 @@
#include <stdio.h>
enum pipe_data_mode {
PIPE_DATA_ASCII,
PIPE_DATA_WIDE,
};
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb);
pipe_feed(enum pipe_data_mode mode, const void **buf, int buf_nmemb);
void
pipe_close(FILE *fp);