Compare commits

..

28 Commits

Author SHA1 Message Date
Guillem Jover
edea268ce9 Release libbsd 0.11.2 2021-02-08 04:02:46 +01:00
Guillem Jover
e832b7687e closefrom: Use close_range() on Linux when available
Closes: !11
Based-on-patch-by: cptpcrd <cptpcrd.git@gmail.com>
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-02-08 04:02:46 +01:00
cptpcrd
c4fca5bb4f closefrom: Handle lowfd < 0 properly
More important if close_range() is going to be used, since casting
negative values to 'unsigned int' might hide the errors.

[guillem@hadrons.org: Minor coding style fix. ]

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-02-08 04:02:46 +01:00
Guillem Jover
a1f79978e8 closefrom: Import some changes from sudo
Take most of the changes done in sudo, but preserve the existing local
changes and refactoring.

In addition, refactor pstat implementation into closefrom_pstat(), so
that the code is easier to read, and requires no conditional
declarations.
2021-02-08 04:02:46 +01:00
Faidon Liambotis
4676026286 Update <sys/queue.h> from FreeBSD
This brings <sys/queue.h> to the most up-to-date version from FreeBSD,
incorporating 18 commits from the past 5 years (2015-02-24 - 2021-01-25):

  $ git log --oneline 9090a24aed70..8d55837dc133 sys/sys/queue.h share/man/man3/queue.3

Only minimal changes compared to the FreeBSD version have been applied
(queue.3 -> queue.3bsd, _LIBBSD_ prefix).

[guillem@hadrons.org: Remove reference to kernel mode in man page. ]

Closes: !12
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-02-08 04:02:16 +01:00
Guillem Jover
25f9b30678 test: Improve code coverage for strnstr(3) unit tests 2021-02-07 23:24:51 +01:00
Guillem Jover
18ebabf223 man: Update libbsd(7) man page with updates in 0.11.0 2021-02-07 15:17:33 +01:00
Guillem Jover
4ab11c7f48 build: Install libmd-dev in the gitlab CI 2021-02-07 10:37:18 +01:00
Guillem Jover
766c883e30 build: Switch gitlab CI to use a Debian buster 2021-02-07 10:35:57 +01:00
Guillem Jover
a4de4d95a6 Release libbsd 0.11.1 2021-02-07 02:03:59 +01:00
Guillem Jover
233cab9d64 Add support for new LIBBSD_VIS_OPENBSD selection macro
This will make it possible to explicitly select the OpenBSD vis
implementation (the current default) for code of OpenBSD origins.
2021-02-07 02:03:22 +01:00
Guillem Jover
2462cd8888 Release libbsd 0.11.0 2021-02-07 01:28:27 +01:00
Guillem Jover
d54ceb37ce Update copyright claims 2021-02-07 01:28:27 +01:00
Guillem Jover
847e682f8d Use libmd hashing function implementations instead of embedding our own
This splits the implementation responsibilities, and reduces embedded
code copies, which was one of the driving points with this project to
start with, so it's nice to give a good example.
2021-02-07 01:28:27 +01:00
Aaron Dierking
68f980c90d Provide a default progname on Windows
[guillem@hadrons.org:
 - Remove .exe extension from default program name.
 - Call reallocarray() once by switching to a «do {} while» loop.
 - Minor coding style fixes. ]

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-02-07 01:28:27 +01:00
Guillem Jover
37a9b56c05 Import pwcache module from OpenBSD 2021-02-07 01:28:27 +01:00
Guillem Jover
45dd5229ea man: Remove empty line in reallocarray(3bsd)
Warned-by: lintian
Fixes: commit 01f0d1ea1e
2021-02-07 01:28:27 +01:00
Faidon Liambotis
01f0d1ea1e Add recallocarray() and freezero() from OpenBSD
Add recallocarray(), introduced in OpenBSD 6.1, and freezero(),
introduced in OpenBSD 6.2. The former is imported as-is from OpenBSD,
while the latter is the non-malloc-internal branch of the same code (and
also the OpenSSH portable variant).

Both of these originated in OpenBSD, but have also been implemented by
IllumOS, cf. https://www.illumos.org/issues/8546

Documentation for these functions is in malloc(3) upstream, the relevant
parts of which were previously imported in reallocarray(3bsd). Update
reallocarray(3bsd) with the changes that were introduced since, and add
the relevant bits for recallocarray() and freezero(), plus aliases.

[guillem@hadrons.org: Update copyright in COPYING. ]

Closes: !10
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-01-01 18:18:51 +01:00
Seth R Johnson
9c85d828a1 Fix ELF detection on Intel compilers
The Intel compiler does not define __amd64__ on x86_64 platforms;
instead, like other compilers, it defines __x86_64__ .

Closes: !8
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2021-01-01 18:12:12 +01:00
Guillem Jover
eac4ce0c67 man: Add a timespec(3bsd) alias to timeval(3bsd)
Even though man-pages project now includes man pages for system data
types, we still include these for any other system that does not have
them, to provide a self-contained project with code and documentation.
2020-12-21 17:48:46 +01:00
Guillem Jover
5ecff0c903 man: Add missing LIBRARY section 2020-12-21 17:44:26 +01:00
Guillem Jover
8c5a83d678 Fix coding style 2020-12-21 17:44:26 +01:00
Guillem Jover
d5b04ab19c test: Fix short lived memory leaks
These are non-issues, but having a clean ASAN test suite makes it
possible to detect actual problems in the tested code.

Warned-by: gcc ASAN
2020-12-21 17:44:26 +01:00
Guillem Jover
cfeafeabad funopen: Fix memory leak in funopen_close() when closefn is NULL
We need to free the cookiewrap even when the closefn method is NULL.

Warned-by: gcc ASAN
2020-12-21 17:44:26 +01:00
Guillem Jover
3d6b6ead64 build: Detect support for --version-script in ld 2020-12-21 17:43:11 +01:00
Guillem Jover
eb445425ff Do not define SIZE_T_MAX if already defined 2020-12-21 17:19:30 +01:00
Guillem Jover
59f6a95609 man: Add missing doc-operating-system-NetBSD string variable
Fixes: commit 99320b9168.
2020-12-21 17:19:23 +01:00
Guillem Jover
3548c5f6bf Add missing strnvisx() to the symbols script
Fixes: commit 2d7de186e9.
2020-12-21 17:19:12 +01:00
66 changed files with 1913 additions and 996 deletions

View File

@@ -1,9 +1,9 @@
image: debian:stretch image: debian:buster
test: test:
before_script: before_script:
- apt update -qq - apt update -qq
- apt install -qq -y --no-install-recommends git gcc make autoconf automake libtool - apt install -qq -y --no-install-recommends git gcc make autoconf automake libtool libmd-dev
script: script:
- ./autogen && ./configure - ./autogen && ./configure
- make check - make check

24
COPYING
View File

@@ -3,7 +3,7 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Files: Files:
* *
Copyright: Copyright:
Copyright © 2004-2006, 2008-2018 Guillem Jover <guillem@hadrons.org> Copyright © 2004-2006, 2008-2021 Guillem Jover <guillem@hadrons.org>
License: BSD-3-clause License: BSD-3-clause
Files: Files:
@@ -105,6 +105,7 @@ Files:
man/getbsize.3bsd man/getbsize.3bsd
man/heapsort.3bsd man/heapsort.3bsd
man/nlist.3bsd man/nlist.3bsd
man/pwcache.3bsd
man/queue.3bsd man/queue.3bsd
man/radixsort.3bsd man/radixsort.3bsd
man/reallocarray.3bsd man/reallocarray.3bsd
@@ -121,6 +122,7 @@ Files:
src/heapsort.c src/heapsort.c
src/merge.c src/merge.c
src/nlist.c src/nlist.c
src/pwcache.c
src/radixsort.c src/radixsort.c
src/setmode.c src/setmode.c
src/strmode.c src/strmode.c
@@ -131,6 +133,7 @@ Files:
Copyright: Copyright:
Copyright © 1980, 1982, 1986, 1989-1994 Copyright © 1980, 1982, 1986, 1989-1994
The Regents of the University of California. All rights reserved. The Regents of the University of California. All rights reserved.
Copyright © 1992 Keith Muller.
Copyright © 2001 Mike Barcroft <mike@FreeBSD.org> Copyright © 2001 Mike Barcroft <mike@FreeBSD.org>
. .
Some code is derived from software contributed to Berkeley by Some code is derived from software contributed to Berkeley by
@@ -275,8 +278,6 @@ Files:
man/getpeereid.3bsd man/getpeereid.3bsd
man/pidfile.3bsd man/pidfile.3bsd
src/expand_number.c src/expand_number.c
src/hash/sha512.h
src/hash/sha512c.c
src/pidfile.c src/pidfile.c
src/reallocf.c src/reallocf.c
src/timeconv.c src/timeconv.c
@@ -368,6 +369,7 @@ Files:
src/arc4random_unix.h src/arc4random_unix.h
src/arc4random_win.h src/arc4random_win.h
src/closefrom.c src/closefrom.c
src/freezero.c
src/getentropy_aix.c src/getentropy_aix.c
src/getentropy_bsd.c src/getentropy_bsd.c
src/getentropy_hpux.c src/getentropy_hpux.c
@@ -378,6 +380,7 @@ Files:
src/getentropy_win.c src/getentropy_win.c
src/readpassphrase.c src/readpassphrase.c
src/reallocarray.c src/reallocarray.c
src/recallocarray.c
src/strlcat.c src/strlcat.c
src/strlcpy.c src/strlcpy.c
Copyright: Copyright:
@@ -389,7 +392,7 @@ Copyright:
Todd C. Miller <Todd.Miller@courtesan.com> Todd C. Miller <Todd.Miller@courtesan.com>
Copyright © 2004 Ted Unangst Copyright © 2004 Ted Unangst
Copyright © 2008 Damien Miller <djm@openbsd.org> Copyright © 2008 Damien Miller <djm@openbsd.org>
Copyright © 2008 Otto Moerbeek <otto@drijf.net> Copyright © 2008, 2010-2011, 2016-2017 Otto Moerbeek <otto@drijf.net>
Copyright © 2013 Markus Friedl <markus@openbsd.org> Copyright © 2013 Markus Friedl <markus@openbsd.org>
Copyright © 2014 Bob Beck <beck@obtuse.com> Copyright © 2014 Bob Beck <beck@obtuse.com>
Copyright © 2014 Brent Cook <bcook@openbsd.org> Copyright © 2014 Brent Cook <bcook@openbsd.org>
@@ -453,17 +456,6 @@ License: Expat
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE. USE OR OTHER DEALINGS IN THE SOFTWARE.
Files:
include/bsd/md5.h
src/hash/md5.c
Copyright:
None
License: public-domain-Colin-Plumb
This code implements the MD5 message-digest algorithm.
The algorithm is due to Ron Rivest. This code was
written by Colin Plumb in 1993, no copyright is claimed.
This code is in the public domain; do with it what you wish.
Files: Files:
src/explicit_bzero.c src/explicit_bzero.c
src/chacha_private.h src/chacha_private.h
@@ -474,8 +466,6 @@ License: public-domain
Files: Files:
man/mdX.3bsd man/mdX.3bsd
src/hash/md5hl.c
src/hash/helper.c
Copyright: Copyright:
None None
License: Beerware License: Beerware

3
README
View File

@@ -5,6 +5,9 @@ and lacking on others like GNU systems, thus making it easier to port
projects with strong BSD origins, without needing to embed the same projects with strong BSD origins, without needing to embed the same
code over and over again on each project. code over and over again on each project.
A BSD compatible message-digest library is required, on systems where
this is not provided by its libc or libmd libraries, the canonical
implementation to use is <https://www.hadrons.org/software/libmd/>.
Releases Releases
-------- --------

View File

@@ -12,8 +12,8 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])]) [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
LIBBSD_ABI_MAJOR=0 LIBBSD_ABI_MAJOR=0
LIBBSD_ABI_MINOR=10 LIBBSD_ABI_MINOR=11
LIBBSD_ABI_PATCH=0 LIBBSD_ABI_PATCH=2
LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH" LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH"
AC_SUBST([LIBBSD_ABI]) AC_SUBST([LIBBSD_ABI])
@@ -27,6 +27,25 @@ AC_SYS_LARGEFILE
LT_INIT LT_INIT
AC_CACHE_CHECK([if ld supports --version-script flag],
[libbsd_cv_version_script], [
echo "{ global: symbol; local: *; };" >conftest.map
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
AC_LINK_IFELSE([
AC_LANG_PROGRAM([], [])
], [
libbsd_cv_version_script=yes
], [
libbsd_cv_version_script=no
])
LDFLAGS="$save_LDFLAGS"
rm -f conftest.map
]
)
AM_CONDITIONAL([HAVE_LINKER_VERSION_SCRIPT],
[test "x$libbsd_cv_version_script" = "xyes"])
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_INSTALL AC_PROG_INSTALL
@@ -44,6 +63,17 @@ AC_SUBST([TESTU01_LIBS])
AM_CONDITIONAL([HAVE_LIBTESTU01], AM_CONDITIONAL([HAVE_LIBTESTU01],
[test "x$ac_cv_lib_testu01_unif01_CreateExternGenBits" = "xyes"]) [test "x$ac_cv_lib_testu01_unif01_CreateExternGenBits" = "xyes"])
saved_LIBS="$LIBS"
AC_SEARCH_LIBS([MD5Update], [md], [
AC_SEARCH_LIBS([SHA512Update], [md], [
MD_LIBS="-lmd"
])
], [
AC_MSG_ERROR([cannot find required message digest functions in libc or libmd])
])
AC_SUBST([MD_LIBS])
LIBS="$saved_LIBS"
is_windows=no is_windows=no
AS_CASE([$host_os], AS_CASE([$host_os],
[*-gnu*], [ [*-gnu*], [
@@ -68,7 +98,7 @@ AS_CASE([$host_os],
AM_CONDITIONAL([OS_WINDOWS], [test "x$is_windows" = "xyes"]) AM_CONDITIONAL([OS_WINDOWS], [test "x$is_windows" = "xyes"])
# Checks for header files. # Checks for header files.
AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h grp.h]) AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h pwd.h grp.h])
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE AC_C_INLINE

View File

@@ -14,10 +14,12 @@ nobase_include_HEADERS = \
bsd/bsd.h \ bsd/bsd.h \
bsd/err.h \ bsd/err.h \
bsd/getopt.h \ bsd/getopt.h \
bsd/grp.h \
bsd/inttypes.h \ bsd/inttypes.h \
bsd/libutil.h \ bsd/libutil.h \
bsd/md5.h \ bsd/md5.h \
bsd/nlist.h \ bsd/nlist.h \
bsd/pwd.h \
bsd/readpassphrase.h \ bsd/readpassphrase.h \
bsd/stdio.h \ bsd/stdio.h \
bsd/stdlib.h \ bsd/stdlib.h \

51
include/bsd/grp.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright © 2021 Guillem Jover <guillem@hadrons.org>
*
* 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. 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 ``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.
*/
#ifdef LIBBSD_OVERLAY
#include <sys/cdefs.h>
#if __has_include_next(<grp.h>)
#include_next <grp.h>
#endif
#else
#include <bsd/sys/cdefs.h>
#if __has_include(<grp.h>)
#include <grp.h>
#endif
#endif
#ifndef LIBBSD_GRP_H
#define LIBBSD_GRP_H
#define _GR_BUF_LEN (1024 + 200 * sizeof(char *))
__BEGIN_DECLS
int
gid_from_group(const char *, gid_t *);
const char *
group_from_gid(gid_t, int);
__END_DECLS
#endif

View File

@@ -1,58 +1,31 @@
/* $OpenBSD: md5.h,v 1.16 2004/06/22 01:57:30 jfb Exp $ */
/* /*
* This code implements the MD5 message-digest algorithm. * Copyright © 2021 Guillem Jover <guillem@hadrons.org>
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
* *
* Equivalent code is available from RSA Data Security, Inc. * Redistribution and use in source and binary forms, with or without
* This code has been tested against that, and is equivalent, * modification, are permitted provided that the following conditions
* except that you don't need to include two pages of legalese * are met:
* with every copy. * 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. 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 ``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.
*/ */
#ifndef LIBBSD_MD5_H
#define LIBBSD_MD5_H
#include <stdint.h>
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
typedef struct MD5Context {
uint32_t state[4]; /* state */
uint64_t count; /* number of bits, mod 2^64 */
uint8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
} MD5_CTX;
#ifdef LIBBSD_OVERLAY #ifdef LIBBSD_OVERLAY
#include <sys/cdefs.h> #include_next <md5.h>
#else #else
#include <bsd/sys/cdefs.h> #include <md5.h>
#endif #endif
#include <sys/types.h>
__BEGIN_DECLS
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, const uint8_t *, size_t)
__attribute__((__bounded__(__string__,2,3)));
void MD5Pad(MD5_CTX *);
void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)));
void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH])
__attribute__((__bounded__(__minbytes__,1,4)))
__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));
char *MD5End(MD5_CTX *, char *)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5File(const char *, char *)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5FileChunk(const char *, char *, off_t, off_t)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5Data(const uint8_t *, size_t, char *)
__attribute__((__bounded__(__string__,1,2)))
__attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH)));
__END_DECLS
#endif /* LIBBSD_MD5_H */

