summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2016-06-02 18:34:21 -0300
committerRenato Botelho <renato@netgate.com>2016-06-02 18:34:21 -0300
commit4775a2bdcd046cf79426a4cdd0dbc8f52a414ca8 (patch)
treef7ba4164f8a1690df639984ef7588d4ed6ed80cd /lib
parent58cc1dd9a16eac0125c6fce83aa28f26d7e13989 (diff)
parentada12d916d2fc4a725e9c2f0ec61f027ce65471a (diff)
downloadFreeBSD-src-4775a2bdcd046cf79426a4cdd0dbc8f52a414ca8.zip
FreeBSD-src-4775a2bdcd046cf79426a4cdd0dbc8f52a414ca8.tar.gz
Merge remote-tracking branch 'origin/master' into devel-11
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile7
-rw-r--r--lib/clang/include/clang/Basic/Version.inc2
-rw-r--r--lib/libblacklist/Makefile30
-rw-r--r--lib/libc++/Makefile4
-rw-r--r--lib/libc/db/hash/ndbm.c2
-rw-r--r--lib/libc/db/man/dbm.36
-rw-r--r--lib/libc/gen/psignal.34
-rw-r--r--lib/libc/gen/psignal.c4
-rw-r--r--lib/libc/iconv/citrus_esdb.c18
-rw-r--r--lib/libc/locale/ascii.c2
-rw-r--r--lib/libc/locale/none.c1
-rw-r--r--lib/libc/stdlib/div.c2
-rw-r--r--lib/libc/stdlib/imaxdiv.c2
-rw-r--r--lib/libc/stdlib/ldiv.c2
-rw-r--r--lib/libc/stdlib/lldiv.c2
-rw-r--r--lib/libc/stdlib/rand.c52
-rw-r--r--lib/libc/stdlib/random.c62
-rw-r--r--lib/libc/sys/_umtx_op.295
-rw-r--r--lib/libc/sys/jail.22
-rw-r--r--lib/libc/sys/thr_exit.226
-rw-r--r--lib/libc/sys/thr_kill.210
-rw-r--r--lib/libc/sys/thr_new.238
-rw-r--r--lib/libc/sys/thr_self.210
-rw-r--r--lib/libc/sys/thr_set_name.27
-rw-r--r--lib/libc/sys/wait.210
-rw-r--r--lib/libcasper/services/cap_grp/cap_grp.c4
-rw-r--r--lib/libcrypt/Makefile2
-rw-r--r--lib/libcxxrt/Makefile2
-rw-r--r--lib/libdevdctl/Makefile21
-rw-r--r--lib/libdevdctl/consumer.cc258
-rw-r--r--lib/libdevdctl/consumer.h174
-rw-r--r--lib/libdevdctl/event.cc602
-rw-r--r--lib/libdevdctl/event.h423
-rw-r--r--lib/libdevdctl/event_factory.cc99
-rw-r--r--lib/libdevdctl/event_factory.h94
-rw-r--r--lib/libdevdctl/exception.cc125
-rw-r--r--lib/libdevdctl/exception.h168
-rw-r--r--lib/libdevdctl/guid.cc82
-rw-r--r--lib/libdevdctl/guid.h143
-rw-r--r--lib/libdevdctl/tests/Makefile21
-rw-r--r--lib/libdevdctl/tests/libdevdctl_unittest.cc138
-rw-r--r--lib/libfetch/http.c3
-rw-r--r--lib/libmd/Makefile138
-rw-r--r--lib/libmd/mdX.38
-rw-r--r--lib/libmd/ripemd.37
-rw-r--r--lib/libmd/sha.36
-rw-r--r--lib/libmd/sha256.37
-rw-r--r--lib/libmd/sha512.350
-rw-r--r--lib/libmd/shadriver.c4
-rw-r--r--lib/libmd/skein.3214
-rw-r--r--lib/libmd/skeindriver.c68
-rw-r--r--lib/libthr/libthr.34
-rw-r--r--lib/libthr/thread/thr_cond.c24
-rw-r--r--lib/libthr/thread/thr_exit.c31
-rw-r--r--lib/libthr/thread/thr_mutex.c23
-rw-r--r--lib/libthr/thread/thr_printf.c25
-rw-r--r--lib/libthr/thread/thr_private.h11
-rw-r--r--lib/libxo/add.man4
-rw-r--r--lib/libxo/xo_config.h12
59 files changed, 3127 insertions, 268 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 0c8120c..d475c6c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -28,6 +28,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libatm} \
libauditd \
libbegemot \
+ ${_libblacklist} \
libblocksruntime \
${_libbluetooth} \
${_libbsnmp} \
@@ -41,6 +42,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
libcompat \
libcrypt \
libdevctl \
+ libdevdctl \
libdevinfo \
libdevstat \
libdpv \
@@ -148,7 +150,6 @@ SUBDIR_DEPEND_libpjdlog= libutil
SUBDIR_DEPEND_libprocstat= libkvm libutil
SUBDIR_DEPEND_libradius= libmd
SUBDIR_DEPEND_libsmb= libkiconv
-SUBDIR_DEPEND_libstdc++:= msun
SUBDIR_DEPEND_libtacplus= libmd
SUBDIR_DEPEND_libulog= libmd
SUBDIR_DEPEND_libunbound= ${_libldns}
@@ -160,6 +161,10 @@ SUBDIR_DEPEND_liblzma= ${_libthr}
_libngatm= libngatm
.endif
+.if ${MK_BLACKLIST_SUPPORT} != "no"
+_libblacklist= libblacklist
+.endif
+
.if ${MK_BLUETOOTH} != "no"
_libbluetooth= libbluetooth
_libsdp= libsdp
diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc
index c143edd..72c5bed 100644
--- a/lib/clang/include/clang/Basic/Version.inc
+++ b/lib/clang/include/clang/Basic/Version.inc
@@ -9,4 +9,4 @@
#define SVN_REVISION "262564"
-#define FREEBSD_CC_VERSION 1100002U
+#define FREEBSD_CC_VERSION 1100004U
diff --git a/lib/libblacklist/Makefile b/lib/libblacklist/Makefile
new file mode 100644
index 0000000..8187479
--- /dev/null
+++ b/lib/libblacklist/Makefile
@@ -0,0 +1,30 @@
+# $FreeBSD$
+
+BLACKLIST_DIR=${SRCTOP}/contrib/blacklist
+
+.PATH: ${BLACKLIST_DIR}/lib ${BLACKLIST_DIR}/include
+
+LIB= blacklist
+SHLIB_MAJOR= 0
+
+LIBADD+= pthread
+
+CFLAGS.clang+=-Wno-thread-safety-analysis
+
+CFLAGS+=-I${BLACKLIST_DIR}/include -I${BLACKLIST_DIR}/port \
+ -D_REENTRANT -DHAVE_CONFIG_H -DHAVE_DB_H -DHAVE_LIBUTIL_H \
+ -DHAVE_CLOCK_GETTIME -DHAVE_FGETLN -DHAVE_GETPROGNAME \
+ -DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRUCT_SOCKADDR_SA_LEN
+
+SRCS= bl.c blacklist.c
+INCS= blacklist.h
+MAN= libblacklist.3
+
+MLINKS= libblacklist.3 blacklist_open.3 \
+ libblacklist.3 blacklist_close.3 \
+ libblacklist.3 blacklist.3 \
+ libblacklist.3 blacklist_r.3 \
+ libblacklist.3 blacklist_sa.3 \
+ libblacklist.3 blacklist_sa_r.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libc++/Makefile b/lib/libc++/Makefile
index 984e70b..6e70cf1 100644
--- a/lib/libc++/Makefile
+++ b/lib/libc++/Makefile
@@ -63,7 +63,7 @@ cxxrt_${_S}: ${_LIBCXXRTDIR}/${_S} .NOMETA
.endfor
WARNS= 0
-CFLAGS+= -I${HDRDIR} -I${_LIBCXXRTDIR} -nostdinc++ -nostdlib -DLIBCXXRT
+CFLAGS+= -isystem ${HDRDIR} -isystem ${_LIBCXXRTDIR} -nostdinc++ -nostdlib -DLIBCXXRT
.if empty(CXXFLAGS:M-std=*)
CXXFLAGS+= -std=c++11
.endif
@@ -187,7 +187,7 @@ RT_HEADERS= cxxabi.h\
.for hdr in ${STD_HEADERS}
STD+= ${HDRDIR}/${hdr}
-INCSLINKS+= ${CXXINCLUDEDIR}/${hdr} ${CXXINCLUDEDIR}/tr1/${hdr}
+INCSLINKS+= ../${hdr} ${CXXINCLUDEDIR}/tr1/${hdr}
.endfor
.for hdr in ${RT_HEADERS}
STD+= ${_LIBCXXRTDIR}/${hdr}
diff --git a/lib/libc/db/hash/ndbm.c b/lib/libc/db/hash/ndbm.c
index 37adaf6..1a02d00 100644
--- a/lib/libc/db/hash/ndbm.c
+++ b/lib/libc/db/hash/ndbm.c
@@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$");
* NULL on failure
*/
extern DBM *
-dbm_open(const char *file, int flags, int mode)
+dbm_open(const char *file, int flags, mode_t mode)
{
HASHINFO info;
char path[MAXPATHLEN];
diff --git a/lib/libc/db/man/dbm.3 b/lib/libc/db/man/dbm.3
index eedf804..4fe5d82 100644
--- a/lib/libc/db/man/dbm.3
+++ b/lib/libc/db/man/dbm.3
@@ -15,7 +15,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 19, 2015
+.Dd May 30, 2016
.Dt DBM 3
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.In fcntl.h
.In ndbm.h
.Ft DBM *
-.Fn dbm_open "const char *base" "int flags" "int mode"
+.Fn dbm_open "const char *base" "int flags" "mode_t mode"
.Ft void
.Fn dbm_close "DBM *db"
.Ft int
@@ -66,7 +66,7 @@ is declared in
.In ndbm.h :
.Bd -literal
typedef struct {
- char *dptr;
+ void *dptr;
int dsize;
} datum;
.Ed
diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3
index 231acfa..ed7023b 100644
--- a/lib/libc/gen/psignal.3
+++ b/lib/libc/gen/psignal.3
@@ -28,7 +28,7 @@
.\" @(#)psignal.3 8.2 (Berkeley) 2/27/95
.\" $FreeBSD$
.\"
-.Dd February 4, 2011
+.Dd May 30, 2016
.Dt PSIGNAL 3
.Os
.Sh NAME
@@ -42,7 +42,7 @@
.Sh SYNOPSIS
.In signal.h
.Ft void
-.Fn psignal "unsigned sig" "const char *s"
+.Fn psignal "int sig" "const char *s"
.Vt extern const char * const sys_siglist[] ;
.Vt extern const char * const sys_signame[] ;
.In string.h
diff --git a/lib/libc/gen/psignal.c b/lib/libc/gen/psignal.c
index 5c5aada..d1c70c6 100644
--- a/lib/libc/gen/psignal.c
+++ b/lib/libc/gen/psignal.c
@@ -44,11 +44,11 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
void
-psignal(unsigned int sig, const char *s)
+psignal(int sig, const char *s)
{
const char *c;
- if (sig < NSIG)
+ if (sig >= 0 && sig < NSIG)
c = sys_siglist[sig];
else
c = "Unknown signal";
diff --git a/lib/libc/iconv/citrus_esdb.c b/lib/libc/iconv/citrus_esdb.c
index ed404a6..299dd5f 100644
--- a/lib/libc/iconv/citrus_esdb.c
+++ b/lib/libc/iconv/citrus_esdb.c
@@ -291,18 +291,12 @@ _citrus_esdb_get_list(char ***rlist, size_t *rnum, bool sorted)
/* get alias entries */
while ((ret = _lookup_seq_next(cla, &key, &data)) == 0) {
- if (sorted)
- snprintf(buf, sizeof(buf), "%.*s/%.*s",
- (int)_region_size(&data),
- (const char *)_region_head(&data),
- (int)_region_size(&key),
- (const char *)_region_head(&key));
- else
- snprintf(buf, sizeof(buf), "%.*s/%.*s",
- (int)_region_size(&data),
- (const char *)_region_head(&data),
- (int)_region_size(&key),
- (const char *)_region_head(&key));
+ /* XXX: sorted? */
+ snprintf(buf, sizeof(buf), "%.*s/%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data),
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
_bcs_convert_to_upper(buf);
list[num] = strdup(buf);
if (list[num] == NULL) {
diff --git a/lib/libc/locale/ascii.c b/lib/libc/locale/ascii.c
index 784814d..a70d71a 100644
--- a/lib/libc/locale/ascii.c
+++ b/lib/libc/locale/ascii.c
@@ -143,6 +143,7 @@ _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
nchr = 0;
while (len-- > 0 && nms-- > 0) {
if (*s & 0x80) {
+ *src = s;
errno = EILSEQ;
return ((size_t)-1);
}
@@ -177,6 +178,7 @@ _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
nchr = 0;
while (len-- > 0 && nwc-- > 0) {
if (*s < 0 || *s > 127) {
+ *src = s;
errno = EILSEQ;
return ((size_t)-1);
}
diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c
index c4695fd..4e5a61d 100644
--- a/lib/libc/locale/none.c
+++ b/lib/libc/locale/none.c
@@ -174,6 +174,7 @@ _none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
nchr = 0;
while (len-- > 0 && nwc-- > 0) {
if (*s < 0 || *s > UCHAR_MAX) {
+ *src = s;
errno = EILSEQ;
return ((size_t)-1);
}
diff --git a/lib/libc/stdlib/div.c b/lib/libc/stdlib/div.c
index 7dfe553..0bafbe6 100644
--- a/lib/libc/stdlib/div.c
+++ b/lib/libc/stdlib/div.c
@@ -46,6 +46,7 @@ div(num, denom)
r.quot = num / denom;
r.rem = num % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
/*
* The ANSI standard says that |r.quot| <= |n/d|, where
* n/d is to be computed in infinite precision. In other
@@ -73,5 +74,6 @@ div(num, denom)
r.quot++;
r.rem -= denom;
}
+#endif
return (r);
}
diff --git a/lib/libc/stdlib/imaxdiv.c b/lib/libc/stdlib/imaxdiv.c
index 7dae467..adcab0b 100644
--- a/lib/libc/stdlib/imaxdiv.c
+++ b/lib/libc/stdlib/imaxdiv.c
@@ -37,9 +37,11 @@ imaxdiv(intmax_t numer, intmax_t denom)
retval.quot = numer / denom;
retval.rem = numer % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
if (numer >= 0 && retval.rem < 0) {
retval.quot++;
retval.rem -= denom;
}
+#endif
return (retval);
}
diff --git a/lib/libc/stdlib/ldiv.c b/lib/libc/stdlib/ldiv.c
index 0ec98e6..745c566 100644
--- a/lib/libc/stdlib/ldiv.c
+++ b/lib/libc/stdlib/ldiv.c
@@ -48,9 +48,11 @@ ldiv(num, denom)
r.quot = num / denom;
r.rem = num % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
if (num >= 0 && r.rem < 0) {
r.quot++;
r.rem -= denom;
}
+#endif
return (r);
}
diff --git a/lib/libc/stdlib/lldiv.c b/lib/libc/stdlib/lldiv.c
index b34b65e..197b48f 100644
--- a/lib/libc/stdlib/lldiv.c
+++ b/lib/libc/stdlib/lldiv.c
@@ -37,9 +37,11 @@ lldiv(long long numer, long long denom)
retval.quot = numer / denom;
retval.rem = numer % denom;
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
if (numer >= 0 && retval.rem < 0) {
retval.quot++;
retval.rem -= denom;
}
+#endif
return (retval);
}
diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c
index eb3c10a..2e0456a 100644
--- a/lib/libc/stdlib/rand.c
+++ b/lib/libc/stdlib/rand.c
@@ -48,14 +48,6 @@ __FBSDID("$FreeBSD$");
static int
do_rand(unsigned long *ctx)
{
-#ifdef USE_WEAK_SEEDING
-/*
- * Historic implementation compatibility.
- * The random sequences do not vary much with the seed,
- * even with overflowing.
- */
- return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
-#else /* !USE_WEAK_SEEDING */
/*
* Compute x = (7^5 * x) mod (2^31 - 1)
* without overflowing 31 bits:
@@ -66,48 +58,34 @@ do_rand(unsigned long *ctx)
*/
long hi, lo, x;
- /* Must be in [1, 0x7ffffffe] range at this point. */
- hi = *ctx / 127773;
- lo = *ctx % 127773;
+ /* Transform to [1, 0x7ffffffe] range. */
+ x = (*ctx % 0x7ffffffe) + 1;
+ hi = x / 127773;
+ lo = x % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
- *ctx = x;
/* Transform to [0, 0x7ffffffd] range. */
- return (x - 1);
-#endif /* !USE_WEAK_SEEDING */
+ x--;
+ *ctx = x;
+ return (x);
}
int
-rand_r(unsigned int *ctx)
+rand_r(unsigned *ctx)
{
u_long val;
int r;
-#ifdef USE_WEAK_SEEDING
val = *ctx;
-#else
- /* Transform to [1, 0x7ffffffe] range. */
- val = (*ctx % 0x7ffffffe) + 1;
-#endif
r = do_rand(&val);
-
-#ifdef USE_WEAK_SEEDING
- *ctx = (unsigned int)val;
-#else
- *ctx = (unsigned int)(val - 1);
-#endif
+ *ctx = (unsigned)val;
return (r);
}
-static u_long next =
-#ifdef USE_WEAK_SEEDING
- 1;
-#else
- 2;
-#endif
+static u_long next = 1;
int
rand(void)
@@ -116,13 +94,9 @@ rand(void)
}
void
-srand(u_int seed)
+srand(unsigned seed)
{
next = seed;
-#ifndef USE_WEAK_SEEDING
- /* Transform to [1, 0x7ffffffe] range. */
- next = (next % 0x7ffffffe) + 1;
-#endif
}
@@ -144,10 +118,6 @@ sranddev(void)
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
sysctl(mib, 2, (void *)&next, &len, NULL, 0);
-#ifndef USE_WEAK_SEEDING
- /* Transform to [1, 0x7ffffffe] range. */
- next = (next % 0x7ffffffe) + 1;
-#endif
}
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c
index f7b745e..fe8fc86 100644
--- a/lib/libc/stdlib/random.c
+++ b/lib/libc/stdlib/random.c
@@ -137,11 +137,7 @@ __FBSDID("$FreeBSD$");
*/
#define MAX_TYPES 5 /* max number of types above */
-#ifdef USE_WEAK_SEEDING
-#define NSHUFF 0
-#else /* !USE_WEAK_SEEDING */
#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
-#endif /* !USE_WEAK_SEEDING */
static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
@@ -162,23 +158,12 @@ static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
static uint32_t randtbl[DEG_3 + 1] = {
TYPE_3,
-#ifdef USE_WEAK_SEEDING
-/* Historic implementation compatibility */
-/* The random sequences do not vary much with the seed */
- 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
- 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
- 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
- 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
- 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
- 0x27fb47b9,
-#else /* !USE_WEAK_SEEDING */
- 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
- 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
- 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
- 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
- 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
- 0xf3bec5da
-#endif /* !USE_WEAK_SEEDING */
+ 0x2cf41758, 0x27bb3711, 0x4916d4d1, 0x7b02f59f, 0x9b8e28eb, 0xc0e80269,
+ 0x696f5c16, 0x878f1ff5, 0x52d9c07f, 0x916a06cd, 0xb50b3a20, 0x2776970a,
+ 0xee4eb2a6, 0xe94640ec, 0xb1d65612, 0x9d1ed968, 0x1043f6b7, 0xa3432a76,
+ 0x17eacbb9, 0x3c09e2eb, 0x4f8c2b3, 0x708a1f57, 0xee341814, 0x95d0e4d2,
+ 0xb06f216c, 0x8bd2e72e, 0x8f7c38d7, 0xcfc6a8fc, 0x2a59495, 0xa20d2a69,
+ 0xe29d12d1
};
/*
@@ -215,16 +200,8 @@ static int rand_sep = SEP_3;
static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
static inline uint32_t
-good_rand(int32_t x)
+good_rand(uint32_t ctx)
{
-#ifdef USE_WEAK_SEEDING
-/*
- * Historic implementation compatibility.
- * The random sequences do not vary much with the seed,
- * even with overflowing.
- */
- return (1103515245 * x + 12345);
-#else /* !USE_WEAK_SEEDING */
/*
* Compute x = (7^5 * x) mod (2^31 - 1)
* wihout overflowing 31 bits:
@@ -233,18 +210,17 @@ good_rand(int32_t x)
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
*/
- int32_t hi, lo;
+ int32_t hi, lo, x;
- /* Can't be initialized with 0, so use another value. */
- if (x == 0)
- x = 123459876;
+ /* Transform to [1, 0x7ffffffe] range. */
+ x = (ctx % 0x7ffffffe) + 1;
hi = x / 127773;
lo = x % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
- return (x);
-#endif /* !USE_WEAK_SEEDING */
+ /* Transform to [0, 0x7ffffffd] range. */
+ return (x - 1);
}
/*
@@ -404,16 +380,8 @@ setstate(char *arg_state)
uint32_t rear = new_state[0] / MAX_TYPES;
char *ostate = (char *)(&state[-1]);
- switch(type) {
- case TYPE_0:
- case TYPE_1:
- case TYPE_2:
- case TYPE_3:
- case TYPE_4:
- break;
- default:
+ if (type != TYPE_0 && rear >= degrees[type])
return (NULL);
- }
if (rand_type == TYPE_0)
state[-1] = rand_type;
else
@@ -455,14 +423,14 @@ random(void)
if (rand_type == TYPE_0) {
i = state[0];
- state[0] = i = (good_rand(i)) & 0x7fffffff;
+ state[0] = i = good_rand(i);
} else {
/*
* Use local variables rather than static variables for speed.
*/
f = fptr; r = rptr;
*f += *r;
- i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */
+ i = *f >> 1; /* chucking least random bit */
if (++f >= end_ptr) {
f = state;
++r;
diff --git a/lib/libc/sys/_umtx_op.2 b/lib/libc/sys/_umtx_op.2
index e2ce109..bd4ad3b 100644
--- a/lib/libc/sys/_umtx_op.2
+++ b/lib/libc/sys/_umtx_op.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 17, 2016
+.Dd May 29, 2016
.Dt _UMTX_OP 2
.Os
.Sh NAME
@@ -257,7 +257,7 @@ are defined, in addition to the common flags:
.It Dv URWLOCK_PREFER_READER
If specified, immediately grant read lock requests when
.Dv urwlock
-is already read-locked, even in presence of the unsatisfied write
+is already read-locked, even in presence of unsatisfied write
lock requests.
By default, if there is a write lock waiter, further read requests are
not granted, to prevent unfair write lock waiter starvation.
@@ -387,7 +387,7 @@ variant which returns an error rather than sleeping if the lock cannot
be obtained.
Also,
.Fn _umtx_op
-provides requests which explicitely put the thread to sleep.
+provides requests which explicitly put the thread to sleep.
.Pp
Wakes need to know which threads to make runnable, so sleeping threads
are grouped into containers called
@@ -399,12 +399,12 @@ Note that the
.Em physical
address is used, which means that same variable mapped multiple
times will give one key value.
-This mechanism enables the construction of the
+This mechanism enables the construction of
.Em process-shared
locks.
.Pp
A related attribute of the key is shareability.
-Some requests always interpet keys as private for the current process,
+Some requests always interpret keys as private for the current process,
creating sleep queues with the scope of the current process even if
the memory is shared.
Others either select the shareability automatically from the
@@ -435,7 +435,8 @@ the queue are selected.
The
.Em robust umutexes
are provided as a substrate for a userspace library to implement
-POSIX robust mutexes.
+.Tn POSIX
+robust mutexes.
A robust umutex must have the
.Dv UMUTEX_ROBUST
flag set.
@@ -524,13 +525,13 @@ argument is compared with the
If they are equal, the requesting thread is put to interruptible sleep
until woken up or the optionally specified timeout expires.
.Pp
-The comparision and sleep are atomic.
+The comparison and sleep are atomic.
In other words, if another thread writes a new value to
.Dv *obj
and then issues
.Dv UMTX_OP_WAKE ,
the request is guaranteed to not miss the wakeup,
-which might otherwise happen between comparision and blocking.
+which might otherwise happen between comparison and blocking.
.Pp
The physical address of memory where the
.Fa *obj
@@ -599,7 +600,7 @@ contention indicator, and provides the acquire barrier for
lock entrance semantic.
.Pp
If the lock cannot be obtained immediately because another thread owns
-the lock, the current thread is put into sleep, with
+the lock, the current thread is put to sleep, with
.Dv UMUTEX_CONTESTED
bit set before.
Upon wake up, the lock conditions are re-tested.
@@ -668,7 +669,9 @@ New ceiling value.
.It Fa uaddr
Address of a variable of type
.Vt uint32_t .
-If not NULL, after the successful update the previous ceiling value is
+If not
+.Dv NULL
+and the update was successful, the previous ceiling value is
written to the location pointed to by
.Fa uaddr .
.El
@@ -685,7 +688,9 @@ member of the
after which the umutex is unlocked.
.Pp
The locking does not adhere to the priority protect protocol,
-to confirm with the POSIX requirements for the
+to conform to the
+.Tn POSIX
+requirements for the
.Xr pthread_mutex_setprioceiling 3
interface.
.It Dv UMTX_OP_CV_WAIT
@@ -769,7 +774,8 @@ If the
flag is supplied, the timeout specifies absolute time value, otherwise
it denotes a relative time interval.
.Pp
-The request is not restartable. An unblocked signal delivered during
+The request is not restartable.
+An unblocked signal delivered during
the wait always results in sleep interruption and
.Er EINTR
error.
@@ -845,7 +851,7 @@ If the
.Dv URWLOCK_WRITE_OWNER
bit is set in the word
.Dv rw_state ,
-the lock was granted to a writer which has not yet relinguished
+the lock was granted to a writer which has not yet relinquished
its ownership.
In this case the current thread is put to sleep until it makes sense to
retry.
@@ -959,7 +965,7 @@ Same as
.Dv UMTX_OP_WAKE ,
but unconditionally select the process-private sleep queue.
.It Dv UMTX_OP_MUTEX_WAIT
-Wait for the mutex availability.
+Wait for mutex availability.
The arguments to the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -986,12 +992,12 @@ priority inherited protocol mutexes.
Optionally, a timeout for the request may be specified.
.Pp
.Pp
-The request with a timeout specified is not restartable.
+A request with a timeout specified is not restartable.
An unblocked signal delivered during the wait always results in sleep
interruption and
.Er EINTR
error.
-The request without a timeout automatically restarts if the signal disposition
+A request without a timeout automatically restarts if the signal disposition
requested restart via the
.Dv SA_RESTART
flag in
@@ -999,7 +1005,7 @@ flag in
member
.Dv sa_flags .
.It Dv UMTX_OP_NWAKE_PRIVATE
-Wake up a batch of sleeping thread.
+Wake up a batch of sleeping threads.
The arguments to the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1016,7 +1022,7 @@ wakes up all threads waiting on the
sleep queue with the key
being the byte addressed by the array element.
.It Dv UMTX_OP_MUTEX_WAKE
-Check if the normal umutex is unlocked and wake up a waiter.
+Check if a normal umutex is unlocked and wake up a waiter.
The arguments for the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1035,8 +1041,22 @@ with the byte addressed by the
if any.
Only normal mutexes are supported by the request.
The sleep queue is always one for a normal mutex type.
+.Pp
+This request is deprecated in favor of
+.Dv UMTX_OP_MUTEX_WAKE2
+since mutexes using it cannot synchronize their own destruction.
+That is, the
+.Dv m_owner
+word has already been set to
+.Dv UMUTEX_UNOWNED
+when this request is made,
+so that another thread can lock, unlock and destroy the mutex
+(if no other thread uses the mutex afterwards).
+Clearing the
+.Dv UMUTEX_CONTESTED
+bit may then modify freed memory.
.It Dv UMTX_OP_MUTEX_WAKE2
-Check if the umutex is unlocked and wake up a waiter.
+Check if a umutex is unlocked and wake up a waiter.
The arguments for the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1048,7 +1068,7 @@ The umutex flags.
The request does not read the
.Dv m_flags
member of the
-.Vt struct umutex ,
+.Vt struct umutex ;
instead, the
.Fa val
argument supplies flag information, in particular, to determine the
@@ -1064,8 +1084,7 @@ one waiter but the mutex is owned by a thread, the
bit is set in the
.Dv m_owner
word of the
-.Vt struct umutex
-the request operates upon.
+.Vt struct umutex .
.It Dv UMTX_OP_SEM2_WAIT
Wait until semaphore is available.
The arguments to the request are:
@@ -1076,12 +1095,12 @@ Pointer to the semaphore (of type
.El
Put the requesting thread onto a sleep queue if the semaphore counter
is zero.
-If thread is put to sleep, the
+If the thread is put to sleep, the
.Dv USEM_HAS_WAITERS
bit is set in the
.Dv _count
word to indicate waiters.
-Function returns either due to
+The function returns either due to
.Dv _count
indicating the semaphore is available (non-zero count due to post),
or due to a wakeup.
@@ -1096,7 +1115,7 @@ interruption and
.Er EINTR
error.
.It Dv UMTX_OP_SEM2_WAKE
-Wake up waiters on the semaphore lock.
+Wake up waiters on semaphore lock.
The arguments to the request are:
.Bl -tag -width "It Fa obj"
.It Fa obj
@@ -1112,7 +1131,9 @@ bit was set in the
.Dv _count
word, and the last sleeping thread was woken up, the bit is cleared.
.It Dv UMTX_OP_SHM
-Manage the anonymous POSIX shared objects (see
+Manage anonymous
+.Tn POSIX
+shared memory objects (see
.Xr shm_open 2 ) ,
which can be attached to a byte of physical memory, mapped into the
process address space.
@@ -1126,7 +1147,7 @@ argument specifies the sub-request of the
request:
.Bl -tag -width "Dv UMTX_SHM_DESTROY"
.It Dv UMTX_SHM_CREAT
-Creates the POSIX anonymous memory shared object, which can be looked up
+Creates the anonymous shared memory object, which can be looked up
with the specified key
.Fa uaddr.
If the object associated with the
@@ -1143,7 +1164,7 @@ Same as
request, but if there is no shared memory object associated with
the specified key
.Fa uaddr ,
-an error is returned, and new object is not created.
+an error is returned, and no new object is created.
.It Dv UMTX_SHM_DESTROY
De-associate the shared object with the specified key
.Fa uaddr.
@@ -1158,7 +1179,7 @@ This request is an optimization of the
.Dv UMTX_SHM_LOOKUP
request.
It is cheaper when only the liveness of the associated object is asked
-for, since the file descriptor is not installed in the process fd table
+for, since no file descriptor is installed in the process fd table
on success.
.El
.Pp
@@ -1212,7 +1233,7 @@ The kernel inspects the
in addition to walking the shared and private lists.
Also, the mutex pointed to by
.Dv robust_inact_offset
-is handled more loosly at the thread termination time,
+is handled more loosely at the thread termination time,
than other mutexes on the list.
That mutex is allowed to be not owned by the current thread,
in which case list processing is continued.
@@ -1233,7 +1254,7 @@ The
.Dv UMTX_SHM_CREAT
and
.Dv UMTX_SHM_LOOKUP
-return a POSIX shared memory file descriptor on success.
+return a shared memory file descriptor on success.
On error \-1 is returned, and the
.Va errno
variable is set to indicate the error.
@@ -1326,15 +1347,15 @@ and
.Dv UMTX_SHM_ALIVE
sub-requests of the
.Dv UMTX_OP_SHM
-request, there is no shared object associated with the provided key.
+request, there is no shared memory object associated with the provided key.
.It Bq Er ENOMEM
The
.Dv UMTX_SHM_CREAT
sub-request of the
.Dv UMTX_OP_SHM
-request cannot be satisfied, because allocation of the shared object
+request cannot be satisfied, because allocation of the shared memory object
would exceed the
-.Dv RLIMIT_UMXP
+.Dv RLIMIT_UMTXP
resource limit, see
.Xr setrlimit 2 .
.It Bq Er EAGAIN
@@ -1358,7 +1379,7 @@ specified in absolute time may be restartable.
.It Bq Er ERESTART
A signal was delivered during wait, for a restartable operation.
Mutex lock requests without timeout specified are restartable.
-The error is typically not returned to userspace code, restart
+The error is not returned to userspace code since restart
is handled by usual adjustment of the instruction counter.
.El
.Sh BUGS
@@ -1374,7 +1395,7 @@ implementation is only vulnerable to this race when operating on
a shared mutex.
A possible fix for the current implementation is to strengthen the checks
for shared mutexes before terminating them, in particular, verifying
-that the mutex memory is mapped from the POSIX shared object, allocated
+that the mutex memory is mapped from a shared memory object allocated
by the
.Dv UMTX_OP_SHM
request.
@@ -1402,5 +1423,5 @@ system call is non-standard and is used by the
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2
index 8b6add9..2e13a6c 100644
--- a/lib/libc/sys/jail.2
+++ b/lib/libc/sys/jail.2
@@ -106,7 +106,7 @@ pointers can be set to an arrays of IPv4 and IPv6 addresses to be assigned to
the prison, or NULL if none.
IPv4 addresses must be in network byte order.
.Pp
-This is equivalent to the
+This is equivalent to, and deprecated in favor of, the
.Fn jail_set
system call (see below), with the parameters
.Va path ,
diff --git a/lib/libc/sys/thr_exit.2 b/lib/libc/sys/thr_exit.2
index 0804219..781b07f 100644
--- a/lib/libc/sys/thr_exit.2
+++ b/lib/libc/sys/thr_exit.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_EXIT 2
.Os
.Sh NAME
@@ -41,24 +41,33 @@
.Ft void
.Fn thr_exit "long *state"
.Sh DESCRIPTION
+.Bf -symbolic
+This function is intended for implementing threading.
+Normal applications should call
+.Xr pthread_exit 3
+instead.
+.Ef
+.Pp
The
.Fn thr_exit
system call terminates the current kernel-scheduled thread.
.Pp
If the
.Fa state
-argument is not NULL, the location pointed to by the argument is
-updated with an arbitrary non-zero value, and
+argument is not
+.Dv NULL ,
+the location pointed to by the argument is
+updated with an arbitrary non-zero value, and an
.Xr _umtx_op 2
.Dv UMTX_OP_WAKE
operation is consequently performed on the location.
.Pp
-Attempts to terminate last thread in the process are silently ignored.
+Attempts to terminate the last thread in the process are silently ignored.
Use
.Xr _exit 2
syscall to terminate the process.
.Sh RETURN VALUES
-The function does not return any values.
+The function does not return a value.
A return from the function indicates that the calling thread was the
last one in the process.
.Sh SEE ALSO
@@ -68,13 +77,14 @@ last one in the process.
.Xr thr_new 2 ,
.Xr thr_self 2 ,
.Xr thr_set_name 2 ,
-.Xr _umtx_op 2
+.Xr _umtx_op 2 ,
+.Xr pthread_exit 3
.Sh STANDARDS
The
.Fn thr_exit
-system call is non-standard and is used by the
+system call is non-standard and is used by
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_kill.2 b/lib/libc/sys/thr_kill.2
index 8c12ef7..04293aa 100644
--- a/lib/libc/sys/thr_kill.2
+++ b/lib/libc/sys/thr_kill.2
@@ -28,12 +28,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_kill 2
.Os
.Sh NAME
.Nm thr_kill
-.Nd send signal to the thread
+.Nd send signal to thread
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -72,7 +72,7 @@ The
.Fa sig
argument defines the delivered signal.
It must be a valid signal number or zero.
-In the later case no signal is actually send, and the call is used to
+In the latter case no signal is actually sent, and the call is used to
verify the liveness of the thread.
.Pp
The signal is delivered with
@@ -112,11 +112,13 @@ The current process does not have sufficient privilege to check existence or
send a signal to the specified process.
.El
.Sh SEE ALSO
+.Xr kill 2 ,
.Xr thr_exit 2 ,
.Xr thr_new 2 ,
.Xr thr_self 2 ,
.Xr thr_set_name 2 ,
.Xr _umtx_op 2 ,
+.Xr pthread_kill 3 ,
.Xr signal 3
.Sh STANDARDS
The
@@ -127,5 +129,5 @@ system calls are non-standard and are used by the
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_new.2 b/lib/libc/sys/thr_new.2
index 44c468d..1de5f92 100644
--- a/lib/libc/sys/thr_new.2
+++ b/lib/libc/sys/thr_new.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_NEW 2
.Os
.Sh NAME
@@ -41,6 +41,13 @@
.Ft int
.Fn thr_new "struct thr_param *param" "int param_size"
.Sh DESCRIPTION
+.Bf -symbolic
+This function is intended for implementing threading.
+Normal applications should call
+.Xr pthread_create 3
+instead.
+.Ef
+.Pp
The
.Fn thr_new
system call creates a new kernel-scheduled thread of execution in the context
@@ -52,7 +59,7 @@ The machine context for the new thread is copied from the creating thread's
context, including coprocessor state.
FPU state and specific machine registers are excluded from the copy.
These are set according to ABI requirements and syscall parameters.
-The FPU state for new thread is reinitialized to clean.
+The FPU state for the new thread is reinitialized to clean.
.Pp
The
.Fa param
@@ -77,22 +84,22 @@ struct thr_param {
and contains the following fields:
.Bl -tag -width ".Va parent_tid"
.It Va start_func
-The pointer to the thread entry function.
-Kernel arranges for the new thread to start executing the function
+Pointer to the thread entry function.
+The kernel arranges for the new thread to start executing the function
upon the first return to userspace.
.It Va arg
Opaque argument supplied to the entry function.
.It Va stack_base
Stack base address.
The stack must be allocated by the caller.
-On some architectures, the ABI might require that system put information
+On some architectures, the ABI might require that the system put information
on the stack to ensure the execution environment for
.Va start_func .
.It Va stack_size
Stack size.
.It Va tls_base
TLS base address.
-The value of TLS base is loaded to the ABI-defined machine register
+The value of TLS base is loaded into the ABI-defined machine register
in the new thread context.
.It Va tls_size
TLS size.
@@ -113,9 +120,9 @@ issuing the
syscall, while
.Va parent_tid
is used by the thread creator.
-The later is separate from the
+The latter is separate from
.Va child_tid
-because new thread might exit and free its thread data before parent
+because the new thread might exit and free its thread data before the parent
has a chance to execute far enough to access it.
.It Va flags
Thread creation flags.
@@ -132,7 +139,9 @@ The flag is not currently implemented.
.El
.It Va rtp
Real-time scheduling priority for the new thread.
-May be NULL if thread should inherit the priority from the
+May be
+.Dv NULL
+to inherit the priority from the
creating thread.
.El
.Pp
@@ -184,14 +193,16 @@ initial data on the stack.
.It Bq Er EINVAL
The
.Fa param_size
-argument specifies negative value, or its value is greater than the
+argument specifies a negative value, or the value is greater than the
largest
.Fa struct param
size the kernel can interpret.
.It Bq Er EINVAL
The
.Fa rtp
-member is not NULL, but specifies invalid scheduling parameters.
+member is not
+.Dv NULL
+and specifies invalid scheduling parameters.
.It Bq Er EINVAL
The specified TLS base is invalid.
.It Bq Er EPROCLIM
@@ -216,7 +227,8 @@ No kernel memory to allocate for the new thread structures.
.Xr thr_kill2 2 ,
.Xr thr_self 2 ,
.Xr thr_set_name 2 ,
-.Xr _umtx_op 2
+.Xr _umtx_op 2 ,
+.Xr pthread_create 3
.Sh STANDARDS
The
.Fn thr_new
@@ -224,5 +236,5 @@ system call is non-standard and is used by the
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_self.2 b/lib/libc/sys/thr_self.2
index d90b863..949b600 100644
--- a/lib/libc/sys/thr_self.2
+++ b/lib/libc/sys/thr_self.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_SELF 2
.Os
.Sh NAME
@@ -76,13 +76,15 @@ argument is not valid.
.Xr thr_kill2 2 ,
.Xr thr_new 2 ,
.Xr thr_set_name 2 ,
-.Xr _umtx_op 2
+.Xr _umtx_op 2 ,
+.Xr pthread_getthreadid_np 3 ,
+.Xr pthread_self 3
.Sh STANDARDS
The
.Fn thr_self
-system call is non-standard and is used by the
+system call is non-standard and is used by
.Lb libthr
to implement
.St -p1003.1-2001
-.Xr pthread(3)
+.Xr pthread 3
functionality.
diff --git a/lib/libc/sys/thr_set_name.2 b/lib/libc/sys/thr_set_name.2
index 681e94b..d2549e4 100644
--- a/lib/libc/sys/thr_set_name.2
+++ b/lib/libc/sys/thr_set_name.2
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 5, 2016
+.Dd June 1, 2016
.Dt THR_SET_NAME 2
.Os
.Sh NAME
@@ -45,7 +45,7 @@ The
.Fn thr_set_name
sets the user-visible name for the kernel thread with the identifier
.Va id
-in the current process, to the NULL-terminated string
+in the current process, to the NUL-terminated string
.Va name .
The thread name can be seen in the output of the
.Xr ps 1
@@ -87,10 +87,11 @@ does not exist in the current process.
.Xr thr_new 2 ,
.Xr thr_self 2 ,
.Xr _umtx_op 2 ,
+.Xr pthread_set_name_np 3 ,
.Xr ddb 4 ,
.Xr ktr 9
.Sh STANDARDS
The
.Fn thr_new
-system call is non-standard and is used by the
+system call is non-standard and is used by
.Lb libthr .
diff --git a/lib/libc/sys/wait.2 b/lib/libc/sys/wait.2
index 687bc18..38b7bb7 100644
--- a/lib/libc/sys/wait.2
+++ b/lib/libc/sys/wait.2
@@ -28,7 +28,7 @@
.\" @(#)wait.2 8.2 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd December 3, 2013
+.Dd June 1, 2016
.Dt WAIT 2
.Os
.Sh NAME
@@ -596,6 +596,14 @@ and
fields of
.Fa infop
must be checked against zero to determine if a process reported status.
+.Pp
+.Fn wait
+called with -1 to wait for any child process will ignore a child that is
+referenced by a process descriptor (see
+.Xr pdfork 2 ) .
+Specific processes can still be waited on by specifying the process ID
+or descriptor (see
+.Xr pdwait 4 ) .
.Sh ERRORS
The
.Fn wait
diff --git a/lib/libcasper/services/cap_grp/cap_grp.c b/lib/libcasper/services/cap_grp/cap_grp.c
index d358cea..54a022f 100644
--- a/lib/libcasper/services/cap_grp/cap_grp.c
+++ b/lib/libcasper/services/cap_grp/cap_grp.c
@@ -703,7 +703,9 @@ grp_setgrent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused,
nvlist_t *nvlout __unused)
{
- return (setgrent() == 0 ? EFAULT : 0);
+ setgrent();
+
+ return (0);
}
static int
diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile
index c1f8542..3b982a3 100644
--- a/lib/libcrypt/Makefile
+++ b/lib/libcrypt/Makefile
@@ -31,6 +31,8 @@ CFLAGS+= -I${.CURDIR} -DHAS_DES -DHAS_BLOWFISH
.for sym in MD4Init MD4Final MD4Update MD4Pad \
MD5Init MD5Final MD5Update MD5Pad \
SHA256_Init SHA256_Final SHA256_Update \
+ SHA512_224_Init SHA512_224_Final SHA512_224_Update \
+ SHA512_256_Init SHA512_256_Final SHA512_256_Update \
SHA384_Init SHA384_Final SHA384_Update \
SHA512_Init SHA512_Final SHA512_Update
CFLAGS+= -D${sym}=__${sym}
diff --git a/lib/libcxxrt/Makefile b/lib/libcxxrt/Makefile
index 15420a6..f2efe8d 100644
--- a/lib/libcxxrt/Makefile
+++ b/lib/libcxxrt/Makefile
@@ -21,7 +21,7 @@ SRCS+= libelftc_dem_gnu3.c\
guard.cc
WARNS= 0
-CFLAGS+= -I${SRCDIR} -nostdinc++
+CFLAGS+= -isystem ${SRCDIR} -nostdinc++
.if empty(CXXFLAGS:M-std=*)
CXXFLAGS+= -std=c++11
.endif
diff --git a/lib/libdevdctl/Makefile b/lib/libdevdctl/Makefile
new file mode 100644
index 0000000..5a18a14
--- /dev/null
+++ b/lib/libdevdctl/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+LIB_CXX= devdctl
+INCS= consumer.h \
+ event.h \
+ event_factory.h \
+ exception.h \
+ guid.h
+SRCS= consumer.cc \
+ event.cc \
+ event_factory.cc \
+ exception.cc \
+ guid.cc
+
+INCSDIR= ${INCLUDEDIR}/devdctl
+
+WARNS?= 3
+PRIVATELIB= true
+SHLIB_MAJOR= 0
+
+.include <bsd.lib.mk>
diff --git a/lib/libdevdctl/consumer.cc b/lib/libdevdctl/consumer.cc
new file mode 100644
index 0000000..e769894
--- /dev/null
+++ b/lib/libdevdctl/consumer.cc
@@ -0,0 +1,258 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file consumer.cc
+ */
+
+#include <sys/cdefs.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <cstdarg>
+#include <cstring>
+#include <list>
+#include <map>
+#include <string>
+
+#include "guid.h"
+#include "event.h"
+#include "event_factory.h"
+#include "exception.h"
+
+#include "consumer.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+using std::string;
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+/*----------------------------- DevdCtl::Consumer ----------------------------*/
+//- Consumer Static Private Data -----------------------------------------------
+const char Consumer::s_devdSockPath[] = "/var/run/devd.seqpacket.pipe";
+
+//- Consumer Public Methods ----------------------------------------------------
+Consumer::Consumer(Event::BuildMethod *defBuilder,
+ EventFactory::Record *regEntries,
+ size_t numEntries)
+ : m_devdSockFD(-1),
+ m_eventFactory(defBuilder),
+ m_replayingEvents(false)
+{
+ m_eventFactory.UpdateRegistry(regEntries, numEntries);
+}
+
+Consumer::~Consumer()
+{
+ DisconnectFromDevd();
+}
+
+bool
+Consumer::ConnectToDevd()
+{
+ struct sockaddr_un devdAddr;
+ int sLen;
+ int result;
+
+ if (m_devdSockFD != -1) {
+ /* Already connected. */
+ syslog(LOG_DEBUG, "%s: Already connected.", __func__);
+ return (true);
+ }
+ syslog(LOG_INFO, "%s: Connecting to devd.", __func__);
+
+ memset(&devdAddr, 0, sizeof(devdAddr));
+ devdAddr.sun_family= AF_UNIX;
+ strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path));
+ sLen = SUN_LEN(&devdAddr);
+
+ m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+ if (m_devdSockFD == -1)
+ err(1, "Unable to create socket");
+ if (fcntl(m_devdSockFD, F_SETFL, O_NONBLOCK) < 0)
+ err(1, "fcntl");
+ result = connect(m_devdSockFD,
+ reinterpret_cast<sockaddr *>(&devdAddr),
+ sLen);
+ if (result == -1) {
+ syslog(LOG_INFO, "Unable to connect to devd");
+ DisconnectFromDevd();
+ return (false);
+ }
+
+ syslog(LOG_INFO, "Connection to devd successful");
+ return (true);
+}
+
+void
+Consumer::DisconnectFromDevd()
+{
+ if (m_devdSockFD != -1) {
+ syslog(LOG_INFO, "Disconnecting from devd.");
+ close(m_devdSockFD);
+ }
+ m_devdSockFD = -1;
+}
+
+std::string
+Consumer::ReadEvent()
+{
+ char buf[MAX_EVENT_SIZE + 1];
+ ssize_t len;
+
+ len = ::recv(m_devdSockFD, buf, MAX_EVENT_SIZE, MSG_WAITALL);
+ if (len == -1)
+ return (std::string(""));
+ else {
+ /* NULL-terminate the result */
+ buf[len] = '\0';
+ return (std::string(buf));
+ }
+}
+
+void
+Consumer::ReplayUnconsumedEvents(bool discardUnconsumed)
+{
+ EventList::iterator event(m_unconsumedEvents.begin());
+ bool replayed_any = (event != m_unconsumedEvents.end());
+
+ m_replayingEvents = true;
+ if (replayed_any)
+ syslog(LOG_INFO, "Started replaying unconsumed events");
+ while (event != m_unconsumedEvents.end()) {
+ bool consumed((*event)->Process());
+ if (consumed || discardUnconsumed) {
+ delete *event;
+ event = m_unconsumedEvents.erase(event);
+ } else {
+ event++;
+ }
+ }
+ if (replayed_any)
+ syslog(LOG_INFO, "Finished replaying unconsumed events");
+ m_replayingEvents = false;
+}
+
+bool
+Consumer::SaveEvent(const Event &event)
+{
+ if (m_replayingEvents)
+ return (false);
+ m_unconsumedEvents.push_back(event.DeepCopy());
+ return (true);
+}
+
+Event *
+Consumer::NextEvent()
+{
+ if (!Connected())
+ return(NULL);
+
+ Event *event(NULL);
+ try {
+ string evString;
+
+ evString = ReadEvent();
+ if (! evString.empty()) {
+ Event::TimestampEventString(evString);
+ event = Event::CreateEvent(m_eventFactory, evString);
+ }
+ } catch (const Exception &exp) {
+ exp.Log();
+ DisconnectFromDevd();
+ }
+ return (event);
+}
+
+/* Capture and process buffered events. */
+void
+Consumer::ProcessEvents()
+{
+ Event *event;
+ while ((event = NextEvent()) != NULL) {
+ if (event->Process())
+ SaveEvent(*event);
+ delete event;
+ }
+}
+
+void
+Consumer::FlushEvents()
+{
+ std::string s;
+
+ do
+ s = ReadEvent();
+ while (! s.empty()) ;
+}
+
+bool
+Consumer::EventsPending()
+{
+ struct pollfd fds[1];
+ int result;
+
+ do {
+ fds->fd = m_devdSockFD;
+ fds->events = POLLIN;
+ fds->revents = 0;
+ result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/0);
+ } while (result == -1 && errno == EINTR);
+
+ if (result == -1)
+ err(1, "Polling for devd events failed");
+
+ if ((fds->revents & POLLERR) != 0)
+ throw Exception("Consumer::EventsPending(): "
+ "POLLERR detected on devd socket.");
+
+ if ((fds->revents & POLLHUP) != 0)
+ throw Exception("Consumer::EventsPending(): "
+ "POLLHUP detected on devd socket.");
+
+ return ((fds->revents & POLLIN) != 0);
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/consumer.h b/lib/libdevdctl/consumer.h
new file mode 100644
index 0000000..0f15b79
--- /dev/null
+++ b/lib/libdevdctl/consumer.h
@@ -0,0 +1,174 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_consumer.h
+ */
+#ifndef _DEVDCTL_CONSUMER_H_
+#define _DEVDCTL_CONSUMER_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*=========================== Forward Declarations ===========================*/
+class Event;
+
+/*============================ Class Declarations ============================*/
+/*----------------------------- DevdCtl::Consumer ----------------------------*/
+
+/**
+ */
+class Consumer
+{
+public:
+ Consumer(Event::BuildMethod *defBuilder = NULL,
+ EventFactory::Record *regEntries = NULL,
+ size_t numEntries = 0);
+ virtual ~Consumer();
+
+ bool Connected() const;
+
+ /**
+ * Return file descriptor useful for client's wishing to poll(2)
+ * for new events.
+ */
+ int GetPollFd();
+
+ /**
+ * Queue an event for deferred processing or replay.
+ */
+ bool SaveEvent(const Event &event);
+
+ /**
+ * Reprocess any events saved via the SaveEvent() facility.
+ *
+ * \param discardUnconsumed If true, events that are not consumed
+ * during replay are discarded.
+ */
+ void ReplayUnconsumedEvents(bool discardUnconsumed);
+
+ /** Return an event, if one is available. */
+ Event *NextEvent();
+
+ /**
+ * Extract events and invoke each event's Process method.
+ */
+ void ProcessEvents();
+
+ /** Discard all data pending in m_devdSockFD. */
+ void FlushEvents();
+
+ /**
+ * Test for data pending in m_devdSockFD
+ *
+ * \return True if data is pending. Otherwise false.
+ */
+ bool EventsPending();
+
+ /**
+ * Open a connection to devd's unix domain socket.
+ *
+ * \return True if the connection attempt is successsful. Otherwise
+ * false.
+ */
+ bool ConnectToDevd();
+
+ /**
+ * Close a connection (if any) to devd's unix domain socket.
+ */
+ void DisconnectFromDevd();
+
+ EventFactory GetFactory();
+
+protected:
+ /**
+ * \brief Reads the most recent record
+ *
+ * On error, "" is returned, and errno will be set by the OS
+ *
+ * \returns A string containing the record
+ */
+ std::string ReadEvent();
+
+ enum {
+ /*
+ * The maximum event size supported by libdevdctl.
+ */
+ MAX_EVENT_SIZE = 8192,
+ };
+
+ static const char s_devdSockPath[];
+
+ /**
+ * File descriptor representing the unix domain socket
+ * connection with devd.
+ */
+ int m_devdSockFD;
+
+ EventFactory m_eventFactory;
+
+ /** Queued events for replay. */
+ EventList m_unconsumedEvents;
+
+ /**
+ * Flag controlling whether events can be queued. This boolean
+ * is set during event replay to ensure that previosuly deferred
+ * events are not requeued and thus retained forever.
+ */
+ bool m_replayingEvents;
+};
+
+//- Consumer Const Public Inline Methods ---------------------------------------
+inline bool
+Consumer::Connected() const
+{
+ return (m_devdSockFD != -1);
+}
+
+//- Consumer Public Inline Methods ---------------------------------------------
+inline int
+Consumer::GetPollFd()
+{
+ return (m_devdSockFD);
+}
+
+inline EventFactory
+Consumer::GetFactory()
+{
+ return (m_eventFactory);
+}
+
+} // namespace DevdCtl
+#endif /* _DEVDCTL_CONSUMER_H_ */
diff --git a/lib/libdevdctl/event.cc b/lib/libdevdctl/event.cc
new file mode 100644
index 0000000..d63e8e2
--- /dev/null
+++ b/lib/libdevdctl/event.cc
@@ -0,0 +1,602 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file event.cc
+ *
+ * Implementation of the class hierarchy used to express events
+ * received via the devdctl API.
+ */
+#include <sys/cdefs.h>
+#include <sys/disk.h>
+#include <sys/filio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <cstdarg>
+#include <cstring>
+#include <iostream>
+#include <list>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "guid.h"
+#include "event.h"
+#include "event_factory.h"
+#include "exception.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+using std::cout;
+using std::endl;
+using std::string;
+using std::stringstream;
+
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*----------------------------------- Event ----------------------------------*/
+//- Event Static Protected Data ------------------------------------------------
+const string Event::s_theEmptyString;
+
+Event::EventTypeRecord Event::s_typeTable[] =
+{
+ { Event::NOTIFY, "Notify" },
+ { Event::NOMATCH, "No Driver Match" },
+ { Event::ATTACH, "Attach" },
+ { Event::DETACH, "Detach" }
+};
+
+//- Event Static Public Methods ------------------------------------------------
+Event *
+Event::Builder(Event::Type type, NVPairMap &nvPairs,
+ const string &eventString)
+{
+ return (new Event(type, nvPairs, eventString));
+}
+
+Event *
+Event::CreateEvent(const EventFactory &factory, const string &eventString)
+{
+ NVPairMap &nvpairs(*new NVPairMap);
+ Type type(static_cast<Event::Type>(eventString[0]));
+
+ try {
+ ParseEventString(type, eventString, nvpairs);
+ } catch (const ParseException &exp) {
+ if (exp.GetType() == ParseException::INVALID_FORMAT)
+ exp.Log();
+ return (NULL);
+ }
+
+ /*
+ * Allow entries in our table for events with no system specified.
+ * These entries should specify the string "none".
+ */
+ NVPairMap::iterator system_item(nvpairs.find("system"));
+ if (system_item == nvpairs.end())
+ nvpairs["system"] = "none";
+
+ return (factory.Build(type, nvpairs, eventString));
+}
+
+bool
+Event::DevName(std::string &name) const
+{
+ return (false);
+}
+
+/* TODO: simplify this function with C++-11 <regex> methods */
+bool
+Event::IsDiskDev() const
+{
+ const int numDrivers = 2;
+ static const char *diskDevNames[numDrivers] =
+ {
+ "da",
+ "ada"
+ };
+ const char **dName;
+ string devName;
+
+ if (! DevName(devName))
+ return false;
+
+ size_t find_start = devName.rfind('/');
+ if (find_start == string::npos) {
+ find_start = 0;
+ } else {
+ /* Just after the last '/'. */
+ find_start++;
+ }
+
+ for (dName = &diskDevNames[0];
+ dName <= &diskDevNames[numDrivers - 1]; dName++) {
+
+ size_t loc(devName.find(*dName, find_start));
+ if (loc == find_start) {
+ size_t prefixLen(strlen(*dName));
+
+ if (devName.length() - find_start >= prefixLen
+ && isdigit(devName[find_start + prefixLen]))
+ return (true);
+ }
+ }
+
+ return (false);
+}
+
+const char *
+Event::TypeToString(Event::Type type)
+{
+ EventTypeRecord *rec(s_typeTable);
+ EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1);
+
+ for (; rec <= lastRec; rec++) {
+ if (rec->m_type == type)
+ return (rec->m_typeName);
+ }
+ return ("Unknown");
+}
+
+//- Event Public Methods -------------------------------------------------------
+const string &
+Event::Value(const string &varName) const
+{
+ NVPairMap::const_iterator item(m_nvPairs.find(varName));
+ if (item == m_nvPairs.end())
+ return (s_theEmptyString);
+
+ return (item->second);
+}
+
+bool
+Event::Contains(const string &varName) const
+{
+ return (m_nvPairs.find(varName) != m_nvPairs.end());
+}
+
+string
+Event::ToString() const
+{
+ stringstream result;
+
+ NVPairMap::const_iterator devName(m_nvPairs.find("device-name"));
+ if (devName != m_nvPairs.end())
+ result << devName->second << ": ";
+
+ NVPairMap::const_iterator systemName(m_nvPairs.find("system"));
+ if (systemName != m_nvPairs.end()
+ && systemName->second != "none")
+ result << systemName->second << ": ";
+
+ result << TypeToString(GetType()) << ' ';
+
+ for (NVPairMap::const_iterator curVar = m_nvPairs.begin();
+ curVar != m_nvPairs.end(); curVar++) {
+ if (curVar == devName || curVar == systemName)
+ continue;
+
+ result << ' '
+ << curVar->first << "=" << curVar->second;
+ }
+ result << endl;
+
+ return (result.str());
+}
+
+void
+Event::Print() const
+{
+ cout << ToString() << std::flush;
+}
+
+void
+Event::Log(int priority) const
+{
+ syslog(priority, "%s", ToString().c_str());
+}
+
+//- Event Virtual Public Methods -----------------------------------------------
+Event::~Event()
+{
+ delete &m_nvPairs;
+}
+
+Event *
+Event::DeepCopy() const
+{
+ return (new Event(*this));
+}
+
+bool
+Event::Process() const
+{
+ return (false);
+}
+
+timeval
+Event::GetTimestamp() const
+{
+ timeval tv_timestamp;
+ struct tm tm_timestamp;
+
+ if (!Contains("timestamp")) {
+ throw Exception("Event contains no timestamp: %s",
+ m_eventString.c_str());
+ }
+ strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp);
+ tv_timestamp.tv_sec = mktime(&tm_timestamp);
+ tv_timestamp.tv_usec = 0;
+ return (tv_timestamp);
+}
+
+bool
+Event::DevPath(std::string &path) const
+{
+ string devName;
+
+ if (!DevName(devName))
+ return (false);
+
+ string devPath(_PATH_DEV + devName);
+ int devFd(open(devPath.c_str(), O_RDONLY));
+ if (devFd == -1)
+ return (false);
+
+ /* Normalize the device name in case the DEVFS event is for a link. */
+ devName = fdevname(devFd);
+ path = _PATH_DEV + devName;
+
+ close(devFd);
+
+ return (true);
+}
+
+bool
+Event::PhysicalPath(std::string &path) const
+{
+ string devPath;
+
+ if (!DevPath(devPath))
+ return (false);
+
+ int devFd(open(devPath.c_str(), O_RDONLY));
+ if (devFd == -1)
+ return (false);
+
+ char physPath[MAXPATHLEN];
+ physPath[0] = '\0';
+ bool result(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0);
+ close(devFd);
+ if (result)
+ path = physPath;
+ return (result);
+}
+
+//- Event Protected Methods ----------------------------------------------------
+Event::Event(Type type, NVPairMap &map, const string &eventString)
+ : m_type(type),
+ m_nvPairs(map),
+ m_eventString(eventString)
+{
+}
+
+Event::Event(const Event &src)
+ : m_type(src.m_type),
+ m_nvPairs(*new NVPairMap(src.m_nvPairs)),
+ m_eventString(src.m_eventString)
+{
+}
+
+void
+Event::ParseEventString(Event::Type type,
+ const string &eventString,
+ NVPairMap& nvpairs)
+{
+ size_t start;
+ size_t end;
+
+ switch (type) {
+ case ATTACH:
+ case DETACH:
+
+ /*
+ * <type><device-name><unit> <pnpvars> \
+ * at <location vars> <pnpvars> \
+ * on <parent>
+ *
+ * Handle all data that doesn't conform to the
+ * "name=value" format, and let the generic parser
+ * below handle the rest.
+ *
+ * Type is a single char. Skip it.
+ */
+ start = 1;
+ end = eventString.find_first_of(" \t\n", start);
+ if (end == string::npos)
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, start);
+
+ nvpairs["device-name"] = eventString.substr(start, end - start);
+
+ start = eventString.find(" on ", end);
+ if (end == string::npos)
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, start);
+ start += 4;
+ end = eventString.find_first_of(" \t\n", start);
+ nvpairs["parent"] = eventString.substr(start, end);
+ break;
+ case NOTIFY:
+ break;
+ case NOMATCH:
+ throw ParseException(ParseException::DISCARDED_EVENT_TYPE,
+ eventString);
+ default:
+ throw ParseException(ParseException::UNKNOWN_EVENT_TYPE,
+ eventString);
+ }
+
+ /* Process common "key=value" format. */
+ for (start = 1; start < eventString.length(); start = end + 1) {
+
+ /* Find the '=' in the middle of the key/value pair. */
+ end = eventString.find('=', start);
+ if (end == string::npos)
+ break;
+
+ /*
+ * Find the start of the key by backing up until
+ * we hit whitespace or '!' (event type "notice").
+ * Due to the devdctl format, all key/value pair must
+ * start with one of these two characters.
+ */
+ start = eventString.find_last_of("! \t\n", end);
+ if (start == string::npos)
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, end);
+ start++;
+ string key(eventString.substr(start, end - start));
+
+ /*
+ * Walk forward from the '=' until either we exhaust
+ * the buffer or we hit whitespace.
+ */
+ start = end + 1;
+ if (start >= eventString.length())
+ throw ParseException(ParseException::INVALID_FORMAT,
+ eventString, end);
+ end = eventString.find_first_of(" \t\n", start);
+ if (end == string::npos)
+ end = eventString.length() - 1;
+ string value(eventString.substr(start, end - start));
+
+ nvpairs[key] = value;
+ }
+}
+
+void
+Event::TimestampEventString(std::string &eventString)
+{
+ if (eventString.size() > 0) {
+ /*
+ * Add a timestamp as the final field of the event if it is
+ * not already present.
+ */
+ if (eventString.find("timestamp=") == string::npos) {
+ const size_t bufsize = 32; // Long enough for a 64-bit int
+ timeval now;
+ char timebuf[bufsize];
+
+ size_t eventEnd(eventString.find_last_not_of('\n') + 1);
+ if (gettimeofday(&now, NULL) != 0)
+ err(1, "gettimeofday");
+ snprintf(timebuf, bufsize, " timestamp=%" PRId64,
+ (int64_t) now.tv_sec);
+ eventString.insert(eventEnd, timebuf);
+ }
+ }
+}
+
+/*-------------------------------- DevfsEvent --------------------------------*/
+//- DevfsEvent Static Public Methods -------------------------------------------
+Event *
+DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs,
+ const string &eventString)
+{
+ return (new DevfsEvent(type, nvPairs, eventString));
+}
+
+//- DevfsEvent Static Protected Methods ----------------------------------------
+bool
+DevfsEvent::IsWholeDev(const string &devName)
+{
+ string::const_iterator i(devName.begin());
+
+ size_t start = devName.rfind('/');
+ if (start == string::npos) {
+ start = 0;
+ } else {
+ /* Just after the last '/'. */
+ start++;
+ }
+ i += start;
+
+ /* alpha prefix followed only by digits. */
+ for (; i < devName.end() && !isdigit(*i); i++)
+ ;
+
+ if (i == devName.end())
+ return (false);
+
+ for (; i < devName.end() && isdigit(*i); i++)
+ ;
+
+ return (i == devName.end());
+}
+
+//- DevfsEvent Virtual Public Methods ------------------------------------------
+Event *
+DevfsEvent::DeepCopy() const
+{
+ return (new DevfsEvent(*this));
+}
+
+bool
+DevfsEvent::Process() const
+{
+ return (true);
+}
+
+//- DevfsEvent Public Methods --------------------------------------------------
+bool
+DevfsEvent::IsWholeDev() const
+{
+ string devName;
+
+ return (DevName(devName) && IsDiskDev() && IsWholeDev(devName));
+}
+
+bool
+DevfsEvent::DevName(std::string &name) const
+{
+ if (Value("subsystem") != "CDEV")
+ return (false);
+
+ name = Value("cdev");
+ return (!name.empty());
+}
+
+//- DevfsEvent Protected Methods -----------------------------------------------
+DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : Event(type, nvpairs, eventString)
+{
+}
+
+DevfsEvent::DevfsEvent(const DevfsEvent &src)
+ : Event(src)
+{
+}
+
+/*--------------------------------- GeomEvent --------------------------------*/
+//- GeomEvent Static Public Methods --------------------------------------------
+Event *
+GeomEvent::Builder(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+{
+ return (new GeomEvent(type, nvpairs, eventString));
+}
+
+//- GeomEvent Virtual Public Methods -------------------------------------------
+Event *
+GeomEvent::DeepCopy() const
+{
+ return (new GeomEvent(*this));
+}
+
+bool
+GeomEvent::DevName(std::string &name) const
+{
+ name = Value("devname");
+ return (!name.empty());
+}
+
+
+//- GeomEvent Protected Methods ------------------------------------------------
+GeomEvent::GeomEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : Event(type, nvpairs, eventString),
+ m_devname(Value("devname"))
+{
+}
+
+GeomEvent::GeomEvent(const GeomEvent &src)
+ : Event(src),
+ m_devname(src.m_devname)
+{
+}
+
+/*--------------------------------- ZfsEvent ---------------------------------*/
+//- ZfsEvent Static Public Methods ---------------------------------------------
+Event *
+ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+{
+ return (new ZfsEvent(type, nvpairs, eventString));
+}
+
+//- ZfsEvent Virtual Public Methods --------------------------------------------
+Event *
+ZfsEvent::DeepCopy() const
+{
+ return (new ZfsEvent(*this));
+}
+
+bool
+ZfsEvent::DevName(std::string &name) const
+{
+ return (false);
+}
+
+//- ZfsEvent Protected Methods -------------------------------------------------
+ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs,
+ const string &eventString)
+ : Event(type, nvpairs, eventString),
+ m_poolGUID(Guid(Value("pool_guid"))),
+ m_vdevGUID(Guid(Value("vdev_guid")))
+{
+}
+
+ZfsEvent::ZfsEvent(const ZfsEvent &src)
+ : Event(src),
+ m_poolGUID(src.m_poolGUID),
+ m_vdevGUID(src.m_vdevGUID)
+{
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/event.h b/lib/libdevdctl/event.h
new file mode 100644
index 0000000..74ee3f7
--- /dev/null
+++ b/lib/libdevdctl/event.h
@@ -0,0 +1,423 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_event.h
+ *
+ * \brief Class hierarchy used to express events received via
+ * the devdctl API.
+ */
+
+#ifndef _DEVDCTL_EVENT_H_
+#define _DEVDCTL_EVENT_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*=========================== Forward Declarations ===========================*/
+class EventFactory;
+
+/*============================= Class Definitions ============================*/
+/*-------------------------------- NVPairMap ---------------------------------*/
+/**
+ * NVPairMap is a specialization of the standard map STL container.
+ */
+typedef std::map<std::string, std::string> NVPairMap;
+
+/*----------------------------------- Event ----------------------------------*/
+/**
+ * \brief Container for the name => value pairs that comprise the content of
+ * a device control event.
+ *
+ * All name => value data for events can be accessed via the Contains()
+ * and Value() methods. name => value pairs for data not explicitly
+ * received as a name => value pair are synthesized during parsing. For
+ * example, ATTACH and DETACH events have "device-name" and "parent"
+ * name => value pairs added.
+ */
+class Event
+{
+ friend class EventFactory;
+
+public:
+ /** Event type */
+ enum Type {
+ /** Generic event notification. */
+ NOTIFY = '!',
+
+ /** A driver was not found for this device. */
+ NOMATCH = '?',
+
+ /** A bus device instance has been added. */
+ ATTACH = '+',
+
+ /** A bus device instance has been removed. */
+ DETACH = '-'
+ };
+
+ /**
+ * Factory method type to construct an Event given
+ * the type of event and an NVPairMap populated from
+ * the event string received from devd.
+ */
+ typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &);
+
+ /** Generic Event object factory. */
+ static BuildMethod Builder;
+
+ static Event *CreateEvent(const EventFactory &factory,
+ const std::string &eventString);
+
+ /**
+ * Returns the devname, if any, associated with the event
+ *
+ * \param name Devname, returned by reference
+ * \return True iff the event contained a devname
+ */
+ virtual bool DevName(std::string &name) const;
+
+ /**
+ * Returns the absolute pathname of the device associated with this
+ * event.
+ *
+ * \param name Devname, returned by reference
+ * \return True iff the event contained a devname
+ */
+ bool DevPath(std::string &path) const;
+
+ /**
+ * Returns true iff this event refers to a disk device
+ */
+ bool IsDiskDev() const;
+
+ /** Returns the physical path of the device, if any
+ *
+ * \param path Physical path, returned by reference
+ * \return True iff the event contains a device with a physical
+ * path
+ */
+ bool PhysicalPath(std::string &path) const;
+
+ /**
+ * Provide a user friendly string representation of an
+ * event type.
+ *
+ * \param type The type of event to map to a string.
+ *
+ * \return A user friendly string representing the input type.
+ */
+ static const char *TypeToString(Type type);
+
+ /**
+ * Determine the availability of a name => value pair by name.
+ *
+ * \param name The key name to search for in this event instance.
+ *
+ * \return true if the specified key is available in this
+ * event, otherwise false.
+ */
+ bool Contains(const std::string &name) const;
+
+ /**
+ * \param key The name of the key for which to retrieve its
+ * associated value.
+ *
+ * \return A const reference to the string representing the
+ * value associated with key.
+ *
+ * \note For key's with no registered value, the empty string
+ * is returned.
+ */
+ const std::string &Value(const std::string &key) const;
+
+ /**
+ * Get the type of this event instance.
+ *
+ * \return The type of this event instance.
+ */
+ Type GetType() const;
+
+ /**
+ * Get the original DevdCtl event string for this event.
+ *
+ * \return The DevdCtl event string.
+ */
+ const std::string &GetEventString() const;
+
+ /**
+ * Convert the event instance into a string suitable for
+ * printing to the console or emitting to syslog.
+ *
+ * \return A string of formatted event data.
+ */
+ std::string ToString() const;
+
+ /**
+ * Pretty-print this event instance to cout.
+ */
+ void Print() const;
+
+ /**
+ * Pretty-print this event instance to syslog.
+ *
+ * \param priority The logging priority/facility.
+ * See syslog(3).
+ */
+ void Log(int priority) const;
+
+ /**
+ * Create and return a fully independent clone
+ * of this event.
+ */
+ virtual Event *DeepCopy() const;
+
+ /** Destructor */
+ virtual ~Event();
+
+ /**
+ * Interpret and perform any actions necessary to
+ * consume the event.
+ *
+ * \return True if this event should be queued for later reevaluation
+ */
+ virtual bool Process() const;
+
+ /**
+ * Get the time that the event was created
+ */
+ timeval GetTimestamp() const;
+
+ /**
+ * Add a timestamp to the event string, if one does not already exist
+ * TODO: make this an instance method that operates on the std::map
+ * instead of the string. We must fix zfsd's CaseFile serialization
+ * routines first, so that they don't need the raw event string.
+ *
+ * \param[in,out] eventString The devd event string to modify
+ */
+ static void TimestampEventString(std::string &eventString);
+
+ /**
+ * Access all parsed key => value pairs.
+ */
+ const NVPairMap &GetMap() const;
+
+protected:
+ /** Table entries used to map a type to a user friendly string. */
+ struct EventTypeRecord
+ {
+ Type m_type;
+ const char *m_typeName;
+ };
+
+ /**
+ * Constructor
+ *
+ * \param type The type of event to create.
+ */
+ Event(Type type, NVPairMap &map, const std::string &eventString);
+
+ /** Deep copy constructor. */
+ Event(const Event &src);
+
+ /** Always empty string returned when NVPairMap lookups fail. */
+ static const std::string s_theEmptyString;
+
+ /** Unsorted table of event types. */
+ static EventTypeRecord s_typeTable[];
+
+ /** The type of this event. */
+ const Type m_type;
+
+ /**
+ * Event attribute storage.
+ *
+ * \note Although stored by reference (since m_nvPairs can
+ * never be NULL), the NVPairMap referenced by this field
+ * is dynamically allocated and owned by this event object.
+ * m_nvPairs must be deleted at event destruction.
+ */
+ NVPairMap &m_nvPairs;
+
+ /**
+ * The unaltered event string, as received from devd, used to
+ * create this event object.
+ */
+ std::string m_eventString;
+
+private:
+ /**
+ * Ingest event data from the supplied string.
+ *
+ * \param[in] eventString The string of devd event data to parse.
+ * \param[out] nvpairs Returns the parsed data
+ */
+ static void ParseEventString(Type type, const std::string &eventString,
+ NVPairMap &nvpairs);
+};
+
+inline Event::Type
+Event::GetType() const
+{
+ return (m_type);
+}
+
+inline const std::string &
+Event::GetEventString() const
+{
+ return (m_eventString);
+}
+
+inline const NVPairMap &
+Event::GetMap() const
+{
+ return (m_nvPairs);
+}
+
+/*--------------------------------- EventList --------------------------------*/
+/**
+ * EventList is a specialization of the standard list STL container.
+ */
+typedef std::list<Event *> EventList;
+
+/*-------------------------------- DevfsEvent --------------------------------*/
+class DevfsEvent : public Event
+{
+public:
+ /** Specialized Event object factory for Devfs events. */
+ static BuildMethod Builder;
+
+ virtual Event *DeepCopy() const;
+
+ /**
+ * Interpret and perform any actions necessary to
+ * consume the event.
+ * \return True if this event should be queued for later reevaluation
+ */
+ virtual bool Process() const;
+
+ bool IsWholeDev() const;
+ virtual bool DevName(std::string &name) const;
+
+protected:
+ /**
+ * Given the device name of a disk, determine if the device
+ * represents the whole device, not just a partition.
+ *
+ * \param devName Device name of disk device to test.
+ *
+ * \return True if the device name represents the whole device.
+ * Otherwise false.
+ */
+ static bool IsWholeDev(const std::string &devName);
+
+ /** DeepCopy Constructor. */
+ DevfsEvent(const DevfsEvent &src);
+
+ /** Constructor */
+ DevfsEvent(Type, NVPairMap &, const std::string &);
+};
+
+/*--------------------------------- GeomEvent --------------------------------*/
+class GeomEvent : public Event
+{
+public:
+ /** Specialized Event object factory for GEOM events. */
+ static BuildMethod Builder;
+
+ virtual Event *DeepCopy() const;
+
+ virtual bool DevName(std::string &name) const;
+
+ const std::string &DeviceName() const;
+
+protected:
+ /** Constructor */
+ GeomEvent(Type, NVPairMap &, const std::string &);
+
+ /** Deep copy constructor. */
+ GeomEvent(const GeomEvent &src);
+
+ std::string m_devname;
+};
+
+/*--------------------------------- ZfsEvent ---------------------------------*/
+class ZfsEvent : public Event
+{
+public:
+ /** Specialized Event object factory for ZFS events. */
+ static BuildMethod Builder;
+
+ virtual Event *DeepCopy() const;
+
+ virtual bool DevName(std::string &name) const;
+
+ const std::string &PoolName() const;
+ Guid PoolGUID() const;
+ Guid VdevGUID() const;
+
+protected:
+ /** Constructor */
+ ZfsEvent(Type, NVPairMap &, const std::string &);
+
+ /** Deep copy constructor. */
+ ZfsEvent(const ZfsEvent &src);
+
+ Guid m_poolGUID;
+ Guid m_vdevGUID;
+};
+
+//- ZfsEvent Inline Public Methods --------------------------------------------
+inline const std::string&
+ZfsEvent::PoolName() const
+{
+ /* The pool name is reported as the subsystem of ZFS events. */
+ return (Value("subsystem"));
+}
+
+inline Guid
+ZfsEvent::PoolGUID() const
+{
+ return (m_poolGUID);
+}
+
+inline Guid
+ZfsEvent::VdevGUID() const
+{
+ return (m_vdevGUID);
+}
+
+} // namespace DevdCtl
+#endif /*_DEVDCTL_EVENT_H_ */
diff --git a/lib/libdevdctl/event_factory.cc b/lib/libdevdctl/event_factory.cc
new file mode 100644
index 0000000..3901fd5
--- /dev/null
+++ b/lib/libdevdctl/event_factory.cc
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file event_factory.cc
+ */
+#include <sys/cdefs.h>
+#include <sys/time.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include "guid.h"
+#include "event.h"
+#include "event_factory.h"
+
+__FBSDID("$FreeBSD$");
+
+/*================================== Macros ==================================*/
+#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*------------------------------- EventFactory -------------------------------*/
+//- Event Public Methods -------------------------------------------------------
+EventFactory::EventFactory(Event::BuildMethod *defaultBuildMethod)
+ : m_defaultBuildMethod(defaultBuildMethod)
+{
+}
+
+void
+EventFactory::UpdateRegistry(Record regEntries[], size_t numEntries)
+{
+ EventFactory::Record *rec(regEntries);
+ EventFactory::Record *lastRec(rec + numEntries - 1);
+
+ for (; rec <= lastRec; rec++) {
+ Key key(rec->m_type, rec->m_subsystem);
+
+ if (rec->m_buildMethod == NULL)
+ m_registry.erase(key);
+ else
+ m_registry[key] = rec->m_buildMethod;
+ }
+}
+
+Event *
+EventFactory::Build(Event::Type type, NVPairMap &nvpairs,
+ const std::string eventString) const
+{
+ Key key(type, nvpairs["system"]);
+ Event::BuildMethod *buildMethod(m_defaultBuildMethod);
+
+ Registry::const_iterator foundMethod(m_registry.find(key));
+ if (foundMethod != m_registry.end())
+ buildMethod = foundMethod->second;
+
+ if (buildMethod == NULL) {
+ delete &nvpairs;
+ return (NULL);
+ }
+
+ return (buildMethod(type, nvpairs, eventString));
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/event_factory.h b/lib/libdevdctl/event_factory.h
new file mode 100644
index 0000000..e23332c
--- /dev/null
+++ b/lib/libdevdctl/event_factory.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_event_factory.h
+ */
+
+#ifndef _DEVDCTL_EVENT_FACTORY_H_
+#define _DEVDCTL_EVENT_FACTORY_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+/*------------------------------- EventFactory -------------------------------*/
+/**
+ * \brief Container for "event type" => "event object" creation methods.
+ */
+class EventFactory
+{
+public:
+ /**
+ * Event creation handlers are matched by event type and a
+ * string representing the system emitting the event.
+ */
+ typedef std::pair<Event::Type, std::string> Key;
+
+ /** Map type for Factory method lookups. */
+ typedef std::map<Key, Event::BuildMethod *> Registry;
+
+ /** Table record of factory methods to add to our registry. */
+ struct Record
+ {
+ Event::Type m_type;
+ const char *m_subsystem;
+ Event::BuildMethod *m_buildMethod;
+ };
+
+ const Registry &GetRegistry() const;
+ Event *Build(Event::Type type, NVPairMap &nvpairs,
+ const std::string eventString) const;
+
+ EventFactory(Event::BuildMethod *defaultBuildMethod = NULL);
+
+ void UpdateRegistry(Record regEntries[], size_t numEntries);
+
+
+protected:
+ /** Registry of event factory methods providing O(log(n)) lookup. */
+ Registry m_registry;
+
+ Event::BuildMethod *m_defaultBuildMethod;
+};
+
+inline const EventFactory::Registry &
+EventFactory::GetRegistry() const
+{
+ return (m_registry);
+}
+
+} // namespace DevdCtl
+#endif /*_DEVDCTL_EVENT_FACTORY_H_ */
diff --git a/lib/libdevdctl/exception.cc b/lib/libdevdctl/exception.cc
new file mode 100644
index 0000000..4dc8cf5
--- /dev/null
+++ b/lib/libdevdctl/exception.cc
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013, 2014 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ */
+
+/**
+ * \file exception.cc
+ */
+#include <sys/cdefs.h>
+
+#include <syslog.h>
+
+#include <cstdio>
+#include <cstdarg>
+#include <sstream>
+#include <string>
+
+#include "exception.h"
+
+__FBSDID("$FreeBSD$");
+
+/*============================ Namespace Control =============================*/
+using std::string;
+using std::stringstream;
+using std::endl;
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*--------------------------------- Exception --------------------------------*/
+void
+Exception::FormatLog(const char *fmt, va_list ap)
+{
+ char buf[256];
+
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ m_log = buf;
+}
+
+Exception::Exception(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ FormatLog(fmt, ap);
+ va_end(ap);
+}
+
+Exception::Exception()
+{
+}
+
+void
+Exception::Log() const
+{
+ syslog(LOG_ERR, "%s", m_log.c_str());
+}
+
+/*------------------------------ ParseException ------------------------------*/
+//- ParseException Inline Public Methods ---------------------------------------
+ParseException::ParseException(Type type, const std::string &parsedBuffer,
+ size_t offset)
+ : Exception(),
+ m_type(type),
+ m_parsedBuffer(parsedBuffer),
+ m_offset(offset)
+{
+ stringstream logstream;
+
+ logstream << "Parsing ";
+
+ switch (Type()) {
+ case INVALID_FORMAT:
+ logstream << "invalid format ";
+ break;
+ case DISCARDED_EVENT_TYPE:
+ logstream << "discarded event ";
+ break;
+ case UNKNOWN_EVENT_TYPE:
+ logstream << "unknown event ";
+ break;
+ default:
+ break;
+ }
+ logstream << "exception on buffer: \'";
+ if (GetOffset() == 0) {
+ logstream << m_parsedBuffer << '\'' << endl;
+ } else {
+ string markedBuffer(m_parsedBuffer);
+
+ markedBuffer.insert(GetOffset(), "<HERE-->");
+ logstream << markedBuffer << '\'' << endl;
+ }
+
+ GetString() = logstream.str();
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/exception.h b/lib/libdevdctl/exception.h
new file mode 100644
index 0000000..9f4403c
--- /dev/null
+++ b/lib/libdevdctl/exception.h
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Justin T. Gibbs (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file zfsd_exception.h
+ *
+ * Definition of the ZfsdException class hierarchy. All exceptions
+ * explicitly thrown by Zfsd are defined here.
+ */
+#ifndef _DEVDCTL_EXCEPTION_H_
+#define _DEVDCTL_EXCEPTION_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+
+/*--------------------------------- Exception --------------------------------*/
+/**
+ * \brief Class allowing unified reporting/logging of exceptional events.
+ */
+class Exception
+{
+public:
+ /**
+ * \brief Exception constructor allowing arbitrary string
+ * data to be reported.
+ *
+ * \param fmt Printf-like string format specifier.
+ */
+ Exception(const char *fmt, ...);
+
+ /**
+ * \brief Augment/Modify a Exception's string data.
+ */
+ std::string& GetString();
+
+ /**
+ * \brief Emit exception data to syslog(3).
+ */
+ virtual void Log() const;
+
+protected:
+ Exception();
+
+ /**
+ * \brief Convert exception string format and arguments provided
+ * in event constructors into a linear string.
+ */
+ void FormatLog(const char *fmt, va_list ap);
+
+ std::string m_log;
+};
+
+inline std::string &
+Exception::GetString()
+{
+ return (m_log);
+}
+
+/*------------------------------ ParseException ------------------------------*/
+/**
+ * Exception thrown when an event string is not converted to an actionable
+ * Event object.
+ */
+class ParseException : public Exception
+{
+public:
+ enum Type
+ {
+ /** Improperly formatted event string encountered. */
+ INVALID_FORMAT,
+
+ /** No handlers for this event type. */
+ DISCARDED_EVENT_TYPE,
+
+ /** Unhandled event type. */
+ UNKNOWN_EVENT_TYPE
+ };
+
+ /**
+ * Constructor
+ *
+ * \param type The type of this exception.
+ * \param parsedBuffer The parsing buffer active at the time of
+ * the exception.
+ * \param offset The location in the parse buffer where this
+ * exception occurred.
+ */
+ ParseException(Type type, const std::string &parsedBuffer,
+ size_t offset = 0);
+
+ /**
+ * Accessor
+ *
+ * \return The classification for this exception.
+ */
+ Type GetType() const;
+
+ /**
+ * Accessor
+ *
+ * \return The offset into the event string where this exception
+ * occurred.
+ */
+ size_t GetOffset() const;
+
+private:
+ /** The type of this exception. */
+ Type m_type;
+
+ /** The parsing buffer that was active at the time of the exception. */
+ const std::string m_parsedBuffer;
+
+ /**
+ * The offset into the event string buffer from where this
+ * exception was triggered.
+ */
+ size_t m_offset;
+};
+
+//- ParseException Inline Const Public Methods ---------------------------------
+inline ParseException::Type
+ParseException::GetType() const
+{
+ return (m_type);
+}
+
+inline size_t
+ParseException::GetOffset() const
+{
+ return (m_offset);
+}
+
+} // namespace DevdCtl
+#endif /* _DEVDCTL_EXCEPTION_H_ */
diff --git a/lib/libdevdctl/guid.cc b/lib/libdevdctl/guid.cc
new file mode 100644
index 0000000..42d326f
--- /dev/null
+++ b/lib/libdevdctl/guid.cc
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file guid.cc
+ *
+ * Implementation of the Guid class.
+ */
+#include <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
+
+#include <iostream>
+#include <string>
+
+#include "guid.h"
+
+__FBSDID("$FreeBSD$");
+/*============================ Namespace Control =============================*/
+using std::string;
+namespace DevdCtl
+{
+
+/*=========================== Class Implementations ==========================*/
+/*----------------------------------- Guid -----------------------------------*/
+Guid::Guid(const string &guidString)
+{
+ if (guidString.empty()) {
+ m_GUID = INVALID_GUID;
+ } else {
+ /*
+ * strtoumax() returns zero on conversion failure
+ * which nicely matches our choice for INVALID_GUID.
+ */
+ m_GUID = (uint64_t)strtoumax(guidString.c_str(), NULL, 0);
+ }
+}
+
+std::ostream&
+operator<< (std::ostream& out, Guid g)
+{
+ if (g.IsValid())
+ out << (uint64_t)g;
+ else
+ out << "None";
+ return (out);
+}
+
+} // namespace DevdCtl
diff --git a/lib/libdevdctl/guid.h b/lib/libdevdctl/guid.h
new file mode 100644
index 0000000..ede414b
--- /dev/null
+++ b/lib/libdevdctl/guid.h
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2012, 2013 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * \file devdctl_guid.h
+ *
+ * Definition of the Guid class.
+ */
+#ifndef _DEVDCTL_GUID_H_
+#define _DEVDCTL_GUID_H_
+
+/*============================ Namespace Control =============================*/
+namespace DevdCtl
+{
+
+/*============================= Class Definitions ============================*/
+/*----------------------------------- Guid -----------------------------------*/
+/**
+ * \brief Object that represents guids.
+ *
+ * It can generally be manipulated as a uint64_t, but with a special
+ * value INVALID_GUID that does not equal any valid guid.
+ *
+ * As of this writing, this class is only used to represent ZFS
+ * guids in events and spa_generate_guid() in spa_misc.c explicitly
+ * refuses to return a guid of 0. So this class uses 0 as the value
+ * for INVALID_GUID. In the future, if 0 is allowed to be a valid
+ * guid, the implementation of this class must change.
+ */
+class Guid
+{
+public:
+ /* Constructors */
+ Guid();
+ Guid(uint64_t guid);
+ Guid(const std::string &guid);
+
+ /* Assignment */
+ Guid& operator=(const Guid& rhs);
+
+ /* Test the validity of this guid. */
+ bool IsValid() const;
+
+ /* Comparison to other Guid operators */
+ bool operator==(const Guid& rhs) const;
+ bool operator!=(const Guid& rhs) const;
+
+ /* Integer conversion operators */
+ operator uint64_t() const;
+ operator bool() const;
+
+ static const uint64_t INVALID_GUID = 0;
+protected:
+ /* The integer value of the GUID. */
+ uint64_t m_GUID;
+};
+
+//- Guid Inline Public Methods ------------------------------------------------
+inline
+Guid::Guid()
+ : m_GUID(INVALID_GUID)
+{
+}
+
+inline
+Guid::Guid(uint64_t guid)
+ : m_GUID(guid)
+{
+}
+
+inline Guid&
+Guid::operator=(const Guid &rhs)
+{
+ m_GUID = rhs.m_GUID;
+ return (*this);
+}
+
+inline bool
+Guid::IsValid() const
+{
+ return (m_GUID != INVALID_GUID);
+}
+
+inline bool
+Guid::operator==(const Guid& rhs) const
+{
+ return (m_GUID == rhs.m_GUID);
+}
+
+inline bool
+Guid::operator!=(const Guid& rhs) const
+{
+ return (m_GUID != rhs.m_GUID);
+}
+
+inline
+Guid::operator uint64_t() const
+{
+ return (m_GUID);
+}
+
+inline
+Guid::operator bool() const
+{
+ return (m_GUID != INVALID_GUID);
+}
+
+/** Convert the GUID into its string representation */
+std::ostream& operator<< (std::ostream& out, Guid g);
+
+} // namespace DevdCtl
+#endif /* _DEVDCTL_GUID_H_ */
diff --git a/lib/libdevdctl/tests/Makefile b/lib/libdevdctl/tests/Makefile
new file mode 100644
index 0000000..3bbbd0d
--- /dev/null
+++ b/lib/libdevdctl/tests/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/lib/libdevdctl
+
+.PATH: ${.CURDIR}/..
+
+PLAIN_TESTS_CXX= libdevdctl_unittest
+
+SRCS.libdevdctl_unittest+= event_factory.cc \
+ libdevdctl_unittest.cc \
+ event.cc exception.cc \
+ guid.cc
+CFLAGS.libdevdctl_unittest+= -I ${LOCALBASE}/include -D_THREAD_SAFE -pthread
+DPADD.libdevdctl_unittest+= ${LIBDEVDCTL}
+LDADD.libdevdctl_unittest+= -L ${LOCALBASE}/lib -D_THREAD_SAFE -pthread -lgtest -lgtest_main
+
+# Googletest options
+LOCALBASE?= /usr/local
+
+WARNS?= 3
+.include <bsd.test.mk>
diff --git a/lib/libdevdctl/tests/libdevdctl_unittest.cc b/lib/libdevdctl/tests/libdevdctl_unittest.cc
new file mode 100644
index 0000000..4f69cb6
--- /dev/null
+++ b/lib/libdevdctl/tests/libdevdctl_unittest.cc
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 2016 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Alan Somers (Spectra Logic Corporation)
+ *
+ * $FreeBSD$
+ */
+
+#include <gtest/gtest.h>
+
+#include <list>
+#include <map>
+#include <string>
+
+#include <devdctl/guid.h>
+#include <devdctl/event.h>
+#include <devdctl/event_factory.h>
+
+using namespace DevdCtl;
+using namespace std;
+using namespace testing;
+
+#define REGISTRY_SIZE 2
+
+struct DevNameTestParams
+{
+ const char* evs;
+ bool is_disk;
+ const char* devname;
+};
+
+class DevNameTest : public TestWithParam<DevNameTestParams>{
+protected:
+ virtual void SetUp()
+ {
+ m_factory = new EventFactory();
+ m_factory->UpdateRegistry(s_registry, REGISTRY_SIZE);
+ }
+
+ virtual void TearDown()
+ {
+ if (m_ev) delete m_ev;
+ if (m_factory) delete m_factory;
+ }
+
+ EventFactory *m_factory;
+ Event *m_ev;
+ static EventFactory::Record s_registry[REGISTRY_SIZE];
+};
+
+DevdCtl::EventFactory::Record DevNameTest::s_registry[REGISTRY_SIZE] = {
+ { Event::NOTIFY, "DEVFS", &DevfsEvent::Builder },
+ { Event::NOTIFY, "GEOM", &GeomEvent::Builder }
+};
+
+TEST_P(DevNameTest, TestDevname) {
+ std::string devname;
+ DevNameTestParams param = GetParam();
+
+ string evString(param.evs);
+ m_ev = Event::CreateEvent(*m_factory, evString);
+ m_ev->DevName(devname);
+ EXPECT_STREQ(param.devname, devname.c_str());
+}
+
+TEST_P(DevNameTest, TestIsDiskDev) {
+ DevNameTestParams param = GetParam();
+
+ string evString(param.evs);
+ m_ev = Event::CreateEvent(*m_factory, evString);
+ EXPECT_EQ(param.is_disk, m_ev->IsDiskDev());
+}
+
+/* TODO: clean this up using C++-11 uniform initializers */
+INSTANTIATE_TEST_CASE_P(IsDiskDevTestInstantiation, DevNameTest, Values(
+ (DevNameTestParams){
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=da6\n",
+ .is_disk = true, .devname = "da6"},
+ (DevNameTestParams){.is_disk = false, .devname = "cuau0",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=cuau0\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "ada6",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=ada6\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "da6p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=da6p1\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "ada6p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=ada6p1\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "da6s0p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=da6s0p1\n"},
+ (DevNameTestParams){.is_disk = true, .devname = "ada6s0p1",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=ada6s0p1\n"},
+ /*
+ * Test physical path nodes. These are currently all set to false since
+ * physical path nodes are implemented with symlinks, and most CAM and
+ * ZFS operations can't use symlinked device nodes
+ */
+ /* A SpectraBSD-style physical path node*/
+ (DevNameTestParams){.is_disk = false, .devname = "enc@50030480019f53fd/elmtype@array_device/slot@18/da",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@50030480019f53fd/elmtype@array_device/slot@18/da\n"},
+ (DevNameTestParams){.is_disk = false, .devname = "enc@50030480019f53fd/elmtype@array_device/slot@18/pass",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@50030480019f53fd/elmtype@array_device/slot@18/pass\n"},
+ /* A FreeBSD-style physical path node */
+ (DevNameTestParams){.is_disk = true, .devname = "enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/da6",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/da6\n"},
+ (DevNameTestParams){.is_disk = false, .devname = "enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/pass6",
+ .evs = "!system=DEVFS subsystem=CDEV type=CREATE cdev=enc@n50030480019f53fd/type@0/slot@18/elmdesc@ArrayDevice18/pass6\n"},
+
+ /*
+ * Test some GEOM events
+ */
+ (DevNameTestParams){.is_disk = true, .devname = "da5",
+ .evs = "!system=GEOM subsystem=disk type=GEOM::physpath devname=da5\n"})
+);
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index f80404d..0c575d0 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -114,6 +114,7 @@ __FBSDID("$FreeBSD$");
#define HTTP_REDIRECT(xyz) ((xyz) == HTTP_MOVED_PERM \
|| (xyz) == HTTP_MOVED_TEMP \
|| (xyz) == HTTP_TEMP_REDIRECT \
+ || (xyz) == HTTP_PERM_REDIRECT \
|| (xyz) == HTTP_USE_PROXY \
|| (xyz) == HTTP_SEE_OTHER)
@@ -1767,6 +1768,8 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
break;
case HTTP_MOVED_PERM:
case HTTP_MOVED_TEMP:
+ case HTTP_TEMP_REDIRECT:
+ case HTTP_PERM_REDIRECT:
case HTTP_SEE_OTHER:
case HTTP_USE_PROXY:
/*
diff --git a/lib/libmd/Makefile b/lib/libmd/Makefile
index bde4fb5..bb50623 100644
--- a/lib/libmd/Makefile
+++ b/lib/libmd/Makefile
@@ -9,12 +9,15 @@ SRCS= md4c.c md5c.c md4hl.c md5hl.c \
sha0c.c sha0hl.c sha1c.c sha1hl.c \
sha256c.c sha256hl.c \
sha384hl.c \
- sha512c.c sha512hl.c
-INCS= md4.h md5.h ripemd.h sha.h sha256.h sha384.h sha512.h
+ sha512c.c sha512hl.c sha512thl.c \
+ skein.c skein_block.c \
+ skein256hl.c skein512hl.c skein1024hl.c
+INCS= md4.h md5.h ripemd.h sha.h sha256.h sha384.h sha512.h sha512t.h \
+ skein.h skein_port.h skein_freebsd.h skein_iv.h
WARNS?= 0
-MAN+= md4.3 md5.3 ripemd.3 sha.3 sha256.3 sha512.3
+MAN+= md4.3 md5.3 ripemd.3 sha.3 sha256.3 sha512.3 skein.3
MLINKS+=md4.3 MD4Init.3 md4.3 MD4Update.3 md4.3 MD4Final.3
MLINKS+=md4.3 MD4End.3 md4.3 MD4File.3 md4.3 MD4FileChunk.3
MLINKS+=md4.3 MD4Data.3
@@ -43,11 +46,31 @@ MLINKS+=sha512.3 SHA512_Init.3 sha512.3 SHA512_Update.3
MLINKS+=sha512.3 SHA512_Final.3 sha512.3 SHA512_End.3
MLINKS+=sha512.3 SHA512_File.3 sha512.3 SHA512_FileChunk.3
MLINKS+=sha512.3 SHA512_Data.3
+MLINKS+=sha512.3 SHA512_256_Init.3 sha512.3 SHA512_256_Update.3
+MLINKS+=sha512.3 SHA512_256_Final.3 sha512.3 SHA512_256_End.3
+MLINKS+=sha512.3 SHA512_256_File.3 sha512.3 SHA512_256_FileChunk.3
+MLINKS+=sha512.3 SHA512_256_Data.3
+MLINKS+=skein.3 SKEIN256_Init.3 skein.3 SKEIN256_Update.3
+MLINKS+=skein.3 SKEIN256_Final.3 skein.3 SKEIN256_End.3
+MLINKS+=skein.3 SKEIN256_File.3 skein.3 SKEIN256_FileChunk.3
+MLINKS+=skein.3 SKEIN256_Data.3 skein.3 skein256.3
+MLINKS+=skein.3 SKEIN512_Init.3 skein.3 SKEIN512_Update.3
+MLINKS+=skein.3 SKEIN512_Final.3 skein.3 SKEIN512_End.3
+MLINKS+=skein.3 SKEIN512_File.3 skein.3 SKEIN512_FileChunk.3
+MLINKS+=skein.3 SKEIN512_Data.3 skein.3 skein512.3
+MLINKS+=skein.3 SKEIN1024_Init.3 skein.3 SKEIN1024_Update.3
+MLINKS+=skein.3 SKEIN1024_Final.3 skein.3 SKEIN1024_End.3
+MLINKS+=skein.3 SKEIN1024_File.3 skein.3 SKEIN1024_FileChunk.3
+MLINKS+=skein.3 SKEIN1024_Data.3 skein.3 skein1024.3
+
CLEANFILES+= md[245]hl.c md[245].ref md[245].3 mddriver \
rmd160.ref rmd160hl.c rmddriver \
sha0.ref sha0hl.c sha1.ref sha1hl.c shadriver \
sha256.ref sha256hl.c sha384hl.c sha384.ref \
- sha512.ref sha512hl.c
+ sha512.ref sha512hl.c sha512t256.ref sha512thl.c \
+ skein256hl.c skein512hl.c skein1024hl.c \
+ skein256.ref skein512.ref skein1024.ref \
+ skeindriver
# Define WEAK_REFS to provide weak aliases for libmd symbols
#
@@ -56,8 +79,10 @@ CLEANFILES+= md[245]hl.c md[245].ref md[245].3 mddriver \
# * macros are used to rename symbols to libcrypt internal names
# * no weak aliases are generated
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys/crypto/sha2
+CFLAGS+= -I${.CURDIR}/../../sys/crypto/skein
CFLAGS+= -DWEAK_REFS
.PATH: ${.CURDIR}/${MACHINE_ARCH} ${.CURDIR}/../../sys/crypto/sha2
+.PATH: ${.CURDIR}/../../sys/crypto/skein ${.CURDIR}/../../sys/crypto/skein/${MACHINE_ARCH}
.if exists(${MACHINE_ARCH}/sha.S)
SRCS+= sha.S
@@ -67,7 +92,11 @@ CFLAGS+= -DSHA1_ASM
SRCS+= rmd160.S
CFLAGS+= -DRMD160_ASM
.endif
-.if exists(${MACHINE_ARCH}/sha.S) || exists(${MACHINE_ARCH}/rmd160.S)
+.if exists(${MACHINE_ARCH}/skein_block_asm.s)
+SRCS+= skein_block_asm.s
+CFLAGS+= -DSKEIN_ASM -DSKEIN_USE_ASM=1792 # list of block functions to replace with assembly: 256+512+1024 = 1792
+.endif
+.if exists(${MACHINE_ARCH}/sha.S) || exists(${MACHINE_ARCH}/rmd160.S) || exists(${MACHINE_ARCH}/skein_block_asm.s)
ACFLAGS+= -DELF -Wa,--noexecstack
.endif
@@ -107,12 +136,38 @@ sha512hl.c: mdXhl.c
-e 's/SHA512__/SHA512_/g' \
${.ALLSRC}) > ${.TARGET}
+sha512thl.c: mdXhl.c
+ (echo '#define LENGTH 32'; \
+ sed -e 's/mdX/sha512t/g' -e 's/MDX/SHA512_256_/g' \
+ -e 's/SHA512_256__/SHA512_256_/g' \
+ -e 's/SHA512_256_CTX/SHA512_CTX/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
rmd160hl.c: mdXhl.c
(echo '#define LENGTH 20'; \
sed -e 's/mdX/ripemd/g' -e 's/MDX/RIPEMD160_/g' \
-e 's/RIPEMD160__/RIPEMD160_/g' \
${.ALLSRC}) > ${.TARGET}
+skein256hl.c: mdXhl.c
+ (echo '#define LENGTH 32'; \
+ sed -e 's/mdX/skein/g' -e 's/MDX/SKEIN256_/g' \
+ -e 's/SKEIN256__/SKEIN256_/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
+skein512hl.c: mdXhl.c
+ (echo '#define LENGTH 64'; \
+ sed -e 's/mdX/skein/g' -e 's/MDX/SKEIN512_/g' \
+ -e 's/SKEIN512__/SKEIN512_/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
+skein1024hl.c: mdXhl.c
+ (echo '#define LENGTH 128'; \
+ sed -e 's/mdX/skein/g' -e 's/MDX/SKEIN1024_/g' \
+ -e 's/SKEIN1024__/SKEIN1024_/g' \
+ ${.ALLSRC}) > ${.TARGET}
+
+
.for i in 2 4 5
md${i}.3: ${.CURDIR}/mdX.3
sed -e "s/mdX/md${i}/g" -e "s/MDX/MD${i}/g" ${.ALLSRC} > ${.TARGET}
@@ -211,6 +266,21 @@ sha512.ref:
@echo 'SHA-512 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
'72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843' >> ${.TARGET}
+sha512t256.ref:
+ echo 'SHA-512256 test suite:' > ${.TARGET}
+ @echo 'SHA-512256 ("") =' \
+ 'c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a' >> ${.TARGET}
+ @echo 'SHA-512256 ("abc") =' \
+ '53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23' >> ${.TARGET}
+ @echo 'SHA-512256 ("message digest") =' \
+ '0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb' >> ${.TARGET}
+ @echo 'SHA-512256 ("abcdefghijklmnopqrstuvwxyz") =' \
+ 'fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26' >> ${.TARGET}
+ @echo 'SHA-512256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ 'cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8' >> ${.TARGET}
+ @echo 'SHA-512256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ '2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148' >> ${.TARGET}
+
rmd160.ref:
echo 'RIPEMD160 test suite:' > ${.TARGET}
@echo 'RIPEMD160 ("") = 9c1185a5c5e9fc54612808977ee8f548b2258d31' >> ${.TARGET}
@@ -224,8 +294,51 @@ rmd160.ref:
@echo 'RIPEMD160 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
'9b752e45573d4b39f4dbd3323cab82bf63326bfb' >> ${.TARGET}
+skein256.ref:
+ echo 'SKEIN256 test suite:' > ${.TARGET}
+ @echo 'SKEIN256 ("") = c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba' >> ${.TARGET}
+ @echo 'SKEIN256 ("abc") = 258bdec343b9fde1639221a5ae0144a96e552e5288753c5fec76c05fc2fc1870' >> ${.TARGET}
+ @echo 'SKEIN256 ("message digest") =' \
+ '4d2ce0062b5eb3a4db95bc1117dd8aa014f6cd50fdc8e64f31f7d41f9231e488' >> ${.TARGET}
+ @echo 'SKEIN256 ("abcdefghijklmnopqrstuvwxyz") =' \
+ '46d8440685461b00e3ddb891b2ecc6855287d2bd8834a95fb1c1708b00ea5e82' >> ${.TARGET}
+ @echo 'SKEIN256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ '7c5eb606389556b33d34eb2536459528dc0af97adbcd0ce273aeb650f598d4b2' >> ${.TARGET}
+ @echo 'SKEIN256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ '4def7a7e5464a140ae9c3a80279fbebce4bd00f9faad819ab7e001512f67a10d' >> ${.TARGET}
+
+skein512.ref:
+ echo 'SKEIN512 test suite:' > ${.TARGET}
+ @echo 'SKEIN512 ("") =' \
+ 'bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a' >> ${.TARGET}
+ @echo 'SKEIN512 ("abc") =' \
+ '8f5dd9ec798152668e35129496b029a960c9a9b88662f7f9482f110b31f9f93893ecfb25c009baad9e46737197d5630379816a886aa05526d3a70df272d96e75' >> ${.TARGET}
+ @echo 'SKEIN512 ("message digest") =' \
+ '15b73c158ffb875fed4d72801ded0794c720b121c0c78edf45f900937e6933d9e21a3a984206933d504b5dbb2368000411477ee1b204c986068df77886542fcc' >> ${.TARGET}
+ @echo 'SKEIN512 ("abcdefghijklmnopqrstuvwxyz") =' \
+ '23793ad900ef12f9165c8080da6fdfd2c8354a2929b8aadf83aa82a3c6470342f57cf8c035ec0d97429b626c4d94f28632c8f5134fd367dca5cf293d2ec13f8c' >> ${.TARGET}
+ @echo 'SKEIN512 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ '0c6bed927e022f5ddcf81877d42e5f75798a9f8fd3ede3d83baac0a2f364b082e036c11af35fe478745459dd8f5c0b73efe3c56ba5bb2009208d5a29cc6e469c' >> ${.TARGET}
+ @echo 'SKEIN512 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ '2ca9fcffb3456f297d1b5f407014ecb856f0baac8eb540f534b1f187196f21e88f31103128c2f03fcc9857d7a58eb66f9525e2302d88833ee069295537a434ce' >> ${.TARGET}
+
+skein1024.ref:
+ echo 'SKEIN1024 test suite:' > ${.TARGET}
+ @echo 'SKEIN1024 ("") =' \
+ '0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6' >> ${.TARGET}
+ @echo 'SKEIN1024 ("abc") =' \
+ '35a599a0f91abcdb4cb73c19b8cb8d947742d82c309137a7caed29e8e0a2ca7a9ff9a90c34c1908cc7e7fd99bb15032fb86e76df21b72628399b5f7c3cc209d7bb31c99cd4e19465622a049afbb87c03b5ce3888d17e6e667279ec0aa9b3e2712624c01b5f5bbe1a564220bdcf6990af0c2539019f313fdd7406cca3892a1f1f' >> ${.TARGET}
+ @echo 'SKEIN1024 ("message digest") =' \
+ 'ea891f5268acd0fac97467fc1aa89d1ce8681a9992a42540e53babee861483110c2d16f49e73bac27653ff173003e40cfb08516cd34262e6af95a5d8645c9c1abb3e813604d508b8511b30f9a5c1b352aa0791c7d2f27b2706dccea54bc7de6555b5202351751c3299f97c09cf89c40f67187e2521c0fad82b30edbb224f0458' >> ${.TARGET}
+ @echo 'SKEIN1024 ("abcdefghijklmnopqrstuvwxyz") =' \
+ 'f23d95c2a25fbcd0e797cd058fec39d3c52d2b5afd7a9af1df934e63257d1d3dcf3246e7329c0f1104c1e51e3d22e300507b0c3b9f985bb1f645ef49835080536becf83788e17fed09c9982ba65c3cb7ffe6a5f745b911c506962adf226e435c42f6f6bc08d288f9c810e807e3216ef444f3db22744441deefa4900982a1371f' >> ${.TARGET}
+ @echo 'SKEIN1024 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =' \
+ 'cf3889e8a8d11bfd3938055d7d061437962bc5eac8ae83b1b71c94be201b8cf657fdbfc38674997a008c0c903f56a23feb3ae30e012377f1cfa080a9ca7fe8b96138662653fb3335c7d06595bf8baf65e215307532094cfdfa056bd8052ab792a3944a2adaa47b30335b8badb8fe9eb94fe329cdca04e58bbc530f0af709f469' >> ${.TARGET}
+ @echo 'SKEIN1024 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") =' \
+ 'cf21a613620e6c119eca31fdfaad449a8e02f95ca256c21d2a105f8e4157048f9fe1e897893ea18b64e0e37cb07d5ac947f27ba544caf7cbc1ad094e675aed77a366270f7eb7f46543bccfa61c526fd628408058ed00ed566ac35a9761d002e629c4fb0d430b2f4ad016fcc49c44d2981c4002da0eecc42144160e2eaea4855a' >> ${.TARGET}
+
test: md4.ref md5.ref sha0.ref rmd160.ref sha1.ref sha256.ref sha384.ref \
- sha512.ref
+ sha512.ref sha512t256.ref skein256.ref skein512.ref skein1024.ref
@${ECHO} if any of these test fail, the code produces wrong results
@${ECHO} and should NOT be used.
${CC} ${CFLAGS} ${LDFLAGS} -DMD=4 -o mddriver ${.CURDIR}/mddriver.c libmd.a
@@ -254,6 +367,19 @@ test: md4.ref md5.ref sha0.ref rmd160.ref sha1.ref sha256.ref sha384.ref \
${CC} ${CFLAGS} ${LDFLAGS} -DSHA=512 -o shadriver ${.CURDIR}/shadriver.c libmd.a
./shadriver | cmp sha512.ref -
@${ECHO} SHA-512 passed test
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSHA=512256 -o shadriver ${.CURDIR}/shadriver.c libmd.a
+ ./shadriver | cmp sha512t256.ref -
+ @${ECHO} SHA-512t256 passed test
-rm -f shadriver
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSKEIN=256 -o skeindriver ${.CURDIR}/skeindriver.c libmd.a
+ ./skeindriver | cmp skein256.ref -
+ @${ECHO} SKEIN256 passed test
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSKEIN=512 -o skeindriver ${.CURDIR}/skeindriver.c libmd.a
+ ./skeindriver | cmp skein512.ref -
+ @${ECHO} SKEIN512 passed test
+ ${CC} ${CFLAGS} ${LDFLAGS} -DSKEIN=1024 -o skeindriver ${.CURDIR}/skeindriver.c libmd.a
+ ./skeindriver | cmp skein1024.ref -
+ @${ECHO} SKEIN1024 passed test
+ -rm -f skeindriver
.include <bsd.lib.mk>
diff --git a/lib/libmd/mdX.3 b/lib/libmd/mdX.3
index 4cc321f..daa5c36 100644
--- a/lib/libmd/mdX.3
+++ b/lib/libmd/mdX.3
@@ -8,7 +8,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 11, 1999
+.Dd April 26, 2016
.Dt MDX 3
.Os
.Sh NAME
@@ -145,7 +145,11 @@ argument is non-null it must point to at least 33 characters of buffer space.
.Sh SEE ALSO
.Xr md4 3 ,
.Xr md5 3 ,
-.Xr sha 3
+.Xr ripemd 3 ,
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Rs
.%A R. Rivest
.%T The MD4 Message-Digest Algorithm
diff --git a/lib/libmd/ripemd.3 b/lib/libmd/ripemd.3
index 2c9d2d3..8e868b8 100644
--- a/lib/libmd/ripemd.3
+++ b/lib/libmd/ripemd.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd March 28, 2014
+.Dd April 26, 2016
.Dt RIPEMD 3
.Os
.Sh NAME
@@ -125,7 +125,10 @@ argument is non-null it must point to at least 41 characters of buffer space.
.Sh SEE ALSO
.Xr md4 3 ,
.Xr md5 3 ,
-.Xr sha 3
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 4.0 .
diff --git a/lib/libmd/sha.3 b/lib/libmd/sha.3
index fe5c339..95c0603 100644
--- a/lib/libmd/sha.3
+++ b/lib/libmd/sha.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd March 28, 2014
+.Dd April 26, 2016
.Dt SHA 3
.Os
.Sh NAME
@@ -157,7 +157,9 @@ argument is non-null it must point to at least 41 characters of buffer space.
.Xr md4 3 ,
.Xr md5 3 ,
.Xr ripemd 3 ,
-.Xr sha256 3
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 4.0 .
diff --git a/lib/libmd/sha256.3 b/lib/libmd/sha256.3
index 6117e70..530c644 100644
--- a/lib/libmd/sha256.3
+++ b/lib/libmd/sha256.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd March 28, 2014
+.Dd April 26, 2016
.Dt SHA256 3
.Os
.Sh NAME
@@ -123,7 +123,10 @@ argument is non-null it must point to at least 65 characters of buffer space.
.Xr md4 3 ,
.Xr md5 3 ,
.Xr ripemd 3 ,
-.Xr sha 3
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 6.0 .
diff --git a/lib/libmd/sha512.3 b/lib/libmd/sha512.3
index d6b3aaf..d718ada 100644
--- a/lib/libmd/sha512.3
+++ b/lib/libmd/sha512.3
@@ -9,7 +9,7 @@
.\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp
.\" $FreeBSD$
.\"
-.Dd October 17, 2015
+.Dd April 22, 2016
.Dt SHA512 3
.Os
.Sh NAME
@@ -26,7 +26,14 @@
.Nm SHA384_End ,
.Nm SHA384_File ,
.Nm SHA384_FileChunk ,
-.Nm SHA384_Data
+.Nm SHA384_Data,
+.Nm SHA512_256_Init ,
+.Nm SHA512_256_Update ,
+.Nm SHA512_256_Final ,
+.Nm SHA512_256_End ,
+.Nm SHA512_256_File ,
+.Nm SHA512_256_FileChunk ,
+.Nm SHA512_256_Data
.Nd calculate the FIPS 180-4 ``SHA-512'' family of message digests
.Sh LIBRARY
.Lb libmd
@@ -47,6 +54,7 @@
.Fn SHA512_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
.Ft "char *"
.Fn SHA512_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.In sha384.h
.Ft void
.Fn SHA384_Init "SHA384_CTX *context"
.Ft void
@@ -61,6 +69,21 @@
.Fn SHA384_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
.Ft "char *"
.Fn SHA384_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.In sha512t.h
+.Ft void
+.Fn SHA512_256_Init "SHA512_CTX *context"
+.Ft void
+.Fn SHA512_256_Update "SHA512_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SHA512_256_Final "unsigned char digest[32]" "SHA512_CTX *context"
+.Ft "char *"
+.Fn SHA512_256_End "SHA512_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SHA512_256_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SHA512_256_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SHA512_256_Data "const unsigned char *data" "unsigned int len" "char *buf"
.Sh DESCRIPTION
The
.Li SHA512_
@@ -92,7 +115,7 @@ and finally extract the result using
.Fn SHA512_End
is a wrapper for
.Fn SHA512_Final
-which converts the return value to a 65-character
+which converts the return value to a 129-character
(including the terminating '\e0')
.Tn ASCII
string which represents the 512 bits in hexadecimal.
@@ -139,27 +162,40 @@ and subsequently must be explicitly deallocated using
after use.
If the
.Fa buf
-argument is non-null it must point to at least 65 characters of buffer space.
+argument is non-null it must point to at least 129 characters of buffer space.
.Pp
The
.Li SHA384_
+and
+.Li SHA512_256_
functions are identical to the
.Li SHA512_
functions except they use a different initial hash value and the output is
-truncated to 384 bits.
+truncated to 384 bits and 256 bits respectively.
.Pp
.Fn SHA384_End
is a wrapper for
.Fn SHA384_Final
-which converts the return value to a 49-character
+which converts the return value to a 97-character
(including the terminating '\e0')
.Tn ASCII
string which represents the 384 bits in hexadecimal.
+.Pp
+.Fn SHA512_256_End
+is a wrapper for
+.Fn SHA512_Final
+which converts the return value to a 65-character
+(including the terminating '\e0')
+.Tn ASCII
+string which represents the 256 bits in hexadecimal.
.Sh SEE ALSO
.Xr md4 3 ,
.Xr md5 3 ,
.Xr ripemd 3 ,
-.Xr sha 3
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3 ,
+.Xr skein 3
.Sh HISTORY
These functions appeared in
.Fx 9.0 .
diff --git a/lib/libmd/shadriver.c b/lib/libmd/shadriver.c
index e7e7b5d..b643f96 100644
--- a/lib/libmd/shadriver.c
+++ b/lib/libmd/shadriver.c
@@ -24,6 +24,7 @@ __FBSDID("$FreeBSD$");
#include "sha256.h"
#include "sha384.h"
#include "sha512.h"
+#include "sha512t.h"
/* The following makes SHA default to SHA-1 if it has not already been
* defined with C compiler flags. */
@@ -43,6 +44,9 @@ __FBSDID("$FreeBSD$");
#elif SHA == 512
#undef SHA_Data
#define SHA_Data SHA512_Data
+#elif SHA == 512256
+#undef SHA_Data
+#define SHA_Data SHA512_256_Data
#endif
/* Digests a string and prints the result. */
diff --git a/lib/libmd/skein.3 b/lib/libmd/skein.3
new file mode 100644
index 0000000..11c78a7
--- /dev/null
+++ b/lib/libmd/skein.3
@@ -0,0 +1,214 @@
+.\"-
+.\" Copyright (c) 2016 Allan Jude
+.\" 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$
+.\"
+.Dd May 28, 2016
+.Dt SKEIN 3
+.Os
+.Sh NAME
+.Nm SKEIN256_Init ,
+.Nm SKEIN256_Update ,
+.Nm SKEIN256_Final ,
+.Nm SKEIN256_End ,
+.Nm SKEIN256_File ,
+.Nm SKEIN256_FileChunk ,
+.Nm SKEIN256_Data ,
+.Nm SKEIN512_Init ,
+.Nm SKEIN512_Update ,
+.Nm SKEIN512_Final ,
+.Nm SKEIN512_End ,
+.Nm SKEIN512_File ,
+.Nm SKEIN512_FileChunk ,
+.Nm SKEIN512_Data ,
+.Nm SKEIN1024_Init ,
+.Nm SKEIN1024_Update ,
+.Nm SKEIN1024_Final ,
+.Nm SKEIN1024_End ,
+.Nm SKEIN1024_File ,
+.Nm SKEIN1024_FileChunk ,
+.Nm SKEIN1024_Data
+.Nd calculate the ``SKEIN'' family of message digests
+.Sh LIBRARY
+.Lb libmd
+.Sh SYNOPSIS
+.In sys/types.h
+.In skein.h
+.Ft void
+.Fn SKEIN256_Init "SKEIN256_CTX *context"
+.Ft void
+.Fn SKEIN256_Update "SKEIN256_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SKEIN256_Final "unsigned char digest[32]" "SKEIN256_CTX *context"
+.Ft "char *"
+.Fn SKEIN256_End "SKEIN256_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SKEIN256_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SKEIN256_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SKEIN256_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.Ft void
+.Fn SKEIN512_Init "SKEIN512_CTX *context"
+.Ft void
+.Fn SKEIN512_Update "SKEIN512_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SKEIN512_Final "unsigned char digest[64]" "SKEIN512_CTX *context"
+.Ft "char *"
+.Fn SKEIN512_End "SKEIN512_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SKEIN512_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SKEIN512_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SKEIN512_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.Ft void
+.Fn SKEIN1024_Init "SKEIN1024_CTX *context"
+.Ft void
+.Fn SKEIN1024_Update "SKEIN1024_CTX *context" "const unsigned char *data" "size_t len"
+.Ft void
+.Fn SKEIN1024_Final "unsigned char digest[128]" "SKEIN1024_CTX *context"
+.Ft "char *"
+.Fn SKEIN1024_End "SKEIN1024_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SKEIN1024_File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SKEIN1024_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
+.Ft "char *"
+.Fn SKEIN1024_Data "const unsigned char *data" "unsigned int len" "char *buf"
+.Sh DESCRIPTION
+.Li Skein
+is a new family of cryptographic hash functions based on the
+.Li Threefish
+large-block cipher.
+Its design combines speed, security, simplicity, and a great deal of
+flexibility in a modular package that is easy to analyze.
+.Li Skein
+is defined for three different internal state sizes\(em256 bits, 512 bits, and
+1024 bits\(emand any output size.
+This allows Skein to be a drop-in replacement for the entire SHA family
+of hash functions.
+.Pp
+The
+.Fn SKEIN256_Init ,
+.Fn SKEIN256_Update ,
+and
+.Fn SKEIN256_Final
+functions are the core functions.
+Allocate an
+.Vt SKEIN256_CTX ,
+initialize it with
+.Fn SKEIN256_Init ,
+run over the data with
+.Fn SKEIN256_Update ,
+and finally extract the result using
+.Fn SKEIN256_Final .
+.Pp
+.Fn SKEIN256_End
+is a wrapper for
+.Fn SKEIN256_Final
+which converts the return value to a 33-character
+(including the terminating '\e0')
+.Tn ASCII
+string which represents the 256 bits in hexadecimal.
+.Pp
+.Fn SKEIN256_File
+calculates the digest of a file, and uses
+.Fn SKEIN256_End
+to return the result.
+If the file cannot be opened, a null pointer is returned.
+.Fn SKEIN256_FileChunk
+is similar to
+.Fn SKEIN256_File ,
+but it only calculates the digest over a byte-range of the file specified,
+starting at
+.Fa offset
+and spanning
+.Fa length
+bytes.
+If the
+.Fa length
+parameter is specified as 0, or more than the length of the remaining part
+of the file,
+.Fn SKEIN256_FileChunk
+calculates the digest from
+.Fa offset
+to the end of file.
+.Fn SKEIN256_Data
+calculates the digest of a chunk of data in memory, and uses
+.Fn SKEIN256_End
+to return the result.
+.Pp
+When using
+.Fn SKEIN256_End ,
+.Fn SKEIN256_File ,
+or
+.Fn SKEIN256_Data ,
+the
+.Fa buf
+argument can be a null pointer, in which case the returned string
+is allocated with
+.Xr malloc 3
+and subsequently must be explicitly deallocated using
+.Xr free 3
+after use.
+If the
+.Fa buf
+argument is non-null it must point to at least 33 characters of buffer space.
+.Pp
+The
+.Li SKEIN512_
+and
+.Li SKEIN1024_
+functions are similar to the
+.Li SKEIN256_
+functions except they produce a 512-bit, 65 character,
+or 1024-bit, 129 character, output.
+.Sh SEE ALSO
+.Xr md4 3 ,
+.Xr md5 3 ,
+.Xr ripemd 3 ,
+.Xr sha 3 ,
+.Xr sha256 3 ,
+.Xr sha512 3
+.Sh HISTORY
+These functions appeared in
+.Fx 11.0 .
+.Sh AUTHORS
+.An -nosplit
+The core hash routines were imported from version 1.3 of the optimized
+Skein reference implementation written by
+.An Doug Whiting
+as submitted to the NSA SHA-3 contest.
+The algorithms were developed by
+.An Niels Ferguson ,
+.An Stefan Lucks ,
+.An Bruce Schneier ,
+.An Doug Whiting ,
+.An Mihir Bellare ,
+.An Tadayoshi Kohno ,
+.An Jon Callas,
+and
+.An Jesse Walker .
diff --git a/lib/libmd/skeindriver.c b/lib/libmd/skeindriver.c
new file mode 100644
index 0000000..5960457
--- /dev/null
+++ b/lib/libmd/skeindriver.c
@@ -0,0 +1,68 @@
+/* SKEINDRIVER.C - test driver for SKEIN */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights
+ * reserved.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software. */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+
+#include "skein.h"
+
+/* The following makes SKEIN default to SKEIN512 if it has not already been
+ * defined with C compiler flags. */
+#ifndef SKEIN
+#define SKEIN 512
+#endif
+
+#if SKEIN == 256
+#undef SKEIN_Data
+#define SKEIN_Data SKEIN256_Data
+#elif SKEIN == 512
+#undef SKEIN_Data
+#define SKEIN_Data SKEIN512_Data
+#elif SKEIN == 1024
+#undef SKEIN_Data
+#define SKEIN_Data SKEIN1024_Data
+#endif
+
+/* Digests a string and prints the result. */
+static void
+SKEINString(char *string)
+{
+ char buf[2*128 + 1];
+
+ printf("SKEIN%d (\"%s\") = %s\n",
+ SKEIN, string, SKEIN_Data(string, strlen(string), buf));
+}
+
+/* Digests a reference suite of strings and prints the results. */
+int
+main(void)
+{
+ printf("SKEIN%d test suite:\n", SKEIN);
+
+ SKEINString("");
+ SKEINString("abc");
+ SKEINString("message digest");
+ SKEINString("abcdefghijklmnopqrstuvwxyz");
+ SKEINString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz0123456789");
+ SKEINString("1234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890");
+
+ return 0;
+}
diff --git a/lib/libthr/libthr.3 b/lib/libthr/libthr.3
index 2b79e95..8b3f9cc 100644
--- a/lib/libthr/libthr.3
+++ b/lib/libthr/libthr.3
@@ -47,9 +47,7 @@ library provides a 1:1 implementation of the
library interfaces for application threading.
It
has been optimized for use by applications expecting system scope thread
-semantics, and can provide significant performance improvements
-compared to
-.Lb libkse .
+semantics.
.Pp
The library is tightly integrated with the run-time link editor
.Xr ld-elf.so.1 1
diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c
index 4d9356a..506b8ec 100644
--- a/lib/libthr/thread/thr_cond.c
+++ b/lib/libthr/thread/thr_cond.c
@@ -69,18 +69,18 @@ __weak_reference(_pthread_cond_destroy, pthread_cond_destroy);
__weak_reference(_pthread_cond_signal, pthread_cond_signal);
__weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast);
-#define CV_PSHARED(cvp) (((cvp)->__flags & USYNC_PROCESS_SHARED) != 0)
+#define CV_PSHARED(cvp) (((cvp)->kcond.c_flags & USYNC_PROCESS_SHARED) != 0)
static void
cond_init_body(struct pthread_cond *cvp, const struct pthread_cond_attr *cattr)
{
if (cattr == NULL) {
- cvp->__clock_id = CLOCK_REALTIME;
+ cvp->kcond.c_clockid = CLOCK_REALTIME;
} else {
if (cattr->c_pshared)
- cvp->__flags |= USYNC_PROCESS_SHARED;
- cvp->__clock_id = cattr->c_clockid;
+ cvp->kcond.c_flags |= USYNC_PROCESS_SHARED;
+ cvp->kcond.c_clockid = cattr->c_clockid;
}
}
@@ -205,9 +205,8 @@ cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
if (cancel)
_thr_cancel_enter2(curthread, 0);
- error = _thr_ucond_wait((struct ucond *)&cvp->__has_kern_waiters,
- (struct umutex *)&mp->m_lock, abstime, CVWAIT_ABSTIME |
- CVWAIT_CLOCKID);
+ error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime,
+ CVWAIT_ABSTIME | CVWAIT_CLOCKID);
if (cancel)
_thr_cancel_leave(curthread, 0);
@@ -259,7 +258,7 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
curthread = _get_curthread();
if (curthread->wchan != NULL)
- PANIC("thread was already on queue.");
+ PANIC("thread %p was already on queue.", curthread);
if (cancel)
_thr_testcancel(curthread);
@@ -292,7 +291,7 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
if (cancel)
_thr_cancel_enter2(curthread, 0);
- error = _thr_sleep(curthread, cvp->__clock_id, abstime);
+ error = _thr_sleep(curthread, cvp->kcond.c_clockid, abstime);
if (cancel)
_thr_cancel_leave(curthread, 0);
@@ -349,8 +348,7 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
if (curthread->attr.sched_policy != SCHED_OTHER ||
(mp->m_lock.m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT |
- USYNC_PROCESS_SHARED)) != 0 ||
- (cvp->__flags & USYNC_PROCESS_SHARED) != 0)
+ USYNC_PROCESS_SHARED)) != 0 || CV_PSHARED(cvp))
return (cond_wait_kernel(cvp, mp, abstime, cancel));
else
return (cond_wait_user(cvp, mp, abstime, cancel));
@@ -413,7 +411,7 @@ cond_signal_common(pthread_cond_t *cond)
pshared = CV_PSHARED(cvp);
- _thr_ucond_signal((struct ucond *)&cvp->__has_kern_waiters);
+ _thr_ucond_signal(&cvp->kcond);
if (pshared || cvp->__has_user_waiters == 0)
return (0);
@@ -496,7 +494,7 @@ cond_broadcast_common(pthread_cond_t *cond)
pshared = CV_PSHARED(cvp);
- _thr_ucond_broadcast((struct ucond *)&cvp->__has_kern_waiters);
+ _thr_ucond_broadcast(&cvp->kcond);
if (pshared || cvp->__has_user_waiters == 0)
return (0);
diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c
index e76623c..3ead7ff 100644
--- a/lib/libthr/thread/thr_exit.c
+++ b/lib/libthr/thread/thr_exit.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#ifdef _PTHREAD_FORCED_UNWIND
#include <dlfcn.h>
#endif
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
@@ -172,18 +173,31 @@ thread_unwind(void)
#endif
void
-_thread_exit(const char *fname, int lineno, const char *msg)
+_thread_exitf(const char *fname, int lineno, const char *fmt, ...)
{
+ va_list ap;
/* Write an error message to the standard error file descriptor: */
- _thread_printf(2,
- "Fatal error '%s' at line %d in file %s (errno = %d)\n",
- msg, lineno, fname, errno);
+ _thread_printf(STDERR_FILENO, "Fatal error '");
+
+ va_start(ap, fmt);
+ _thread_vprintf(STDERR_FILENO, fmt, ap);
+ va_end(ap);
+
+ _thread_printf(STDERR_FILENO, "' at line %d in file %s (errno = %d)\n",
+ lineno, fname, errno);
abort();
}
void
+_thread_exit(const char *fname, int lineno, const char *msg)
+{
+
+ _thread_exitf(fname, lineno, "%s", msg);
+}
+
+void
_pthread_exit(void *status)
{
_pthread_exit_mask(status, NULL);
@@ -195,13 +209,10 @@ _pthread_exit_mask(void *status, sigset_t *mask)
struct pthread *curthread = _get_curthread();
/* Check if this thread is already in the process of exiting: */
- if (curthread->cancelling) {
- char msg[128];
- snprintf(msg, sizeof(msg), "Thread %p has called "
+ if (curthread->cancelling)
+ PANIC("Thread %p has called "
"pthread_exit() from a destructor. POSIX 1003.1 "
"1996 s16.2.5.2 does not allow this!", curthread);
- PANIC(msg);
- }
/* Flag this thread as exiting. */
curthread->cancelling = 1;
@@ -298,7 +309,7 @@ exit_thread(void)
#if defined(_PTHREADS_INVARIANTS)
if (THR_IN_CRITICAL(curthread))
- PANIC("thread exits with resources held!");
+ PANIC("thread %p exits with resources held!", curthread);
#endif
/*
* Kernel will do wakeup at the address, so joiner thread
diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c
index 2d507e7..5a99605 100644
--- a/lib/libthr/thread/thr_mutex.c
+++ b/lib/libthr/thread/thr_mutex.c
@@ -135,13 +135,9 @@ mutex_assert_is_owned(struct pthread_mutex *m __unused)
{
#if defined(_PTHREADS_INVARIANTS)
- if (__predict_false(m->m_qe.tqe_prev == NULL)) {
- char msg[128];
- snprintf(msg, sizeof(msg),
- "mutex %p own %#x is not on list %p %p",
+ if (__predict_false(m->m_qe.tqe_prev == NULL))
+ PANIC("mutex %p own %#x is not on list %p %p",
m, m->m_lock.m_owner, m->m_qe.tqe_prev, m->m_qe.tqe_next);
- PANIC(msg);
- }
#endif
}
@@ -152,27 +148,20 @@ mutex_assert_not_owned(struct pthread *curthread __unused,
#if defined(_PTHREADS_INVARIANTS)
if (__predict_false(m->m_qe.tqe_prev != NULL ||
- m->m_qe.tqe_next != NULL)) {
- char msg[128];
- snprintf(msg, sizeof(msg),
- "mutex %p own %#x is on list %p %p",
+ m->m_qe.tqe_next != NULL))
+ PANIC("mutex %p own %#x is on list %p %p",
m, m->m_lock.m_owner, m->m_qe.tqe_prev, m->m_qe.tqe_next);
- PANIC(msg);
- }
if (__predict_false(is_robust_mutex(m) &&
(m->m_lock.m_rb_lnk != 0 || m->m_rb_prev != NULL ||
(is_pshared_mutex(m) && curthread->robust_list ==
(uintptr_t)&m->m_lock) ||
(!is_pshared_mutex(m) && curthread->priv_robust_list ==
- (uintptr_t)&m->m_lock)))) {
- char msg[128];
- snprintf(msg, sizeof(msg),
+ (uintptr_t)&m->m_lock))))
+ PANIC(
"mutex %p own %#x is on robust linkage %p %p head %p phead %p",
m, m->m_lock.m_owner, (void *)m->m_lock.m_rb_lnk,
m->m_rb_prev, (void *)curthread->robust_list,
(void *)curthread->priv_robust_list);
- PANIC(msg);
- }
#endif
}
diff --git a/lib/libthr/thread/thr_printf.c b/lib/libthr/thread/thr_printf.c
index ed94287..d38ee18 100644
--- a/lib/libthr/thread/thr_printf.c
+++ b/lib/libthr/thread/thr_printf.c
@@ -52,23 +52,35 @@ static void pstr(int fd, const char *s);
void
_thread_printf(int fd, const char *fmt, ...)
{
+ va_list ap;
+
+ va_start(ap, fmt);
+ _thread_vprintf(fd, fmt, ap);
+ va_end(ap);
+}
+
+void
+_thread_vprintf(int fd, const char *fmt, va_list ap)
+{
static const char digits[16] = "0123456789abcdef";
- va_list ap;
char buf[20];
char *s;
unsigned long r, u;
int c;
long d;
- int islong;
+ int islong, isalt;
- va_start(ap, fmt);
while ((c = *fmt++)) {
+ isalt = 0;
islong = 0;
if (c == '%') {
next: c = *fmt++;
if (c == '\0')
- goto out;
+ return;
switch (c) {
+ case '#':
+ isalt = 1;
+ goto next;
case 'c':
pchar(fd, va_arg(ap, int));
continue;
@@ -79,10 +91,13 @@ next: c = *fmt++;
islong = 1;
goto next;
case 'p':
+ pstr(fd, "0x");
islong = 1;
case 'd':
case 'u':
case 'x':
+ if (c == 'x' && isalt)
+ pstr(fd, "0x");
r = ((c == 'u') || (c == 'd')) ? 10 : 16;
if (c == 'd') {
if (islong)
@@ -111,8 +126,6 @@ next: c = *fmt++;
}
pchar(fd, c);
}
-out:
- va_end(ap);
}
/*
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 21399f3..02b575d 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -86,7 +86,7 @@ TAILQ_HEAD(mutex_queue, pthread_mutex);
/*
* Kernel fatal error handler macro.
*/
-#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
+#define PANIC(args...) _thread_exitf(__FILE__, __LINE__, ##args)
/* Output debug messages like this: */
#define stdout_debug(args...) _thread_printf(STDOUT_FILENO, ##args)
@@ -190,9 +190,7 @@ struct pthread_mutex_attr {
struct pthread_cond {
__uint32_t __has_user_waiters;
- __uint32_t __has_kern_waiters;
- __uint32_t __flags;
- __uint32_t __clock_id;
+ struct ucond kcond;
};
struct pthread_cond_attr {
@@ -780,6 +778,8 @@ void _mutex_leave_robust(struct pthread *curthread, struct pthread_mutex *m)
void _libpthread_init(struct pthread *) __hidden;
struct pthread *_thr_alloc(struct pthread *) __hidden;
void _thread_exit(const char *, int, const char *) __hidden __dead2;
+void _thread_exitf(const char *, int, const char *, ...) __hidden __dead2
+ __printflike(3, 4);
int _thr_ref_add(struct pthread *, struct pthread *, int) __hidden;
void _thr_ref_delete(struct pthread *, struct pthread *) __hidden;
void _thr_ref_delete_unlocked(struct pthread *, struct pthread *) __hidden;
@@ -791,7 +791,8 @@ void _thr_stack_free(struct pthread_attr *) __hidden;
void _thr_free(struct pthread *, struct pthread *) __hidden;
void _thr_gc(struct pthread *) __hidden;
void _thread_cleanupspecific(void) __hidden;
-void _thread_printf(int, const char *, ...) __hidden;
+void _thread_printf(int, const char *, ...) __hidden __printflike(2, 3);
+void _thread_vprintf(int, const char *, va_list) __hidden;
void _thr_spinlock_init(void) __hidden;
void _thr_cancel_enter(struct pthread *) __hidden;
void _thr_cancel_enter2(struct pthread *, int) __hidden;
diff --git a/lib/libxo/add.man b/lib/libxo/add.man
index d314685..ee79bf3 100644
--- a/lib/libxo/add.man
+++ b/lib/libxo/add.man
@@ -3,10 +3,10 @@
.Fx
uses
.Nm libxo
-version 0.6.1.
+version 0.6.2.
Complete documentation can be found on github:
.Bd -literal -offset indent
-http://juniper.github.io/libxo/0.6.1/libxo\-manual.html
+http://juniper.github.io/libxo/0.6.2/libxo\-manual.html
.Ed
.Pp
.Nm libxo
diff --git a/lib/libxo/xo_config.h b/lib/libxo/xo_config.h
index b26fded..9020b8c 100644
--- a/lib/libxo/xo_config.h
+++ b/lib/libxo/xo_config.h
@@ -183,16 +183,16 @@
/* #undef LIBXO_TEXT_ONLY */
/* Version number as dotted value */
-#define LIBXO_VERSION "0.6.1"
+#define LIBXO_VERSION "0.6.2"
/* Version number extra information */
#define LIBXO_VERSION_EXTRA ""
/* Version number as a number */
-#define LIBXO_VERSION_NUMBER 6001
+#define LIBXO_VERSION_NUMBER 6002
/* Version number as string */
-#define LIBXO_VERSION_STRING "6001"
+#define LIBXO_VERSION_STRING "6002"
/* Enable local wcwidth implementation */
#define LIBXO_WCWIDTH 1
@@ -210,7 +210,7 @@
#define PACKAGE_NAME "libxo"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libxo 0.6.1"
+#define PACKAGE_STRING "libxo 0.6.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libxo"
@@ -219,7 +219,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.6.1"
+#define PACKAGE_VERSION "0.6.2"
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@@ -233,7 +233,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "0.6.1"
+#define VERSION "0.6.2"
/* Retain hash bucket size */
/* #undef XO_RETAIN_SIZE */
OpenPOWER on IntegriCloud