mirror of
https://gitlab.freedesktop.org/libbsd/libbsd.git
synced 2025-10-20 14:02:43 +02:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1fb25b7dca | ||
![]() |
31f034e386 | ||
![]() |
2374f409de | ||
![]() |
a4e0db2b97 | ||
![]() |
43d34c9d3b | ||
![]() |
1c3ff61699 | ||
![]() |
edea268ce9 | ||
![]() |
e832b7687e | ||
![]() |
c4fca5bb4f | ||
![]() |
a1f79978e8 | ||
![]() |
4676026286 | ||
![]() |
25f9b30678 | ||
![]() |
18ebabf223 | ||
![]() |
4ab11c7f48 | ||
![]() |
766c883e30 | ||
![]() |
a4de4d95a6 | ||
![]() |
233cab9d64 |
@@ -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
|
||||||
|
33
configure.ac
33
configure.ac
@@ -13,7 +13,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
|
|||||||
|
|
||||||
LIBBSD_ABI_MAJOR=0
|
LIBBSD_ABI_MAJOR=0
|
||||||
LIBBSD_ABI_MINOR=11
|
LIBBSD_ABI_MINOR=11
|
||||||
LIBBSD_ABI_PATCH=0
|
LIBBSD_ABI_PATCH=3
|
||||||
|
|
||||||
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])
|
||||||
@@ -64,14 +64,27 @@ 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"
|
saved_LIBS="$LIBS"
|
||||||
AC_SEARCH_LIBS([MD5Update], [md], [
|
AC_SEARCH_LIBS([dlsym], [dl], [
|
||||||
AC_SEARCH_LIBS([SHA512Update], [md], [
|
AS_IF([test "x$ac_cv_search_dlsym" != "xnone required"], [
|
||||||
MD_LIBS="-lmd"
|
LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_dlsym"
|
||||||
])
|
])
|
||||||
], [
|
], [
|
||||||
AC_MSG_ERROR([cannot find required message digest functions in libc or libmd])
|
AC_MSG_ERROR([cannot find required dlsym function])
|
||||||
|
])
|
||||||
|
AC_SEARCH_LIBS([MD5Update], [md], [
|
||||||
|
AS_IF([test "x$ac_cv_search_MD5Update" != "xnone required"], [
|
||||||
|
LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_MD5Update"
|
||||||
|
])
|
||||||
|
], [
|
||||||
|
AC_MSG_ERROR([cannot find required MD5 functions in libc or libmd])
|
||||||
|
])
|
||||||
|
AC_SEARCH_LIBS([SHA512Update], [md], [
|
||||||
|
AS_IF([test "x$ac_cv_search_SHA512Update" != "xnone required"], [
|
||||||
|
LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_SHA512Update"
|
||||||
|
])
|
||||||
|
], [
|
||||||
|
AC_MSG_ERROR([cannot find required SHA-2 functions in libc or libmd])
|
||||||
])
|
])
|
||||||
AC_SUBST([MD_LIBS])
|
|
||||||
LIBS="$saved_LIBS"
|
LIBS="$saved_LIBS"
|
||||||
|
|
||||||
is_windows=no
|
is_windows=no
|
||||||
@@ -81,10 +94,9 @@ AS_CASE([$host_os],
|
|||||||
saved_LIBS="$LIBS"
|
saved_LIBS="$LIBS"
|
||||||
AC_SEARCH_LIBS([clock_gettime], [rt], [
|
AC_SEARCH_LIBS([clock_gettime], [rt], [
|
||||||
AS_IF([test "x$ac_cv_search_clock_gettime" != "xnone required"], [
|
AS_IF([test "x$ac_cv_search_clock_gettime" != "xnone required"], [
|
||||||
CLOCK_GETTIME_LIBS="$ac_cv_search_clock_gettime"
|
LIBBSD_LIBS="$LIBBSD_LIBS $ac_cv_search_clock_gettime"
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
AC_SUBST([CLOCK_GETTIME_LIBS])
|
|
||||||
LIBS="$saved_LIBS"
|
LIBS="$saved_LIBS"
|
||||||
],
|
],
|
||||||
[*-musl*], [
|
[*-musl*], [
|
||||||
@@ -192,8 +204,7 @@ AC_LINK_IFELSE(
|
|||||||
[AC_DEFINE([HAVE___REGISTER_ATFORK], [1],
|
[AC_DEFINE([HAVE___REGISTER_ATFORK], [1],
|
||||||
[Define to 1 if you have __register_atfork])
|
[Define to 1 if you have __register_atfork])
|
||||||
AC_MSG_RESULT([yes])],
|
AC_MSG_RESULT([yes])],
|
||||||
[ARC4RANDOM_ATFORK_LIBS="-pthread"
|
[LIBBSD_LIBS="$LIBBSD_LIBS -pthread"
|
||||||
AC_SUBST([ARC4RANDOM_ATFORK_LIBS])
|
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -202,6 +213,8 @@ AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
|
|||||||
pstat_getproc sysconf])
|
pstat_getproc sysconf])
|
||||||
AM_CONDITIONAL([HAVE_GETENTROPY], [test "x$ac_cv_func_getentropy" = "xtrue"])
|
AM_CONDITIONAL([HAVE_GETENTROPY], [test "x$ac_cv_func_getentropy" = "xtrue"])
|
||||||
|
|
||||||
|
AC_SUBST([LIBBSD_LIBS])
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
include/Makefile
|
include/Makefile
|
||||||
|
@@ -187,10 +187,10 @@
|
|||||||
# else
|
# else
|
||||||
# ifndef __cplusplus
|
# ifndef __cplusplus
|
||||||
# define __offsetof(type, field) \
|
# define __offsetof(type, field) \
|
||||||
((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field))
|
((size_t)(uintptr_t)((const volatile void *)&((type *)0)->field))
|
||||||
# else
|
# else
|
||||||
# define __offsetof(type, field) \
|
# define __offsetof(type, field) \
|
||||||
(__offsetof__ (reinterpret_cast <__size_t> \
|
(__offsetof__ (reinterpret_cast <size_t> \
|
||||||
(&reinterpret_cast <const volatile char &> \
|
(&reinterpret_cast <const volatile char &> \
|
||||||
(static_cast<type *> (0)->field))))
|
(static_cast<type *> (0)->field))))
|
||||||
# endif
|
# endif
|
||||||
@@ -243,15 +243,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __DECONST
|
#ifndef __DECONST
|
||||||
#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var))
|
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __DEVOLATILE
|
#ifndef __DEVOLATILE
|
||||||
#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var))
|
#define __DEVOLATILE(type, var) ((type)(uintptr_t)(volatile void *)(var))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __DEQUALIFY
|
#ifndef __DEQUALIFY
|
||||||
#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var))
|
#define __DEQUALIFY(type, var) ((type)(uintptr_t)(const volatile void *)(var))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
1
man/LIST_CLASS_ENTRY.3bsd
Normal file
1
man/LIST_CLASS_ENTRY.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
1
man/LIST_CLASS_HEAD.3bsd
Normal file
1
man/LIST_CLASS_HEAD.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
@@ -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 \
|
||||||
|
1
man/SLIST_CLASS_ENTRY.3bsd
Normal file
1
man/SLIST_CLASS_ENTRY.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
1
man/SLIST_CLASS_HEAD.3bsd
Normal file
1
man/SLIST_CLASS_HEAD.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
1
man/SLIST_REMOVE_PREVPTR.3bsd
Normal file
1
man/SLIST_REMOVE_PREVPTR.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
1
man/STAILQ_CLASS_ENTRY.3bsd
Normal file
1
man/STAILQ_CLASS_ENTRY.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
1
man/STAILQ_CLASS_HEAD.3bsd
Normal file
1
man/STAILQ_CLASS_HEAD.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
1
man/TAILQ_CLASS_ENTRY.3bsd
Normal file
1
man/TAILQ_CLASS_ENTRY.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
1
man/TAILQ_CLASS_HEAD.3bsd
Normal file
1
man/TAILQ_CLASS_HEAD.3bsd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.so man3/queue.3bsd
|
43
man/libbsd.7
43
man/libbsd.7
@@ -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.
|
||||||
@@ -216,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 ,
|
||||||
|
153
man/queue.3bsd
153
man/queue.3bsd
@@ -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 ,
|
||||||
@@ -122,52 +132,60 @@ lists and tail queues
|
|||||||
.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"
|
||||||
@@ -179,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"
|
||||||
@@ -205,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
|
||||||
@@ -230,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:
|
||||||
@@ -277,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:
|
||||||
@@ -308,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
|
||||||
@@ -367,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
|
||||||
@@ -474,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
|
||||||
@@ -690,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
|
||||||
@@ -789,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
|
||||||
@@ -1210,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
|
||||||
|
@@ -52,9 +52,7 @@ libbsd_la_DEPENDENCIES = \
|
|||||||
$(libbsd_la_included_sources) \
|
$(libbsd_la_included_sources) \
|
||||||
libbsd.map
|
libbsd.map
|
||||||
libbsd_la_LIBADD = \
|
libbsd_la_LIBADD = \
|
||||||
$(MD_LIBS) \
|
$(LIBBSD_LIBS) \
|
||||||
$(CLOCK_GETTIME_LIBS) \
|
|
||||||
$(ARC4RANDOM_ATFORK_LIBS) \
|
|
||||||
$(nil)
|
$(nil)
|
||||||
libbsd_la_LDFLAGS = \
|
libbsd_la_LDFLAGS = \
|
||||||
-version-number $(LIBBSD_ABI)
|
-version-number $(LIBBSD_ABI)
|
||||||
|
115
src/closefrom.c
115
src/closefrom.c
@@ -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 */
|
|
||||||
|
@@ -8,4 +8,5 @@ Description: Utility functions from BSD systems
|
|||||||
Version: @VERSION@
|
Version: @VERSION@
|
||||||
URL: https://libbsd.freedesktop.org/
|
URL: https://libbsd.freedesktop.org/
|
||||||
Libs: -L${libdir} -lbsd
|
Libs: -L${libdir} -lbsd
|
||||||
|
Libs.private: @LIBBSD_LIBS@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
86
src/md5.c
86
src/md5.c
@@ -24,68 +24,100 @@
|
|||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <md5.h>
|
#include <md5.h>
|
||||||
#include "local-link.h"
|
|
||||||
|
static void (*libmd_MD5Init)(MD5_CTX *);
|
||||||
|
static void (*libmd_MD5Update)(MD5_CTX *, const uint8_t *, size_t);
|
||||||
|
static void (*libmd_MD5Pad)(MD5_CTX *);
|
||||||
|
static void (*libmd_MD5Final)(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *);
|
||||||
|
static void (*libmd_MD5Transform)(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH]);
|
||||||
|
static char *(*libmd_MD5End)(MD5_CTX *, char *);
|
||||||
|
static char *(*libmd_MD5File)(const char *, char *);
|
||||||
|
static char *(*libmd_MD5FileChunk)(const char *, char *, off_t, off_t);
|
||||||
|
static char *(*libmd_MD5Data)(const uint8_t *, size_t, char *);
|
||||||
|
|
||||||
|
static void *
|
||||||
|
libmd_loader(const char *symbol)
|
||||||
|
{
|
||||||
|
void *func;
|
||||||
|
|
||||||
|
func = dlsym(RTLD_NEXT, symbol);
|
||||||
|
if (func == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"libbsd: cannot find wrapped symbol %s in libc or libmd\n",
|
||||||
|
symbol);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define libmd_wrapper(symbol) \
|
||||||
|
if (libmd_ ## symbol == NULL) \
|
||||||
|
libmd_ ## symbol = libmd_loader(#symbol)
|
||||||
|
|
||||||
void
|
void
|
||||||
bsd_MD5Init(MD5_CTX *context)
|
MD5Init(MD5_CTX *context)
|
||||||
{
|
{
|
||||||
MD5Init(context);
|
libmd_wrapper(MD5Init);
|
||||||
|
libmd_MD5Init(context);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5Init, bsd_MD5Init, LIBBSD_0.0);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
bsd_MD5Update(MD5_CTX *context, const uint8_t *data, size_t len)
|
MD5Update(MD5_CTX *context, const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
MD5Update(context, data, len);
|
libmd_wrapper(MD5Update);
|
||||||
|
libmd_MD5Update(context, data, len);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5Update, bsd_MD5Update, LIBBSD_0.0);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
bsd_MD5Pad(MD5_CTX *context)
|
MD5Pad(MD5_CTX *context)
|
||||||
{
|
{
|
||||||
MD5Pad(context);
|
libmd_wrapper(MD5Pad);
|
||||||
|
libmd_MD5Pad(context);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5Pad, bsd_MD5Pad, LIBBSD_0.0);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
bsd_MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
|
MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
|
||||||
{
|
{
|
||||||
MD5Final(digest, context);
|
libmd_wrapper(MD5Final);
|
||||||
|
libmd_MD5Final(digest, context);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5Final, bsd_MD5Final, LIBBSD_0.0);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
bsd_MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
|
MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
|
||||||
{
|
{
|
||||||
MD5Transform(state, block);
|
libmd_wrapper(MD5Transform);
|
||||||
|
libmd_MD5Transform(state, block);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5Transform, bsd_MD5Transform, LIBBSD_0.0);
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
bsd_MD5End(MD5_CTX *context, char *buf)
|
MD5End(MD5_CTX *context, char *buf)
|
||||||
{
|
{
|
||||||
return MD5End(context, buf);
|
libmd_wrapper(MD5End);
|
||||||
|
return libmd_MD5End(context, buf);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5End, bsd_MD5End, LIBBSD_0.0);
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
bsd_MD5File(const char *filename, char *buf)
|
MD5File(const char *filename, char *buf)
|
||||||
{
|
{
|
||||||
|
libmd_wrapper(MD5File);
|
||||||
return MD5File(filename, buf);
|
return MD5File(filename, buf);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5File, bsd_MD5File, LIBBSD_0.0);
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
bsd_MD5FileChunk(const char *filename, char *buf, off_t offset, off_t length)
|
MD5FileChunk(const char *filename, char *buf, off_t offset, off_t length)
|
||||||
{
|
{
|
||||||
return MD5FileChunk(filename, buf, offset, length);
|
libmd_wrapper(MD5FileChunk);
|
||||||
|
return libmd_MD5FileChunk(filename, buf, offset, length);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5FileChunk, bsd_MD5FileChunk, LIBBSD_0.0);
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
bsd_MD5Data(const uint8_t *data, size_t len, char *buf)
|
MD5Data(const uint8_t *data, size_t len, char *buf)
|
||||||
{
|
{
|
||||||
return MD5Data(data, len, buf);
|
libmd_wrapper(MD5Data);
|
||||||
|
return libmd_MD5Data(data, len, buf);
|
||||||
}
|
}
|
||||||
libbsd_symver_variant(MD5Data, bsd_MD5Data, LIBBSD_0.0);
|
|
||||||
|
@@ -52,8 +52,6 @@ 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)
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user