51
include/bsd/pwd.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright © 2021 Guillem Jover <guillem@hadrons.org>
*
* 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. 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 ``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.
*/
#ifdef LIBBSD_OVERLAY
#include <sys/cdefs.h>
#if __has_include_next(<pwd.h>)
#include_next <pwd.h>
#endif
#else
#include <bsd/sys/cdefs.h>
#if __has_include(<pwd.h>)
#include <pwd.h>
#endif
#endif
#ifndef LIBBSD_PWD_H
#define LIBBSD_PWD_H
#define _PW_BUF_LEN 1024 /* length of getpw*_r buffer */
__BEGIN_DECLS
int
uid_from_user(const char *, uid_t *);
const char *
user_from_uid(uid_t, int);
__END_DECLS
#endif

View File

@@ -62,7 +62,7 @@ int dehumanize_number(const char *str, int64_t *size);
const char *getprogname(void); const char *getprogname(void);
void setprogname(const char *); void setprogname(const char *);
int heapsort (void *, size_t, size_t, int (*)(const void *, const void *)); int heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
int mergesort(void *base, size_t nmemb, size_t size, int mergesort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *)); int (*cmp)(const void *, const void *));
int radixsort(const unsigned char **base, int nmemb, int radixsort(const unsigned char **base, int nmemb,
@@ -75,6 +75,8 @@ void *reallocf(void *ptr, size_t size);
(defined(__GLIBC__) && (!__GLIBC_PREREQ(2, 26) || !defined(_GNU_SOURCE))) (defined(__GLIBC__) && (!__GLIBC_PREREQ(2, 26) || !defined(_GNU_SOURCE)))
void *reallocarray(void *ptr, size_t nmemb, size_t size); void *reallocarray(void *ptr, size_t nmemb, size_t size);
#endif #endif
void *recallocarray(void *ptr, size_t oldnmemb, size_t nmemb, size_t size);
void freezero(void *ptr, size_t size);
long long strtonum(const char *nptr, long long minval, long long maxval, long long strtonum(const char *nptr, long long minval, long long maxval,
const char **errstr); const char **errstr);

View File

@@ -1,4 +1,6 @@
/*- /*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@@ -10,7 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -80,17 +82,25 @@
* *
* For details on the use of these macros, see the queue(3) manual page. * For details on the use of these macros, see the queue(3) manual page.
* *
* Below is a summary of implemented functions where:
* + means the macro is available
* - means the macro is not available
* s means the macro is available but is slow (runs in O(n) time)
* *
* SLIST LIST STAILQ TAILQ * SLIST LIST STAILQ TAILQ
* _HEAD + + + + * _HEAD + + + +
* _CLASS_HEAD + + + +
* _HEAD_INITIALIZER + + + + * _HEAD_INITIALIZER + + + +
* _ENTRY + + + + * _ENTRY + + + +
* _CLASS_ENTRY + + + +
* _INIT + + + + * _INIT + + + +
* _EMPTY + + + + * _EMPTY + + + +
* _END + + + +
* _FIRST + + + + * _FIRST + + + +
* _NEXT + + + + * _NEXT + + + +
* _PREV - + - + * _PREV - + - +
* _LAST - - + + * _LAST - - + +
* _LAST_FAST - - - +
* _FOREACH + + + + * _FOREACH + + + +
* _FOREACH_FROM + + + + * _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + + * _FOREACH_SAFE + + + +
@@ -103,14 +113,20 @@
* _INSERT_BEFORE - + - + * _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + + * _INSERT_AFTER + + + +
* _INSERT_TAIL - - + + * _INSERT_TAIL - - + +
* _CONCAT - - + + * _CONCAT s s + +
* _REMOVE_AFTER + - + - * _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + - * _REMOVE_HEAD + - + -
* _REMOVE + + + + * _REMOVE s + s +
* _SWAP + + + + * _SWAP + + + +
* *
*/ */
#ifdef QUEUE_MACRO_DEBUG #ifdef QUEUE_MACRO_DEBUG
#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH
#define QUEUE_MACRO_DEBUG_TRACE
#define QUEUE_MACRO_DEBUG_TRASH
#endif
#ifdef QUEUE_MACRO_DEBUG_TRACE
/* Store the last 2 places the queue element or head was altered */ /* Store the last 2 places the queue element or head was altered */
struct qm_trace { struct qm_trace {
unsigned long lastline; unsigned long lastline;
@@ -120,9 +136,7 @@ struct qm_trace {
}; };
#define TRACEBUF struct qm_trace trace; #define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } , #define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } ,
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define QMD_TRACE_HEAD(head) do { \ #define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \ (head)->trace.prevline = (head)->trace.lastline; \
@@ -138,14 +152,31 @@ struct qm_trace {
(elem)->trace.lastfile = __FILE__; \ (elem)->trace.lastfile = __FILE__; \
} while (0) } while (0)
#else #else /* !QUEUE_MACRO_DEBUG_TRACE */
#define QMD_TRACE_ELEM(elem) #define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head) #define QMD_TRACE_HEAD(head)
#define QMD_SAVELINK(name, link)
#define TRACEBUF #define TRACEBUF
#define TRACEBUF_INITIALIZER #define TRACEBUF_INITIALIZER
#endif /* QUEUE_MACRO_DEBUG_TRACE */
#ifdef QUEUE_MACRO_DEBUG_TRASH
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1)
#else /* !QUEUE_MACRO_DEBUG_TRASH */
#define QMD_SAVELINK(name, link)
#define TRASHIT(x) #define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */ #define QMD_IS_TRASHED(x) 0
#endif /* QUEUE_MACRO_DEBUG_TRASH */
#ifdef __cplusplus
/*
* In C++ there can be structure lists and class lists:
*/
#define QUEUE_TYPEOF(type) type
#else
#define QUEUE_TYPEOF(type) struct type
#endif
/* /*
* Singly-linked List declarations. * Singly-linked List declarations.
@@ -155,6 +186,11 @@ struct name { \
struct type *slh_first; /* first element */ \ struct type *slh_first; /* first element */ \
} }
#define SLIST_CLASS_HEAD(name, type) \
struct name { \
class type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \ #define SLIST_HEAD_INITIALIZER(head) \
{ NULL } { NULL }
@@ -163,9 +199,37 @@ struct { \
struct type *sle_next; /* next element */ \ struct type *sle_next; /* next element */ \
} }
#define SLIST_CLASS_ENTRY(type) \
struct { \
class type *sle_next; /* next element */ \
}
/* /*
* Singly-linked List functions. * Singly-linked List functions.
*/ */
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \
if (*(prevp) != (elm)) \
panic("Bad prevptr *(%p) == %p != %p", \
(prevp), *(prevp), (elm)); \
} while (0)
#else
#define QMD_SLIST_CHECK_PREVPTR(prevp, elm)
#endif
#define SLIST_CONCAT(head1, head2, type, field) do { \
QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \
if (curelm == NULL) { \
if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \
SLIST_INIT(head2); \
} else if (SLIST_FIRST(head2) != NULL) { \
while (SLIST_NEXT(curelm, field) != NULL) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \
SLIST_INIT(head2); \
} \
} while (0)
#define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_FIRST(head) ((head)->slh_first)
@@ -217,7 +281,7 @@ struct { \
SLIST_REMOVE_HEAD((head), field); \ SLIST_REMOVE_HEAD((head), field); \
} \ } \
else { \ else { \
struct type *curelm = SLIST_FIRST((head)); \ QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \
while (SLIST_NEXT(curelm, field) != (elm)) \ while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \ curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \ SLIST_REMOVE_AFTER(curelm, field); \
@@ -234,12 +298,20 @@ struct { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0) } while (0)
#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \
QMD_SLIST_CHECK_PREVPTR(prevp, elm); \
*(prevp) = SLIST_NEXT(elm, field); \
TRASHIT((elm)->field.sle_next); \
} while (0)
#define SLIST_SWAP(head1, head2, type) do { \ #define SLIST_SWAP(head1, head2, type) do { \
struct type *swap_first = SLIST_FIRST(head1); \ QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \ SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \ SLIST_FIRST(head2) = swap_first; \
} while (0) } while (0)
#define SLIST_END(head) NULL
/* /*
* Singly-linked Tail queue declarations. * Singly-linked Tail queue declarations.
*/ */
@@ -249,6 +321,12 @@ struct name { \
struct type **stqh_last;/* addr of last next element */ \ struct type **stqh_last;/* addr of last next element */ \
} }
#define STAILQ_CLASS_HEAD(name, type) \
struct name { \
class type *stqh_first; /* first element */ \
class type **stqh_last; /* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \ #define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first } { NULL, &(head).stqh_first }
@@ -257,6 +335,11 @@ struct { \
struct type *stqe_next; /* next element */ \ struct type *stqe_next; /* next element */ \
} }
#define STAILQ_CLASS_ENTRY(type) \
struct { \
class type *stqe_next; /* next element */ \
}
/* /*
* Singly-linked Tail queue functions. * Singly-linked Tail queue functions.
*/ */
@@ -315,9 +398,10 @@ struct { \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0) } while (0)
#define STAILQ_LAST(head, type, field) \ #define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? NULL : \ (STAILQ_EMPTY((head)) ? NULL : \
__containerof((head)->stqh_last, struct type, field.stqe_next)) __containerof((head)->stqh_last, \
QUEUE_TYPEOF(type), field.stqe_next))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
@@ -327,7 +411,7 @@ struct { \
STAILQ_REMOVE_HEAD((head), field); \ STAILQ_REMOVE_HEAD((head), field); \
} \ } \
else { \ else { \
struct type *curelm = STAILQ_FIRST((head)); \ QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \
while (STAILQ_NEXT(curelm, field) != (elm)) \ while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \ curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \ STAILQ_REMOVE_AFTER(head, curelm, field); \
@@ -348,8 +432,8 @@ struct { \
} while (0) } while (0)
#define STAILQ_SWAP(head1, head2, type) do { \ #define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \ QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \ QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
(head1)->stqh_last = (head2)->stqh_last; \ (head1)->stqh_last = (head2)->stqh_last; \
STAILQ_FIRST(head2) = swap_first; \ STAILQ_FIRST(head2) = swap_first; \
@@ -360,6 +444,8 @@ struct { \
(head2)->stqh_last = &STAILQ_FIRST(head2); \ (head2)->stqh_last = &STAILQ_FIRST(head2); \
} while (0) } while (0)
#define STAILQ_END(head) NULL
/* /*
* List declarations. * List declarations.
@@ -369,6 +455,11 @@ struct name { \
struct type *lh_first; /* first element */ \ struct type *lh_first; /* first element */ \
} }
#define LIST_CLASS_HEAD(name, type) \
struct name { \
class type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \ #define LIST_HEAD_INITIALIZER(head) \
{ NULL } { NULL }
@@ -378,11 +469,23 @@ struct { \
struct type **le_prev; /* address of previous next element */ \ struct type **le_prev; /* address of previous next element */ \
} }
#define LIST_CLASS_ENTRY(type) \
struct { \
class type *le_next; /* next element */ \
class type **le_prev; /* address of previous next element */ \
}
/* /*
* List functions. * List functions.
*/ */
#if (defined(_KERNEL) && defined(INVARIANTS)) #if (defined(_KERNEL) && defined(INVARIANTS))
/*
* QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME)
*
* If the list is non-empty, validates that the first element of the list
* points back at 'head.'
*/
#define QMD_LIST_CHECK_HEAD(head, field) do { \ #define QMD_LIST_CHECK_HEAD(head, field) do { \
if (LIST_FIRST((head)) != NULL && \ if (LIST_FIRST((head)) != NULL && \
LIST_FIRST((head))->field.le_prev != \ LIST_FIRST((head))->field.le_prev != \
@@ -390,6 +493,12 @@ struct { \
panic("Bad list head %p first->prev != head", (head)); \ panic("Bad list head %p first->prev != head", (head)); \
} while (0) } while (0)
/*
* QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME)
*
* If an element follows 'elm' in the list, validates that the next element
* points back at 'elm.'
*/
#define QMD_LIST_CHECK_NEXT(elm, field) do { \ #define QMD_LIST_CHECK_NEXT(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL && \ if (LIST_NEXT((elm), field) != NULL && \
LIST_NEXT((elm), field)->field.le_prev != \ LIST_NEXT((elm), field)->field.le_prev != \
@@ -397,6 +506,11 @@ struct { \
panic("Bad link elm %p next->prev != elm", (elm)); \ panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0) } while (0)
/*
* QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME)
*
* Validates that the previous element (or head of the list) points to 'elm.'
*/
#define QMD_LIST_CHECK_PREV(elm, field) do { \ #define QMD_LIST_CHECK_PREV(elm, field) do { \
if (*(elm)->field.le_prev != (elm)) \ if (*(elm)->field.le_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \ panic("Bad link elm %p prev->next != elm", (elm)); \
@@ -407,6 +521,23 @@ struct { \
#define QMD_LIST_CHECK_PREV(elm, field) #define QMD_LIST_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */ #endif /* (_KERNEL && INVARIANTS) */
#define LIST_CONCAT(head1, head2, type, field) do { \
QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \
if (curelm == NULL) { \
if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \
LIST_FIRST(head2)->field.le_prev = \
&LIST_FIRST((head1)); \
LIST_INIT(head2); \
} \
} else if (LIST_FIRST(head2) != NULL) { \
while (LIST_NEXT(curelm, field) != NULL) \
curelm = LIST_NEXT(curelm, field); \
LIST_NEXT(curelm, field) = LIST_FIRST(head2); \
LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \
LIST_INIT(head2); \
} \
} while (0)
#define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first) #define LIST_FIRST(head) ((head)->lh_first)
@@ -462,9 +593,10 @@ struct { \
#define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \ #define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, struct type, field.le_next)) __containerof((elm)->field.le_prev, \
QUEUE_TYPEOF(type), field.le_next))
#define LIST_REMOVE(elm, field) do { \ #define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \ QMD_SAVELINK(oldnext, (elm)->field.le_next); \
@@ -480,7 +612,7 @@ struct { \
} while (0) } while (0)
#define LIST_SWAP(head1, head2, type, field) do { \ #define LIST_SWAP(head1, head2, type, field) do { \
struct type *swap_tmp = LIST_FIRST((head1)); \ QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \
LIST_FIRST((head1)) = LIST_FIRST((head2)); \ LIST_FIRST((head1)) = LIST_FIRST((head2)); \
LIST_FIRST((head2)) = swap_tmp; \ LIST_FIRST((head2)) = swap_tmp; \
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
@@ -489,6 +621,8 @@ struct { \
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
} while (0) } while (0)
#define LIST_END(head) NULL
/* /*
* Tail queue declarations. * Tail queue declarations.
*/ */
@@ -499,6 +633,13 @@ struct name { \
TRACEBUF \ TRACEBUF \
} }
#define TAILQ_CLASS_HEAD(name, type) \
struct name { \
class type *tqh_first; /* first element */ \
class type **tqh_last; /* addr of last next element */ \
TRACEBUF \
}
#define TAILQ_HEAD_INITIALIZER(head) \ #define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
@@ -509,10 +650,23 @@ struct { \
TRACEBUF \ TRACEBUF \
} }
#define TAILQ_CLASS_ENTRY(type) \
struct { \
class type *tqe_next; /* next element */ \
class type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
}
/* /*
* Tail queue functions. * Tail queue functions.
*/ */
#if (defined(_KERNEL) && defined(INVARIANTS)) #if (defined(_KERNEL) && defined(INVARIANTS))
/*
* QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
*
* If the tailq is non-empty, validates that the first element of the tailq
* points back at 'head.'
*/
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ #define QMD_TAILQ_CHECK_HEAD(head, field) do { \
if (!TAILQ_EMPTY(head) && \ if (!TAILQ_EMPTY(head) && \
TAILQ_FIRST((head))->field.tqe_prev != \ TAILQ_FIRST((head))->field.tqe_prev != \
@@ -520,11 +674,22 @@ struct { \
panic("Bad tailq head %p first->prev != head", (head)); \ panic("Bad tailq head %p first->prev != head", (head)); \
} while (0) } while (0)
/*
* QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
*
* Validates that the tail of the tailq is a pointer to pointer to NULL.
*/
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ #define QMD_TAILQ_CHECK_TAIL(head, field) do { \
if (*(head)->tqh_last != NULL) \ if (*(head)->tqh_last != NULL) \
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
} while (0) } while (0)
/*
* QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME)
*
* If an element follows 'elm' in the tailq, validates that the next element
* points back at 'elm.'
*/
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ #define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
if (TAILQ_NEXT((elm), field) != NULL && \ if (TAILQ_NEXT((elm), field) != NULL && \
TAILQ_NEXT((elm), field)->field.tqe_prev != \ TAILQ_NEXT((elm), field)->field.tqe_prev != \
@@ -532,6 +697,11 @@ struct { \
panic("Bad link elm %p next->prev != elm", (elm)); \ panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0) } while (0)
/*
* QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME)
*
* Validates that the previous element (or head of the tailq) points to 'elm.'
*/
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ #define QMD_TAILQ_CHECK_PREV(elm, field) do { \
if (*(elm)->field.tqe_prev != (elm)) \ if (*(elm)->field.tqe_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \ panic("Bad link elm %p prev->next != elm", (elm)); \
@@ -616,7 +786,7 @@ struct { \
TAILQ_NEXT((listelm), field) = (elm); \ TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
QMD_TRACE_ELEM(&(elm)->field); \ QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \ QMD_TRACE_ELEM(&(listelm)->field); \
} while (0) } while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
@@ -626,7 +796,7 @@ struct { \
*(listelm)->field.tqe_prev = (elm); \ *(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
QMD_TRACE_ELEM(&(elm)->field); \ QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \ QMD_TRACE_ELEM(&(listelm)->field); \
} while (0) } while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \ #define TAILQ_INSERT_HEAD(head, elm, field) do { \
@@ -655,11 +825,25 @@ struct { \
#define TAILQ_LAST(head, headname) \ #define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last)) (*(((struct headname *)((head)->tqh_last))->tqh_last))
/*
* The FAST function is fast in that it causes no data access other
* then the access to the head. The standard LAST function above
* will cause a data access of both the element you want and
* the previous element. FAST is very useful for instances when
* you may want to prefetch the last data element.
*/
#define TAILQ_LAST_FAST(head, type, field) \
(TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \ #define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_PREV_FAST(elm, head, type, field) \
((elm)->field.tqe_prev == &(head)->tqh_first ? NULL : \
__containerof((elm)->field.tqe_prev, QUEUE_TYPEOF(type), field.tqe_next))
#define TAILQ_REMOVE(head, elm, field) do { \ #define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
@@ -679,8 +863,8 @@ struct { \
} while (0) } while (0)
#define TAILQ_SWAP(head1, head2, type, field) do { \ #define TAILQ_SWAP(head1, head2, type, field) do { \
struct type *swap_first = (head1)->tqh_first; \ QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \
struct type **swap_last = (head1)->tqh_last; \ QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \
(head1)->tqh_first = (head2)->tqh_first; \ (head1)->tqh_first = (head2)->tqh_first; \
(head1)->tqh_last = (head2)->tqh_last; \ (head1)->tqh_last = (head2)->tqh_last; \
(head2)->tqh_first = swap_first; \ (head2)->tqh_first = swap_first; \
@@ -695,4 +879,6 @@ struct { \
(head2)->tqh_last = &(head2)->tqh_first; \ (head2)->tqh_last = &(head2)->tqh_first; \
} while (0) } while (0)
#define TAILQ_END(head) NULL
#endif /* !LIBBSD_SYS_QUEUE_H */ #endif /* !LIBBSD_SYS_QUEUE_H */

View File

@@ -99,8 +99,11 @@
* Provide both implementations and default for now on the historical one to * Provide both implementations and default for now on the historical one to
* avoid breakage, we will switch to the NetBSD one in libbsd 0.10.0 or so. * avoid breakage, we will switch to the NetBSD one in libbsd 0.10.0 or so.
* Define LIBBSD_NETBSD_VIS to switch to the NetBSD one now. * Define LIBBSD_NETBSD_VIS to switch to the NetBSD one now.
* Define LIBBSD_OPENBSD_VIS to keep using the OpenBSD one.
*/ */
#ifndef LIBBSD_NETBSD_VIS #if defined(LIBBSD_OPENBSD_VIS)
#undef LIBBSD_NETBSD_VIS
#elif !defined(LIBBSD_NETBSD_VIS)
#warning "NetBSD added incompatible strnvis() and strnunvis(), please see <bsd/vis.h> for more detils." #warning "NetBSD added incompatible strnvis() and strnunvis(), please see <bsd/vis.h> for more detils."
#endif #endif

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

1
man/LIST_CLASS_HEAD.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -14,6 +14,8 @@ md5.3bsd: $(srcdir)/mdX.3bsd
$(AM_V_GEN) sed $(SED_MD5_SUBST) $< > $@ $(AM_V_GEN) sed $(SED_MD5_SUBST) $< > $@
dist_man_MANS = \ dist_man_MANS = \
LIST_CLASS_ENTRY.3bsd \
LIST_CLASS_HEAD.3bsd \
LIST_EMPTY.3bsd \ LIST_EMPTY.3bsd \
LIST_ENTRY.3bsd \ LIST_ENTRY.3bsd \
LIST_FIRST.3bsd \ LIST_FIRST.3bsd \
@@ -54,6 +56,8 @@ dist_man_MANS = \
RB_REMOVE.3bsd \ RB_REMOVE.3bsd \
RB_RIGHT.3bsd \ RB_RIGHT.3bsd \
RB_ROOT.3bsd \ RB_ROOT.3bsd \
SLIST_CLASS_ENTRY.3bsd \
SLIST_CLASS_HEAD.3bsd \
SLIST_EMPTY.3bsd \ SLIST_EMPTY.3bsd \
SLIST_ENTRY.3bsd \ SLIST_ENTRY.3bsd \
SLIST_FIRST.3bsd \ SLIST_FIRST.3bsd \
@@ -70,6 +74,7 @@ dist_man_MANS = \
SLIST_REMOVE.3bsd \ SLIST_REMOVE.3bsd \
SLIST_REMOVE_AFTER.3bsd \ SLIST_REMOVE_AFTER.3bsd \
SLIST_REMOVE_HEAD.3bsd \ SLIST_REMOVE_HEAD.3bsd \
SLIST_REMOVE_PREVPTR.3bsd \
SLIST_SWAP.3bsd \ SLIST_SWAP.3bsd \
SPLAY_EMPTY.3bsd \ SPLAY_EMPTY.3bsd \
SPLAY_ENTRY.3bsd \ SPLAY_ENTRY.3bsd \
@@ -88,6 +93,8 @@ dist_man_MANS = \
SPLAY_REMOVE.3bsd \ SPLAY_REMOVE.3bsd \
SPLAY_RIGHT.3bsd \ SPLAY_RIGHT.3bsd \
SPLAY_ROOT.3bsd \ SPLAY_ROOT.3bsd \
STAILQ_CLASS_ENTRY.3bsd \
STAILQ_CLASS_HEAD.3bsd \
STAILQ_CONCAT.3bsd \ STAILQ_CONCAT.3bsd \
STAILQ_EMPTY.3bsd \ STAILQ_EMPTY.3bsd \
STAILQ_ENTRY.3bsd \ STAILQ_ENTRY.3bsd \
@@ -108,6 +115,8 @@ dist_man_MANS = \
STAILQ_REMOVE_AFTER.3bsd \ STAILQ_REMOVE_AFTER.3bsd \
STAILQ_REMOVE_HEAD.3bsd \ STAILQ_REMOVE_HEAD.3bsd \
STAILQ_SWAP.3bsd \ STAILQ_SWAP.3bsd \
TAILQ_CLASS_ENTRY.3bsd \
TAILQ_CLASS_HEAD.3bsd \
TAILQ_CONCAT.3bsd \ TAILQ_CONCAT.3bsd \
TAILQ_EMPTY.3bsd \ TAILQ_EMPTY.3bsd \
TAILQ_ENTRY.3bsd \ TAILQ_ENTRY.3bsd \
@@ -165,6 +174,7 @@ dist_man_MANS = \
fgetln.3bsd \ fgetln.3bsd \
fgetwln.3bsd \ fgetwln.3bsd \
flopen.3bsd \ flopen.3bsd \
freezero.3bsd \
fmtcheck.3bsd \ fmtcheck.3bsd \
fparseln.3bsd \ fparseln.3bsd \
fpurge.3bsd \ fpurge.3bsd \
@@ -173,6 +183,8 @@ dist_man_MANS = \
getmode.3bsd \ getmode.3bsd \
getpeereid.3bsd \ getpeereid.3bsd \
getprogname.3bsd \ getprogname.3bsd \
gid_from_group.3bsd \
group_from_gid.3bsd \
heapsort.3bsd \ heapsort.3bsd \
humanize_number.3bsd \ humanize_number.3bsd \
le16dec.3bsd \ le16dec.3bsd \
@@ -190,11 +202,13 @@ dist_man_MANS = \
pidfile_open.3bsd \ pidfile_open.3bsd \
pidfile_remove.3bsd \ pidfile_remove.3bsd \
pidfile_write.3bsd \ pidfile_write.3bsd \
pwcache.3bsd \
queue.3bsd \ queue.3bsd \
radixsort.3bsd \ radixsort.3bsd \
readpassphrase.3bsd \ readpassphrase.3bsd \
reallocarray.3bsd \ reallocarray.3bsd \
reallocf.3bsd \ reallocf.3bsd \
recallocarray.3bsd \
setmode.3bsd \ setmode.3bsd \
setproctitle.3bsd \ setproctitle.3bsd \
setproctitle_init.3bsd \ setproctitle_init.3bsd \
@@ -223,6 +237,7 @@ dist_man_MANS = \
timercmp.3bsd \ timercmp.3bsd \
timerisset.3bsd \ timerisset.3bsd \
timersub.3bsd \ timersub.3bsd \
timespec.3bsd \
timespecadd.3bsd \ timespecadd.3bsd \
timespecclear.3bsd \ timespecclear.3bsd \
timespeccmp.3bsd \ timespeccmp.3bsd \
@@ -230,7 +245,9 @@ dist_man_MANS = \
timespecsub.3bsd \ timespecsub.3bsd \
timeval.3bsd \ timeval.3bsd \
tree.3bsd \ tree.3bsd \
uid_from_user.3bsd \
unvis.3bsd \ unvis.3bsd \
user_from_uid.3bsd \
vis.3bsd \ vis.3bsd \
wcslcat.3bsd \ wcslcat.3bsd \
wcslcpy.3bsd \ wcslcpy.3bsd \

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -0,0 +1 @@
.so man3/queue.3bsd

View File

@@ -44,6 +44,10 @@
.Nm bitstr_size , .Nm bitstr_size ,
.Nm bit_test .Nm bit_test
.Nd bit-string manipulation macros .Nd bit-string manipulation macros
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
.Lb libbsd
.Sh SYNOPSIS .Sh SYNOPSIS
.In bitstring.h .In bitstring.h
(See (See

View File

@@ -31,6 +31,10 @@
.Nm be16enc , be16dec , be32enc , be32dec , be64enc , be64dec , .Nm be16enc , be16dec , be32enc , be32dec , be64enc , be64dec ,
.Nm le16enc , le16dec , le32enc , le32dec , le64enc , le64dec .Nm le16enc , le16dec , le32enc , le32dec , le64enc , le64dec
.Nd byte order operations .Nd byte order operations
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
.Lb libbsd
.Sh SYNOPSIS .Sh SYNOPSIS
.In sys/endian.h .In sys/endian.h
(See (See

1
man/freezero.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/reallocarray.3bsd

1
man/gid_from_group.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/pwcache.3bsd

1
man/group_from_gid.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/pwcache.3bsd

View File

@@ -94,11 +94,13 @@ be prefixed with
.It In bitstring.h .It In bitstring.h
.It In err.h .It In err.h
.It In getopt.h .It In getopt.h
.It In grp.h
.It In inttypes.h .It In inttypes.h
.It In libutil.h .It In libutil.h
.It In md5.h .It In md5.h
.It In netinet/ip_icmp.h .It In netinet/ip_icmp.h
.It In nlist.h .It In nlist.h
.It In pwd.h
.It In readpassphrase.h .It In readpassphrase.h
.It In stdio.h .It In stdio.h
.It In stdlib.h .It In stdlib.h
@@ -107,6 +109,7 @@ be prefixed with
.It In sys/bitstring.h .It In sys/bitstring.h
.It In sys/cdefs.h .It In sys/cdefs.h
.It In sys/endian.h .It In sys/endian.h
.It In sys/param.h
.It In sys/poll.h .It In sys/poll.h
.It In sys/queue.h .It In sys/queue.h
.It In sys/time.h .It In sys/time.h
@@ -125,6 +128,45 @@ It only works in non-overlay mode.
.Bl -tag -width 4m -compact .Bl -tag -width 4m -compact
.It In bsd/bsd.h .It In bsd/bsd.h
.El .El
.Sh ALTERNATIVES
Some functions have different prototypes depending on the BSD where they
originated from, and these various implementations provided are selectable
at build-time.
.Pp
This is the list of functions that provide multiple implementations:
.Bl -tag -width 4m
.It Fn strnvis 3
.It Fn strnunvis 3
.Nx
added
.Fn strnvis 3
and
.Fn strnunvis 3
but unfortunately made it incompatible with the existing one in
.Ox
and Freedesktop's libbsd (the former having existed for over ten years).
Despite this incompatibility being reported during development (see
http://gnats.netbsd.org/44977) they still shipped it.
Even more unfortunately
.Fx
and later MacOS picked up this incompatible implementation.
.Pp
Provide both implementations and default for now to the historical one to
avoid breakage, but we will switch to the
.Nx
one in a later release, which is internally consistent with the other
.Xr vis 3
functions and is now more widespread.
Define
.Dv LIBBSD_NETBSD_VIS
to switch to the
.Nx one now.
Define
.Dv LIBBSD_OPENBSD_VIS
to keep using the
.Ox
one.
.El
.Sh DEPRECATED .Sh DEPRECATED
Some functions have been deprecated, they will emit warnings at compile time Some functions have been deprecated, they will emit warnings at compile time
and possibly while being linked at run-time. and possibly while being linked at run-time.
@@ -180,9 +222,10 @@ for example.
.It Fn MD5File 3 .It Fn MD5File 3
.It Fn MD5FileChunk 3 .It Fn MD5FileChunk 3
.It Fn MD5Data 3 .It Fn MD5Data 3
The set of MD5 digest functions are now provided by the The set of MD5 digest functions are now proxies for the implementations
provided by the
.Nm libmd .Nm libmd
companion library, so it is advised to use that instead. companion library, so it is advised to switch to use that directly instead.
.It Fn explicit_bzero 3 .It Fn explicit_bzero 3
This function is provided by This function is provided by
.Nm glibc .Nm glibc
@@ -215,6 +258,7 @@ This function is provided by
.Xr md5 3bsd , .Xr md5 3bsd ,
.Xr nlist 3bsd , .Xr nlist 3bsd ,
.Xr pidfile 3bsd , .Xr pidfile 3bsd ,
.Xr pwcache 3bsd ,
.Xr queue 3bsd , .Xr queue 3bsd ,
.Xr radixsort 3bsd , .Xr radixsort 3bsd ,
.Xr readpassphrase 3bsd , .Xr readpassphrase 3bsd ,

143
man/pwcache.3bsd Normal file
View File

@@ -0,0 +1,143 @@
.\" $OpenBSD: pwcache.3,v 1.15 2018/09/13 16:50:54 jmc Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
.\"
.Dd $Mdocdate: September 13 2018 $
.Dt USER_FROM_UID 3
.Os
.Sh NAME
.Nm user_from_uid ,
.Nm uid_from_user ,
.Nm group_from_gid ,
.Nm gid_from_group
.Nd cache password and group entries
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
.Lb libbsd
.Sh SYNOPSIS
.In pwd.h
(See
.Xr libbsd 7
for include usage.)
.Ft int
.Fn uid_from_user "const char *name" "uid_t *uid"
.Ft const char *
.Fn user_from_uid "uid_t uid" "int nouser"
.In grp.h
.Ft int
.Fn gid_from_group "const char *name" "gid_t *gid"
.Ft const char *
.Fn group_from_gid "gid_t gid" "int nogroup"
.Sh DESCRIPTION
The
.Fn user_from_uid
function returns the user name associated with the argument
.Fa uid .
The user name is cached so that multiple calls with the same
.Fa uid
do not require additional calls to
.Xr getpwuid 3 .
If there is no user associated with the
.Fa uid ,
a pointer is returned
to a string representation of the
.Fa uid ,
unless the argument
.Fa nouser
is non-zero, in which case a null pointer is returned.
.Pp
The
.Fn uid_from_user
function returns the user ID associated with the argument
.Fa name .
The user ID is cached so that multiple calls with the same
.Fa name
do not require additional calls to
.Xr getpwnam 3 .
If there is no user ID associated with the
.Fa name ,
the
.Fn uid_from_user
function returns -1;
otherwise it stores the user ID at the location pointed to by
.Fa uid
and returns 0.
.Pp
The
.Fn group_from_gid
function returns the group name associated with the argument
.Fa gid .
The group name is cached so that multiple calls with the same
.Fa gid
do not require additional calls to
.Xr getgrgid 3 .
If there is no group associated with the
.Fa gid ,
a pointer is returned
to a string representation of the
.Fa gid ,
unless the argument
.Fa nogroup
is non-zero, in which case a null pointer is returned.
.Pp
The
.Fn gid_from_group
function returns the group ID associated with the argument
.Fa name .
The group ID is cached so that multiple calls with the same
.Fa name
do not require additional calls to
.Xr getgrnam 3 .
If there is no group ID associated with the
.Fa name ,
the
.Fn gid_from_group
function returns -1;
otherwise it stores the group ID at the location pointed to by
.Fa gid
and returns 0.
.Sh SEE ALSO
.Xr getgrgid 3 ,
.Xr getpwuid 3
.Sh HISTORY
The
.Fn user_from_uid
and
.Fn group_from_gid
functions first appeared in
.Bx 4.4 .
.Pp
The
.Fn uid_from_user
and
.Fn gid_from_group
functions were ported from
.Nx
and first appeared in
.Ox 6.4 .

View File

@@ -28,35 +28,40 @@
.\" @(#)queue.3 8.2 (Berkeley) 1/24/94 .\" @(#)queue.3 8.2 (Berkeley) 1/24/94
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd June 17, 2013 .Dd September 8, 2016
.Dt QUEUE 3bsd .Dt QUEUE 3bsd
.Os .Os
.Sh NAME .Sh NAME
.Nm SLIST_CLASS_ENTRY ,
.Nm SLIST_CLASS_HEAD ,
.Nm SLIST_CONCAT ,
.Nm SLIST_EMPTY , .Nm SLIST_EMPTY ,
.Nm SLIST_ENTRY , .Nm SLIST_ENTRY ,
.Nm SLIST_FIRST , .Nm SLIST_FIRST ,
.Nm SLIST_FOREACH , .Nm SLIST_FOREACH ,
.Nm SLIST_FOREACH_FROM , .Nm SLIST_FOREACH_FROM ,
.Nm SLIST_FOREACH_SAFE ,
.Nm SLIST_FOREACH_FROM_SAFE , .Nm SLIST_FOREACH_FROM_SAFE ,
.Nm SLIST_FOREACH_SAFE ,
.Nm SLIST_HEAD , .Nm SLIST_HEAD ,
.Nm SLIST_HEAD_INITIALIZER , .Nm SLIST_HEAD_INITIALIZER ,
.Nm SLIST_INIT , .Nm SLIST_INIT ,
.Nm SLIST_INSERT_AFTER , .Nm SLIST_INSERT_AFTER ,
.Nm SLIST_INSERT_HEAD , .Nm SLIST_INSERT_HEAD ,
.Nm SLIST_NEXT , .Nm SLIST_NEXT ,
.Nm SLIST_REMOVE ,
.Nm SLIST_REMOVE_AFTER , .Nm SLIST_REMOVE_AFTER ,
.Nm SLIST_REMOVE_HEAD , .Nm SLIST_REMOVE_HEAD ,
.Nm SLIST_REMOVE ,
.Nm SLIST_SWAP , .Nm SLIST_SWAP ,
.Nm STAILQ_CLASS_ENTRY ,
.Nm STAILQ_CLASS_HEAD ,
.Nm STAILQ_CONCAT , .Nm STAILQ_CONCAT ,
.Nm STAILQ_EMPTY , .Nm STAILQ_EMPTY ,
.Nm STAILQ_ENTRY , .Nm STAILQ_ENTRY ,
.Nm STAILQ_FIRST , .Nm STAILQ_FIRST ,
.Nm STAILQ_FOREACH , .Nm STAILQ_FOREACH ,
.Nm STAILQ_FOREACH_FROM , .Nm STAILQ_FOREACH_FROM ,
.Nm STAILQ_FOREACH_SAFE ,
.Nm STAILQ_FOREACH_FROM_SAFE , .Nm STAILQ_FOREACH_FROM_SAFE ,
.Nm STAILQ_FOREACH_SAFE ,
.Nm STAILQ_HEAD , .Nm STAILQ_HEAD ,
.Nm STAILQ_HEAD_INITIALIZER , .Nm STAILQ_HEAD_INITIALIZER ,
.Nm STAILQ_INIT , .Nm STAILQ_INIT ,
@@ -65,17 +70,20 @@
.Nm STAILQ_INSERT_TAIL , .Nm STAILQ_INSERT_TAIL ,
.Nm STAILQ_LAST , .Nm STAILQ_LAST ,
.Nm STAILQ_NEXT , .Nm STAILQ_NEXT ,
.Nm STAILQ_REMOVE ,
.Nm STAILQ_REMOVE_AFTER , .Nm STAILQ_REMOVE_AFTER ,
.Nm STAILQ_REMOVE_HEAD , .Nm STAILQ_REMOVE_HEAD ,
.Nm STAILQ_REMOVE ,
.Nm STAILQ_SWAP , .Nm STAILQ_SWAP ,
.Nm LIST_CLASS_ENTRY ,
.Nm LIST_CLASS_HEAD ,
.Nm LIST_CONCAT ,
.Nm LIST_EMPTY , .Nm LIST_EMPTY ,
.Nm LIST_ENTRY , .Nm LIST_ENTRY ,
.Nm LIST_FIRST , .Nm LIST_FIRST ,
.Nm LIST_FOREACH , .Nm LIST_FOREACH ,
.Nm LIST_FOREACH_FROM , .Nm LIST_FOREACH_FROM ,
.Nm LIST_FOREACH_SAFE ,
.Nm LIST_FOREACH_FROM_SAFE , .Nm LIST_FOREACH_FROM_SAFE ,
.Nm LIST_FOREACH_SAFE ,
.Nm LIST_HEAD , .Nm LIST_HEAD ,
.Nm LIST_HEAD_INITIALIZER , .Nm LIST_HEAD_INITIALIZER ,
.Nm LIST_INIT , .Nm LIST_INIT ,
@@ -86,18 +94,20 @@
.Nm LIST_PREV , .Nm LIST_PREV ,
.Nm LIST_REMOVE , .Nm LIST_REMOVE ,
.Nm LIST_SWAP , .Nm LIST_SWAP ,
.Nm TAILQ_CLASS_ENTRY ,
.Nm TAILQ_CLASS_HEAD ,
.Nm TAILQ_CONCAT , .Nm TAILQ_CONCAT ,
.Nm TAILQ_EMPTY , .Nm TAILQ_EMPTY ,
.Nm TAILQ_ENTRY , .Nm TAILQ_ENTRY ,
.Nm TAILQ_FIRST , .Nm TAILQ_FIRST ,
.Nm TAILQ_FOREACH , .Nm TAILQ_FOREACH ,
.Nm TAILQ_FOREACH_FROM , .Nm TAILQ_FOREACH_FROM ,
.Nm TAILQ_FOREACH_SAFE ,
.Nm TAILQ_FOREACH_FROM_SAFE , .Nm TAILQ_FOREACH_FROM_SAFE ,
.Nm TAILQ_FOREACH_REVERSE , .Nm TAILQ_FOREACH_REVERSE ,
.Nm TAILQ_FOREACH_REVERSE_FROM , .Nm TAILQ_FOREACH_REVERSE_FROM ,
.Nm TAILQ_FOREACH_REVERSE_SAFE ,
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE , .Nm TAILQ_FOREACH_REVERSE_FROM_SAFE ,
.Nm TAILQ_FOREACH_REVERSE_SAFE ,
.Nm TAILQ_FOREACH_SAFE ,
.Nm TAILQ_HEAD , .Nm TAILQ_HEAD ,
.Nm TAILQ_HEAD_INITIALIZER , .Nm TAILQ_HEAD_INITIALIZER ,
.Nm TAILQ_INIT , .Nm TAILQ_INIT ,
@@ -112,58 +122,70 @@
.Nm TAILQ_SWAP .Nm TAILQ_SWAP
.Nd implementations of singly-linked lists, singly-linked tail queues, .Nd implementations of singly-linked lists, singly-linked tail queues,
lists and tail queues lists and tail queues
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
.Lb libbsd
.Sh SYNOPSIS .Sh SYNOPSIS
.In sys/queue.h .In sys/queue.h
(See (See
.Xr libbsd 7 .Xr libbsd 7
for include usage.) for include usage.)
.\" .\"
.Fn SLIST_CLASS_ENTRY "CLASSTYPE"
.Fn SLIST_CLASS_HEAD "HEADNAME" "CLASSTYPE"
.Fn SLIST_CONCAT "SLIST_HEAD *head1" "SLIST_HEAD *head2" "TYPE" "SLIST_ENTRY NAME"
.Fn SLIST_EMPTY "SLIST_HEAD *head" .Fn SLIST_EMPTY "SLIST_HEAD *head"
.Fn SLIST_ENTRY "TYPE" .Fn SLIST_ENTRY "TYPE"
.Fn SLIST_FIRST "SLIST_HEAD *head" .Fn SLIST_FIRST "SLIST_HEAD *head"
.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" .Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" .Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var" .Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_HEAD "HEADNAME" "TYPE" .Fn SLIST_HEAD "HEADNAME" "TYPE"
.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head" .Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
.Fn SLIST_INIT "SLIST_HEAD *head" .Fn SLIST_INIT "SLIST_HEAD *head"
.Fn SLIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "SLIST_ENTRY NAME" .Fn SLIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "SLIST_ENTRY NAME"
.Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME" .Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME"
.Fn SLIST_NEXT "TYPE *elm" "SLIST_ENTRY NAME" .Fn SLIST_NEXT "TYPE *elm" "SLIST_ENTRY NAME"
.Fn SLIST_REMOVE "SLIST_HEAD *head" "TYPE *elm" "TYPE" "SLIST_ENTRY NAME"
.Fn SLIST_REMOVE_AFTER "TYPE *elm" "SLIST_ENTRY NAME" .Fn SLIST_REMOVE_AFTER "TYPE *elm" "SLIST_ENTRY NAME"
.Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "SLIST_ENTRY NAME" .Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_REMOVE "SLIST_HEAD *head" "TYPE *elm" "TYPE" "SLIST_ENTRY NAME" .Fn SLIST_SWAP "SLIST_HEAD *head1" "SLIST_HEAD *head2" "TYPE"
.Fn SLIST_SWAP "SLIST_HEAD *head1" "SLIST_HEAD *head2" "SLIST_ENTRY NAME"
.\" .\"
.Fn STAILQ_CLASS_ENTRY "CLASSTYPE"
.Fn STAILQ_CLASS_HEAD "HEADNAME" "CLASSTYPE"
.Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2" .Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
.Fn STAILQ_EMPTY "STAILQ_HEAD *head" .Fn STAILQ_EMPTY "STAILQ_HEAD *head"
.Fn STAILQ_ENTRY "TYPE" .Fn STAILQ_ENTRY "TYPE"
.Fn STAILQ_FIRST "STAILQ_HEAD *head" .Fn STAILQ_FIRST "STAILQ_HEAD *head"
.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" .Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" .Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var" .Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_HEAD "HEADNAME" "TYPE" .Fn STAILQ_HEAD "HEADNAME" "TYPE"
.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head" .Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
.Fn STAILQ_INIT "STAILQ_HEAD *head" .Fn STAILQ_INIT "STAILQ_HEAD *head"
.Fn STAILQ_INSERT_AFTER "STAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "STAILQ_ENTRY NAME" .Fn STAILQ_INSERT_AFTER "STAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "STAILQ_ENTRY NAME"
.Fn STAILQ_INSERT_HEAD "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME" .Fn STAILQ_INSERT_HEAD "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
.Fn STAILQ_INSERT_TAIL "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME" .Fn STAILQ_INSERT_TAIL "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
.Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE" "STAILQ_ENTRY NAME" .Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
.Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME" .Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME"
.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME"
.Fn STAILQ_REMOVE_AFTER "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME" .Fn STAILQ_REMOVE_AFTER "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
.Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" .Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME" .Fn STAILQ_SWAP "STAILQ_HEAD *head1" "STAILQ_HEAD *head2" "TYPE"
.Fn STAILQ_SWAP "STAILQ_HEAD *head1" "STAILQ_HEAD *head2" "STAILQ_ENTRY NAME"
.\" .\"
.Fn LIST_CLASS_ENTRY "CLASSTYPE"
.Fn LIST_CLASS_HEAD "HEADNAME" "CLASSTYPE"
.Fn LIST_CONCAT "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
.Fn LIST_EMPTY "LIST_HEAD *head" .Fn LIST_EMPTY "LIST_HEAD *head"
.Fn LIST_ENTRY "TYPE" .Fn LIST_ENTRY "TYPE"
.Fn LIST_FIRST "LIST_HEAD *head" .Fn LIST_FIRST "LIST_HEAD *head"
.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" .Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" .Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var" .Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_HEAD "HEADNAME" "TYPE" .Fn LIST_HEAD "HEADNAME" "TYPE"
.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head" .Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
.Fn LIST_INIT "LIST_HEAD *head" .Fn LIST_INIT "LIST_HEAD *head"
@@ -175,18 +197,20 @@ for include usage.)
.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME" .Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME" .Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
.\" .\"
.Fn TAILQ_CLASS_ENTRY "CLASSTYPE"
.Fn TAILQ_CLASS_HEAD "HEADNAME" "CLASSTYPE"
.Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TAILQ_ENTRY NAME" .Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TAILQ_ENTRY NAME"
.Fn TAILQ_EMPTY "TAILQ_HEAD *head" .Fn TAILQ_EMPTY "TAILQ_HEAD *head"
.Fn TAILQ_ENTRY "TYPE" .Fn TAILQ_ENTRY "TYPE"
.Fn TAILQ_FIRST "TAILQ_HEAD *head" .Fn TAILQ_FIRST "TAILQ_HEAD *head"
.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var" .Fn TAILQ_FOREACH_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var" .Fn TAILQ_FOREACH_REVERSE_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_HEAD "HEADNAME" "TYPE" .Fn TAILQ_HEAD "HEADNAME" "TYPE"
.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head" .Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
.Fn TAILQ_INIT "TAILQ_HEAD *head" .Fn TAILQ_INIT "TAILQ_HEAD *head"
@@ -201,8 +225,18 @@ for include usage.)
.Fn TAILQ_SWAP "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TYPE" "TAILQ_ENTRY NAME" .Fn TAILQ_SWAP "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TYPE" "TAILQ_ENTRY NAME"
.\" .\"
.Sh DESCRIPTION .Sh DESCRIPTION
These macros define and operate on four types of data structures: These macros define and operate on four types of data structures which
singly-linked lists, singly-linked tail queues, lists, and tail queues. can be used in both C and C++ source code:
.Bl -enum -compact -offset indent
.It
Lists
.It
Singly-linked lists
.It
Singly-linked tail queues
.It
Tail queues
.El
All four structures support the following functionality: All four structures support the following functionality:
.Bl -enum -compact -offset indent .Bl -enum -compact -offset indent
.It .It
@@ -226,6 +260,8 @@ Singly-linked lists add the following functionality:
.Bl -enum -compact -offset indent .Bl -enum -compact -offset indent
.It .It
O(n) removal of any entry in the list. O(n) removal of any entry in the list.
.It
O(n) concatenation of two lists.
.El .El
.Pp .Pp
Singly-linked tail queues add the following functionality: Singly-linked tail queues add the following functionality:
@@ -273,6 +309,8 @@ Linked lists are the simplest of the doubly linked data structures.
They add the following functionality over the above: They add the following functionality over the above:
.Bl -enum -compact -offset indent .Bl -enum -compact -offset indent
.It .It
O(n) concatenation of two lists.
.It
They may be traversed backwards. They may be traversed backwards.
.El .El
However: However:
@@ -304,24 +342,39 @@ than singly-linked lists.
.Pp .Pp
In the macro definitions, In the macro definitions,
.Fa TYPE .Fa TYPE
is the name of a user defined structure, is the name of a user defined structure.
that must contain a field of type The structure must contain a field called
.Fa NAME
which is of type
.Li SLIST_ENTRY , .Li SLIST_ENTRY ,
.Li STAILQ_ENTRY , .Li STAILQ_ENTRY ,
.Li LIST_ENTRY , .Li LIST_ENTRY ,
or or
.Li TAILQ_ENTRY , .Li TAILQ_ENTRY .
named In the macro definitions,
.Fa NAME . .Fa CLASSTYPE
is the name of a user defined class.
The class must contain a field called
.Fa NAME
which is of type
.Li SLIST_CLASS_ENTRY ,
.Li STAILQ_CLASS_ENTRY ,
.Li LIST_CLASS_ENTRY ,
or
.Li TAILQ_CLASS_ENTRY .
The argument The argument
.Fa HEADNAME .Fa HEADNAME
is the name of a user defined structure that must be declared is the name of a user defined structure that must be declared
using the macros using the macros
.Li SLIST_HEAD , .Li SLIST_HEAD ,
.Li SLIST_CLASS_HEAD ,
.Li STAILQ_HEAD , .Li STAILQ_HEAD ,
.Li STAILQ_CLASS_HEAD ,
.Li LIST_HEAD , .Li LIST_HEAD ,
.Li LIST_CLASS_HEAD ,
.Li TAILQ_HEAD ,
or or
.Li TAILQ_HEAD . .Li TAILQ_CLASS_HEAD .
See the examples below for further explanation of how these See the examples below for further explanation of how these
macros are used. macros are used.
.Sh SINGLY-LINKED LISTS .Sh SINGLY-LINKED LISTS
@@ -363,6 +416,19 @@ evaluates to an initializer for the list
.Fa head . .Fa head .
.Pp .Pp
The macro The macro
.Nm SLIST_CONCAT
concatenates the list headed by
.Fa head2
onto the end of the one headed by
.Fa head1
removing all entries from the former.
Use of this macro should be avoided as it traverses the entirety of the
.Fa head1
list.
A singly-linked tail queue should be used if this macro is needed in
high-usage code paths or to operate on long lists.
.Pp
The macro
.Nm SLIST_EMPTY .Nm SLIST_EMPTY
evaluates to true if there are no elements in the list. evaluates to true if there are no elements in the list.
.Pp .Pp
@@ -470,6 +536,9 @@ The macro
removes the element removes the element
.Fa elm .Fa elm
from the list. from the list.
Use of this macro should be avoided as it traverses the entire list.
A doubly-linked list should be used if this macro is needed in
high-usage code paths or to operate on long lists.
.Pp .Pp
The macro The macro
.Nm SLIST_SWAP .Nm SLIST_SWAP
@@ -686,6 +755,9 @@ The macro
removes the element removes the element
.Fa elm .Fa elm
from the tail queue. from the tail queue.
Use of this macro should be avoided as it traverses the entire list.
A doubly-linked tail queue should be used if this macro is needed in
high-usage code paths or to operate on long tail queues.
.Pp .Pp
The macro The macro
.Nm STAILQ_SWAP .Nm STAILQ_SWAP
@@ -785,6 +857,19 @@ evaluates to an initializer for the list
.Fa head . .Fa head .
.Pp .Pp
The macro The macro
.Nm LIST_CONCAT
concatenates the list headed by
.Fa head2
onto the end of the one headed by
.Fa head1
removing all entries from the former.
Use of this macro should be avoided as it traverses the entirety of the
.Fa head1
list.
A tail queue should be used if this macro is needed in
high-usage code paths or to operate on long lists.
.Pp
The macro
.Nm LIST_EMPTY .Nm LIST_EMPTY
evaluates to true if there are no elements in the list. evaluates to true if there are no elements in the list.
.Pp .Pp
@@ -1206,6 +1291,26 @@ while (n1 != NULL) {
} }
TAILQ_INIT(&head); TAILQ_INIT(&head);
.Ed .Ed
.Sh DIAGNOSTICS
When debugging
.Nm queue(3) ,
it can be useful to trace queue changes.
To enable tracing, define the macro
.Va QUEUE_MACRO_DEBUG_TRACE
at compile time.
.Pp
It can also be useful to trash pointers that have been unlinked from a queue,
to detect use after removal.
To enable pointer trashing, define the macro
.Va QUEUE_MACRO_DEBUG_TRASH
at compile time.
The macro
.Fn QMD_IS_TRASHED "void *ptr"
returns true if
.Fa ptr
has been trashed by the
.Va QUEUE_MACRO_DEBUG_TRASH
option.
.Sh SEE ALSO .Sh SEE ALSO
.Xr tree 3bsd .Xr tree 3bsd
.Sh HISTORY .Sh HISTORY

View File

@@ -30,13 +30,15 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: malloc.3,v 1.78 2014/05/01 18:41:59 jmc Exp $ .\" $OpenBSD: malloc.3,v 1.126 2019/09/14 13:16:50 otto Exp $
.\" .\"
.Dd $Mdocdate: May 1 2014 $ .Dd $Mdocdate: September 14 2019 $
.Dt REALLOCARRAY 3bsd .Dt REALLOCARRAY 3bsd
.Os .Os
.Sh NAME .Sh NAME
.Nm reallocarray .Nm reallocarray ,
.Nm recallocarray ,
.Nm freezero
.Nd memory allocation and deallocation .Nd memory allocation and deallocation
.Sh LIBRARY .Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd) .ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
@@ -49,59 +51,244 @@
for include usage.) for include usage.)
.Ft void * .Ft void *
.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size" .Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
.Ft void *
.Fn recallocarray "void *ptr" "size_t oldnmemb" "size_t nmemb" "size_t size"
.Ft void
.Fn freezero "void *ptr" "size_t size"
.Sh DESCRIPTION .Sh DESCRIPTION
.Pp .Pp
When using Designed for safe allocation of arrays,
.Fn malloc the
be careful to avoid the following idiom:
.Bd -literal -offset indent
if ((p = malloc(num * size)) == NULL)
err(1, "malloc");
.Ed
.Pp
The multiplication may lead to an integer overflow, which can
be avoided using the extension
.Fn reallocarray ,
as follows:
.Bd -literal -offset indent
if ((p = reallocarray(NULL, num, size)) == NULL)
err(1, "malloc");
.Ed
.Pp
Alternatively
.Fn calloc
is a more portable solution which comes with the cost of clearing memory.
.Pp
If
.Fn malloc
must be used, be sure to test for overflow:
.Bd -literal -offset indent
if (size && num > SIZE_MAX / size) {
errno = ENOMEM;
err(1, "overflow");
}
.Ed
.Pp
The use of
.Fn reallocarray .Fn reallocarray
or function is similar to
.Fn calloc .Fn realloc
is strongly encouraged when allocating multiple sized objects except it operates on
in order to avoid possible integer overflows. .Fa nmemb
members of size
.Fa size
and checks for integer overflow in the calculation
.Fa nmemb
*
.Fa size .
.Pp
Used for the allocation of memory holding sensitive data,
the
.Fn recallocarray
function guarantees that memory becoming unallocated is explicitly
.Em discarded ,
meaning cached free objects are cleared with
.Xr explicit_bzero 3 .
.Pp
The
.Fn recallocarray
function is similar to
.Fn reallocarray
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 behavior is undefined.
The
.Fn freezero
function is similar to the
.Fn free
function except it ensures memory is explicitly discarded.
If
.Fa ptr
is
.Dv NULL ,
no action occurs.
If
.Fa ptr
is not
.Dv NULL ,
the
.Fa size
argument must be equal to or smaller than the size of the earlier allocation
that returned
.Fa ptr .
.Fn freezero
guarantees the memory range starting at
.Fa ptr
with length
.Fa size
is discarded while deallocating the whole object originally allocated.
.Sh RETURN VALUES .Sh RETURN VALUES
The The
.Fn reallocarray .Fn reallocarray
function returns a pointer to the allocated space if successful; otherwise, and
.Fn recallocarray
functions return a pointer to the allocated space if successful; otherwise,
a null pointer is returned and a null pointer is returned and
.Va errno .Va errno
is set to is set to
.Er ENOMEM . .Er ENOMEM .
.Pp
If multiplying
.Fa nmemb
and
.Fa size
results in integer overflow,
.Fn reallocarray
and
.Fn recallocarray
return
.Dv NULL
and set
.Va errno
to
.Er ENOMEM .
.Pp
If
.Fa ptr
is not
.Dv NULL
and multiplying
.Fa oldnmemb
and
.Fa size
results in integer overflow
.Fn recallocarray
returns
.Dv NULL
and sets
.Va errno
to
.Er EINVAL .
.Sh IDIOMS
Consider
.Fn calloc
or the extensions
.Fn reallocarray
and
.Fn recallocarray
when there is multiplication in the
.Fa size
argument of
.Fn malloc
or
.Fn realloc .
For example, avoid this common idiom as it may lead to integer overflow:
.Bd -literal -offset indent
if ((p = malloc(num * size)) == NULL)
err(1, NULL);
.Ed
.Pp
A drop-in replacement is
.Fn reallocarray :
.Bd -literal -offset indent
if ((p = reallocarray(NULL, num, size)) == NULL)
err(1, NULL);
.Ed
.Pp
Alternatively,
.Fn calloc
may be used at the cost of initialization overhead.
.Pp
When using
.Fn realloc ,
be careful to avoid the following idiom:
.Bd -literal -offset indent
size += 50;
if ((p = realloc(p, size)) == NULL)
return (NULL);
.Ed
.Pp
Do not adjust the variable describing how much memory has been allocated
until the allocation has been successful.
This can cause aberrant program behavior if the incorrect size value is used.
In most cases, the above sample will also result in a leak of memory.
As stated earlier, a return value of
.Dv NULL
indicates that the old object still remains allocated.
Better code looks like this:
.Bd -literal -offset indent
newsize = size + 50;
if ((newp = realloc(p, newsize)) == NULL) {
free(p);
p = NULL;
size = 0;
return (NULL);
}
p = newp;
size = newsize;
.Ed
.Pp
As with
.Fn malloc ,
it is important to ensure the new size value will not overflow;
i.e. avoid allocations like the following:
.Bd -literal -offset indent
if ((newp = realloc(p, num * size)) == NULL) {
...
.Ed
.Pp
Instead, use
.Fn reallocarray :
.Bd -literal -offset indent
if ((newp = reallocarray(p, num, size)) == NULL) {
...
.Ed
.Pp
Calling
.Fn realloc
with a
.Dv NULL
.Fa ptr
is equivalent to calling
.Fn malloc .
Instead of this idiom:
.Bd -literal -offset indent
if (p == NULL)
newp = malloc(newsize);
else
newp = realloc(p, newsize);
.Ed
.Pp
Use the following:
.Bd -literal -offset indent
newp = realloc(p, newsize);
.Ed
.Pp
The
.Fn recallocarray
function should be used for resizing objects containing sensitive data like
keys.
To avoid leaking information,
it guarantees memory is cleared before placing it on the internal free list.
Deallocation of such an object should be done by calling
.Fn freezero .
.Sh SEE ALSO .Sh SEE ALSO
.Xr malloc 3 , .Xr malloc 3 ,
.Xr calloc 3 , .Xr calloc 3 ,
.Xr alloca 3 .Xr alloca 3
.Sh HISTORY .Sh HISTORY
The
.Fn reallocarray .Fn reallocarray
appeared in function appeared in
.Ox 5.6 , .Ox 5.6 ,
glibc 2.26. and glibc 2.26.
The
.Fn recallocarray
function appeared in
.Ox 6.1 .
The
.Fn freezero
function appeared in
.Ox 6.2 .

1
man/recallocarray.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/reallocarray.3bsd

1
man/timespec.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/timeval.3bsd

View File

@@ -75,6 +75,10 @@
.Nm RB_INSERT , .Nm RB_INSERT ,
.Nm RB_REMOVE .Nm RB_REMOVE
.Nd implementations of splay and red-black trees .Nd implementations of splay and red-black trees
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
.Lb libbsd
.Sh SYNOPSIS .Sh SYNOPSIS
.In sys/tree.h .In sys/tree.h
(See (See

1
man/uid_from_user.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/pwcache.3bsd

1
man/user_from_uid.3bsd Normal file
View File

@@ -0,0 +1 @@
.so man3/pwcache.3bsd

View File

@@ -529,6 +529,7 @@ The destination buffer size is not large enough to perform the conversion.
.%O "RFC 2045" .%O "RFC 2045"
.Re .Re
.Sh HISTORY .Sh HISTORY
.ds doc-operating-system-NetBSD-7.0 7.0
The The
.Fn vis , .Fn vis ,
.Fn strvis , .Fn strvis ,

View File

@@ -15,7 +15,6 @@ AM_CPPFLAGS += \
endif endif
libbsd_la_included_sources = \ libbsd_la_included_sources = \
hash/helper.c \
getentropy_aix.c \ getentropy_aix.c \
getentropy_bsd.c \ getentropy_bsd.c \
getentropy_hpux.c \ getentropy_hpux.c \
@@ -34,10 +33,6 @@ EXTRA_DIST = \
$(libbsd_la_included_sources) \ $(libbsd_la_included_sources) \
$(nil) $(nil)
CLEANFILES = \
hash/md5hl.c \
$(nil)
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \ pkgconfig_DATA = \
libbsd.pc \ libbsd.pc \
@@ -53,20 +48,20 @@ pkgconfig_DATA += libbsd-ctor.pc
lib_LIBRARIES += libbsd-ctor.a lib_LIBRARIES += libbsd-ctor.a
endif endif
hash/md5hl.c: $(srcdir)/hash/helper.c
$(AM_V_at) $(MKDIR_P) hash
$(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@
libbsd_la_DEPENDENCIES = \ libbsd_la_DEPENDENCIES = \
$(libbsd_la_included_sources) \ $(libbsd_la_included_sources) \
libbsd.map libbsd.map
libbsd_la_LIBADD = \ libbsd_la_LIBADD = \
$(MD_LIBS) \
$(CLOCK_GETTIME_LIBS) \ $(CLOCK_GETTIME_LIBS) \
$(ARC4RANDOM_ATFORK_LIBS) \ $(ARC4RANDOM_ATFORK_LIBS) \
$(nil) $(nil)
libbsd_la_LDFLAGS = \ libbsd_la_LDFLAGS = \
-Wl,--version-script=$(srcdir)/libbsd.map \
-version-number $(LIBBSD_ABI) -version-number $(LIBBSD_ABI)
if HAVE_LINKER_VERSION_SCRIPT
libbsd_la_LDFLAGS += \
-Wl,--version-script=$(srcdir)/libbsd.map
endif
libbsd_la_SOURCES = \ libbsd_la_SOURCES = \
arc4random.c \ arc4random.c \
arc4random.h \ arc4random.h \
@@ -83,6 +78,7 @@ libbsd_la_SOURCES = \
expand_number.c \ expand_number.c \
explicit_bzero.c \ explicit_bzero.c \
fgetln.c \ fgetln.c \
freezero.c \
fgetwln.c \ fgetwln.c \
flopen.c \ flopen.c \
fmtcheck.c \ fmtcheck.c \
@@ -91,23 +87,22 @@ libbsd_la_SOURCES = \
funopen.c \ funopen.c \
getbsize.c \ getbsize.c \
getpeereid.c \ getpeereid.c \
hash/md5.c \
hash/md5hl.c \
hash/sha512.h \
hash/sha512c.c \
heapsort.c \ heapsort.c \
humanize_number.c \ humanize_number.c \
inet_net_pton.c \ inet_net_pton.c \
local-elf.h \ local-elf.h \
local-link.h \ local-link.h \
md5.c \
merge.c \ merge.c \
nlist.c \ nlist.c \
pidfile.c \ pidfile.c \
progname.c \ progname.c \
pwcache.c \
radixsort.c \ radixsort.c \
readpassphrase.c \ readpassphrase.c \
reallocarray.c \ reallocarray.c \
reallocf.c \ reallocf.c \
recallocarray.c \
setmode.c \ setmode.c \
setproctitle.c \ setproctitle.c \
strlcat.c \ strlcat.c \

View File

@@ -1,6 +1,8 @@
/* /*
* Copyright (c) 2004-2005, 2007, 2010, 2012-2014 * SPDX-License-Identifier: ISC
* Todd C. Miller <Todd.Miller@courtesan.com> *
* Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2018
* Todd C. Miller <Todd.Miller@sudo.ws>
* *
* Permission to use, copy, modify, and 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 * purpose with or without fee is hereby granted, provided that the above
@@ -17,19 +19,17 @@
#include <config.h> #include <config.h>
#include <sys/types.h> #ifdef __linux__
#include <unistd.h> # include <sys/syscall.h>
#include <stdio.h> # if defined(__NR_close_range) && !defined(SYS_close_range)
#ifdef STDC_HEADERS # define SYS_close_range __NR_close_range
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif # endif
#endif /* STDC_HEADERS */ #endif
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_PSTAT_GETPROC #ifdef HAVE_PSTAT_GETPROC
# include <sys/param.h> # include <sys/param.h>
# include <sys/pstat.h> # include <sys/pstat.h>
@@ -56,10 +56,6 @@
# define OPEN_MAX 256 # define OPEN_MAX 256
#endif #endif
#if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)
# define closefrom closefrom_fallback
#endif
static inline void static inline void
closefrom_close(int fd) closefrom_close(int fd)
{ {
@@ -71,6 +67,14 @@ closefrom_close(int fd)
#endif #endif
} }
#if defined(__linux__) && defined(SYS_close_range)
static inline int
sys_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags)
{
return syscall(SYS_close_range, fd, max_fd, flags);
}
#endif
/* /*
* Close all file descriptors greater than or equal to lowfd. * Close all file descriptors greater than or equal to lowfd.
* This is the expensive (fallback) method. * This is the expensive (fallback) method.
@@ -81,46 +85,46 @@ closefrom_fallback(int lowfd)
long fd, maxfd; long fd, maxfd;
/* /*
* Fall back on sysconf() or getdtablesize(). We avoid checking * Fall back on sysconf(_SC_OPEN_MAX) or getdtablesize(). This is
* resource limits since it is possible to open a file descriptor * equivalent to checking the RLIMIT_NOFILE soft limit. It is
* and then drop the rlimit such that it is below the open fd. * possible for there to be open file descriptors past this limit
* but there is not much we can do about that since the hard limit
* may be RLIM_INFINITY (LLONG_MAX or ULLONG_MAX on modern systems).
*/ */
#ifdef HAVE_SYSCONF #ifdef HAVE_SYSCONF
maxfd = sysconf(_SC_OPEN_MAX); maxfd = sysconf(_SC_OPEN_MAX);
#else #else
maxfd = getdtablesize(); maxfd = getdtablesize();
#endif /* HAVE_SYSCONF */ #endif /* HAVE_SYSCONF */
if (maxfd < 0) if (maxfd < OPEN_MAX)
maxfd = OPEN_MAX; maxfd = OPEN_MAX;
/* Make sure we did not get RLIM_INFINITY as the upper limit. */
if (maxfd > INT_MAX)
maxfd = INT_MAX;
for (fd = lowfd; fd < maxfd; fd++) for (fd = lowfd; fd < maxfd; fd++)
closefrom_close(fd); closefrom_close(fd);
} }
/* #if defined(HAVE_PSTAT_GETPROC)
* Close all file descriptors greater than or equal to lowfd. static int
* We try the fast way first, falling back on the slow method. closefrom_pstat(int lowfd)
*/
#if defined(HAVE_FCNTL_CLOSEM)
void
closefrom(int lowfd)
{ {
if (fcntl(lowfd, F_CLOSEM, 0) == -1) struct pst_status pst;
closefrom_fallback(lowfd);
}
#elif defined(HAVE_PSTAT_GETPROC)
void
closefrom(int lowfd)
{
struct pst_status pstat;
int fd; int fd;
if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1) { /*
for (fd = lowfd; fd <= pstat.pst_highestfd; fd++) * EOVERFLOW is not a fatal error for the fields we use.
* See the "EOVERFLOW Error" section of pstat_getvminfo(3).
*/
if (pstat_getproc(&pst, sizeof(pst), 0, getpid()) != -1 ||
errno == EOVERFLOW) {
for (fd = lowfd; fd <= pst.pst_highestfd; fd++)
(void)close(fd); (void)close(fd);
} else { return 0;
closefrom_fallback(lowfd);
} }
return -1;
} }
#elif defined(HAVE_DIRFD) #elif defined(HAVE_DIRFD)
static int static int
@@ -135,8 +139,8 @@ closefrom_procfs(int lowfd)
int ret = 0; int ret = 0;
int i; int i;
/* Use /proc/self/fd (or /dev/fd on FreeBSD) if it exists. */ /* Use /proc/self/fd (or /dev/fd on macOS) if it exists. */
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) # ifdef __APPLE__
path = "/dev/fd"; path = "/dev/fd";
# else # else
path = "/proc/self/fd"; path = "/proc/self/fd";
@@ -180,13 +184,36 @@ closefrom_procfs(int lowfd)
return ret; return ret;
} }
#endif
/*
* Close all file descriptors greater than or equal to lowfd.
* We try the fast way first, falling back on the slow method.
*/
void void
closefrom(int lowfd) closefrom(int lowfd)
{ {
if (closefrom_procfs(lowfd) == 0) if (lowfd < 0)
return; lowfd = 0;
/* Try the fast methods first, if possible. */
#if defined(HAVE_FCNTL_CLOSEM)
if (fcntl(lowfd, F_CLOSEM, 0) != -1)
return;
#endif /* HAVE_FCNTL_CLOSEM */
#if defined(__linux__) && defined(SYS_close_range)
if (sys_close_range(lowfd, UINT_MAX, 0) == 0)
return;
#endif
#if defined(HAVE_PSTAT_GETPROC)
if (closefrom_pstat(lowfd) != -1)
return;
#elif defined(HAVE_DIRFD)
if (closefrom_procfs(lowfd) != -1)
return;
#endif /* HAVE_DIRFD */
/* Do things the slow way. */
closefrom_fallback(lowfd); closefrom_fallback(lowfd);
} }
#endif /* HAVE_FCNTL_CLOSEM */

30
src/freezero.c Normal file
View File

@@ -0,0 +1,30 @@
/* $OpenBSD: malloc.c,v 1.267 2020/11/23 15:42:11 otto Exp $ */
/*
* Copyright (c) 2008, 2010, 2011, 2016 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 <stdlib.h>
#include <string.h>
void
freezero(void *ptr, size_t sz)
{
/* This is legal. */
if (ptr == NULL)
return;
explicit_bzero(ptr, sz);
free(ptr);
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2011, 2013, 2017 Guillem Jover * Copyright © 2011, 2013, 2017, 2020 Guillem Jover
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -87,10 +87,10 @@ funopen_close(void *cookie)
struct funopen_cookie *cookiewrap = cookie; struct funopen_cookie *cookiewrap = cookie;
int rc; int rc;
if (cookiewrap->closefn == NULL) if (cookiewrap->closefn)
return 0; rc = cookiewrap->closefn(cookiewrap->orig_cookie);
else
rc = cookiewrap->closefn(cookiewrap->orig_cookie); rc = 0;
free(cookiewrap); free(cookiewrap);

View File

@@ -39,7 +39,7 @@
#include <string.h> #include <string.h>
#include <termios.h> #include <termios.h>
#include "hash/sha512.h" #include <sha512.h>
#include <libperfstat.h> #include <libperfstat.h>
@@ -54,9 +54,9 @@
HD(b); \ HD(b); \
} while (0) } while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HR(x, l) (SHA512_Update(&ctx, (uint8_t *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HD(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) #define HF(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len); int getentropy(void *buf, size_t len);

View File

@@ -42,7 +42,7 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include "hash/sha512.h" #include <sha512.h>
#include <sys/vfs.h> #include <sys/vfs.h>
@@ -59,9 +59,9 @@
HD(b); \ HD(b); \
} while (0) } while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HR(x, l) (SHA512_Update(&ctx, (uint8_t *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HD(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) #define HF(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len); int getentropy(void *buf, size_t len);

View File

@@ -44,7 +44,7 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include "hash/sha512.h" #include <sha512.h>
#ifdef HAVE_GETAUXVAL #ifdef HAVE_GETAUXVAL
#include <sys/auxv.h> #include <sys/auxv.h>
@@ -62,9 +62,9 @@
HD(b); \ HD(b); \
} while (0) } while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HR(x, l) (SHA512_Update(&ctx, (uint8_t *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HD(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) #define HF(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len); int getentropy(void *buf, size_t len);
@@ -228,7 +228,7 @@ getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{ {
SHA512_CTX *ctx = data; SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr)); SHA512_Update(ctx, (uint8_t *)&info->dlpi_addr, sizeof (info->dlpi_addr));
return (0); return (0);
} }

View File

@@ -48,7 +48,7 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include "hash/sha512.h" #include <sha512.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/random.h> #include <linux/random.h>
@@ -68,9 +68,9 @@
HD(b); \ HD(b); \
} while (0) } while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HR(x, l) (SHA512_Update(&ctx, (uint8_t *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HD(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) #define HF(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len); int getentropy(void *buf, size_t len);
@@ -333,7 +333,7 @@ getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{ {
SHA512_CTX *ctx = data; SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr)); SHA512_Update(ctx, (uint8_t *)&info->dlpi_addr, sizeof (info->dlpi_addr));
return (0); return (0);
} }

View File

@@ -76,9 +76,9 @@
HD(b); \ HD(b); \
} while (0) } while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HR(x, l) (SHA512_Update(&ctx, (uint8_t *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HD(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) #define HF(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len); int getentropy(void *buf, size_t len);

View File

@@ -62,9 +62,9 @@
HD(b); \ HD(b); \
} while (0) } while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HR(x, l) (SHA512_Update(&ctx, (uint8_t *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HD(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) #define HF(x) (SHA512_Update(&ctx, (uint8_t *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len); int getentropy(void *buf, size_t len);
@@ -249,7 +249,7 @@ getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{ {
SHA512_CTX *ctx = data; SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr)); SHA512_Update(ctx, (uint8_t *)&info->dlpi_addr, sizeof (info->dlpi_addr));
return (0); return (0);
} }

1
src/hash/.gitignore vendored
View File

@@ -1 +0,0 @@
md5hl.c

View File

@@ -1,105 +0,0 @@
/** $MirOS: src/lib/libc/hash/helper.c,v 1.5 2007/05/07 15:21:18 tg Exp $ */
/* $OpenBSD: helper.c,v 1.8 2005/08/08 08:05:35 espie Exp $ */
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <hashinc>
/* ARGSUSED */
char *
HASHEnd(HASH_CTX *ctx, char *buf)
{
int i;
uint8_t digest[HASH_DIGEST_LENGTH];
#ifdef HASH_DIGEST_UPPERCASE
static const char hex[] = "0123456789ABCDEF";
#else
static const char hex[] = "0123456789abcdef";
#endif
if (buf == NULL && (buf = malloc(HASH_DIGEST_STRING_LENGTH)) == NULL)
return (NULL);
HASHFinal(digest, ctx);
for (i = 0; i < HASH_DIGEST_LENGTH; i++) {
buf[i + i] = hex[digest[i] >> 4];
buf[i + i + 1] = hex[digest[i] & 0x0f];
}
buf[i + i] = '\0';
memset(digest, 0, sizeof(digest));
return (buf);
}
char *
HASHFileChunk(const char *filename, char *buf, off_t off, off_t len)
{
struct stat sb;
unsigned char buffer[BUFSIZ];
HASH_CTX ctx;
int fd, save_errno;
ssize_t nr;
HASHInit(&ctx);
if ((fd = open(filename, O_RDONLY)) < 0)
return (NULL);
if (len == 0) {
if (fstat(fd, &sb) == -1) {
close(fd);
return (NULL);
}
len = sb.st_size;
}
if ((len < 0) || (off > 0 && lseek(fd, off, SEEK_SET) < 0)) {
close(fd);
return (NULL);
}
while ((nr = read(fd, buffer,
(size_t)(len ? MIN(BUFSIZ, len) : BUFSIZ))) > 0) {
HASHUpdate(&ctx, buffer, (size_t)nr);
if (len > 0 && (len -= nr) == 0)
break;
}
save_errno = errno;
close(fd);
errno = save_errno;
return (nr < 0 ? NULL : HASHEnd(&ctx, buf));
}
char *
HASHFile(const char *filename, char *buf)
{
return (HASHFileChunk(filename, buf, (off_t)0, (off_t)0));
}
char *
HASHData(const unsigned char *data, size_t len, char *buf)
{
HASH_CTX ctx;
HASHInit(&ctx);
HASHUpdate(&ctx, data, len);
return (HASHEnd(&ctx, buf));
}

View File

@@ -1,248 +0,0 @@
/* $OpenBSD: md5.c,v 1.8 2005/08/08 08:05:35 espie Exp $ */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#include <sys/types.h>
#include <string.h>
#include <md5.h>
#define PUT_64BIT_LE(cp, value) do { \
(cp)[7] = (value) >> 56; \
(cp)[6] = (value) >> 48; \
(cp)[5] = (value) >> 40; \
(cp)[4] = (value) >> 32; \
(cp)[3] = (value) >> 24; \
(cp)[2] = (value) >> 16; \
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
#define PUT_32BIT_LE(cp, value) do { \
(cp)[3] = (value) >> 24; \
(cp)[2] = (value) >> 16; \
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void
MD5Init(MD5_CTX *ctx)
{
ctx->count = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xefcdab89;
ctx->state[2] = 0x98badcfe;
ctx->state[3] = 0x10325476;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
{
size_t have, need;
/* Check how many bytes we already have and how many more we need. */
have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
need = MD5_BLOCK_LENGTH - have;
/* Update bitcount */
ctx->count += (uint64_t)len << 3;
if (len >= need) {
if (have != 0) {
memcpy(ctx->buffer + have, input, need);
MD5Transform(ctx->state, ctx->buffer);
input += need;
len -= need;
have = 0;
}
/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
while (len >= MD5_BLOCK_LENGTH) {
MD5Transform(ctx->state, input);
input += MD5_BLOCK_LENGTH;
len -= MD5_BLOCK_LENGTH;
}
}
/* Handle any remaining bytes of data. */
if (len != 0)
memcpy(ctx->buffer + have, input, len);
}
/*
* Pad pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void
MD5Pad(MD5_CTX *ctx)
{
uint8_t count[8];
size_t padlen;
/* Convert count to 8 bytes in little endian order. */
PUT_64BIT_LE(count, ctx->count);
/* Pad out to 56 mod 64. */
padlen = MD5_BLOCK_LENGTH -
((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
if (padlen < 1 + 8)
padlen += MD5_BLOCK_LENGTH;
MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
MD5Update(ctx, count, 8);
}
/*
* Final wrapup--call MD5Pad, fill in digest and zero out ctx.
*/
void
MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
{
int i;
MD5Pad(ctx);
if (digest != NULL) {
for (i = 0; i < 4; i++)
PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
memset(ctx, 0, sizeof(*ctx));
}
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void
MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
{
uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
#if BYTE_ORDER == LITTLE_ENDIAN
memcpy(in, block, sizeof(in));
#else
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
in[a] = (uint32_t)(
(uint32_t)(block[a * 4 + 0]) |
(uint32_t)(block[a * 4 + 1]) << 8 |
(uint32_t)(block[a * 4 + 2]) << 16 |
(uint32_t)(block[a * 4 + 3]) << 24);
}
#endif
a = state[0];
b = state[1];
c = state[2];
d = state[3];
MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}

View File

@@ -1,53 +0,0 @@
/*-
* Copyright 2005 Colin Percival
* 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 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.
*
* $FreeBSD$
*/
#ifndef _SHA512_H_
#define _SHA512_H_
#include <sys/types.h>
#define SHA512_DIGEST_LENGTH 64
typedef struct SHA512Context {
uint64_t state[8];
uint64_t count[2];
unsigned char buf[128];
} SHA512_CTX;
__BEGIN_DECLS
void SHA512_Init(SHA512_CTX *);
void SHA512_Update(SHA512_CTX *, const void *, size_t);
void SHA512_Final(unsigned char [64], SHA512_CTX *);
char *SHA512_End(SHA512_CTX *, char *);
char *SHA512_File(const char *, char *);
char *SHA512_FileChunk(const char *, char *, off_t, off_t);
char *SHA512_Data(const void *, unsigned int, char *);
__END_DECLS
#endif /* !_SHA512_H_ */

View File

@@ -1,318 +0,0 @@
/*-
* Copyright 2005 Colin Percival
* 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 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/cdefs.h>
#include <sys/endian.h>
#include <sys/types.h>
#include <string.h>
#include "sha512.h"
#if BYTE_ORDER == BIG_ENDIAN
/* Copy a vector of big-endian uint64_t into a vector of bytes */
#define be64enc_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
/* Copy a vector of bytes into a vector of big-endian uint64_t */
#define be64dec_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
#else /* BYTE_ORDER != BIG_ENDIAN */
/*
* Encode a length len/4 vector of (uint64_t) into a length len vector of
* (unsigned char) in big-endian form. Assumes len is a multiple of 8.
*/
static void
be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
be64enc(dst + i * 8, src[i]);
}
/*
* Decode a big-endian length len vector of (unsigned char) into a length
* len/4 vector of (uint64_t). Assumes len is a multiple of 8.
*/
static void
be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
dst[i] = be64dec(src + i * 8);
}
#endif /* BYTE_ORDER != BIG_ENDIAN */
/* Elementary functions used by SHA512 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
/* SHA512 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
t0 = h + S1(e) + Ch(e, f, g) + k; \
t1 = S0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, k) \
RND(S[(80 - i) % 8], S[(81 - i) % 8], \
S[(82 - i) % 8], S[(83 - i) % 8], \
S[(84 - i) % 8], S[(85 - i) % 8], \
S[(86 - i) % 8], S[(87 - i) % 8], \
W[i] + k)
/*
* SHA512 block compression function. The 512-bit state is transformed via
* the 512-bit input block to produce a new state.
*/
static void
SHA512_Transform(uint64_t * state, const unsigned char block[128])
{
uint64_t W[80];
uint64_t S[8];
uint64_t t0, t1;
int i;
/* 1. Prepare message schedule W. */
be64dec_vect(W, block, 128);
for (i = 16; i < 80; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 64);
/* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
RNDr(S, W, 1, 0x7137449123ef65cdULL);
RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
RNDr(S, W, 4, 0x3956c25bf348b538ULL);
RNDr(S, W, 5, 0x59f111f1b605d019ULL);
RNDr(S, W, 6, 0x923f82a4af194f9bULL);
RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
RNDr(S, W, 8, 0xd807aa98a3030242ULL);
RNDr(S, W, 9, 0x12835b0145706fbeULL);
RNDr(S, W, 10, 0x243185be4ee4b28cULL);
RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
RNDr(S, W, 12, 0x72be5d74f27b896fULL);
RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
RNDr(S, W, 15, 0xc19bf174cf692694ULL);
RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
RNDr(S, W, 23, 0x76f988da831153b5ULL);
RNDr(S, W, 24, 0x983e5152ee66dfabULL);
RNDr(S, W, 25, 0xa831c66d2db43210ULL);
RNDr(S, W, 26, 0xb00327c898fb213fULL);
RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
RNDr(S, W, 29, 0xd5a79147930aa725ULL);
RNDr(S, W, 30, 0x06ca6351e003826fULL);
RNDr(S, W, 31, 0x142929670a0e6e70ULL);
RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
RNDr(S, W, 35, 0x53380d139d95b3dfULL);
RNDr(S, W, 36, 0x650a73548baf63deULL);
RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
RNDr(S, W, 39, 0x92722c851482353bULL);
RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
RNDr(S, W, 41, 0xa81a664bbc423001ULL);
RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
RNDr(S, W, 43, 0xc76c51a30654be30ULL);
RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
RNDr(S, W, 45, 0xd69906245565a910ULL);
RNDr(S, W, 46, 0xf40e35855771202aULL);
RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
RNDr(S, W, 49, 0x1e376c085141ab53ULL);
RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
RNDr(S, W, 57, 0x78a5636f43172f60ULL);
RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
RNDr(S, W, 59, 0x8cc702081a6439ecULL);
RNDr(S, W, 60, 0x90befffa23631e28ULL);
RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
RNDr(S, W, 63, 0xc67178f2e372532bULL);
RNDr(S, W, 64, 0xca273eceea26619cULL);
RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
RNDr(S, W, 68, 0x06f067aa72176fbaULL);
RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
RNDr(S, W, 70, 0x113f9804bef90daeULL);
RNDr(S, W, 71, 0x1b710b35131c471bULL);
RNDr(S, W, 72, 0x28db77f523047d84ULL);
RNDr(S, W, 73, 0x32caab7b40c72493ULL);
RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
RNDr(S, W, 75, 0x431d67c49c100d4cULL);
RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
RNDr(S, W, 77, 0x597f299cfc657e2aULL);
RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
RNDr(S, W, 79, 0x6c44198c4a475817ULL);
/* 4. Mix local working variables into global state */
for (i = 0; i < 8; i++)
state[i] += S[i];
}
static unsigned char PAD[128] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Add padding and terminating bit-count. */
static void
SHA512_Pad(SHA512_CTX * ctx)
{
unsigned char len[16];
uint64_t r, plen;
/*
* Convert length to a vector of bytes -- we do this now rather
* than later because the length will change after we pad.
*/
be64enc_vect(len, ctx->count, 16);
/* Add 1--128 bytes so that the resulting length is 112 mod 128 */
r = (ctx->count[1] >> 3) & 0x7f;
plen = (r < 112) ? (112 - r) : (240 - r);
SHA512_Update(ctx, PAD, (size_t)plen);
/* Add the terminating bit-count */
SHA512_Update(ctx, len, 16);
}
/* SHA-512 initialization. Begins a SHA-512 operation. */
void
SHA512_Init(SHA512_CTX * ctx)
{
/* Zero bits processed so far */
ctx->count[0] = ctx->count[1] = 0;
/* Magic initialization constants */
ctx->state[0] = 0x6a09e667f3bcc908ULL;
ctx->state[1] = 0xbb67ae8584caa73bULL;
ctx->state[2] = 0x3c6ef372fe94f82bULL;
ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
ctx->state[4] = 0x510e527fade682d1ULL;
ctx->state[5] = 0x9b05688c2b3e6c1fULL;
ctx->state[6] = 0x1f83d9abfb41bd6bULL;
ctx->state[7] = 0x5be0cd19137e2179ULL;
}
/* Add bytes into the hash */
void
SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
{
uint64_t bitlen[2];
uint64_t r;
const unsigned char *src = in;
/* Number of bytes left in the buffer from previous updates */
r = (ctx->count[1] >> 3) & 0x7f;
/* Convert the length into a number of bits */
bitlen[1] = ((uint64_t)len) << 3;
bitlen[0] = ((uint64_t)len) >> 61;
/* Update number of bits */
if ((ctx->count[1] += bitlen[1]) < bitlen[1])
ctx->count[0]++;
ctx->count[0] += bitlen[0];
/* Handle the case where we don't need to perform any transforms */
if (len < 128 - r) {
memcpy(&ctx->buf[r], src, len);
return;
}
/* Finish the current block */
memcpy(&ctx->buf[r], src, 128 - r);
SHA512_Transform(ctx->state, ctx->buf);
src += 128 - r;
len -= 128 - r;
/* Perform complete blocks */
while (len >= 128) {
SHA512_Transform(ctx->state, src);
src += 128;
len -= 128;
}
/* Copy left over data into buffer */
memcpy(ctx->buf, src, len);
}
/*
* SHA-512 finalization. Pads the input data, exports the hash value,
* and clears the context state.
*/
void
SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
{
/* Add padding */
SHA512_Pad(ctx);
/* Write the hash */
be64enc_vect(digest, ctx->state, 64);
/* Clear the context state */
memset((void *)ctx, 0, sizeof(*ctx));
}

View File

@@ -35,6 +35,8 @@ LIBBSD_0.0 {
strunvis; strunvis;
strunvisx; strunvisx;
/* The following functions are provided via the system libc or libmd
* implementations. */
MD5Init; MD5Init;
MD5Update; MD5Update;
MD5Pad; MD5Pad;
@@ -181,3 +183,15 @@ LIBBSD_0.10.0 {
err; err;
errx; errx;
} LIBBSD_0.9.1; } LIBBSD_0.9.1;
LIBBSD_0.11.0 {
strnvisx;
recallocarray;
freezero;
gid_from_group;
group_from_gid;
uid_from_user;
user_from_uid;
} LIBBSD_0.10.0;

View File

@@ -45,7 +45,7 @@
#define ELF_TARG_CLASS ELFCLASS64 #define ELF_TARG_CLASS ELFCLASS64
#define ELF_TARG_DATA ELFDATA2LSB #define ELF_TARG_DATA ELFDATA2LSB
#elif defined(__amd64__) #elif defined(__amd64__) || defined(__x86_64__)
#define ELF_TARG_MACH EM_X86_64 #define ELF_TARG_MACH EM_X86_64
#if defined(__ILP32__) #if defined(__ILP32__)

91
src/md5.c Normal file
View File

@@ -0,0 +1,91 @@
/*
* Copyright © 2021 Guillem Jover <guillem@hadrons.org>
*
* 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. 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 ``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.
*/
#include <md5.h>
#include "local-link.h"
void
bsd_MD5Init(MD5_CTX *context)
{
MD5Init(context);
}
libbsd_symver_variant(MD5Init, bsd_MD5Init, LIBBSD_0.0);
void
bsd_MD5Update(MD5_CTX *context, const uint8_t *data, size_t len)
{
MD5Update(context, data, len);
}
libbsd_symver_variant(MD5Update, bsd_MD5Update, LIBBSD_0.0);
void
bsd_MD5Pad(MD5_CTX *context)
{
MD5Pad(context);
}
libbsd_symver_variant(MD5Pad, bsd_MD5Pad, LIBBSD_0.0);
void
bsd_MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
{
MD5Final(digest, context);
}
libbsd_symver_variant(MD5Final, bsd_MD5Final, LIBBSD_0.0);
void
bsd_MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
{
MD5Transform(state, block);
}
libbsd_symver_variant(MD5Transform, bsd_MD5Transform, LIBBSD_0.0);
char *
bsd_MD5End(MD5_CTX *context, char *buf)
{
return MD5End(context, buf);
}
libbsd_symver_variant(MD5End, bsd_MD5End, LIBBSD_0.0);
char *
bsd_MD5File(const char *filename, char *buf)
{
return MD5File(filename, buf);
}
libbsd_symver_variant(MD5File, bsd_MD5File, LIBBSD_0.0);
char *
bsd_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);
char *
bsd_MD5Data(const uint8_t *data, size_t len, char *buf)
{
return MD5Data(data, len, buf);
}
libbsd_symver_variant(MD5Data, bsd_MD5Data, LIBBSD_0.0);

View File

@@ -43,7 +43,9 @@
#include "local-elf.h" #include "local-elf.h"
#ifndef SIZE_T_MAX
#define SIZE_T_MAX 0xffffffffU #define SIZE_T_MAX 0xffffffffU
#endif
/* Note: This function is used by libkvm0, so we need to export it. /* Note: This function is used by libkvm0, so we need to export it.
* It is not declared in the include files though. */ * It is not declared in the include files though. */

View File

@@ -1,6 +1,7 @@
/* /*
* Copyright © 2006 Robert Millan * Copyright © 2006 Robert Millan
* Copyright © 2010-2012 Guillem Jover <guillem@hadrons.org> * Copyright © 2010-2012 Guillem Jover <guillem@hadrons.org>
* Copyright © 2018 Facebook, Inc.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -30,11 +31,16 @@
* <https://sourceware.org/ml/libc-alpha/2006-03/msg00125.html>. * <https://sourceware.org/ml/libc-alpha/2006-03/msg00125.html>.
*/ */
#include <sys/param.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef _WIN32
#include <Windows.h>
#include <shlwapi.h>
#endif
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) #ifdef _WIN32
#define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/' || (c) == '\\') #define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/' || (c) == '\\')
#else #else
#define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/') #define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/')
@@ -56,6 +62,70 @@ getprogname(void)
/* getexecname(3) returns an absolute pathname, normalize it. */ /* getexecname(3) returns an absolute pathname, normalize it. */
if (__progname == NULL) if (__progname == NULL)
setprogname(getexecname()); setprogname(getexecname());
#elif defined(_WIN32)
if (__progname == NULL) {
WCHAR *wpath = NULL;
WCHAR *wname = NULL;
WCHAR *wext = NULL;
DWORD wpathsiz = MAX_PATH / 2;
DWORD len, i;
char *mbname = NULL;
int mbnamesiz;
/* Use the Unicode version of this function to support long
* paths. MAX_PATH isn't actually the maximum length of a
* path in this case. */
do {
WCHAR *wpathnew;
wpathsiz *= 2;
wpathsiz = MIN(wpathsiz, UNICODE_STRING_MAX_CHARS);
wpathnew = reallocarray(wpath, wpathsiz, sizeof(*wpath));
if (wpathnew == NULL)
goto done;
wpath = wpathnew;
len = GetModuleFileNameW(NULL, wpath, wpathsiz);
if (wpathsiz == UNICODE_STRING_MAX_CHARS)
goto done;
} while (wpathsiz == len);
if (len == 0)
goto done;
/* GetModuleFileNameW() retrieves an absolute path. Locate the
* filename now to only convert necessary characters and save
* memory. */
wname = wpath;
for (i = len; i > 0; i--) {
if (LIBBSD_IS_PATHNAME_SEPARATOR(wpath[i - 1])) {
wname = wpath + i;
break;
}
}
/* Remove any trailing extension, such as '.exe', to make the
* behavior mach the non-Windows systems. */
wext = PathFindExtensionW(wname);
wext[0] = '\0';
mbnamesiz = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL,
0, NULL, NULL);
if (mbnamesiz == 0)
goto done;
mbname = malloc(mbnamesiz);
if (mbname == NULL)
goto done;
mbnamesiz = WideCharToMultiByte(CP_UTF8, 0, wname, -1, mbname,
mbnamesiz, NULL, NULL);
if (mbnamesiz == 0)
goto done;
__progname = mbname;
mbname = NULL;
done:
free(wpath);
free(mbname);
}
#endif #endif
return __progname; return __progname;

437
src/pwcache.c Normal file
View File

@@ -0,0 +1,437 @@
/* $OpenBSD: pwcache.c,v 1.15 2018/09/22 02:47:23 millert Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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/types.h>
#include <assert.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
* Constants and data structures used to implement group and password file
* caches. Name lengths have been chosen to be as large as those supported
* by the passwd and group files as well as the standard archive formats.
* CACHE SIZES MUST BE PRIME
*/
#define UNMLEN 32 /* >= user name found in any protocol */
#define GNMLEN 32 /* >= group name found in any protocol */
#define UID_SZ 317 /* size of uid to user_name cache */
#define UNM_SZ 317 /* size of user_name to uid cache */
#define GID_SZ 251 /* size of gid to group_name cache */
#define GNM_SZ 251 /* size of group_name to gid cache */
#define VALID 1 /* entry and name are valid */
#define INVALID 2 /* entry valid, name NOT valid */
/*
* Node structures used in the user, group, uid, and gid caches.
*/
typedef struct uidc {
int valid; /* is this a valid or a miss entry */
char name[UNMLEN]; /* uid name */
uid_t uid; /* cached uid */
} UIDC;
typedef struct gidc {
int valid; /* is this a valid or a miss entry */
char name[GNMLEN]; /* gid name */
gid_t gid; /* cached gid */
} GIDC;
/*
* Routines that control user, group, uid and gid caches.
* Traditional passwd/group cache routines perform quite poorly with
* archives. The chances of hitting a valid lookup with an archive is quite a
* bit worse than with files already resident on the file system. These misses
* create a MAJOR performance cost. To adress this problem, these routines
* cache both hits and misses.
*/
static UIDC **uidtb; /* uid to name cache */
static GIDC **gidtb; /* gid to name cache */
static UIDC **usrtb; /* user name to uid cache */
static GIDC **grptb; /* group name to gid cache */
static u_int
st_hash(const char *name, size_t len, int tabsz)
{
u_int key = 0;
assert(name != NULL);
while (len--) {
key += *name++;
key = (key << 8) | (key >> 24);
}
return key % tabsz;
}
/*
* uidtb_start
* creates an an empty uidtb
* Return:
* 0 if ok, -1 otherwise
*/
static int
uidtb_start(void)
{
static int fail = 0;
if (uidtb != NULL)
return 0;
if (fail)
return -1;
if ((uidtb = calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
++fail;
return -1;
}
return 0;
}
/*
* gidtb_start
* creates an an empty gidtb
* Return:
* 0 if ok, -1 otherwise
*/
static int
gidtb_start(void)
{
static int fail = 0;
if (gidtb != NULL)
return 0;
if (fail)
return -1;
if ((gidtb = calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
++fail;
return -1;
}
return 0;
}
/*
* usrtb_start
* creates an an empty usrtb
* Return:
* 0 if ok, -1 otherwise
*/
static int
usrtb_start(void)
{
static int fail = 0;
if (usrtb != NULL)
return 0;
if (fail)
return -1;
if ((usrtb = calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
++fail;
return -1;
}
return 0;
}
/*
* grptb_start
* creates an an empty grptb
* Return:
* 0 if ok, -1 otherwise
*/
static int
grptb_start(void)
{
static int fail = 0;
if (grptb != NULL)
return 0;
if (fail)
return -1;
if ((grptb = calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
++fail;
return -1;
}
return 0;
}
/*
* user_from_uid()
* caches the name (if any) for the uid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return:
* Pointer to stored name (or a empty string)
*/
const char *
user_from_uid(uid_t uid, int noname)
{
struct passwd pwstore, *pw = NULL;
char pwbuf[_PW_BUF_LEN];
UIDC **pptr, *ptr = NULL;
if ((uidtb != NULL) || (uidtb_start() == 0)) {
/*
* see if we have this uid cached
*/
pptr = uidtb + (uid % UID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
/*
* have an entry for this uid
*/
if (!noname || (ptr->valid == VALID))
return ptr->name;
return NULL;
}
if (ptr == NULL)
*pptr = ptr = malloc(sizeof(UIDC));
}
getpwuid_r(uid, &pwstore, pwbuf, sizeof(pwbuf), &pw);
if (pw == NULL) {
/*
* no match for this uid in the local password file
* a string that is the uid in numeric format
*/
if (ptr == NULL)
return NULL;
ptr->uid = uid;
(void)snprintf(ptr->name, UNMLEN, "%u", uid);
ptr->valid = INVALID;
if (noname)
return NULL;
} else {
/*
* there is an entry for this uid in the password file
*/
if (ptr == NULL)
return pw->pw_name;
ptr->uid = uid;
(void)strlcpy(ptr->name, pw->pw_name, sizeof(ptr->name));
ptr->valid = VALID;
}
return ptr->name;
}
/*
* group_from_gid()
* caches the name (if any) for the gid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return:
* Pointer to stored name (or a empty string)
*/
const char *
group_from_gid(gid_t gid, int noname)
{
struct group grstore, *gr = NULL;
char grbuf[_GR_BUF_LEN];
GIDC **pptr, *ptr = NULL;
if ((gidtb != NULL) || (gidtb_start() == 0)) {
/*
* see if we have this gid cached
*/
pptr = gidtb + (gid % GID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
/*
* have an entry for this gid
*/
if (!noname || (ptr->valid == VALID))
return ptr->name;
return NULL;
}
if (ptr == NULL)
*pptr = ptr = malloc(sizeof(GIDC));
}
getgrgid_r(gid, &grstore, grbuf, sizeof(grbuf), &gr);
if (gr == NULL) {
/*
* no match for this gid in the local group file, put in
* a string that is the gid in numeric format
*/
if (ptr == NULL)
return NULL;
ptr->gid = gid;
(void)snprintf(ptr->name, GNMLEN, "%u", gid);
ptr->valid = INVALID;
if (noname)
return NULL;
} else {
/*
* there is an entry for this group in the group file
*/
if (ptr == NULL)
return gr->gr_name;
ptr->gid = gid;
(void)strlcpy(ptr->name, gr->gr_name, sizeof(ptr->name));
ptr->valid = VALID;
}
return ptr->name;
}
/*
* uid_from_user()
* caches the uid for a given user name. We use a simple hash table.
* Return:
* 0 if the user name is found (filling in uid), -1 otherwise
*/
int
uid_from_user(const char *name, uid_t *uid)
{
struct passwd pwstore, *pw = NULL;
char pwbuf[_PW_BUF_LEN];
UIDC **pptr, *ptr = NULL;
size_t namelen;
/*
* return -1 for mangled names
*/
if (name == NULL || ((namelen = strlen(name)) == 0))
return -1;
if ((usrtb != NULL) || (usrtb_start() == 0)) {
/*
* look up in hash table, if found and valid return the uid,
* if found and invalid, return a -1
*/
pptr = usrtb + st_hash(name, namelen, UNM_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) &&
strcmp(name, ptr->name) == 0) {
if (ptr->valid == INVALID)
return -1;
*uid = ptr->uid;
return 0;
}
if (ptr == NULL)
*pptr = ptr = malloc(sizeof(UIDC));
}
/*
* no match, look it up, if no match store it as an invalid entry,
* or store the matching uid
*/
getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pw);
if (ptr == NULL) {
if (pw == NULL)
return -1;
*uid = pw->pw_uid;
return 0;
}
(void)strlcpy(ptr->name, name, sizeof(ptr->name));
if (pw == NULL) {
ptr->valid = INVALID;
return -1;
}
ptr->valid = VALID;
*uid = ptr->uid = pw->pw_uid;
return 0;
}
/*
* gid_from_group()
* caches the gid for a given group name. We use a simple hash table.
* Return:
* 0 if the group name is found (filling in gid), -1 otherwise
*/
int
gid_from_group(const char *name, gid_t *gid)
{
struct group grstore, *gr = NULL;
char grbuf[_GR_BUF_LEN];
GIDC **pptr, *ptr = NULL;
size_t namelen;
/*
* return -1 for mangled names
*/
if (name == NULL || ((namelen = strlen(name)) == 0))
return -1;
if ((grptb != NULL) || (grptb_start() == 0)) {
/*
* look up in hash table, if found and valid return the uid,
* if found and invalid, return a -1
*/
pptr = grptb + st_hash(name, namelen, GID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) &&
strcmp(name, ptr->name) == 0) {
if (ptr->valid == INVALID)
return -1;
*gid = ptr->gid;
return 0;
}
if (ptr == NULL)
*pptr = ptr = malloc(sizeof(GIDC));
}
/*
* no match, look it up, if no match store it as an invalid entry,
* or store the matching gid
*/
getgrnam_r(name, &grstore, grbuf, sizeof(grbuf), &gr);
if (ptr == NULL) {
if (gr == NULL)
return -1;
*gid = gr->gr_gid;
return 0;
}
(void)strlcpy(ptr->name, name, sizeof(ptr->name));
if (gr == NULL) {
ptr->valid = INVALID;
return -1;
}
ptr->valid = VALID;
*gid = ptr->gid = gr->gr_gid;
return 0;
}

80
src/recallocarray.c Normal file
View File

@@ -0,0 +1,80 @@
/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */
/*
* Copyright (c) 2008, 2017 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 <errno.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 *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
{
size_t oldsize, newsize;
void *newptr;
if (ptr == NULL)
return calloc(newnmemb, size);
if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
newnmemb > 0 && SIZE_MAX / newnmemb < size) {
errno = ENOMEM;
return NULL;
}
newsize = newnmemb * size;
if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
errno = EINVAL;
return NULL;
}
oldsize = oldnmemb * size;
/*
* Don't bother too much if we're shrinking just a bit,
* we do not shrink for series of small steps, oh well.
*/
if (newsize <= oldsize) {
size_t d = oldsize - newsize;
if (d < oldsize / 2 && d < (size_t)getpagesize()) {
memset((char *)ptr + newsize, 0, d);
return ptr;
}
}
newptr = malloc(newsize);
if (newptr == NULL)
return NULL;
if (newsize > oldsize) {
memcpy(newptr, ptr, oldsize);
memset((char *)newptr + oldsize, 0, newsize - oldsize);
} else
memcpy(newptr, ptr, newsize);
explicit_bzero(ptr, oldsize);
free(ptr);
return newptr;
}

1
test/.gitignore vendored
View File

@@ -15,6 +15,7 @@ overlay
proctitle-init proctitle-init
proctitle proctitle
progname progname
pwcache
setmode setmode
strl strl
strmode strmode

View File

@@ -43,6 +43,7 @@ check_PROGRAMS = \
nlist \ nlist \
proctitle-init \ proctitle-init \
progname \ progname \
pwcache \
setmode \ setmode \
strl \ strl \
strmode \ strmode \
@@ -51,6 +52,8 @@ check_PROGRAMS = \
vis-openbsd \ vis-openbsd \
$(nil) $(nil)
md5_LDADD = $(LDADD) $(MD_LIBS)
if HAVE_LIBTESTU01 if HAVE_LIBTESTU01
arc4random_LDADD = $(LDADD) $(TESTU01_LIBS) arc4random_LDADD = $(LDADD) $(TESTU01_LIBS)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org> * Copyright © 2013-2015, 2020 Guillem Jover <guillem@hadrons.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -61,6 +61,7 @@ static const wchar_t *data_wide[] = {
struct file { struct file {
FILE *fp; FILE *fp;
void *line_alloc;
const void **lines; const void **lines;
const void *got_buf; const void *got_buf;
@@ -97,6 +98,7 @@ test_fgetln_multi(void)
str = strdup("A\n"); str = strdup("A\n");
str[0] += i; str[0] += i;
files[i].line_alloc = str;
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *)); files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = str; files[i].lines[0] = str;
files[i].lines[1] = str; files[i].lines[1] = str;
@@ -123,8 +125,11 @@ test_fgetln_multi(void)
} }
} }
for (i = 0; i < LINE_COUNT; i++) for (i = 0; i < FILE_COUNT; i++) {
free(files[i].line_alloc);
free(files[i].lines);
pipe_close(files[i].fp); pipe_close(files[i].fp);
}
} }
static void static void
@@ -159,6 +164,7 @@ test_fgetwln_multi(void)
wstr = wcsdup(L"A\n"); wstr = wcsdup(L"A\n");
wstr[0] += i; wstr[0] += i;
files[i].line_alloc = wstr;
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *)); files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = wstr; files[i].lines[0] = wstr;
files[i].lines[1] = wstr; files[i].lines[1] = wstr;
@@ -185,8 +191,11 @@ test_fgetwln_multi(void)
} }
} }
for (i = 0; i < LINE_COUNT; i++) for (i = 0; i < FILE_COUNT; i++) {
free(files[i].line_alloc);
free(files[i].lines);
pipe_close(files[i].fp); pipe_close(files[i].fp);
}
} }
static void static void

View File

@@ -28,6 +28,9 @@
* other headers through magic macros, to check that the overlay is working * other headers through magic macros, to check that the overlay is working
* properly. */ * properly. */
#include <errno.h> #include <errno.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_GRP_H #ifdef HAVE_GRP_H
#include <grp.h> #include <grp.h>
#endif #endif

49
test/pwcache.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* Copyright © 2021 Guillem Jover <guillem@hadrons.org>
*
* 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. 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 ``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.
*/
#include <assert.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
int
main(int argc, char **argv)
{
uid_t uid;
gid_t gid;
assert(uid_from_user("root", &uid) == 0);
assert(uid == 0);
assert(strcmp(user_from_uid(0, 0), "root") == 0);
assert(gid_from_group("root", &gid) == 0);
assert(gid == 0);
assert(strcmp(group_from_gid(0, 0), "root") == 0);
return 0;
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2017 Guillem Jover <guillem@hadrons.org> * Copyright © 2017, 2020 Guillem Jover <guillem@hadrons.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -25,19 +25,31 @@
*/ */
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
void *set;
umask(0); umask(0);
assert(getmode(setmode("0"), 0) == 0); set = setmode("0");
assert(getmode(set, 0) == 0);
free(set);
assert(getmode(setmode("7777"), 0) == 07777); set = setmode("7777");
assert(getmode(setmode("1555"), 0) == 01555); assert(getmode(set, 0) == 07777);
free(set);
assert(getmode(setmode("ugo=rwx"), 0) == 0777); set = setmode("1555");
assert(getmode(set, 0) == 01555);
free(set);
set = setmode("ugo=rwx");
assert(getmode(set, 0) == 0777);
free(set);
/* FIXME: Complete unit tests. */ /* FIXME: Complete unit tests. */

View File

@@ -35,11 +35,15 @@ main(int argc, char **argv)
assert(strnstr(large, "", strlen(large)) == large); assert(strnstr(large, "", strlen(large)) == large);
assert(strnstr(large, "far", strlen(large)) == NULL);
assert(strnstr(large, "quux", strlen(large)) == NULL); assert(strnstr(large, "quux", strlen(large)) == NULL);
assert(strnstr(large, small, 4) == NULL); assert(strnstr(large, small, 4) == NULL);
assert(strnstr(large, small, strlen(large)) == (large + 4)); assert(strnstr(large, small, strlen(large)) == (large + 4));
assert(strnstr("quux", large, strlen("quux")) == NULL);
assert(strnstr("foo", large, strlen("foo")) == NULL);
return 0; return 0;
} }

View File

@@ -24,12 +24,11 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#define LIBBSD_OPENBSD_VIS 1
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcpp"
#include <vis.h> #include <vis.h>
#pragma GCC diagnostic pop
int int
main(int argc, char **argv) main(int argc, char **argv)