Compare commits

..

64 Commits
0.5.0 ... 0.8.0

Author SHA1 Message Date
Guillem Jover
2b030da016 Release libbsd 0.8.0 2015-11-30 23:48:50 +01:00
Guillem Jover
330e211142 Update license and copyright information 2015-11-30 23:48:50 +01:00
Guillem Jover
874a0e51d3 Update arc4random module from OpenBSD and LibreSSL
Rework arc4random_stir() and arc4random_addrandom() code over the new
internal API, and documentation in the man page. Adapt the code to the
local build system.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85827
2015-11-30 23:48:50 +01:00
Guillem Jover
9a9a8b2dba Add private getentropy module from OpenBSD and LibreSSL
Adapt the code to the local build system.
2015-11-30 23:48:50 +01:00
Guillem Jover
5f9265f816 Add private SHA512 module from FreeBSD 2015-11-30 23:48:50 +01:00
Marek Vasut
1f77cdb40a Add NIOS2 support to nlist()
Add support for the NIOS2 soft-core CPU provided by Altera.

Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Guillem Jover <guillem@hadrons.org>
Cc: Ley Foon Tan <lftan@altera.com>
Cc: Thomas Chou <thomas@wytron.com.tw>
Cc: Walter Goossens <waltergoossens@home.nl>
2015-11-30 23:48:50 +01:00
Guillem Jover
f3b115540c man: Rename funopen.3 to funopen.3bsd to avoid clash with funtools
The funtools project ships a man page with the same, name. And although
it mith probably make more sense to rename the man page there, as BSD
systems will certainly not do so, this is the easiest and fastest way
to avoid a file conflict.
2015-11-30 23:48:50 +01:00
Guillem Jover
877732ef4d test: Check asprintf() return code 2015-11-30 23:48:50 +01:00
Guillem Jover
02bccb0a01 test: Add unit test for strmode() 2015-11-30 23:02:23 +01:00
Guillem Jover
58bef83f41 test: Add unit test for arc4random() 2015-11-30 23:02:23 +01:00
Guillem Jover
6e074a2bdc build: Make git log invocation immune to local configuration 2015-11-30 23:02:23 +01:00
Guillem Jover
0871daf7b0 build: Move hash/helper.c into new libbsd_la_included_sources
Use this variable in EXTRA_DIST and libbsd_la_DEPENDENCIES.
2015-11-30 04:12:02 +01:00
Guillem Jover
02c33d5022 build: Move proctitle_LDFLAGS inside BUILD_LIBBSD_CTOR conditional 2015-11-30 04:10:23 +01:00
Guillem Jover
45443583df Add explicit_bzero() function from OpenBSD 2015-09-24 05:47:58 +02:00
Guillem Jover
8641d8aed7 Make closefrom_procfs() fail when reallocarray() fails 2015-09-24 05:28:58 +02:00
Guillem Jover
0982dcd98b Lock the file streams in fgetln() and fparseln()
The fparseln() function had the NetBSD uppercase macros stubbed out,
so replace them with the actual stdio ones. The fgetln() function was
missing any locking at all.
2015-09-23 07:59:34 +02:00
Guillem Jover
ee26e59e72 Mark functions handling format strings with __printflike 2015-09-23 07:59:34 +02:00
Guillem Jover
151bc71d64 Add compile and link-time deprecation warnings for fgetln()
Although the current implementation in libbsd is probably one of the
safest ones around, it still poses some problems when used with many
file streams. This function has now a replacement, that is both more
standard and portable. Ask users to switch to getline(3) instead.
2015-09-23 07:59:34 +02:00
Guillem Jover
41ff37bbcc build: Add support for linker warnings 2015-09-23 07:59:34 +02:00
Guillem Jover
53d989a223 Switch fparseln() implementation from fgetln() to getline() 2015-09-23 07:59:34 +02:00
Guillem Jover
f50b197ea5 test: Add fparseln() unit test 2015-09-23 07:59:34 +02:00
Guillem Jover
54f153414a test: Refactor stream testing functions into a new module 2015-09-23 07:59:34 +02:00
Brent Cook
9688ab26b9 Avoid left shift overflow in reallocarray
Some 64-bit platforms (e.g. Windows 64) have a 32-bit long. So, shifting
1UL 32-bits to the left causes an overflow. This replaces the constant
1UL with (size_t)1 so that we get the correct constant size for the
platform.

Import from OpenBSD.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2015-09-23 07:59:34 +02:00
Guillem Jover
025b44800e Make mergesort setup() static 2015-09-23 07:59:34 +02:00
Guillem Jover
a6a101effa Use ANSI C prototypes 2015-09-23 07:59:34 +02:00
Guillem Jover
32388fe59f Use reallocarray() instead of malloc() or realloc() 2015-09-23 07:59:34 +02:00
Guillem Jover
30e328cbf1 Do not close file descriptors while scanning the /proc filesystem
Closing file descriptors changes the content of the fd directories in
the /proc filesystem, which means readdir() might get very confused.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85663
2015-09-23 07:59:34 +02:00
Guillem Jover
4cc43915f2 Move procfs based implementation into a new closefrom_procfs() function 2015-09-23 07:59:34 +02:00
Guillem Jover
34df142665 Refactor file descriptor closure into a new closefrom_close() 2015-09-23 07:59:34 +02:00
Guillem Jover
3881c4fc68 Update closefrom() function
Import from sudo. Adapt the build system to detect the required features.
2015-09-23 07:59:34 +02:00
Guillem Jover
3a3d87d730 test: Add closefrom() unit test 2015-09-23 07:59:34 +02:00
Guillem Jover
d62f7d8fac test: Add test case for fpurge(NULL) 2015-09-23 07:59:34 +02:00
Guillem Jover
cfb4d462a9 test: Move and activate fpurge() test case from module to a dedicated file 2015-09-23 07:59:34 +02:00
Guillem Jover
205827a2dd build: Centralize testsuite LDADD setting in a single variable 2015-09-23 07:59:34 +02:00
Guillem Jover
c7e01e9884 Sync queue(3) from FreeBSD
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85147
2015-09-23 07:59:34 +02:00
Guillem Jover
3267114483 Add __offsetof, __rangeof and __containerof to sys/cdefs.h
Import and adapt from FreeBSD.
2015-09-23 07:59:27 +02:00
Guillem Jover
0e4e3ab269 Add __DECONST, __DEVOLATILE and __DEQUALIFY macros to sys/cdefs.h
Import from FreeBSD.
2015-09-23 07:59:24 +02:00
Guillem Jover
a6fe103c1b Add new man page for reallocarray(3)
Import man page from OpenBSD.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85622
2015-09-23 07:14:24 +02:00
Guillem Jover
02b55488c5 Use stdint integer types instead of BSD legacy ones 2015-09-23 07:14:21 +02:00
Callum Davies
6378351169 Fix arc4random() and arc4random_stir() prototypes
These two functions accept no arguments.  The prototypes should reflect
this.  This change lets the compiler warn about certain (admittedly
silly) mistakes.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2014-08-12 12:18:13 +02:00
Guillem Jover
e390651b64 Release libbsd 0.7.0 2014-07-29 03:19:15 +02:00
Guillem Jover
e8d3d04177 build: Remove hard requirement for GNU .init_array section support
In case the support is not available, just stop building the
libbsd-ctor.a library, which is a nice to have thing, but should not
have been a hard requirement from the start. This should allow to
build libbsd on non-glibc based systems using another libc.
2014-07-20 02:09:20 +02:00
Benjamin Baier
faa005cb32 Add reallocarray() function from OpenBSD
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2014-07-17 05:13:05 +02:00
Guillem Jover
36aca8c06e Add stringlist module from NetBSD 2014-07-17 05:11:00 +02:00
Guillem Jover
e8f9300355 Add getbsize() function
Import code from DragonFlyBSD and man page from FreeBSD.
2014-07-15 10:57:42 +02:00
Christian Svensson
a88bb8380d Add OpenRISC support to nlist()
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2014-03-06 22:11:27 +01:00
Guillem Jover
8d16c3df67 Add timeconv module from FreeBSD
Inline license information from FreeBSD root dir COPYRIGHT file.
2013-10-21 05:48:30 +02:00
Guillem Jover
f41fdcf186 Add funopen() function
This is a wrapper over the glibc fopencookie() function.

We diverge from the FreeBSD, OpenBSD and DragonFlyBSD declarations,
because seekfn() there wrongly uses fpos_t, assuming it's an integral
type, and any code using that on a system where fpos_t is a struct
(such as GNU-based systems or NetBSD) will fail to build. In which case,
as the code has to be modified anyway, we might just as well use the
correct declaration.
2013-10-21 05:35:44 +02:00
Guillem Jover
86cbff385a Handle glibc partial header inclusions
The glibc headers use selective inclusions through the __need_NAME
mechanism to avoid circular dependencies.

The problem is that if we are being overlaid, and have been requested
a partial inclusion, when we pass control to the system header, then
we might miss definitions needed by our own header, resulting in build
failures.

Workaround that by catching current partial requests, and skip the
current inclusion.
2013-10-21 05:35:17 +02:00
Guillem Jover
ee04e8de14 build: Set subdir-objects automake option
Bump automake minimal version to 1.9.
2013-10-21 05:33:08 +02:00
Guillem Jover
61b2dbb8f5 Fix dehumanize_number() to correctly detect overflows
Do not allow numbers greated than INT64_MAX and smaller than INT64_MIN.
Clarify the positive sign value by prefixing it with an explicit +.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66909
2013-10-21 05:29:37 +02:00
Guillem Jover
119417462e Release libbsd 0.6.0 2013-07-14 13:34:07 +02:00
Guillem Jover
948bcf1db8 Warn when setproctitle() gets called before initialization
Try to give a helpful message in case the program is not initializing
the setproctitle() machinery.
2013-07-14 13:34:07 +02:00
Guillem Jover
c5b9590287 Move setproctitle() automatic initialization to its own library
The automatic initialization cannot be part of the main shared library,
because there is no thread-safe way to change the environ global
variable. This is not a problem if the initializaion happens just at
program load time, but becomes one if the shared library is directly or
indirectly dlopen()ed during the execution of the program, which could
have either kept references to the old environ or could change it in
some other thread. This has been observed for example on systems using
Samba NSS modules.

To avoid any other possible fallout, the constructor is split into a
new static library that needs to be linked explicitly into programs
using setproctitle(). As an additional safety measure the pkg-config
linker flags will mark the program as not allowing to be dlopen()ed
so that we avoid the problem described above.

Reported-by: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66679
2013-07-14 13:32:11 +02:00
Guillem Jover
3077d2fffc build: Move version ABI from Makefile to configure.ac
It's easier to find there, and the value can be reused in case we have
to provide another shared library.
2013-07-14 10:27:25 +02:00
Guillem Jover
1bf0a55579 Release libbsd 0.5.2 2013-06-08 18:26:04 +02:00
Guillem Jover
ad613d9d09 Create a shallow copy of environ before replacing it in setproctitle()
Because clearenv() or setenv() might free the environ array of pointers,
we should make sure to copy it so that we can access it later on when
doing the deep copy via setenv().

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=65470
2013-06-08 18:26:04 +02:00
Guillem Jover
e084ce3fa7 Specify setproctitle_stub() signature manually if typeof is missing
Do not stop exporting the function in the version node even if typeof
is not available, as that would break ABI.
2013-06-08 18:09:36 +02:00
Guillem Jover
50e4c55afd Try to check if setproctitle() constructor got passed arguments 2013-06-08 18:09:36 +02:00
Guillem Jover
6faea4d2a0 Force setproctitle() into .init_array section
The GNU .init_array support is an extension over the standard System V
ABI .init_array support, which passes the main() arguments to the init
function.

This support comes in three parts. First the dynamic linker (from glibc)
needs to support it. Then function pointers need to be placed in the
section, for example by using __attribute__((constructor)), that the
compiler (gcc or clang for example) might place in section .ctors and
the linker (from binutils) will move to .init_array on the output
object, or by placing them directly into .init_array by the compiler
when compiling. If this does not happen and the function pointers end
up in .ctors, then they will not get passed the main() arguments, which
we do really need in this case.

But this relies on recent binutils or gcc having native .init_array
support, and not having it disabled through --disable-initfini-array.

To guarantee we get the correct behaviour, let's just place the function
pointer in the .init_array section directly, so we only require a recent
enough glibc.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=65029
2013-06-08 18:09:29 +02:00
Guillem Jover
367e036537 test: Try setting and getting an environment variable after setproctitle() 2013-06-08 18:08:58 +02:00
Guillem Jover
dc8b09783f build: Ignore automake 1.13+ test suite generated files 2013-05-30 04:09:25 +02:00
Guillem Jover
4663364783 Release libbsd 0.5.1 2013-05-27 06:52:05 +02:00
Guillem Jover
df5aebd7e1 test: Mark a literal integer as long long
This fixes build failures on 32-bit architectures.
2013-05-27 06:51:15 +02:00
86 changed files with 6593 additions and 595 deletions

3
.gitignore vendored
View File

@@ -5,6 +5,9 @@ ChangeLog
*.o
*.so*
*.a
*.log
*.trs
.dirstamp
.deps/
.libs/
Makefile

41
COPYING
View File

@@ -66,7 +66,7 @@ for man/arc4random.3, man/tree.3 and man/getprogname.3.
The rest of the licenses apply to code and/or man pages.
Copyright © 2004-2006, 2008-2012 Guillem Jover <guillem@hadrons.org>
Copyright © 2004-2006, 2008-2015 Guillem Jover <guillem@hadrons.org>
Copyright © 2005 Hector Garcia Alvarez
Copyright © 2005 Aurelien Jarno
Copyright © 2006 Robert Millan
@@ -118,6 +118,12 @@ The rest of the licenses apply to code and/or man pages.
Some code is derived from software contributed to Berkeley by
Chris Torek.
© UNIX System Laboratories, Inc.
All or some portions of this file are derived from material licensed
to the University of California by American Telephone and Telegraph
Co. or Unix System Laboratories, Inc. and are reproduced herein with
the permission of UNIX System Laboratories, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
@@ -201,11 +207,13 @@ The rest of the licenses apply to code and/or man pages.
--
Copyright © 1997-2000, 2002, 2008 The NetBSD Foundation, Inc.
Copyright © 1994, 1997-2000, 2002, 2008 The NetBSD Foundation, Inc.
All rights reserved.
Some code was contributed to The NetBSD Foundation by Allen Briggs.
Some code was contributed to The NetBSD Foundation by Luke Mewburn.
Some code is derived from software contributed to The NetBSD Foundation
by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
@@ -214,6 +222,9 @@ The rest of the licenses apply to code and/or man pages.
by Julio M. Merino Vidal, developed as part of Google's Summer of Code
2005 program.
Some code is derived from software contributed to The NetBSD Foundation
by Christos Zoulas.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
@@ -243,12 +254,18 @@ The rest of the licenses apply to code and/or man pages.
Copyright © 2001 Dima Dorfman.
All rights reserved.
Copyright © 2001 FreeBSD Inc.
All rights reserved.
Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
All rights reserved.
Copyright © 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
All rights reserved.
Copyright © 2005 Colin Percival
All rights reserved.
Copyright © 2007 Eric Anderson <anderson@FreeBSD.org>
Copyright © 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
All rights reserved.
@@ -338,12 +355,23 @@ The rest of the licenses apply to code and/or man pages.
--
Copyright © 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright © 2004 Ted Unangst
Copyright © 2004 Ted Unangst and Todd Miller
All rights reserved.
Copyright © 1996 David Mazieres <dm@uun.org>
Copyright © 1998, 2000, 2004-2005, 2010, 2012-2014
Todd C. Miller <Todd.Miller@courtesan.com>
Copyright © 2004 Ted Unangst
Copyright © 2008 Damien Miller <djm@openbsd.org>
Copyright © 2008 Otto Moerbeek <otto@drijf.net>
Copyright © 2013 Markus Friedl <markus@openbsd.org>
Copyright © 2014 Bob Beck <beck@obtuse.com>
Copyright © 2014 Brent Cook <bcook@openbsd.org>
Copyright © 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
Copyright © 2014 Theo de Raadt <deraadt@openbsd.org>
Copyright © 2015 Michael Felt <aixtools@gmail.com>
Copyright © 2015 Guillem Jover <guillem@hadrons.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
@@ -358,8 +386,7 @@ The rest of the licenses apply to code and/or man pages.
--
Copyright © 2000-2002, 2004-2005, 2007, 2010
Todd C. Miller <Todd.Miller@courtesan.com>
Copyright © 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@@ -12,5 +12,5 @@ EXTRA_DIST = \
dist-hook:
echo $(VERSION) >$(distdir)/.dist-version
if [ -d .git ]; then \
git log --stat -C >$(distdir)/ChangeLog; \
XDG_CONFIG_HOME= HOME= git log --stat -C >$(distdir)/ChangeLog; \
fi

View File

@@ -6,11 +6,18 @@ AC_CONFIG_SRCDIR([src/fgetln.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.8 foreign nostdinc no-dist-gzip dist-xz])
AM_INIT_AUTOMAKE([1.9 foreign nostdinc subdir-objects no-dist-gzip dist-xz])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
LIBBSD_ABI_MAJOR=0
LIBBSD_ABI_MINOR=8
LIBBSD_ABI_PATCH=0
LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH"
AC_SUBST([LIBBSD_ABI])
# Check and store if we got user supplied variables
user_CFLAGS=${CFLAGS-unset}
@@ -31,9 +38,14 @@ if test "$user_CFLAGS" = unset && test "$GCC" = yes; then
fi
# Checks for libraries.
AC_CHECK_LIB([testu01], [unif01_CreateExternGenBits],
[TESTU01_LIBS="-ltestu01"])
AC_SUBST([TESTU01_LIBS])
AM_CONDITIONAL([HAVE_LIBTESTU01],
[test "x$ac_cv_lib_testu01_unif01_CreateExternGenBits" = "xyes"])
# Checks for header files.
AC_CHECK_HEADERS([sys/ndir.h sys/dir.h dir.h dirent.h])
AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@@ -53,6 +65,50 @@ AC_CHECK_DECL([F_CLOSEM],
[#include <limits.h>
#include <fcntl.h>])
AC_CACHE_CHECK(
[for GNU .init_array section support],
[libbsd_cv_gnu_init_array_support],
[AC_RUN_IFELSE(
[AC_LANG_SOURCE(
[[
static int rc = 1;
static void init(int argc) { if (argc == 1) rc = 0; }
void (*init_func)(int argc) __attribute__((section(".init_array"))) = init;
int main() { return rc; }
]]
)],
[libbsd_cv_gnu_init_array_support=yes],
[libbsd_cv_gnu_init_array_support=no],
[AC_PREPROC_IFELSE(
[AC_LANG_SOURCE(
[[
/* Look for a known libc that supports .init_array with the GNU extension
* to pass main() arguments to the init functions. */
#include <stdlib.h>
#if defined __GLIBC_PREREQ
# if __GLIBC_PREREQ(2, 4)
/* glibc supports GNU .init_array since 2.4. */
# else
# error glibc does not support GNU .init_array
# endif
#else
/*
* Basic SysV ABI .init_array support, init functions do not get arguments:
* - Bionic since its inception.
* - uClibc since 0.9.29.
*/
# error unknown whether libc supports GNU .init_array
#endif
]]
)],
[libbsd_cv_gnu_init_array_support=yes],
[libbsd_cv_gnu_init_array_support=no])
]
)]
)
AM_CONDITIONAL([BUILD_LIBBSD_CTOR],
[test "$libbsd_cv_gnu_init_array_support" = yes])
# Checks for library functions.
AC_MSG_CHECKING([for program_invocation_short_name])
AC_LINK_IFELSE(
@@ -72,7 +128,10 @@ AC_LINK_IFELSE(
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])
AC_CHECK_FUNCS([clearenv dirfd __fpurge getexecname getline sysconf])
AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
getauxval getentropy getexecname getline \
pstat_getproc sysconf])
AM_CONDITIONAL(HAVE_GETENTROPY, [test "x$ac_cv_func_getentropy" = "xtrue"])
AC_CONFIG_FILES([
Makefile
@@ -80,6 +139,7 @@ AC_CONFIG_FILES([
man/Makefile
src/Makefile
src/libbsd.pc
src/libbsd-ctor.pc
src/libbsd-overlay.pc
test/Makefile
])

View File

@@ -19,6 +19,8 @@ nobase_include_HEADERS = \
bsd/stdio.h \
bsd/stdlib.h \
bsd/string.h \
bsd/stringlist.h \
bsd/timeconv.h \
bsd/unistd.h \
bsd/vis.h \
bsd/wchar.h \

View File

@@ -39,10 +39,14 @@
#include <stdarg.h>
__BEGIN_DECLS
extern void warnc (int code, const char *format, ...);
extern void vwarnc (int code, const char *format, va_list ap);
extern void errc (int status, int code, const char *format, ...);
extern void verrc (int status, int code, const char *format, va_list ap);
void warnc(int code, const char *format, ...)
__printflike(2, 3);
void vwarnc(int code, const char *format, va_list ap)
__printflike(2, 0);
void errc(int status, int code, const char *format, ...)
__printflike(3, 4);
void verrc(int status, int code, const char *format, va_list ap)
__printflike(3, 0);
__END_DECLS
#endif

View File

@@ -15,26 +15,28 @@
#ifndef _MD5_H_
#define _MD5_H_
#include <stdint.h>
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
typedef struct MD5Context {
u_int32_t state[4]; /* state */
u_int64_t count; /* number of bits, mod 2^64 */
u_int8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
uint32_t state[4]; /* state */
uint64_t count; /* number of bits, mod 2^64 */
uint8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
} MD5_CTX;
#include <sys/cdefs.h>
__BEGIN_DECLS
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, const u_int8_t *, size_t)
void MD5Update(MD5_CTX *, const uint8_t *, size_t)
__attribute__((__bounded__(__string__,2,3)));
void MD5Pad(MD5_CTX *);
void MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)));
void MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH])
void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH])
__attribute__((__bounded__(__minbytes__,1,4)))
__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));
char *MD5End(MD5_CTX *, char *)
@@ -43,7 +45,7 @@ char *MD5File(const char *, char *)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5FileChunk(const char *, char *, off_t, off_t)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5Data(const u_int8_t *, size_t, char *)
char *MD5Data(const uint8_t *, size_t, char *)
__attribute__((__bounded__(__string__,1,2)))
__attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH)));
__END_DECLS

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2004, 2005, 2009, 2011 Guillem Jover <guillem@hadrons.org>
* Copyright © 2004-2005, 2009, 2011-2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,12 +24,17 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__need_FILE) || defined(__need___FILE)
#define LIBBSD_STDIO_H_SKIP
#endif
#ifdef LIBBSD_OVERLAY
#include_next <stdio.h>
#else
#include <stdio.h>
#endif
#ifndef LIBBSD_STDIO_H_SKIP
#ifndef LIBBSD_STDIO_H
#define LIBBSD_STDIO_H
@@ -39,9 +44,33 @@
__BEGIN_DECLS
const char *fmtcheck(const char *, const char *);
char *fgetln(FILE *fp, size_t *lenp);
/* XXX: The function requires cooperation from the system libc to store the
* line buffer in the FILE struct itself. */
char *fgetln(FILE *fp, size_t *lenp)
__attribute__((deprecated("This functions cannot be safely ported, "
"use getline(3) instead, as it is supported "
"by GNU and POSIX.1-2008.")));
/*
* Note: We diverge from the FreeBSD, OpenBSD and DragonFlyBSD declarations,
* because seekfn() there wrongly uses fpos_t, assuming it's an integral
* type, and any code using that on a system where fpos_t is a struct
* (such as GNU-based systems or NetBSD) will fail to build. In which case,
* as the code has to be modified anyway, we might just as well use the
* correct declaration here.
*/
FILE *funopen(const void *cookie,
int (*readfn)(void *cookie, char *buf, int size),
int (*writefn)(void *cookie, const char *buf, int size),
off_t (*seekfn)(void *cookie, off_t offset, int whence),
int (*closefn)(void *cookie));
#define fropen(cookie, fn) funopen(cookie, fn, NULL, NULL, NULL)
#define fwopen(cookie, fn) funopen(cookie, NULL, fn, NULL, NULL)
int fpurge(FILE *fp);
__END_DECLS
#endif
#endif
#undef LIBBSD_STDIO_H_SKIP

View File

@@ -47,11 +47,11 @@
#include <stdint.h>
__BEGIN_DECLS
u_int32_t arc4random();
void arc4random_stir();
uint32_t arc4random(void);
void arc4random_stir(void);
void arc4random_addrandom(u_char *dat, int datlen);
void arc4random_buf(void *_buf, size_t n);
u_int32_t arc4random_uniform(u_int32_t upper_bound);
uint32_t arc4random_uniform(uint32_t upper_bound);
int dehumanize_number(const char *str, int64_t *size);
@@ -67,9 +67,12 @@ int sradixsort(const unsigned char **base, int nmemb,
const unsigned char *table, unsigned endbyte);
void *reallocf(void *ptr, size_t size);
void *reallocarray(void *ptr, size_t nmemb, size_t size);
long long strtonum(const char *nptr, long long minval, long long maxval,
const char **errstr);
char *getbsize(int *headerlenp, long *blocksizep);
__END_DECLS
#endif

View File

@@ -41,6 +41,8 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
size_t strlcat(char *dst, const char *src, size_t siz);
char *strnstr(const char *str, const char *find, size_t str_len);
void strmode(mode_t mode, char *str);
void explicit_bzero(void *buf, size_t len);
__END_DECLS
#endif

54
include/bsd/stringlist.h Normal file
View File

@@ -0,0 +1,54 @@
/* $NetBSD: stringlist.h,v 1.6 2006/07/27 15:37:19 christos Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _STRINGLIST_H
#define _STRINGLIST_H
#include <sys/cdefs.h>
#include <sys/types.h>
/*
* Simple string list
*/
typedef struct _stringlist {
char **sl_str;
size_t sl_max;
size_t sl_cur;
} StringList;
__BEGIN_DECLS
StringList *sl_init(void);
int sl_add(StringList *, char *);
void sl_free(StringList *, int);
char *sl_find(StringList *, const char *);
int sl_delete(StringList *, const char *, int);
__END_DECLS
#endif /* _STRINGLIST_H */

View File

@@ -114,6 +114,47 @@
# define __bounded__(x, y, z)
#endif
/*
* We define this here since <stddef.h>, <sys/queue.h>, and <sys/types.h>
* require it.
*/
#ifndef __offsetof
# if LIBBSD_GCC_VERSION >= 0x0401
# define __offsetof(type, field) __builtin_offsetof(type, field)
# else
# ifndef __cplusplus
# define __offsetof(type, field) \
((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field))
# else
# define __offsetof(type, field) \
(__offsetof__ (reinterpret_cast <__size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<type *> (0)->field))))
# endif
# endif
#endif
#define __rangeof(type, start, end) \
(__offsetof(type, end) - __offsetof(type, start))
/*
* Given the pointer x to the member m of the struct s, return
* a pointer to the containing structure. When using GCC, we first
* assign pointer x to a local variable, to check that its type is
* compatible with member m.
*/
#ifndef __containerof
# if LIBBSD_GCC_VERSION >= 0x0301
# define __containerof(x, s, m) ({ \
const volatile __typeof(((s *)0)->m) *__x = (x); \
__DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m)); \
})
# else
# define __containerof(x, s, m) \
__DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m))
# endif
#endif
#ifndef __RCSID
# define __RCSID(x)
#endif
@@ -138,4 +179,16 @@
# define __COPYRIGHT(x)
#endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var))
#endif
#ifndef __DEVOLATILE
#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var))
#endif
#ifndef __DEQUALIFY
#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var))
#endif
#endif

View File

@@ -65,7 +65,7 @@
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
* may be traversed in either direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
@@ -85,12 +85,16 @@
* _EMPTY + + + +
* _FIRST + + + +
* _NEXT + + + +
* _PREV - - - +
* _PREV - + - +
* _LAST - - + +
* _FOREACH + + + +
* _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + +
* _FOREACH_FROM_SAFE + + + +
* _FOREACH_REVERSE - - - +
* _FOREACH_REVERSE_FROM - - - +
* _FOREACH_REVERSE_SAFE - - - +
* _FOREACH_REVERSE_FROM_SAFE - - - +
* _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
@@ -99,19 +103,22 @@
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
* _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
char * lastfile;
int lastline;
char * prevfile;
int prevline;
unsigned long lastline;
unsigned long prevline;
const char *lastfile;
const char *prevfile;
};
#define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
@@ -130,7 +137,9 @@ struct qm_trace {
#else
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define QMD_SAVELINK(name, link)
#define TRACEBUF
#define TRACEBUF_INITIALIZER
#define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */
@@ -162,11 +171,21 @@ struct { \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
@@ -189,6 +208,7 @@ struct { \
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
@@ -198,7 +218,7 @@ struct { \
curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \
} \
TRASHIT((elm)->field.sle_next); \
TRASHIT(*oldnext); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
@@ -210,6 +230,12 @@ struct { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
#define SLIST_SWAP(head1, head2, type) do { \
struct type *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
@@ -247,12 +273,21 @@ struct { \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
@@ -277,14 +312,13 @@ struct { \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \
NULL : \
((struct type *)(void *) \
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
(STAILQ_EMPTY((head)) ? NULL : \
__containerof((head)->stqh_last, struct type, field.stqe_next))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
@@ -294,13 +328,7 @@ struct { \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
TRASHIT((elm)->field.stqe_next); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
TRASHIT(*oldnext); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
@@ -309,6 +337,12 @@ struct { \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \
@@ -378,11 +412,21 @@ struct { \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
@@ -414,15 +458,21 @@ struct { \
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, struct type, field.le_next))
#define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
QMD_LIST_CHECK_NEXT(elm, field); \
QMD_LIST_CHECK_PREV(elm, field); \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
TRASHIT((elm)->field.le_next); \
TRASHIT((elm)->field.le_prev); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
} while (0)
#define LIST_SWAP(head1, head2, type, field) do { \
@@ -446,7 +496,7 @@ struct name { \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
#define TAILQ_ENTRY(type) \
struct { \
@@ -509,21 +559,41 @@ struct { \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST((head), headname); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
@@ -587,6 +657,8 @@ struct { \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
QMD_TAILQ_CHECK_NEXT(elm, field); \
QMD_TAILQ_CHECK_PREV(elm, field); \
if ((TAILQ_NEXT((elm), field)) != NULL) \
@@ -597,8 +669,8 @@ struct { \
QMD_TRACE_HEAD(head); \
} \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT((elm)->field.tqe_next); \
TRASHIT((elm)->field.tqe_prev); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)

57
include/bsd/timeconv.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)time.h 8.3 (Berkeley) 1/21/94
*/
/*
* $FreeBSD$
*/
#ifndef _TIMECONV_H_
#define _TIMECONV_H_
#include <sys/cdefs.h>
#include <stdint.h>
#include <time.h>
time_t _time32_to_time(int32_t t32);
int32_t _time_to_time32(time_t t);
time_t _time64_to_time(int64_t t64);
int64_t _time_to_time64(time_t t);
long _time_to_long(time_t t);
time_t _long_to_time(long tlong);
int _time_to_int(time_t t);
time_t _int_to_time(int tint);
#endif /* _TIMECONV_H_ */

View File

@@ -56,7 +56,12 @@ void *setmode(const char *mode_str);
void closefrom(int lowfd);
void setproctitle(const char *fmt, ...);
/* Compatibility with sendmail implementations. */
#define initsetproctitle(c, a, e) setproctitle_init((c), (a), (e))
void setproctitle_init(int argc, char *argv[], char *envp[]);
void setproctitle(const char *fmt, ...)
__printflike(1, 2);
int getpeereid(int s, uid_t *euid, gid_t *egid);
__END_DECLS

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org>
* Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,12 +24,18 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__need_wchar_t) || defined(__need_wint_t) || \
defined(__need_mbstate_t)
#define LIBBSD_WCHAR_H_SKIP
#endif
#ifdef LIBBSD_OVERLAY
#include_next <wchar.h>
#else
#include <wchar.h>
#endif
#ifndef LIBBSD_WCHAR_H_SKIP
#ifndef LIBBSD_WCHAR_H
#define LIBBSD_WCHAR_H
@@ -45,3 +51,5 @@ size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
__END_DECLS
#endif
#endif
#undef LIBBSD_WCHAR_H_SKIP

View File

@@ -23,11 +23,14 @@ dist_man_MANS = \
closefrom.3 \
dehumanize_number.3 \
expand_number.3 \
explicit_bzero.3 \
fgetln.3 \
fgetwln.3 \
flopen.3 \
fmtcheck.3 \
fparseln.3 \
funopen.3bsd \
getbsize.3 \
getmode.3 \
getpeereid.3 \
getprogname.3 \
@@ -40,11 +43,13 @@ dist_man_MANS = \
queue.3bsd \
radixsort.3 \
readpassphrase.3 \
reallocarray.3 \
reallocf.3 \
setmode.3 \
setproctitle.3 \
setprogname.3 \
sradixsort.3 \
stringlist.3 \
strlcat.3 \
strlcpy.3 \
strnstr.3 \

View File

@@ -1,4 +1,5 @@
.\" $OpenBSD: arc4random.3,v 1.2 1997/04/27 22:40:25 angelos Exp $
.\" $OpenBSD: arc4random.3,v 1.34 2014/07/19 16:11:16 naddy Exp $
.\"
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
.\" All rights reserved.
.\"
@@ -28,9 +29,8 @@
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" Manual page, using -mandoc macros
.\" $FreeBSD$
.\"
.Dd April 15, 1997
.Dd $Mdocdate: July 19 2014 $
.Dt ARC4RANDOM 3
.Os
.Sh NAME
@@ -45,56 +45,70 @@
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdlib.h
.Ft u_int32_t
.Ft uint32_t
.Fn arc4random "void"
.Ft void
.Fn arc4random_buf "void *buf" "size_t nbytes"
.Ft u_int32_t
.Fn arc4random_uniform "u_int32_t upper_bound"
.Ft uint32_t
.Fn arc4random_uniform "uint32_t upper_bound"
.Ft void
.Fn arc4random_stir "void"
.Ft void
.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
.Sh DESCRIPTION
The
.Fn arc4random
function uses the key stream generator employed by the
arc4 cipher, which uses 8*8 8 bit S-Boxes.
The S-Boxes
can be in about
.if t 2\u\s71700\s10\d
.if n (2**1700)
states.
The
.Fn arc4random
function returns pseudo-random numbers in the range of 0 to
.if t 2\u\s731\s10\d\(mi1,
.if n (2**32)\(mi1,
and therefore has twice the range of
.Xr rand 3
This family of functions provides higher quality data than those
described in
.Xr rand 3 ,
.Xr random 3 ,
and
.Xr random 3 .
.Xr rand48 3 .
.Pp
Use of these functions is encouraged for almost all random number
consumption because the other interfaces are deficient in either
quality, portability, standardization, or availability.
These functions can be called in almost all coding environments,
including
.Xr pthreads 3
and
.Xr chroot 2 .
.Pp
High quality 32-bit pseudo-random numbers are generated very quickly.
On each call, a cryptographic pseudo-random number generator is used
to generate a new result.
One data pool is used for all consumers in a process, so that consumption
under program flow can act as additional stirring.
The subsystem is re-seeded from the kernel random number subsystem using
.Xr getentropy 2
on a regular basis, and also upon
.Xr fork 2 .
.Pp
The
.Fn arc4random
function returns a single 32-bit value.
.Pp
The
.Fn arc4random_buf
function fills the region
.Fa buf
of length
.Fa nbytes
with ARC4-derived random data.
with random data.
.Pp
.Fn arc4random_uniform
will return a uniformly distributed random number less than
will return a single 32-bit value, uniformly distributed but less than
.Fa upper_bound .
.Fn arc4random_uniform
is recommended over constructions like
This is recommended over constructions like
.Dq Li arc4random() % upper_bound
as it avoids "modulo bias" when the upper bound is not a power of two.
In the worst case, this function may consume multiple iterations
to ensure uniformity; see the source code to understand the problem
and solution.
.Pp
The
.Fn arc4random_stir
function reads data from
.Pa /dev/urandom
and uses it to permute the S-Boxes via
.Xr getentropy 2
and uses it to re-seed the subsystem via
.Fn arc4random_addrandom .
.Pp
There is no need to call
@@ -103,26 +117,22 @@ before using
.Fn arc4random
functions family, since
they automatically initialize themselves.
.Sh EXAMPLES
The following produces a drop-in replacement for the traditional
.Fn rand
and
.Fn random
functions using
.Fn arc4random :
.Pp
.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
.Sh RETURN VALUES
These functions are always successful, and no return value is
reserved to indicate an error.
.Sh SEE ALSO
.Xr rand 3 ,
.Xr random 3 ,
.Xr srandomdev 3
.Xr rand48 3 ,
.Xr random 3
.Sh HISTORY
.Pa RC4
has been designed by RSA Data Security, Inc.
It was posted anonymously
to the USENET and was confirmed to be equivalent by several sources who
had access to the original cipher.
Since
.Pa RC4
used to be a trade secret, the cipher is now referred to as
.Pa ARC4 .
These functions first appeared in
.Ox 2.1 .
.Pp
The original version of this random number generator used the
RC4 (also known as ARC4) algorithm.
In
.Ox 5.5
it was replaced with the ChaCha20 cipher, and it may be replaced
again in the future as cryptographic techniques advance.
A good mnemonic is
.Dq A Replacement Call for Random .

72
man/explicit_bzero.3 Normal file
View File

@@ -0,0 +1,72 @@
.\" Copyright (c) 1990, 1991 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Chris Torek.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $OpenBSD: bzero.3,v 1.10 2014/01/22 21:06:45 tedu Exp $
.\"
.Dd $Mdocdate: January 22 2014 $
.Dt BZERO 3
.Os
.Sh NAME
.Nm explicit_bzero
.Nd write zeroes to a byte string
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/string.h
.Ft void
.Fn explicit_bzero "void *buf" "size_t len"
.Sh DESCRIPTION
The
.Fn explicit_bzero
function writes
.Fa len
zero bytes to the string
.Fa buf .
If
.Fa len
is zero,
.Fn explicit_bzero
does nothing.
.Pp
The
.Fn explicit_bzero
variant behaves the same as the
.Fn bzero
function, but will not be removed by a compiler's dead store optimization
pass, making it useful for clearing sensitive memory such as a password.
.Sh SEE ALSO
.Xr bzero 3 ,
.Xr memset 3 ,
.Xr swab 3
.Sh HISTORY
The
.Fn explicit_bzero
function first appeared in
.Ox 5.5 .

View File

@@ -126,9 +126,9 @@ is returned.
The
.Fn fparseln
function uses internally
.Xr fgetln 3 ,
.Xr getline 3 ,
so all error conditions that apply to
.Xr fgetln 3 ,
.Xr getline 3 ,
apply to
.Fn fparseln .
In addition
@@ -141,7 +141,7 @@ and return
.Dv NULL
if it runs out of memory.
.Sh SEE ALSO
.Xr fgetln 3
.Xr getline 3
.Sh HISTORY
The
.Fn fparseln

191
man/funopen.3bsd Normal file
View File

@@ -0,0 +1,191 @@
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Chris Torek.
.\" 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.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)funopen.3 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
.Dd March 19, 2004
.Dt FUNOPEN 3
.Os
.Sh NAME
.Nm funopen ,
.Nm fropen ,
.Nm fwopen
.Nd open a stream
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdio.h
.Ft FILE *
.Fn funopen "const void *cookie" "int (*readfn)(void *, char *, int)" "int (*writefn)(void *, const char *, int)" "off_t (*seekfn)(void *, off_t, int)" "int (*closefn)(void *)"
.Ft FILE *
.Fn fropen "void *cookie" "int (*readfn)(void *, char *, int)"
.Ft FILE *
.Fn fwopen "void *cookie" "int (*writefn)(void *, const char *, int)"
.Sh DESCRIPTION
The
.Fn funopen
function
associates a stream with up to four
.Dq Tn I/O No functions .
Either
.Fa readfn
or
.Fa writefn
must be specified;
the others can be given as an appropriately-typed
.Dv NULL
pointer.
These
.Tn I/O
functions will be used to read, write, seek and
close the new stream.
.Pp
In general, omitting a function means that any attempt to perform the
associated operation on the resulting stream will fail.
If the close function is omitted, closing the stream will flush
any buffered output and then succeed.
.Pp
The calling conventions of
.Fa readfn ,
.Fa writefn ,
.Fa seekfn
and
.Fa closefn
must match those, respectively, of
.Xr read 2 ,
.Xr write 2 ,
.Xr lseek 2 ,
and
.Xr close 2
with the single exception that they are passed the
.Fa cookie
argument specified to
.Fn funopen
in place of the traditional file descriptor argument.
.Pp
Read and write
.Tn I/O
functions are allowed to change the underlying buffer
on fully buffered or line buffered streams by calling
.Xr setvbuf 3 .
They are also not required to completely fill or empty the buffer.
They are not, however, allowed to change streams from unbuffered to buffered
or to change the state of the line buffering flag.
They must also be prepared to have read or write calls occur on buffers other
than the one most recently specified.
.Pp
All user
.Tn I/O
functions can report an error by returning \-1.
Additionally, all of the functions should set the external variable
.Va errno
appropriately if an error occurs.
.Pp
An error on
.Fn closefn
does not keep the stream open.
.Pp
As a convenience, the include file
.In stdio.h
defines the macros
.Fn fropen
and
.Fn fwopen
as calls to
.Fn funopen
with only a read or write function specified.
.Sh RETURN VALUES
Upon successful completion,
.Fn funopen
returns a
.Dv FILE
pointer.
Otherwise,
.Dv NULL
is returned and the global variable
.Va errno
is set to indicate the error.
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EINVAL
The
.Fn funopen
function
was called without either a read or write function.
The
.Fn funopen
function
may also fail and set
.Va errno
for any of the errors
specified for the routine
.Xr malloc 3 .
.El
.Sh SEE ALSO
.Xr fcntl 2 ,
.Xr open 2 ,
.Xr fclose 3 ,
.Xr fopen 3 ,
.Xr fseek 3 ,
.Xr setbuf 3
.Sh HISTORY
The
.Fn funopen
functions first appeared in
.Bx 4.4 .
.Sh BUGS
The
.Fn funopen
function
may not be portable to systems other than
.Bx .
.Pp
On
.Fx ,
.Ox
and
.Dx
the
.Fn funopen
interface erroneously assumes that
.Vt fpos_t
is an integral type, and uses it in the
.Fa seekfn
hook; but because code using a
.Fa seekfn
hook will fail to build on systems where
.Vt fpos_t
is a struct, and it will need to be slightly fixed anyway, the
implementation provided by libbsd (in the same way as
.Nx )
uses the correct
.Vt off_t
types.

95
man/getbsize.3 Normal file
View File

@@ -0,0 +1,95 @@
.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)getbsize.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd November 16, 2012
.Dt GETBSIZE 3
.Os
.Sh NAME
.Nm getbsize
.Nd get preferred block size
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdlib.h
.Ft char *
.Fn getbsize "int *headerlenp" "long *blocksizep"
.Sh DESCRIPTION
The
.Fn getbsize
function returns a preferred block size for reporting by system utilities
.Xr df 1 ,
.Xr du 1 ,
.Xr ls 1
and
.Xr systat 1 ,
based on the value of the
.Ev BLOCKSIZE
environment variable.
.Ev BLOCKSIZE
may be specified directly in bytes, or in multiples of a kilobyte by
specifying a number followed by ``K'' or ``k'', in multiples of a
megabyte by specifying a number followed by ``M'' or ``m'' or in
multiples of a gigabyte by specifying a number followed by ``G'' or
``g''.
Multiples must be integers.
.Pp
Valid values of
.Ev BLOCKSIZE
are 512 bytes to 1 gigabyte.
Sizes less than 512 bytes are rounded up to 512 bytes, and sizes
greater than 1 GB are rounded down to 1 GB.
In each case
.Fn getbsize
produces a warning message.
.Pp
The
.Fn getbsize
function returns a pointer to a null-terminated string describing
the block size, something like
.Dq 1K-blocks .
The memory referenced by
.Fa headerlenp
is filled in with the length of the string (not including the
terminating null).
The memory referenced by
.Fa blocksizep
is filled in with block size, in bytes.
.Sh SEE ALSO
.Xr df 1 ,
.Xr du 1 ,
.Xr ls 1 ,
.Xr systat 1 ,
.Xr environ 7
.Sh HISTORY
The
.Fn getbsize
function first appeared in
.Bx 4.4 .

View File

@@ -32,13 +32,13 @@
.Ft void
.Fn MDXInit "MDX_CTX *context"
.Ft void
.Fn MDXUpdate "MDX_CTX *context" "const u_int8_t *data" "size_t len"
.Fn MDXUpdate "MDX_CTX *context" "const uint8_t *data" "size_t len"
.Ft void
.Fn MDXPad "MDX_CTX *context"
.Ft void
.Fn MDXFinal "u_int8_t digest[MDX_DIGEST_LENGTH]" "MDX_CTX *context"
.Fn MDXFinal "uint8_t digest[MDX_DIGEST_LENGTH]" "MDX_CTX *context"
.Ft void
.Fn MDXTransform "u_int32_t state[4]" "u_int8_t block[MDX_BLOCK_LENGTH]"
.Fn MDXTransform "uint32_t state[4]" "uint8_t block[MDX_BLOCK_LENGTH]"
.Ft "char *"
.Fn MDXEnd "MDX_CTX *context" "char *buf"
.Ft "char *"
@@ -46,7 +46,7 @@
.Ft "char *"
.Fn MDXFileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
.Ft "char *"
.Fn MDXData "const u_int8_t *data" "size_t len" "char *buf"
.Fn MDXData "const uint8_t *data" "size_t len" "char *buf"
.Sh DESCRIPTION
The MDX functions calculate a 128-bit cryptographic checksum (digest)
for any number of input bytes.

View File

@@ -9,7 +9,7 @@
.\" 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.
.\" 4. Neither the name of the University nor the names of its contributors
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
@@ -28,15 +28,17 @@
.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
.\" $FreeBSD$
.\"
.Dd May 13, 2011
.Dt QUEUE 3bsd
.Dd June 17, 2013
.Dt QUEUE 3
.Os
.Sh NAME
.Nm SLIST_EMPTY ,
.Nm SLIST_ENTRY ,
.Nm SLIST_FIRST ,
.Nm SLIST_FOREACH ,
.Nm SLIST_FOREACH_FROM ,
.Nm SLIST_FOREACH_SAFE ,
.Nm SLIST_FOREACH_FROM_SAFE ,
.Nm SLIST_HEAD ,
.Nm SLIST_HEAD_INITIALIZER ,
.Nm SLIST_INIT ,
@@ -52,7 +54,9 @@
.Nm STAILQ_ENTRY ,
.Nm STAILQ_FIRST ,
.Nm STAILQ_FOREACH ,
.Nm STAILQ_FOREACH_FROM ,
.Nm STAILQ_FOREACH_SAFE ,
.Nm STAILQ_FOREACH_FROM_SAFE ,
.Nm STAILQ_HEAD ,
.Nm STAILQ_HEAD_INITIALIZER ,
.Nm STAILQ_INIT ,
@@ -69,7 +73,9 @@
.Nm LIST_ENTRY ,
.Nm LIST_FIRST ,
.Nm LIST_FOREACH ,
.Nm LIST_FOREACH_FROM ,
.Nm LIST_FOREACH_SAFE ,
.Nm LIST_FOREACH_FROM_SAFE ,
.Nm LIST_HEAD ,
.Nm LIST_HEAD_INITIALIZER ,
.Nm LIST_INIT ,
@@ -77,6 +83,7 @@
.Nm LIST_INSERT_BEFORE ,
.Nm LIST_INSERT_HEAD ,
.Nm LIST_NEXT ,
.Nm LIST_PREV ,
.Nm LIST_REMOVE ,
.Nm LIST_SWAP ,
.Nm TAILQ_CONCAT ,
@@ -84,9 +91,13 @@
.Nm TAILQ_ENTRY ,
.Nm TAILQ_FIRST ,
.Nm TAILQ_FOREACH ,
.Nm TAILQ_FOREACH_FROM ,
.Nm TAILQ_FOREACH_SAFE ,
.Nm TAILQ_FOREACH_FROM_SAFE ,
.Nm TAILQ_FOREACH_REVERSE ,
.Nm TAILQ_FOREACH_REVERSE_FROM ,
.Nm TAILQ_FOREACH_REVERSE_SAFE ,
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE ,
.Nm TAILQ_HEAD ,
.Nm TAILQ_HEAD_INITIALIZER ,
.Nm TAILQ_INIT ,
@@ -108,7 +119,9 @@ lists and tail queues
.Fn SLIST_ENTRY "TYPE"
.Fn SLIST_FIRST "SLIST_HEAD *head"
.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_HEAD "HEADNAME" "TYPE"
.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
.Fn SLIST_INIT "SLIST_HEAD *head"
@@ -125,7 +138,9 @@ lists and tail queues
.Fn STAILQ_ENTRY "TYPE"
.Fn STAILQ_FIRST "STAILQ_HEAD *head"
.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_HEAD "HEADNAME" "TYPE"
.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
.Fn STAILQ_INIT "STAILQ_HEAD *head"
@@ -143,7 +158,9 @@ lists and tail queues
.Fn LIST_ENTRY "TYPE"
.Fn LIST_FIRST "LIST_HEAD *head"
.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_HEAD "HEADNAME" "TYPE"
.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
.Fn LIST_INIT "LIST_HEAD *head"
@@ -151,6 +168,7 @@ lists and tail queues
.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_PREV "TYPE *elm" "LIST_HEAD *head" "TYPE" "LIST_ENTRY NAME"
.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
.\"
@@ -159,9 +177,13 @@ lists and tail queues
.Fn TAILQ_ENTRY "TYPE"
.Fn TAILQ_FIRST "TAILQ_HEAD *head"
.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_HEAD "HEADNAME" "TYPE"
.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
.Fn TAILQ_INIT "TAILQ_HEAD *head"
@@ -244,8 +266,18 @@ Code size and execution time of operations (except for removal) is about
twice that of the singly-linked data-structures.
.El
.Pp
Linked lists are the simplest of the doubly linked data structures and support
only the above functionality over singly-linked lists.
Linked lists are the simplest of the doubly linked data structures.
They add the following functionality over the above:
.Bl -enum -compact -offset indent
.It
They may be traversed backwards.
.El
However:
.Bl -enum -compact -offset indent
.It
To traverse backwards, an entry to begin the traversal and the list in
which it is contained must be specified.
.El
.Pp
Tail queues add the following functionality:
.Bl -enum -compact -offset indent
@@ -349,6 +381,19 @@ turn to
.Fa var .
.Pp
The macro
.Nm SLIST_FOREACH_FROM
behaves identically to
.Nm SLIST_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found SLIST element and begins the loop at
.Fa var
instead of the first element in the SLIST referenced by
.Fa head .
.Pp
The macro
.Nm SLIST_FOREACH_SAFE
traverses the list referenced by
.Fa head
@@ -363,6 +408,19 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm SLIST_FOREACH_FROM_SAFE
behaves identically to
.Nm SLIST_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found SLIST element and begins the loop at
.Fa var
instead of the first element in the SLIST referenced by
.Fa head .
.Pp
The macro
.Nm SLIST_INIT
initializes the list referenced by
.Fa head .
@@ -388,7 +446,8 @@ The macro
.Nm SLIST_REMOVE_AFTER
removes the element after
.Fa elm
from the list. Unlike
from the list.
Unlike
.Fa SLIST_REMOVE ,
this macro does not traverse the entire list.
.Pp
@@ -528,6 +587,19 @@ in turn to
.Fa var .
.Pp
The macro
.Nm STAILQ_FOREACH_FROM
behaves identically to
.Nm STAILQ_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found STAILQ element and begins the loop at
.Fa var
instead of the first element in the STAILQ referenced by
.Fa head .
.Pp
The macro
.Nm STAILQ_FOREACH_SAFE
traverses the tail queue referenced by
.Fa head
@@ -542,6 +614,19 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm STAILQ_FOREACH_FROM_SAFE
behaves identically to
.Nm STAILQ_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found STAILQ element and begins the loop at
.Fa var
instead of the first element in the STAILQ referenced by
.Fa head .
.Pp
The macro
.Nm STAILQ_INIT
initializes the tail queue referenced by
.Fa head .
@@ -579,7 +664,8 @@ The macro
.Nm STAILQ_REMOVE_AFTER
removes the element after
.Fa elm
from the tail queue. Unlike
from the tail queue.
Unlike
.Fa STAILQ_REMOVE ,
this macro does not traverse the entire tail queue.
.Pp
@@ -717,6 +803,19 @@ in the forward direction, assigning each element in turn to
.Fa var .
.Pp
The macro
.Nm LIST_FOREACH_FROM
behaves identically to
.Nm LIST_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found LIST element and begins the loop at
.Fa var
instead of the first element in the LIST referenced by
.Fa head .
.Pp
The macro
.Nm LIST_FOREACH_SAFE
traverses the list referenced by
.Fa head
@@ -730,6 +829,19 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm LIST_FOREACH_FROM_SAFE
behaves identically to
.Nm LIST_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found LIST element and begins the loop at
.Fa var
instead of the first element in the LIST referenced by
.Fa head .
.Pp
The macro
.Nm LIST_INIT
initializes the list referenced by
.Fa head .
@@ -759,6 +871,14 @@ The macro
returns the next element in the list, or NULL if this is the last.
.Pp
The macro
.Nm LIST_PREV
returns the previous element in the list, or NULL if this is the first.
List
.Fa head
must contain element
.Fa elm .
.Pp
The macro
.Nm LIST_REMOVE
removes the element
.Fa elm
@@ -894,12 +1014,38 @@ is set to
if the loop completes normally, or if there were no elements.
.Pp
The macro
.Nm TAILQ_FOREACH_FROM
behaves identically to
.Nm TAILQ_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the loop at
.Fa var
instead of the first element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE
traverses the tail queue referenced by
.Fa head
in the reverse direction, assigning each element in turn to
.Fa var .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE_FROM
behaves identically to
.Nm TAILQ_FOREACH_REVERSE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the reverse loop at
.Fa var
instead of the last element in the TAILQ referenced by
.Fa head .
.Pp
The macros
.Nm TAILQ_FOREACH_SAFE
and
@@ -919,6 +1065,32 @@ as well as free it from within the loop safely without interfering with the
traversal.
.Pp
The macro
.Nm TAILQ_FOREACH_FROM_SAFE
behaves identically to
.Nm TAILQ_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the loop at
.Fa var
instead of the first element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE
behaves identically to
.Nm TAILQ_FOREACH_REVERSE_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the reverse loop at
.Fa var
instead of the last element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_INIT
initializes the tail queue referenced by
.Fa head .

102
man/reallocarray.3 Normal file
View File

@@ -0,0 +1,102 @@
.\"
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the American National Standards Committee X3, on Information
.\" Processing Systems.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $OpenBSD: malloc.3,v 1.78 2014/05/01 18:41:59 jmc Exp $
.\"
.Dd $Mdocdate: May 1 2014 $
.Dt MALLOC 3
.Os
.Sh NAME
.Nm reallocarray
.Nd memory allocation and deallocation
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdlib.h
.Ft void *
.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
.Sh DESCRIPTION
.Pp
When using
.Fn malloc
be careful to avoid the following idiom:
.Bd -literal -offset indent
if ((p = malloc(num * size)) == NULL)
err(1, "malloc");
.Ed
.Pp
The multiplication may lead to an integer overflow, which can
be avoided using the extension
.Fn reallocarray ,
as follows:
.Bd -literal -offset indent
if ((p = reallocarray(NULL, num, size)) == NULL)
err(1, "malloc");
.Ed
.Pp
Alternatively
.Fn calloc
is a more portable solution which comes with the cost of clearing memory.
.Pp
If
.Fn malloc
must be used, be sure to test for overflow:
.Bd -literal -offset indent
if (size && num > SIZE_MAX / size) {
errno = ENOMEM;
err(1, "overflow");
}
.Ed
.Pp
The use of
.Fn reallocarray
or
.Fn calloc
is strongly encouraged when allocating multiple sized objects
in order to avoid possible integer overflows.
.Sh RETURN VALUES
The
.Fn reallocarray
function returns a pointer to the allocated space if successful; otherwise,
a null pointer is returned and
.Va errno
is set to
.Er ENOMEM .
.Sh SEE ALSO
.Xr malloc 3 ,
.Xr calloc 3 ,
.Xr alloca 3
.Sh HISTORY
.Fn reallocarray
appeared in
.Ox 5.6 .

View File

@@ -33,6 +33,8 @@
.In sys/types.h
.In bsd/unistd.h
.Ft void
.Fn setproctitle_init "int argc" "char *argv[]" "char *envp[]"
.Ft void
.Fn setproctitle "const char *fmt" "..."
.Sh DESCRIPTION
The
@@ -41,6 +43,15 @@ library routine sets the process title that appears on the
.Xr ps 1
command.
.Pp
The
.Fn setproctitle_init
library routine only needs to be called (before any call to
.Fn setproctitle
and with
.Fn main
arguments), if the automatic constructor support has not
been linked in through the libbsd-ctor pkg-config file.
.Pp
The title is set from the executable's name, followed by the
result of a
.Xr printf 3
@@ -101,6 +112,11 @@ first appeared in
.Fx 2.2 .
Other operating systems have
similar functions.
.Pp
The
.Fn setproctitle_init
function is a libbsd extension not present on the BSDs, avoid using it
in portable code.
.Sh AUTHORS
.An -nosplit
.An Peter Wemm Aq peter@FreeBSD.org

147
man/stringlist.3 Normal file
View File

@@ -0,0 +1,147 @@
.\" $NetBSD: stringlist.3,v 1.15 2010/05/06 09:46:49 jruoho Exp $
.\"
.\" Copyright (c) 1997, 1999 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 6, 2010
.Dt STRINGLIST 3
.Os
.Sh NAME
.Nm stringlist ,
.Nm sl_init ,
.Nm sl_add ,
.Nm sl_free ,
.Nm sl_find ,
.Nm sl_delete
.Nd stringlist manipulation functions
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stringlist.h
.Ft StringList *
.Fn sl_init "void"
.Ft int
.Fn sl_add "StringList *sl" "char *item"
.Ft void
.Fn sl_free "StringList *sl" "int freeall"
.Ft char *
.Fn sl_find "StringList *sl" "const char *item"
.Ft int
.Fn sl_delete "StringList *sl" "const char *item" "int freeit"
.Sh DESCRIPTION
The
.Nm
functions manipulate stringlists, which are lists of
strings that extend automatically if necessary.
.Pp
The
.Ar StringList
structure has the following definition:
.Bd -literal -offset indent
typedef struct _stringlist {
char **sl_str;
size_t sl_max;
size_t sl_cur;
} StringList;
.Ed
.Pp
where:
.Bl -tag -width "sl_str" -offset indent
.It Ar sl_str
is a pointer to the base of the array containing the list,
.It Ar sl_max
is the size of
.Ar sl_str ,
and
.It Ar sl_cur
is the offset in
.Ar sl_str
of the current element.
.El
.Pp
The following stringlist manipulation functions are available:
.Bl -tag -width "sl_delete()" -offset 2n
.It Fn sl_init
Create a stringlist.
Returns a pointer to a
.Ar StringList ,
or
.Dv NULL
in case of failure.
.It Fn sl_free
Releases memory occupied by
.Ar sl
and the
.Ar sl-\*[Gt]sl_str
array.
If
.Ar freeall
is non-zero, then each of the items within
.Ar sl-\*[Gt]sl_str
is released as well.
.It Fn sl_add
Add
.Ar item
to
.Ar sl-\*[Gt]sl_str
at
.Ar sl-\*[Gt]sl_cur ,
extending the size of
.Ar sl-\*[Gt]sl_str .
Returns zero upon success, \-1 upon failure.
.It Fn sl_find
Find
.Ar item
in
.Ar sl ,
returning
.Dv NULL
if it's not found.
.It Fn sl_delete
Remove
.Ar item
from the list.
If
.Ar freeit
is non-zero, the string is freed.
Returns
.Dv 0
if the name is found
and
.Dv \-1
if the name is not found.
.El
.Sh SEE ALSO
.Xr free 3 ,
.Xr malloc 3
.Sh HISTORY
The
.Nm
functions appeared in
.Fx 2.2.6
and
.Nx 1.3 .

View File

@@ -7,11 +7,22 @@ AM_CPPFLAGS = \
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
-D__REENTRANT
libbsd_la_included_sources = \
hash/helper.c \
getentropy_aix.c \
getentropy_bsd.c \
getentropy_hpux.c \
getentropy_linux.c \
getentropy_osx.c \
getentropy_solaris.c \
$(nil)
EXTRA_DIST = \
libbsd.map \
libbsd.pc.in \
libbsd-ctor.pc.in \
libbsd-overlay.pc.in \
hash/helper.c \
$(libbsd_la_included_sources) \
$(nil)
CLEANFILES = \
@@ -25,56 +36,90 @@ pkgconfig_DATA = \
$(nil)
lib_LTLIBRARIES = libbsd.la
lib_LIBRARIES =
if BUILD_LIBBSD_CTOR
pkgconfig_DATA += libbsd-ctor.pc
lib_LIBRARIES += libbsd-ctor.a
endif
hash/md5hl.c: $(srcdir)/hash/helper.c
$(AM_V_at) $(MKDIR_P) hash
$(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@
libbsd_la_DEPENDENCIES = \
$(libbsd_la_included_sources) \
libbsd.map
libbsd_la_LDFLAGS = \
-Wl,--version-script=$(srcdir)/libbsd.map \
-version-number 0:5:0
-version-number $(LIBBSD_ABI)
libbsd_la_SOURCES = \
arc4random.c \
arc4random.h \
arc4random_bsd.h \
arc4random_linux.h \
arc4random_unix.h \
arc4random_openbsd.h \
arc4random_uniform.c \
bsd_getopt.c \
chacha_private.h \
closefrom.c \
dehumanize_number.c \
err.c \
expand_number.c \
explicit_bzero.c \
fgetln.c \
fgetwln.c \
flopen.c \
fmtcheck.c \
fparseln.c \
fpurge.c \
funopen.c \
getbsize.c \
getpeereid.c \
hash/md5.c \
hash/md5hl.c \
hash/sha512.h \
hash/sha512c.c \
heapsort.c \
humanize_number.c \
inet_net_pton.c \
local-elf.h \
local-link.h \
merge.c \
nlist.c \
pidfile.c \
progname.c \
radixsort.c \
readpassphrase.c \
reallocarray.c \
reallocf.c \
setmode.c \
setproctitle.c \
strlcat.c \
strlcpy.c \
stringlist.c \
strmode.c \
strnstr.c \
strtonum.c \
timeconv.c \
unvis.c \
vis.c \
wcslcat.c \
wcslcpy.c \
$(nil)
if !HAVE_GETENTROPY
libbsd_la_SOURCES += \
getentropy.c \
$(nil)
endif
libbsd_ctor_a_SOURCES = \
setproctitle_ctor.c \
$(nil)
runtimelibdir = $(libdir)
install-exec-hook:

View File

@@ -1,6 +1,11 @@
/* $OpenBSD: arc4random.c,v 1.53 2015/09/10 18:53:50 bcook Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2015, Guillem Jover <guillem@hadrons.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -16,281 +21,192 @@
*/
/*
* Arc4 random number generator for OpenBSD.
*
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
* which is a trade secret). The same algorithm is used as a stream
* cipher called "arcfour" in Tatu Ylonen's ssh package.
*
* Here the stream cipher has been modified always to include the time
* when initializing the state. That makes it impossible to
* regenerate the same random sequence twice, so this can't be used
* for encryption, but will generate good random numbers.
*
* RC4 is a registered trademark of RSA Laboratories.
* ChaCha based random number generator for OpenBSD.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
struct arc4_stream {
u_int8_t i;
u_int8_t j;
u_int8_t s[256];
};
#define KEYSTREAM_ONLY
#include "chacha_private.h"
#define RANDOMDEV "/dev/urandom"
#define KEYSIZE 128
#define minimum(a, b) ((a) < (b) ? (a) : (b))
#ifdef __REENTRANT
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define THREAD_LOCK() pthread_mutex_lock(&arc4random_mtx)
#define THREAD_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
#else
#define THREAD_LOCK()
#define THREAD_UNLOCK()
#if defined(__GNUC__) || defined(_MSC_VER)
#define inline __inline
#else /* __GNUC__ || _MSC_VER */
#define inline
#endif /* !__GNUC__ && !_MSC_VER */
#define KEYSZ 32
#define IVSZ 8
#define BLOCKSZ 64
#define RSBUFSZ (16*BLOCKSZ)
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
static struct _rs {
size_t rs_have; /* valid bytes at end of rs_buf */
size_t rs_count; /* bytes till reseed */
} *rs;
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
static struct _rsx {
chacha_ctx rs_chacha; /* chacha context for random keystream */
u_char rs_buf[RSBUFSZ]; /* keystream blocks */
} *rsx;
static inline int _rs_allocate(struct _rs **, struct _rsx **);
static inline void _rs_forkdetect(void);
#include "arc4random.h"
static inline void
_rs_init(u_char *buf, size_t n)
{
if (n < KEYSZ + IVSZ)
return;
if (rs == NULL) {
if (_rs_allocate(&rs, &rsx) == -1)
abort();
}
chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
}
static inline void
_rs_rekey(u_char *dat, size_t datlen)
{
#ifndef KEYSTREAM_ONLY
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
#endif
/* fill rs_buf with the keystream */
chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
rsx->rs_buf, sizeof(rsx->rs_buf));
/* mix in optional user provided data */
if (dat) {
size_t i, m;
static struct arc4_stream rs;
static int rs_initialized;
static int rs_stired;
static int arc4_count;
static inline u_int8_t arc4_getbyte(void);
static void arc4_stir(void);
static inline void
arc4_init(void)
{
int n;
for (n = 0; n < 256; n++)
rs.s[n] = n;
rs.i = 0;
rs.j = 0;
}
static inline void
arc4_addrandom(u_char *dat, int datlen)
{
int n;
u_int8_t si;
rs.i--;
for (n = 0; n < 256; n++) {
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si + dat[n % datlen]);
rs.s[rs.i] = rs.s[rs.j];
rs.s[rs.j] = si;
m = minimum(datlen, KEYSZ + IVSZ);
for (i = 0; i < m; i++)
rsx->rs_buf[i] ^= dat[i];
}
rs.j = rs.i;
/* immediately reinit for backtracking resistance */
_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
}
static void
arc4_stir(void)
_rs_stir(void)
{
int done, fd, n;
struct {
struct timeval tv;
pid_t pid;
u_int8_t rnd[KEYSIZE];
} rdat;
u_char rnd[KEYSZ + IVSZ];
fd = open(RANDOMDEV, O_RDONLY, 0);
done = 0;
if (fd >= 0) {
if (read(fd, &rdat, KEYSIZE) == KEYSIZE)
done = 1;
(void)close(fd);
}
if (!done) {
(void)gettimeofday(&rdat.tv, NULL);
rdat.pid = getpid();
/* We'll just take whatever was on the stack too... */
}
if (getentropy(rnd, sizeof rnd) == -1)
_getentropy_fail();
arc4_addrandom((u_char *)&rdat, KEYSIZE);
if (!rs)
_rs_init(rnd, sizeof(rnd));
else
_rs_rekey(rnd, sizeof(rnd));
explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
/*
* Throw away the first N bytes of output, as suggested in the
* paper "Weaknesses in the Key Scheduling Algorithm of RC4"
* by Fluher, Mantin, and Shamir. N=1024 is based on
* suggestions in the paper "(Not So) Random Shuffles of RC4"
* by Ilya Mironov.
*/
for (n = 0; n < 1024; n++)
(void) arc4_getbyte();
arc4_count = 1600000;
/* invalidate rs_buf */
rs->rs_have = 0;
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
rs->rs_count = 1600000;
}
static inline u_int8_t
arc4_getbyte(void)
static inline void
_rs_stir_if_needed(size_t len)
{
u_int8_t si, sj;
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si);
sj = rs.s[rs.j];
rs.s[rs.i] = sj;
rs.s[rs.j] = si;
return (rs.s[(si + sj) & 0xff]);
_rs_forkdetect();
if (!rs || rs->rs_count <= len)
_rs_stir();
if (rs->rs_count <= len)
rs->rs_count = 0;
else
rs->rs_count -= len;
}
static inline u_int32_t
arc4_getword(void)
static inline void
_rs_random_buf(void *_buf, size_t n)
{
u_int32_t val;
u_char *buf = (u_char *)_buf;
u_char *keystream;
size_t m;
val = arc4_getbyte() << 24;
val |= arc4_getbyte() << 16;
val |= arc4_getbyte() << 8;
val |= arc4_getbyte();
return (val);
}
static void
arc4_check_init(void)
{
if (!rs_initialized) {
arc4_init();
rs_initialized = 1;
_rs_stir_if_needed(n);
while (n > 0) {
if (rs->rs_have > 0) {
m = minimum(n, rs->rs_have);
keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
- rs->rs_have;
memcpy(buf, keystream, m);
memset(keystream, 0, m);
buf += m;
n -= m;
rs->rs_have -= m;
}
if (rs->rs_have == 0)
_rs_rekey(NULL, 0);
}
}
static inline void
arc4_check_stir(void)
_rs_random_u32(uint32_t *val)
{
if (!rs_stired || arc4_count <= 0) {
arc4_stir();
rs_stired = 1;
}
u_char *keystream;
_rs_stir_if_needed(sizeof(*val));
if (rs->rs_have < sizeof(*val))
_rs_rekey(NULL, 0);
keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
memcpy(val, keystream, sizeof(*val));
memset(keystream, 0, sizeof(*val));
rs->rs_have -= sizeof(*val);
}
void
arc4random_stir(void)
{
THREAD_LOCK();
arc4_check_init();
arc4_stir();
rs_stired = 1;
THREAD_UNLOCK();
_ARC4_LOCK();
_rs_stir();
_ARC4_UNLOCK();
}
void
arc4random_addrandom(u_char *dat, int datlen)
{
THREAD_LOCK();
arc4_check_init();
arc4_check_stir();
arc4_addrandom(dat, datlen);
THREAD_UNLOCK();
_ARC4_LOCK();
_rs_stir_if_needed(datlen);
_rs_rekey(dat, datlen);
_ARC4_UNLOCK();
}
u_int32_t
uint32_t
arc4random(void)
{
u_int32_t rnd;
uint32_t val;
THREAD_LOCK();
arc4_check_init();
arc4_check_stir();
rnd = arc4_getword();
arc4_count -= 4;
THREAD_UNLOCK();
return (rnd);
_ARC4_LOCK();
_rs_random_u32(&val);
_ARC4_UNLOCK();
return val;
}
void
arc4random_buf(void *_buf, size_t n)
arc4random_buf(void *buf, size_t n)
{
u_char *buf = (u_char *)_buf;
THREAD_LOCK();
arc4_check_init();
while (n--) {
arc4_check_stir();
buf[n] = arc4_getbyte();
arc4_count--;
}
THREAD_UNLOCK();
_ARC4_LOCK();
_rs_random_buf(buf, n);
_ARC4_UNLOCK();
}
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
u_int32_t
arc4random_uniform(u_int32_t upper_bound)
{
u_int32_t r, min;
if (upper_bound < 2)
return (0);
#if (ULONG_MAX > 0xffffffffUL)
min = 0x100000000UL % upper_bound;
#else
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
if (upper_bound > 0x80000000)
min = 1 + ~upper_bound; /* 2**32 - upper_bound */
else {
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
}
#endif
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return (r % upper_bound);
}
#if 0
/*-------- Test code for i386 --------*/
#include <stdio.h>
#include <machine/pctr.h>
int
main(int argc, char **argv)
{
const int iter = 1000000;
int i;
pctrval v;
v = rdtsc();
for (i = 0; i < iter; i++)
arc4random();
v = rdtsc() - v;
v /= iter;
printf("%qd cycles\n", v);
}
#endif

29
src/arc4random.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef LIBBSD_ARC4RANDOM_H
#define LIBBSD_ARC4RANDOM_H
#include <sys/param.h>
int
getentropy(void *buf, size_t len);
#if defined(__linux__)
#include "arc4random_linux.h"
#elif defined(__FreeBSD__)
#include "arc4random_bsd.h"
#elif defined(__NetBSD__)
#include "arc4random_bsd.h"
#elif defined(__OpenBSD__)
#include "arc4random_openbsd.h"
#elif defined(__sun)
#include "arc4random_unix.h"
#elif defined(__APPLE__)
#include "arc4random_unix.h"
#elif defined(_AIX)
#include "arc4random_unix.h"
#elif defined(__hpux)
#include "arc4random_unix.h"
#else
#error "No arc4random hooks defined for this platform."
#endif
#endif

86
src/arc4random_bsd.h Normal file
View File

@@ -0,0 +1,86 @@
/* $OpenBSD: arc4random_freebsd.h,v 1.2 2015/01/15 06:57:18 deraadt Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <pthread.h>
#include <signal.h>
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
/*
* Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
* a program does not link to -lthr. Callbacks registered with pthread_atfork()
* appear to fail silently. So, it is not always possible to detect a PID
* wraparound.
*/
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static volatile sig_atomic_t _rs_forked;
static inline void
_rs_forkhandler(void)
{
_rs_forked = 1;
}
static inline void
_rs_forkdetect(void)
{
static pid_t _rs_pid = 0;
pid_t pid = getpid();
if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
_rs_pid = pid;
_rs_forked = 0;
if (rs)
memset(rs, 0, sizeof(*rs));
}
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
munmap(*rsp, sizeof(**rsp));
return (-1);
}
_ARC4_ATFORK(_rs_forkhandler);
return (0);
}

86
src/arc4random_linux.h Normal file
View File

@@ -0,0 +1,86 @@
/* $OpenBSD: arc4random_linux.h,v 1.8 2014/08/13 06:04:10 deraadt Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <pthread.h>
#include <signal.h>
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
#ifdef __GLIBC__
extern void *__dso_handle;
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
#else
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
#endif
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static volatile sig_atomic_t _rs_forked;
static inline void
_rs_forkhandler(void)
{
_rs_forked = 1;
}
static inline void
_rs_forkdetect(void)
{
static pid_t _rs_pid = 0;
pid_t pid = getpid();
if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
_rs_pid = pid;
_rs_forked = 0;
if (rs)
memset(rs, 0, sizeof(*rs));
}
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
munmap(*rsp, sizeof(**rsp));
return (-1);
}
_ARC4_ATFORK(_rs_forkhandler);
return (0);
}

61
src/arc4random_openbsd.h Normal file
View File

@@ -0,0 +1,61 @@
/* $OpenBSD: arc4random.h,v 1.3 2014/07/20 20:51:13 bcook Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <signal.h>
#include "thread_private.h"
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
struct {
struct _rs rs;
struct _rsx rsx;
} *p;
if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if (minherit(p, sizeof(*p), MAP_INHERIT_ZERO) == -1) {
munmap(p, sizeof(*p));
return (-1);
}
*rsp = &p->rs;
*rsxp = &p->rsx;
return (0);
}
static inline void
_rs_forkdetect(void)
{
}

57
src/arc4random_uniform.c Normal file
View File

@@ -0,0 +1,57 @@
/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */
/*
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
uint32_t
arc4random_uniform(uint32_t upper_bound)
{
uint32_t r, min;
if (upper_bound < 2)
return 0;
/* 2**32 % x == (2**32 - x) % x */
min = -upper_bound % upper_bound;
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return r % upper_bound;
}
//DEF_WEAK(arc4random_uniform);

80
src/arc4random_unix.h Normal file
View File

@@ -0,0 +1,80 @@
/* $OpenBSD: arc4random_hpux.h,v 1.1 2015/01/06 21:08:11 bcook Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <pthread.h>
#include <signal.h>
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static volatile sig_atomic_t _rs_forked;
static inline void
_rs_forkhandler(void)
{
_rs_forked = 1;
}
static inline void
_rs_forkdetect(void)
{
static pid_t _rs_pid = 0;
pid_t pid = getpid();
if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
_rs_pid = pid;
_rs_forked = 0;
if (rs)
memset(rs, 0, sizeof(*rs));
}
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
munmap(*rsp, sizeof(**rsp));
return (-1);
}
_ARC4_ATFORK(_rs_forkhandler);
return (0);
}

222
src/chacha_private.h Normal file
View File

@@ -0,0 +1,222 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
/* $OpenBSD$ */
typedef unsigned char u8;
typedef unsigned int u32;
typedef struct
{
u32 input[16]; /* could be compressed */
} chacha_ctx;
#define U8C(v) (v##U)
#define U32C(v) (v##U)
#define U8V(v) ((u8)(v) & U8C(0xFF))
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
#define ROTL32(v, n) \
(U32V((v) << (n)) | ((v) >> (32 - (n))))
#define U8TO32_LITTLE(p) \
(((u32)((p)[0]) ) | \
((u32)((p)[1]) << 8) | \
((u32)((p)[2]) << 16) | \
((u32)((p)[3]) << 24))
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define ROTATE(v,c) (ROTL32(v,c))
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
static void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
{
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
static void
chacha_ivsetup(chacha_ctx *x,const u8 *iv)
{
x->input[12] = 0;
x->input[13] = 0;
x->input[14] = U8TO32_LITTLE(iv + 0);
x->input[15] = U8TO32_LITTLE(iv + 4);
}
static void
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
u8 *ctarget = NULL;
u8 tmp[64];
u_int i;
if (!bytes) return;
j0 = x->input[0];
j1 = x->input[1];
j2 = x->input[2];
j3 = x->input[3];
j4 = x->input[4];
j5 = x->input[5];
j6 = x->input[6];
j7 = x->input[7];
j8 = x->input[8];
j9 = x->input[9];
j10 = x->input[10];
j11 = x->input[11];
j12 = x->input[12];
j13 = x->input[13];
j14 = x->input[14];
j15 = x->input[15];
for (;;) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) tmp[i] = m[i];
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
x3 = j3;
x4 = j4;
x5 = j5;
x6 = j6;
x7 = j7;
x8 = j8;
x9 = j9;
x10 = j10;
x11 = j11;
x12 = j12;
x13 = j13;
x14 = j14;
x15 = j15;
for (i = 20;i > 0;i -= 2) {
QUARTERROUND( x0, x4, x8,x12)
QUARTERROUND( x1, x5, x9,x13)
QUARTERROUND( x2, x6,x10,x14)
QUARTERROUND( x3, x7,x11,x15)
QUARTERROUND( x0, x5,x10,x15)
QUARTERROUND( x1, x6,x11,x12)
QUARTERROUND( x2, x7, x8,x13)
QUARTERROUND( x3, x4, x9,x14)
}
x0 = PLUS(x0,j0);
x1 = PLUS(x1,j1);
x2 = PLUS(x2,j2);
x3 = PLUS(x3,j3);
x4 = PLUS(x4,j4);
x5 = PLUS(x5,j5);
x6 = PLUS(x6,j6);
x7 = PLUS(x7,j7);
x8 = PLUS(x8,j8);
x9 = PLUS(x9,j9);
x10 = PLUS(x10,j10);
x11 = PLUS(x11,j11);
x12 = PLUS(x12,j12);
x13 = PLUS(x13,j13);
x14 = PLUS(x14,j14);
x15 = PLUS(x15,j15);
#ifndef KEYSTREAM_ONLY
x0 = XOR(x0,U8TO32_LITTLE(m + 0));
x1 = XOR(x1,U8TO32_LITTLE(m + 4));
x2 = XOR(x2,U8TO32_LITTLE(m + 8));
x3 = XOR(x3,U8TO32_LITTLE(m + 12));
x4 = XOR(x4,U8TO32_LITTLE(m + 16));
x5 = XOR(x5,U8TO32_LITTLE(m + 20));
x6 = XOR(x6,U8TO32_LITTLE(m + 24));
x7 = XOR(x7,U8TO32_LITTLE(m + 28));
x8 = XOR(x8,U8TO32_LITTLE(m + 32));
x9 = XOR(x9,U8TO32_LITTLE(m + 36));
x10 = XOR(x10,U8TO32_LITTLE(m + 40));
x11 = XOR(x11,U8TO32_LITTLE(m + 44));
x12 = XOR(x12,U8TO32_LITTLE(m + 48));
x13 = XOR(x13,U8TO32_LITTLE(m + 52));
x14 = XOR(x14,U8TO32_LITTLE(m + 56));
x15 = XOR(x15,U8TO32_LITTLE(m + 60));
#endif
j12 = PLUSONE(j12);
if (!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
U32TO8_LITTLE(c + 0,x0);
U32TO8_LITTLE(c + 4,x1);
U32TO8_LITTLE(c + 8,x2);
U32TO8_LITTLE(c + 12,x3);
U32TO8_LITTLE(c + 16,x4);
U32TO8_LITTLE(c + 20,x5);
U32TO8_LITTLE(c + 24,x6);
U32TO8_LITTLE(c + 28,x7);
U32TO8_LITTLE(c + 32,x8);
U32TO8_LITTLE(c + 36,x9);
U32TO8_LITTLE(c + 40,x10);
U32TO8_LITTLE(c + 44,x11);
U32TO8_LITTLE(c + 48,x12);
U32TO8_LITTLE(c + 52,x13);
U32TO8_LITTLE(c + 56,x14);
U32TO8_LITTLE(c + 60,x15);
if (bytes <= 64) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) ctarget[i] = c[i];
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
#ifndef KEYSTREAM_ONLY
m += 64;
#endif
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2005, 2007, 2010
* Copyright (c) 2004-2005, 2007, 2010, 2012-2014
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -18,7 +18,6 @@
#include <config.h>
#include <sys/types.h>
#include <sys/param.h>
#include <unistd.h>
#include <stdio.h>
#ifdef STDC_HEADERS
@@ -30,20 +29,26 @@
# endif
#endif /* STDC_HEADERS */
#include <fcntl.h>
#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#include <limits.h>
#ifdef HAVE_PSTAT_GETPROC
# include <sys/param.h>
# include <sys/pstat.h>
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
# else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
# endif
#endif
@@ -51,15 +56,24 @@
# define OPEN_MAX 256
#endif
#ifndef HAVE_FCNTL_CLOSEM
# ifndef HAVE_DIRFD
# define closefrom_fallback closefrom
# endif
#if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)
# define closefrom closefrom_fallback
#endif
static inline void
closefrom_close(int fd)
{
#ifdef __APPLE__
/* Avoid potential libdispatch crash when we close its fds. */
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
#else
(void)close(fd);
#endif
}
/*
* Close all file descriptors greater than or equal to lowfd.
* This is the expensive (ballback) method.
* This is the expensive (fallback) method.
*/
void
closefrom_fallback(int lowfd)
@@ -80,43 +94,99 @@ closefrom_fallback(int lowfd)
maxfd = OPEN_MAX;
for (fd = lowfd; fd < maxfd; fd++)
(void)close((int)fd);
closefrom_close(fd);
}
/*
* Close all file descriptors greater than or equal to lowfd.
* We try the fast way first, falling back on the slow method.
*/
#ifdef HAVE_FCNTL_CLOSEM
#if defined(HAVE_FCNTL_CLOSEM)
void
closefrom(int lowfd)
{
if (fcntl(lowfd, F_CLOSEM, 0) == -1)
closefrom_fallback(lowfd);
}
#else
# ifdef HAVE_DIRFD
#elif defined(HAVE_PSTAT_GETPROC)
void
closefrom(int lowfd)
{
struct dirent *dent;
DIR *dirp;
char *endp;
long fd;
struct pst_status pstat;
int fd;
/* Use /proc/self/fd directory if it exists. */
dirp = opendir("/proc/self/fd");
if (dirp != NULL) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd &&
fd != dirfd(dirp))
(void)close((int)fd);
}
(void)closedir(dirp);
} else
if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1) {
for (fd = lowfd; fd <= pstat.pst_highestfd; fd++)
(void)close(fd);
} else {
closefrom_fallback(lowfd);
}
}
#elif defined(HAVE_DIRFD)
static int
closefrom_procfs(int lowfd)
{
const char *path;
DIR *dirp;
struct dirent *dent;
int *fd_array = NULL;
int fd_array_used = 0;
int fd_array_size = 0;
int ret = 0;
int i;
/* Use /proc/self/fd (or /dev/fd on FreeBSD) if it exists. */
# if defined(__FreeBSD__) || defined(__APPLE__)
path = "/dev/fd";
# else
path = "/proc/self/fd";
# endif
dirp = opendir(path);
if (dirp == NULL)
return -1;
while ((dent = readdir(dirp)) != NULL) {
const char *errstr;
int fd;
fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
if (errstr != NULL || fd == dirfd(dirp))
continue;
if (fd_array_used >= fd_array_size) {
int *ptr;
if (fd_array_size > 0)
fd_array_size *= 2;
else
fd_array_size = 32;
ptr = reallocarray(fd_array, fd_array_size, sizeof(int));
if (ptr == NULL) {
ret = -1;
break;
}
fd_array = ptr;
}
fd_array[fd_array_used++] = fd;
}
for (i = 0; i < fd_array_used; i++)
closefrom_close(fd_array[i]);
free(fd_array);
(void)closedir(dirp);
return ret;
}
void
closefrom(int lowfd)
{
if (closefrom_procfs(lowfd) == 0)
return;
closefrom_fallback(lowfd);
}
#endif /* HAVE_DIRFD */
#endif /* HAVE_FCNTL_CLOSEM */

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org>
* Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,8 +35,8 @@
int
dehumanize_number(const char *buf, int64_t *num)
{
uint64_t rval;
int sign = 1;
uint64_t rval, rmax;
int sign = +1;
int rc;
/* The current expand_number() implementation uses bit shifts, so
@@ -52,7 +52,13 @@ dehumanize_number(const char *buf, int64_t *num)
rc = expand_number(buf, &rval);
if (rc < 0)
return rc;
if (rval == UINT64_MAX && sign == -1) {
/* The sign has been stripped, so rval has the absolute value.
* Error out, regardless of the sign, if rval is greater than
* abs(INT64_MIN) (== INT64_MAX + 1), or if the sign is positive
* and the value has overflown by one (INT64_MAX + 1). */
rmax = INT64_MAX + 1ULL;
if (rval > rmax || (rval == rmax && sign == +1)) {
errno = ERANGE;
return -1;
}

19
src/explicit_bzero.c Normal file
View File

@@ -0,0 +1,19 @@
/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
/*
* Public domain.
* Written by Matthew Dempsky.
*/
#include <string.h>
__attribute__((weak)) void
__explicit_bzero_hook(void *buf, size_t len)
{
}
void
explicit_bzero(void *buf, size_t len)
{
memset(buf, 0, len);
__explicit_bzero_hook(buf, len);
}

View File

@@ -30,6 +30,8 @@
#include <sys/types.h>
#include <string.h>
#include "local-link.h"
#ifdef HAVE_GETLINE
struct filebuf {
FILE *fp;
@@ -48,6 +50,8 @@ fgetln(FILE *stream, size_t *len)
struct filebuf *fb;
ssize_t nread;
flockfile(stream);
/* Try to diminish the possibility of several fgetln() calls being
* used on different streams, by using a pool of buffers per file. */
fb = &fb_pool[fb_pool_cur];
@@ -59,6 +63,9 @@ fgetln(FILE *stream, size_t *len)
fb->fp = stream;
nread = getline(&fb->buf, &fb->len, stream);
funlockfile(stream);
/* Note: the getdelim/getline API ensures nread != 0. */
if (nread == -1) {
*len = 0;
@@ -68,6 +75,9 @@ fgetln(FILE *stream, size_t *len)
return fb->buf;
}
}
libbsd_link_warning(fgetln,
"This functions cannot be safely ported, use getline(3) "
"instead, as it is supported by GNU and POSIX.1-2008.")
#else
#error "Function fgetln() needs to be ported."
#endif

View File

@@ -68,7 +68,7 @@ fgetwln(FILE *stream, size_t *lenp)
else
fb->len = FILEWBUF_INIT_LEN;
wp = realloc(fb->wbuf, fb->len * sizeof(wchar_t));
wp = reallocarray(fb->wbuf, fb->len, sizeof(wchar_t));
if (wp == NULL) {
wused = 0;
break;

View File

@@ -35,8 +35,6 @@ __RCSID("$NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $");
#include <string.h>
#include <stdlib.h>
#define FLOCKFILE(fp)
#define FUNLOCKFILE(fp)
#define _DIAGASSERT(t)
static int isescaped(const char *, const char *, int);
@@ -77,7 +75,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
{
static const char dstr[3] = { '\\', '\\', '#' };
size_t s, len;
ssize_t s;
size_t len, ptrlen;
char *buf;
char *ptr, *cp;
int cnt;
@@ -87,6 +86,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
len = 0;
buf = NULL;
ptrlen = 0;
ptr = NULL;
cnt = 1;
if (str == NULL)
@@ -97,11 +98,11 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
com = str[2];
/*
* XXX: it would be cool to be able to specify the newline character,
* but unfortunately, fgetln does not let us
* getdelim(3) does let us, but supporting it would diverge from BSDs.
*/
nl = '\n';
FLOCKFILE(fp);
flockfile(fp);
while (cnt) {
cnt = 0;
@@ -109,7 +110,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
if (lineno)
(*lineno)++;
if ((ptr = fgetln(fp, &s)) == NULL)
s = getline(&ptr, &ptrlen, fp);
if (s < 0)
break;
if (s && com) { /* Check and eliminate comments */
@@ -147,8 +149,9 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
}
if ((cp = realloc(buf, len + s + 1)) == NULL) {
FUNLOCKFILE(fp);
funlockfile(fp);
free(buf);
free(ptr);
return NULL;
}
buf = cp;
@@ -158,7 +161,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
buf[len] = '\0';
}
FUNLOCKFILE(fp);
funlockfile(fp);
free(ptr);
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
strchr(buf, esc) != NULL) {
@@ -195,36 +199,3 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
*size = len;
return buf;
}
#ifdef TEST
int main(int, char **);
int
main(int argc, char **argv)
{
char *ptr;
size_t size, line;
line = 0;
while ((ptr = fparseln(stdin, &size, &line, NULL,
FPARSELN_UNESCALL)) != NULL)
printf("line %d (%d) |%s|\n", line, size, ptr);
return 0;
}
/*
# This is a test
line 1
line 2 \
line 3 # Comment
line 4 \# Not comment \\\\
# And a comment \
line 5 \\\
line 6
*/
#endif /* TEST */

View File

@@ -44,23 +44,3 @@ fpurge(FILE *fp)
#else
#error "Function fpurge() needs to be ported."
#endif
#ifdef TEST
int
main()
{
static FILE fp_bad;
FILE *fp;
if (fpurge(&fp_bad) == 0)
return 1;
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
fclose(fp);
return 0;
}
#endif

142
src/funopen.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* Copyright © 2011, 2013 Guillem Jover
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_FOPENCOOKIE
struct funopen_cookie {
void *orig_cookie;
int (*readfn)(void *cookie, char *buf, int size);
int (*writefn)(void *cookie, const char *buf, int size);
off_t (*seekfn)(void *cookie, off_t offset, int whence);
int (*closefn)(void *cookie);
};
static ssize_t
funopen_read(void *cookie, char *buf, size_t size)
{
struct funopen_cookie *cookiewrap = cookie;
if (cookiewrap->readfn == NULL) {
errno = EBADF;
return -1;
}
return cookiewrap->readfn(cookiewrap->orig_cookie, buf, size);
}
static ssize_t
funopen_write(void *cookie, const char *buf, size_t size)
{
struct funopen_cookie *cookiewrap = cookie;
if (cookiewrap->writefn == NULL)
return EOF;
return cookiewrap->writefn(cookiewrap->orig_cookie, buf, size);
}
static int
funopen_seek(void *cookie, off64_t *offset, int whence)
{
struct funopen_cookie *cookiewrap = cookie;
off_t soff = *offset;
if (cookiewrap->seekfn == NULL) {
errno = ESPIPE;
return -1;
}
soff = cookiewrap->seekfn(cookiewrap->orig_cookie, soff, whence);
*offset = soff;
return *offset;
}
static int
funopen_close(void *cookie)
{
struct funopen_cookie *cookiewrap = cookie;
int rc;
if (cookiewrap->closefn == NULL)
return 0;
rc = cookiewrap->closefn(cookiewrap->orig_cookie);
free(cookiewrap);
return rc;
}
FILE *
funopen(const void *cookie,
int (*readfn)(void *cookie, char *buf, int size),
int (*writefn)(void *cookie, const char *buf, int size),
off_t (*seekfn)(void *cookie, off_t offset, int whence),
int (*closefn)(void *cookie))
{
struct funopen_cookie *cookiewrap;
cookie_io_functions_t funcswrap = {
.read = funopen_read,
.write = funopen_write,
.seek = funopen_seek,
.close = funopen_close,
};
const char *mode;
if (readfn) {
if (writefn == NULL)
mode = "r";
else
mode = "r+";
} else if (writefn) {
mode = "w";
} else {
errno = EINVAL;
return NULL;
}
cookiewrap = malloc(sizeof(*cookiewrap));
if (cookiewrap == NULL)
return NULL;
cookiewrap->orig_cookie = (void *)cookie;
cookiewrap->readfn = readfn;
cookiewrap->writefn = writefn;
cookiewrap->seekfn = seekfn;
cookiewrap->closefn = closefn;
return fopencookie(cookiewrap, mode, funcswrap);
}
#else
#error "Function funopen() needs to be ported."
#endif

102
src/getbsize.c Normal file
View File

@@ -0,0 +1,102 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)getbsize.c 8.1 (Berkeley) 6/4/93
* $FreeBSD: src/lib/libc/gen/getbsize.c,v 1.9 2008/08/04 06:53:13 cperciva Exp $
* $DragonFly: src/lib/libc/gen/getbsize.c,v 1.4 2005/11/13 00:07:42 swildner Exp $
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *
getbsize(int *headerlenp, long *blocksizep)
{
static char header[20];
long n, max, mul, blocksize;
char *ep, *p;
const char *form;
#define KB (1024L)
#define MB (1024L * 1024L)
#define GB (1024L * 1024L * 1024L)
#define MAXB GB /* No tera, peta, nor exa. */
form = "";
if ((p = getenv("BLOCKSIZE")) != NULL && *p != '\0') {
if ((n = strtol(p, &ep, 10)) < 0)
goto underflow;
if (n == 0)
n = 1;
if (*ep && ep[1])
goto fmterr;
switch (*ep) {
case 'G': case 'g':
form = "G";
max = MAXB / GB;
mul = GB;
break;
case 'K': case 'k':
form = "K";
max = MAXB / KB;
mul = KB;
break;
case 'M': case 'm':
form = "M";
max = MAXB / MB;
mul = MB;
break;
case '\0':
max = MAXB;
mul = 1;
break;
default:
fmterr: warnx("%s: unknown blocksize", p);
n = 512;
max = MAXB;
mul = 1;
break;
}
if (n > max) {
warnx("maximum blocksize is %ldG", MAXB / GB);
n = max;
}
if ((blocksize = n * mul) < 512) {
underflow: warnx("minimum blocksize is 512");
form = "";
blocksize = n = 512;
}
} else
blocksize = n = 512;
snprintf(header, sizeof(header), "%ld%s-blocks", n, form);
*headerlenp = strlen(header);
*blocksizep = blocksize;
return (header);
}

43
src/getentropy.c Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__linux__)
#include "getentropy_linux.c"
#elif defined(__FreeBSD__)
#include "arc4random_bsd.c"
#elif defined(__NetBSD__)
#include "arc4random_bsd.c"
#elif defined(__sun)
#include "arc4random_solaris.c"
#elif defined(__APPLE__)
#include "arc4random_osx.c"
#elif defined(_AIX)
#include "arc4random_aix.c"
#elif defined(__hpux)
#include "arc4random_hpux.c"
#else
#error "No getentropy hooks defined for this platform."
#endif

425
src/getentropy_aix.c Normal file
View File

@@ -0,0 +1,425 @@
/* $OpenBSD: getentropy_aix.c,v 1.3 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2015 Michael Felt <aixtools@gmail.com>
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
/*
* -lperfstat is needed for the psuedo entropy data
*/
#include <sys/mman.h>
#include <sys/procfs.h>
#include <sys/protosw.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/timers.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <openssl/sha.h>
#include <libperfstat.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on AIX that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that AIX
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that AIX should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
perfstat_cpu_total_t cpustats;
#ifdef _AIX61
perfstat_cpu_total_wpar_t cpustats_wpar;
#endif
perfstat_partition_total_t lparstats;
perfstat_disk_total_t diskinfo;
perfstat_netinterface_total_t netinfo;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HX(perfstat_cpu_total(NULL, &cpustats,
sizeof(cpustats), 1) == -1, cpustats);
#ifdef _AIX61
HX(perfstat_cpu_total_wpar(NULL, &cpustats_wpar,
sizeof(cpustats_wpar), 1) == -1, cpustats_wpar);
#endif
HX(perfstat_partition_total(NULL, &lparstats,
sizeof(lparstats), 1) == -1, lparstats);
HX(perfstat_disk_total(NULL, &diskinfo,
sizeof(diskinfo), 1) == -1, diskinfo);
HX(perfstat_netinterface_total(NULL, &netinfo,
sizeof(netinfo), 1) == -1, netinfo);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

62
src/getentropy_bsd.c Normal file
View File

@@ -0,0 +1,62 @@
/* $OpenBSD: getentropy_freebsd.c,v 1.1 2014/11/03 06:23:30 bcook Exp $ */
/*
* Copyright (c) 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* Copyright (c) 2014 Brent Cook <bcook@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <stddef.h>
/*
* Derived from lib/libc/gen/arc4random.c from FreeBSD.
*/
static size_t
getentropy_sysctl(u_char *buf, size_t size)
{
int mib[2];
size_t len, done;
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
done = 0;
do {
len = size;
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
return (done);
done += len;
buf += len;
size -= len;
} while (size > 0);
return (done);
}
int
getentropy(void *buf, size_t len)
{
if (len <= 256 && getentropy_sysctl(buf, len) == len)
return (0);
errno = EIO;
return (-1);
}

419
src/getentropy_hpux.c Normal file
View File

@@ -0,0 +1,419 @@
/* $OpenBSD: getentropy_hpux.c,v 1.3 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <openssl/sha.h>
#include <sys/vfs.h>
#include <sys/pstat.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on hpux that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that hpux
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that hpux should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct pst_vminfo pvi;
struct pst_vm_status pvs;
struct pst_dynamic pdy;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HX(pstat_getvminfo(&pvi, sizeof(pvi), 1, 0) != 1, pvi);
HX(pstat_getprocvm(&pvs, sizeof(pvs), 0, 0) != 1, pvs);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if(pstat_getdynamic(&pdy, sizeof(pdy), 1, 0) != 1) {
HD(errno);
} else {
HD(pdy.psd_avg_1_min);
HD(pdy.psd_avg_5_min);
HD(pdy.psd_avg_15_min);
}
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

547
src/getentropy_linux.c Normal file
View File

@@ -0,0 +1,547 @@
/* $OpenBSD: getentropy_linux.c,v 1.40 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#define _POSIX_C_SOURCE 199309L
#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#ifdef SYS__sysctl
#include <linux/sysctl.h>
#endif
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <openssl/sha.h>
#include <linux/types.h>
#include <linux/random.h>
#ifdef HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
#ifdef SYS_getrandom
static int getentropy_getrandom(void *buf, size_t len);
#endif
static int getentropy_urandom(void *buf, size_t len);
#ifdef SYS__sysctl
static int getentropy_sysctl(void *buf, size_t len);
#endif
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
#ifdef SYS_getrandom
/*
* Try descriptor-less getrandom()
*/
ret = getentropy_getrandom(buf, len);
if (ret != -1)
return (ret);
if (errno != ENOSYS)
return (-1);
#endif
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
#ifdef SYS__sysctl
/*
* Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
* sysctl is a failsafe API, so it guarantees a result. This
* should work inside a chroot, or when file descriptors are
* exhuasted.
*
* However this can fail if the Linux kernel removes support
* for sysctl. Starting in 2007, there have been efforts to
* deprecate the sysctl API/ABI, and push callers towards use
* of the chroot-unavailable fd-using /proc mechanism --
* essentially the same problems as /dev/urandom.
*
* Numerous setbacks have been encountered in their deprecation
* schedule, so as of June 2014 the kernel ABI still exists on
* most Linux architectures. The sysctl() stub in libc is missing
* on some systems. There are also reports that some kernels
* spew messages to the console.
*/
ret = getentropy_sysctl(buf, len);
if (ret != -1)
return (ret);
#endif /* SYS__sysctl */
/*
* Entropy collection via /dev/urandom and sysctl have failed.
*
* No other API exists for collecting entropy. See the large
* comment block above.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Linux
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Linux should either retain their
* sysctl ABI, or consider providing a new failsafe API which
* works in a chroot or when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
#ifdef SYS_getrandom
static int
getentropy_getrandom(void *buf, size_t len)
{
int pre_errno = errno;
int ret;
if (len > 256)
return (-1);
do {
ret = syscall(SYS_getrandom, buf, len, 0);
} while (ret == -1 && errno == EINTR);
if (ret != (int)len)
return (-1);
errno = pre_errno;
return (0);
}
#endif
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, cnt, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
#ifdef SYS__sysctl
static int
getentropy_sysctl(void *buf, size_t len)
{
static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
size_t i;
int save_errno = errno;
for (i = 0; i < len; ) {
size_t chunk = min(len - i, 16);
/* SYS__sysctl because some systems already removed sysctl() */
struct __sysctl_args args = {
.name = mib,
.nlen = 3,
.oldval = (char *)buf + i,
.oldlenp = &chunk,
};
if (syscall(SYS__sysctl, &args) != 0)
goto sysctlfailed;
i += chunk;
}
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
sysctlfailed:
errno = EIO;
return (-1);
}
#endif /* SYS__sysctl */
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
#ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */
p = (char *) getauxval(AT_RANDOM);
if (p)
HR(p, 16);
#endif
#ifdef AT_SYSINFO_EHDR
p = (char *) getauxval(AT_SYSINFO_EHDR);
if (p)
HR(p, pgs);
#endif
#ifdef AT_BASE
p = (char *) getauxval(AT_BASE);
if (p)
HD(p);
#endif
#endif
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

429
src/getentropy_osx.c Normal file
View File

@@ -0,0 +1,429 @@
/* $OpenBSD: getentropy_osx.c,v 1.8 2014/07/21 20:19:47 guenther Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <mach/mach_time.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <sys/socketvar.h>
#include <sys/vmmeter.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/tcp_var.h>
#include <netinet/udp_var.h>
#include <CommonCrypto/CommonDigest.h>
#define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c)))
#define SHA512_Init(xxx) (CC_SHA512_Init((xxx)))
#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy)))
#define SHA512_CTX CC_SHA512_CTX
#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom and sysctl have failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on OSX that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that OSX
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that OSX should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
static int kmib[] = { CTL_KERN, KERN_USRSTACK };
static int hwmib[] = { CTL_HW, HW_USERMEM };
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
struct tcpstat tcpstat;
struct udpstat udpstat;
struct ipstat ipstat;
uint64_t mach_time;
unsigned int idata;
void *addr;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
mach_time = mach_absolute_time();
HD(mach_time);
ii = sizeof(addr);
HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
&addr, &ii, NULL, 0) == -1, addr);
ii = sizeof(idata);
HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
&idata, &ii, NULL, 0) == -1, idata);
ii = sizeof(tcpstat);
HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
&tcpstat, &ii, NULL, 0) == -1, tcpstat);
ii = sizeof(udpstat);
HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
&udpstat, &ii, NULL, 0) == -1, udpstat);
ii = sizeof(ipstat);
HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
&ipstat, &ii, NULL, 0) == -1, ipstat);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
mach_time = mach_absolute_time();
HD(mach_time);
cnt += (int)mach_time;
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

445
src/getentropy_solaris.c Normal file
View File

@@ -0,0 +1,445 @@
/* $OpenBSD: getentropy_solaris.c,v 1.10 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/sha2.h>
#define SHA512_Init SHA512Init
#define SHA512_Update SHA512Update
#define SHA512_Final SHA512Final
#include <sys/vfs.h>
#include <sys/statfs.h>
#include <sys/loadavg.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* Solaris provides /dev/urandom as a symbolic link to
* /devices/pseudo/random@0:urandom which is provided by
* a devfs filesystem. Best practice is to use O_NOFOLLOW,
* so we must try the unpublished name directly.
*
* This can fail if the process is inside a chroot which lacks
* the devfs mount, or if file descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len,
"/devices/pseudo/random@0:urandom", 1);
if (ret != -1)
return (ret);
/*
* Unfortunately, chroot spaces on Solaris are sometimes setup
* with direct device node of the well-known /dev/urandom name
* (perhaps to avoid dragging all of devfs into the space).
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on Solaris that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Solaris
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Solaris should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) ||
(devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
double loadavg[3];
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
HX((getloadavg(loadavg, 3) == -1), loadavg);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

View File

@@ -27,7 +27,7 @@ char *
HASHEnd(HASH_CTX *ctx, char *buf)
{
int i;
u_int8_t digest[HASH_DIGEST_LENGTH];
uint8_t digest[HASH_DIGEST_LENGTH];
#ifdef HASH_DIGEST_UPPERCASE
static const char hex[] = "0123456789ABCDEF";
#else

View File

@@ -37,7 +37,7 @@
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
static u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -71,7 +71,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
need = MD5_BLOCK_LENGTH - have;
/* Update bitcount */
ctx->count += (u_int64_t)len << 3;
ctx->count += (uint64_t)len << 3;
if (len >= need) {
if (have != 0) {
@@ -102,7 +102,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
void
MD5Pad(MD5_CTX *ctx)
{
u_int8_t count[8];
uint8_t count[8];
size_t padlen;
/* Convert count to 8 bytes in little endian order. */
@@ -152,19 +152,19 @@ MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
* the data and converts bytes into longwords for this routine.
*/
void
MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
#if BYTE_ORDER == LITTLE_ENDIAN
memcpy(in, block, sizeof(in));
#else
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
in[a] = (u_int32_t)(
(u_int32_t)(block[a * 4 + 0]) |
(u_int32_t)(block[a * 4 + 1]) << 8 |
(u_int32_t)(block[a * 4 + 2]) << 16 |
(u_int32_t)(block[a * 4 + 3]) << 24);
in[a] = (uint32_t)(
(uint32_t)(block[a * 4 + 0]) |
(uint32_t)(block[a * 4 + 1]) << 8 |
(uint32_t)(block[a * 4 + 2]) << 16 |
(uint32_t)(block[a * 4 + 3]) << 24);
}
#endif

51
src/hash/sha512.h Normal file
View File

@@ -0,0 +1,51 @@
/*-
* Copyright 2005 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SHA512_H_
#define _SHA512_H_
#include <sys/types.h>
typedef struct SHA512Context {
uint64_t state[8];
uint64_t count[2];
unsigned char buf[128];
} SHA512_CTX;
__BEGIN_DECLS
void SHA512_Init(SHA512_CTX *);
void SHA512_Update(SHA512_CTX *, const void *, size_t);
void SHA512_Final(unsigned char [64], SHA512_CTX *);
char *SHA512_End(SHA512_CTX *, char *);
char *SHA512_File(const char *, char *);
char *SHA512_FileChunk(const char *, char *, off_t, off_t);
char *SHA512_Data(const void *, unsigned int, char *);
__END_DECLS
#endif /* !_SHA512_H_ */

320
src/hash/sha512c.c Normal file
View File

@@ -0,0 +1,320 @@
/*-
* Copyright 2005 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/types.h>
#include <string.h>
#include "sha512.h"
#if BYTE_ORDER == BIG_ENDIAN
/* Copy a vector of big-endian uint64_t into a vector of bytes */
#define be64enc_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
/* Copy a vector of bytes into a vector of big-endian uint64_t */
#define be64dec_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
#else /* BYTE_ORDER != BIG_ENDIAN */
/*
* Encode a length len/4 vector of (uint64_t) into a length len vector of
* (unsigned char) in big-endian form. Assumes len is a multiple of 8.
*/
static void
be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
be64enc(dst + i * 8, src[i]);
}
/*
* Decode a big-endian length len vector of (unsigned char) into a length
* len/4 vector of (uint64_t). Assumes len is a multiple of 8.
*/
static void
be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
dst[i] = be64dec(src + i * 8);
}
#endif /* BYTE_ORDER != BIG_ENDIAN */
/* Elementary functions used by SHA512 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
/* SHA512 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
t0 = h + S1(e) + Ch(e, f, g) + k; \
t1 = S0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, k) \
RND(S[(80 - i) % 8], S[(81 - i) % 8], \
S[(82 - i) % 8], S[(83 - i) % 8], \
S[(84 - i) % 8], S[(85 - i) % 8], \
S[(86 - i) % 8], S[(87 - i) % 8], \
W[i] + k)
/*
* SHA512 block compression function. The 512-bit state is transformed via
* the 512-bit input block to produce a new state.
*/
static void
SHA512_Transform(uint64_t * state, const unsigned char block[128])
{
uint64_t W[80];
uint64_t S[8];
uint64_t t0, t1;
int i;
/* 1. Prepare message schedule W. */
be64dec_vect(W, block, 128);
for (i = 16; i < 80; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 64);
/* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
RNDr(S, W, 1, 0x7137449123ef65cdULL);
RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
RNDr(S, W, 4, 0x3956c25bf348b538ULL);
RNDr(S, W, 5, 0x59f111f1b605d019ULL);
RNDr(S, W, 6, 0x923f82a4af194f9bULL);
RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
RNDr(S, W, 8, 0xd807aa98a3030242ULL);
RNDr(S, W, 9, 0x12835b0145706fbeULL);
RNDr(S, W, 10, 0x243185be4ee4b28cULL);
RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
RNDr(S, W, 12, 0x72be5d74f27b896fULL);
RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
RNDr(S, W, 15, 0xc19bf174cf692694ULL);
RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
RNDr(S, W, 23, 0x76f988da831153b5ULL);
RNDr(S, W, 24, 0x983e5152ee66dfabULL);
RNDr(S, W, 25, 0xa831c66d2db43210ULL);
RNDr(S, W, 26, 0xb00327c898fb213fULL);
RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
RNDr(S, W, 29, 0xd5a79147930aa725ULL);
RNDr(S, W, 30, 0x06ca6351e003826fULL);
RNDr(S, W, 31, 0x142929670a0e6e70ULL);
RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
RNDr(S, W, 35, 0x53380d139d95b3dfULL);
RNDr(S, W, 36, 0x650a73548baf63deULL);
RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
RNDr(S, W, 39, 0x92722c851482353bULL);
RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
RNDr(S, W, 41, 0xa81a664bbc423001ULL);
RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
RNDr(S, W, 43, 0xc76c51a30654be30ULL);
RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
RNDr(S, W, 45, 0xd69906245565a910ULL);
RNDr(S, W, 46, 0xf40e35855771202aULL);
RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
RNDr(S, W, 49, 0x1e376c085141ab53ULL);
RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
RNDr(S, W, 57, 0x78a5636f43172f60ULL);
RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
RNDr(S, W, 59, 0x8cc702081a6439ecULL);
RNDr(S, W, 60, 0x90befffa23631e28ULL);
RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
RNDr(S, W, 63, 0xc67178f2e372532bULL);
RNDr(S, W, 64, 0xca273eceea26619cULL);
RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
RNDr(S, W, 68, 0x06f067aa72176fbaULL);
RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
RNDr(S, W, 70, 0x113f9804bef90daeULL);
RNDr(S, W, 71, 0x1b710b35131c471bULL);
RNDr(S, W, 72, 0x28db77f523047d84ULL);
RNDr(S, W, 73, 0x32caab7b40c72493ULL);
RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
RNDr(S, W, 75, 0x431d67c49c100d4cULL);
RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
RNDr(S, W, 77, 0x597f299cfc657e2aULL);
RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
RNDr(S, W, 79, 0x6c44198c4a475817ULL);
/* 4. Mix local working variables into global state */
for (i = 0; i < 8; i++)
state[i] += S[i];
}
static unsigned char PAD[128] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Add padding and terminating bit-count. */
static void
SHA512_Pad(SHA512_CTX * ctx)
{
unsigned char len[16];
uint64_t r, plen;
/*
* Convert length to a vector of bytes -- we do this now rather
* than later because the length will change after we pad.
*/
be64enc_vect(len, ctx->count, 16);
/* Add 1--128 bytes so that the resulting length is 112 mod 128 */
r = (ctx->count[1] >> 3) & 0x7f;
plen = (r < 112) ? (112 - r) : (240 - r);
SHA512_Update(ctx, PAD, (size_t)plen);
/* Add the terminating bit-count */
SHA512_Update(ctx, len, 16);
}
/* SHA-512 initialization. Begins a SHA-512 operation. */
void
SHA512_Init(SHA512_CTX * ctx)
{
/* Zero bits processed so far */
ctx->count[0] = ctx->count[1] = 0;
/* Magic initialization constants */
ctx->state[0] = 0x6a09e667f3bcc908ULL;
ctx->state[1] = 0xbb67ae8584caa73bULL;
ctx->state[2] = 0x3c6ef372fe94f82bULL;
ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
ctx->state[4] = 0x510e527fade682d1ULL;
ctx->state[5] = 0x9b05688c2b3e6c1fULL;
ctx->state[6] = 0x1f83d9abfb41bd6bULL;
ctx->state[7] = 0x5be0cd19137e2179ULL;
}
/* Add bytes into the hash */
void
SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
{
uint64_t bitlen[2];
uint64_t r;
const unsigned char *src = in;
/* Number of bytes left in the buffer from previous updates */
r = (ctx->count[1] >> 3) & 0x7f;
/* Convert the length into a number of bits */
bitlen[1] = ((uint64_t)len) << 3;
bitlen[0] = ((uint64_t)len) >> 61;
/* Update number of bits */
if ((ctx->count[1] += bitlen[1]) < bitlen[1])
ctx->count[0]++;
ctx->count[0] += bitlen[0];
/* Handle the case where we don't need to perform any transforms */
if (len < 128 - r) {
memcpy(&ctx->buf[r], src, len);
return;
}
/* Finish the current block */
memcpy(&ctx->buf[r], src, 128 - r);
SHA512_Transform(ctx->state, ctx->buf);
src += 128 - r;
len -= 128 - r;
/* Perform complete blocks */
while (len >= 128) {
SHA512_Transform(ctx->state, src);
src += 128;
len -= 128;
}
/* Copy left over data into buffer */
memcpy(ctx->buf, src, len);
}
/*
* SHA-512 finalization. Pads the input data, exports the hash value,
* and clears the context state.
*/
void
SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
{
/* Add padding */
SHA512_Pad(ctx);
/* Write the hash */
be64enc_vect(digest, ctx->state, 64);
/* Clear the context state */
memset((void *)ctx, 0, sizeof(*ctx));
}

View File

@@ -130,10 +130,8 @@
* only advantage over quicksort is that it requires little additional memory.
*/
int
heapsort(vbase, nmemb, size, compar)
void *vbase;
size_t nmemb, size;
int (*compar)(const void *, const void *);
heapsort(void *vbase, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
size_t cnt, i, j, l;
char tmp, *tmp1, *tmp2;

View File

@@ -55,11 +55,7 @@ static int inet_net_pton_ipv4(const char *src, u_char *dst, size_t size);
* Paul Vixie (ISC), June 1996
*/
int
inet_net_pton(af, src, dst, size)
int af;
const char *src;
void *dst;
size_t size;
inet_net_pton(int af, const char *src, void *dst, size_t size)
{
switch (af) {
case AF_INET:
@@ -87,10 +83,7 @@ inet_net_pton(af, src, dst, size)
* Paul Vixie (ISC), June 1996
*/
static int
inet_net_pton_ipv4(src, dst, size)
const char *src;
u_char *dst;
size_t size;
inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
{
static const char
xdigits[] = "0123456789abcdef",

12
src/libbsd-ctor.pc.in Normal file
View File

@@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libbsd-ctor
Description: Automatic constructor functions for libbsd
Version: @VERSION@
URL: http://libbsd.freedesktop.org/
Cflags: -I${includedir}
Libs: -L${libdir} -Wl,-z,nodlopen -Wl,-u,libbsd_init_func -lbsd-ctor
Requires: libbsd

View File

@@ -105,3 +105,34 @@ LIBBSD_0.5 {
wcslcat;
wcslcpy;
} LIBBSD_0.4;
LIBBSD_0.6 {
/* Exported to cope with the constructor+dlopen+threads mess. */
setproctitle_init;
} LIBBSD_0.5;
LIBBSD_0.7 {
getbsize;
funopen;
reallocarray;
sl_init;
sl_add;
sl_free;
sl_find;
_time32_to_time;
_time_to_time32;
_time64_to_time;
_time_to_time64;
_time_to_long;
_long_to_time;
_time_to_int;
_int_to_time;
} LIBBSD_0.6;
LIBBSD_0.8 {
explicit_bzero;
} LIBBSD_0.7;

View File

@@ -134,6 +134,12 @@
#define ELF_TARG_DATA ELFDATA2LSB
#endif
#elif defined(__nios2__)
#define ELF_TARG_MACH EM_ALTERA_NIOS2
#define ELF_TARG_CLASS ELFCLASS32
#define ELF_TARG_DATA ELFDATA2LSB
#elif defined(__powerpc__)
#define ELF_TARG_MACH EM_PPC
@@ -179,6 +185,12 @@
#endif
#define ELF_TARG_DATA ELFDATA2MSB
#elif defined(__or1k__)
#define ELF_TARG_MACH EM_OPENRISC
#define ELF_TARG_CLASS ELFCLASS32
#define ELF_TARG_DATA ELFDATA2MSB
#else
#error Unknown ELF machine type

33
src/local-link.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSD_LOCAL_LINK_H
#define LIBBSD_LOCAL_LINK_H
#define libbsd_link_warning(symbol, msg) \
static const char libbsd_emit_link_warning_##symbol[] \
__attribute__((used,section(".gnu.warning." #symbol))) = msg;
#endif

View File

@@ -95,11 +95,8 @@ static void insertionsort(u_char *, size_t, size_t,
* Arguments are as for qsort.
*/
int
mergesort(base, nmemb, size, cmp)
void *base;
size_t nmemb;
size_t size;
int (*cmp)(const void *, const void *);
mergesort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *))
{
size_t i;
int sense;
@@ -258,11 +255,9 @@ COPY: b = t;
* when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
* is defined. Otherwise simple pairwise merging is used.)
*/
void
setup(list1, list2, n, size, cmp)
size_t n, size;
int (*cmp)(const void *, const void *);
u_char *list1, *list2;
static void
setup(u_char *list1, u_char *list2, size_t n, size_t size,
int (*cmp)(const void *, const void *))
{
int i, length, size2, tmp, sense;
u_char *f1, *f2, *s, *l2, *last, *p2;
@@ -333,10 +328,8 @@ setup(list1, list2, n, size, cmp)
* last 4 elements.
*/
static void
insertionsort(a, n, size, cmp)
u_char *a;
size_t n, size;
int (*cmp)(const void *, const void *);
insertionsort(u_char *a, size_t n, size_t size,
int (*cmp)(const void *, const void *))
{
u_char *ai, *s, *t, *u, tmp;
int i;

View File

@@ -70,9 +70,7 @@ static int __elf_fdnlist(int, struct nlist *);
int __fdnlist(int, struct nlist *);
int
nlist(name, list)
const char *name;
struct nlist *list;
nlist(const char *name, struct nlist *list)
{
int fd, n;
@@ -96,9 +94,7 @@ static struct nlist_handlers {
};
int
__fdnlist(fd, list)
int fd;
struct nlist *list;
__fdnlist(int fd, struct nlist *list)
{
size_t i;
int n = -1;
@@ -115,9 +111,7 @@ __fdnlist(fd, list)
#ifdef _NLIST_DO_AOUT
static int
__aout_fdnlist(fd, list)
int fd;
struct nlist *list;
__aout_fdnlist(int fd, struct nlist *list)
{
struct nlist *p, *symtab;
caddr_t strtab, a_out_mmap;
@@ -220,8 +214,7 @@ static void elf_sym_to_nlist(struct nlist *, Elf_Sym *, Elf_Shdr *, int);
* as such its use should be restricted.
*/
static int
__elf_is_okay__(ehdr)
Elf_Ehdr *ehdr;
__elf_is_okay__(Elf_Ehdr *ehdr)
{
int retval = 0;
/*
@@ -244,9 +237,7 @@ __elf_is_okay__(ehdr)
}
static int
__elf_fdnlist(fd, list)
int fd;
struct nlist *list;
__elf_fdnlist(int fd, struct nlist *list)
{
struct nlist *p;
Elf_Off symoff = 0, symstroff = 0;
@@ -386,11 +377,7 @@ __elf_fdnlist(fd, list)
* n_value and n_type members.
*/
static void
elf_sym_to_nlist(nl, s, shdr, shnum)
struct nlist *nl;
Elf_Sym *s;
Elf_Shdr *shdr;
int shnum;
elf_sym_to_nlist(struct nlist *nl, Elf_Sym *s, Elf_Shdr *shdr, int shnum)
{
nl->n_value = s->st_value;

View File

@@ -118,7 +118,8 @@ sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
if (n < THRESHOLD)
simplesort(a, n, 0, tr, endch);
else {
if ((ta = malloc(n * sizeof(a))) == NULL)
ta = reallocarray(NULL, n, sizeof(a));
if (ta == NULL)
return (-1);
r_sort_b(a, ta, n, 0, tr, endch);
free(ta);

38
src/reallocarray.c Normal file
View File

@@ -0,0 +1,38 @@
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}

View File

@@ -154,7 +154,7 @@ common: if (set->cmd2 & CMD2_CLR) {
if (set >= endset) { \
BITCMD *newset; \
setlen += SET_LEN_INCR; \
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
newset = reallocarray(saveset, setlen, sizeof(BITCMD)); \
if (newset == NULL) \
goto out; \
set = newset + (set - saveset); \
@@ -197,7 +197,8 @@ setmode(const char *p)
setlen = SET_LEN + 2;
if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
set = reallocarray(NULL, setlen, sizeof(BITCMD));
if (set == NULL)
return (NULL);
saveset = set;
endset = set + (setlen - 2);

View File

@@ -1,6 +1,6 @@
/*
* Copyright © 2010 William Ahern
* Copyright © 2012 Guillem Jover <guillem@hadrons.org>
* Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -28,6 +28,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <unistd.h>
#include <string.h>
@@ -41,6 +42,7 @@ static struct {
/* Pointer to original nul character within base. */
char *nul;
bool warned;
bool reset;
int error;
} SPT;
@@ -76,36 +78,60 @@ spt_clearenv(void)
}
static int
spt_copyenv(char *oldenv[])
spt_copyenv(int envc, char *envp[])
{
char **envcopy;
char *eq;
int envsize;
int i, error;
if (environ != oldenv)
if (environ != envp)
return 0;
/* Make a copy of the old environ array of pointers, in case
* clearenv() or setenv() is implemented to free the internal
* environ array, because we will need to access the old environ
* contents to make the new copy. */
envsize = (envc + 1) * sizeof(char *);
envcopy = malloc(envsize);
if (envcopy == NULL)
return errno;
memcpy(envcopy, envp, envsize);
error = spt_clearenv();
if (error) {
environ = oldenv;
environ = envp;
free(envcopy);
return error;
}
for (i = 0; oldenv[i]; i++) {
eq = strchr(oldenv[i], '=');
for (i = 0; envcopy[i]; i++) {
eq = strchr(envcopy[i], '=');
if (eq == NULL)
continue;
*eq = '\0';
if (setenv(oldenv[i], eq + 1, 1) < 0)
if (setenv(envcopy[i], eq + 1, 1) < 0)
error = errno;
*eq = '=';
if (error) {
environ = oldenv;
#ifdef HAVE_CLEARENV
/* Because the old environ might not be available
* anymore we will make do with the shallow copy. */
environ = envcopy;
#else
environ = envp;
free(envcopy);
#endif
return error;
}
}
/* Dispose of the shallow copy, now that we've finished transfering
* the old environment. */
free(envcopy);
return 0;
}
@@ -129,11 +155,15 @@ spt_copyargs(int argc, char *argv[])
return 0;
}
static void __attribute__((constructor))
spt_init(int argc, char *argv[], char *envp[])
void
setproctitle_init(int argc, char *argv[], char *envp[])
{
char *base, *end, *nul, *tmp;
int i, error;
int i, envc, error;
/* Try to make sure we got called with main() arguments. */
if (argc < 0)
return;
base = argv[0];
if (base == NULL)
@@ -155,6 +185,7 @@ spt_init(int argc, char *argv[], char *envp[])
end = envp[i] + strlen(envp[i]) + 1;
}
envc = i;
SPT.arg0 = strdup(argv[0]);
if (SPT.arg0 == NULL) {
@@ -169,7 +200,7 @@ spt_init(int argc, char *argv[], char *envp[])
}
setprogname(tmp);
error = spt_copyenv(envp);
error = spt_copyenv(envc, envp);
if (error) {
SPT.error = error;
return;
@@ -199,8 +230,14 @@ setproctitle_impl(const char *fmt, ...)
char *nul;
int len;
if (SPT.base == NULL)
if (SPT.base == NULL) {
if (!SPT.warned) {
warnx("setproctitle not initialized, please either call "
"setproctitle_init() or link against libbsd-ctor.");
SPT.warned = true;
}
return;
}
if (fmt) {
if (fmt[0] == '-') {
@@ -245,11 +282,14 @@ setproctitle_impl(const char *fmt, ...)
}
__asm__(".symver setproctitle_impl,setproctitle@@LIBBSD_0.5");
#ifdef HAVE_TYPEOF
/* The original function introduced in 0.2 was a stub, it only got implemented
* in 0.5, make the implementation available in the old version as an alias
* for code linking against that version, and change the default to use the
* new version, so that new code depends on the implemented version. */
#ifdef HAVE_TYPEOF
extern typeof(setproctitle_impl) setproctitle_stub __attribute__((alias("setproctitle_impl")));
__asm__(".symver setproctitle_stub,setproctitle@LIBBSD_0.2");
#else
void setproctitle_stub(const char *fmt, ...)
__attribute__((alias("setproctitle_impl")));
#endif
__asm__(".symver setproctitle_stub,setproctitle@LIBBSD_0.2");

52
src/setproctitle_ctor.c Normal file
View File

@@ -0,0 +1,52 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <unistd.h>
/*
* The automatic initialization cannot be part of the main shared library,
* because there is no thread-safe way to change the environ global
* variable. This is not a problem if the initializaion happens just at
* program load time, but becomes one if the shared library is directly or
* indirectly dlopen()ed during the execution of the program, which could
* have either kept references to the old environ or could change it in
* some other thread. This has been observed for example on systems using
* Samba NSS modules.
*
* To avoid any other possible fallout, the constructor is split into a
* new static library that needs to be linked explicitly into programs
* using setproctitle(). As an additional safety measure the pkg-config
* linker flags will mark the program as not allowing to be dlopen()ed
* so that we make sure to avoid the problem described above.
*/
/*
* Force setproctitle_init() function into the .init_array section instead of
* expecting either the compiler to place constructors there or the linker to
* move them from .ctors to .init_array.
*/
void (*libbsd_init_func)(int argc, char *argv[], char *envp[])
__attribute__((section(".init_array"))) = setproctitle_init;

155
src/stringlist.c Normal file
View File

@@ -0,0 +1,155 @@
/* $NetBSD: stringlist.c,v 1.12 2007/05/09 17:10:29 christos Exp $ */
/*-
* Copyright (c) 1994, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: stringlist.c,v 1.12 2007/05/09 17:10:29 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stringlist.h>
#define _DIAGASSERT(t)
#ifdef __weak_alias
__weak_alias(sl_add,_sl_add)
__weak_alias(sl_find,_sl_find)
__weak_alias(sl_free,_sl_free)
__weak_alias(sl_init,_sl_init)
__weak_alias(sl_delete,_sl_delete)
#endif
#define _SL_CHUNKSIZE 20
/*
* sl_init(): Initialize a string list
*/
StringList *
sl_init(void)
{
StringList *sl;
sl = malloc(sizeof(StringList));
if (sl == NULL)
return NULL;
sl->sl_cur = 0;
sl->sl_max = _SL_CHUNKSIZE;
sl->sl_str = reallocarray(NULL, sl->sl_max, sizeof(char *));
if (sl->sl_str == NULL) {
free(sl);
sl = NULL;
}
return sl;
}
/*
* sl_add(): Add an item to the string list
*/
int
sl_add(StringList *sl, char *name)
{
_DIAGASSERT(sl != NULL);
if (sl->sl_cur == sl->sl_max - 1) {
char **new;
new = reallocarray(sl->sl_str,
(sl->sl_max + _SL_CHUNKSIZE), sizeof(char *));
if (new == NULL)
return -1;
sl->sl_max += _SL_CHUNKSIZE;
sl->sl_str = new;
}
sl->sl_str[sl->sl_cur++] = name;
return 0;
}
/*
* sl_free(): Free a stringlist
*/
void
sl_free(StringList *sl, int all)
{
size_t i;
if (sl == NULL)
return;
if (sl->sl_str) {
if (all)
for (i = 0; i < sl->sl_cur; i++)
free(sl->sl_str[i]);
free(sl->sl_str);
}
free(sl);
}
/*
* sl_find(): Find a name in the string list
*/
char *
sl_find(StringList *sl, const char *name)
{
size_t i;
_DIAGASSERT(sl != NULL);
for (i = 0; i < sl->sl_cur; i++)
if (strcmp(sl->sl_str[i], name) == 0)
return sl->sl_str[i];
return NULL;
}
int
sl_delete(StringList *sl, const char *name, int all)
{
size_t i, j;
for (i = 0; i < sl->sl_cur; i++)
if (strcmp(sl->sl_str[i], name) == 0) {
if (all)
free(sl->sl_str[i]);
for (j = i + 1; j < sl->sl_cur; j++)
sl->sl_str[j - 1] = sl->sl_str[j];
sl->sl_str[--sl->sl_cur] = NULL;
return 0;
}
return -1;
}

View File

@@ -37,9 +37,7 @@ static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
#include <string.h>
void
strmode(mode, p)
mode_t mode;
char *p;
strmode(mode_t mode, char *p)
{
/* print type */
switch (mode & S_IFMT) {

119
src/timeconv.c Normal file
View File

@@ -0,0 +1,119 @@
/*-
* Copyright (c) 2001 FreeBSD Inc.
* 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.
*
* These routines are for converting time_t to fixed-bit representations
* for use in protocols or storage. When converting time to a larger
* representation of time_t these routines are expected to assume temporal
* locality and use the 50-year rule to properly set the msb bits. XXX
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <timeconv.h>
/*
* Convert a 32 bit representation of time_t into time_t. XXX needs to
* implement the 50-year rule to handle post-2038 conversions.
*/
time_t
_time32_to_time(int32_t t32)
{
return((time_t)t32);
}
/*
* Convert time_t to a 32 bit representation. If time_t is 64 bits we can
* simply chop it down. The resulting 32 bit representation can be
* converted back to a temporally local 64 bit time_t using time32_to_time.
*/
int32_t
_time_to_time32(time_t t)
{
return((int32_t)t);
}
/*
* Convert a 64 bit representation of time_t into time_t. If time_t is
* represented as 32 bits we can simply chop it and not support times
* past 2038.
*/
time_t
_time64_to_time(int64_t t64)
{
return((time_t)t64);
}
/*
* Convert time_t to a 64 bit representation. If time_t is represented
* as 32 bits we simply sign-extend and do not support times past 2038.
*/
int64_t
_time_to_time64(time_t t)
{
return((int64_t)t);
}
/*
* Convert to/from 'long'. Depending on the sizeof(long) this may or
* may not require using the 50-year rule.
*/
long
_time_to_long(time_t t)
{
if (sizeof(long) == sizeof(int64_t))
return(_time_to_time64(t));
return((long)t);
}
time_t
_long_to_time(long tlong)
{
if (sizeof(long) == sizeof(int32_t))
return(_time32_to_time(tlong));
return((time_t)tlong);
}
/*
* Convert to/from 'int'. Depending on the sizeof(int) this may or
* may not require using the 50-year rule.
*/
int
_time_to_int(time_t t)
{
if (sizeof(int) == sizeof(int64_t))
return(_time_to_time64(t));
return((int)t);
}
time_t
_int_to_time(int tint)
{
if (sizeof(int) == sizeof(int32_t))
return(_time32_to_time(tint));
return((time_t)tint);
}

8
test/.gitignore vendored
View File

@@ -1,6 +1,14 @@
arc4random
bzero
closefrom
endian
fgetln
funopen
fparseln
fpurge
headers
humanize
overlay
proctitle-init
proctitle
strmode

View File

@@ -7,17 +7,44 @@ AM_CPPFLAGS = \
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
-D__REENTRANT
LDADD = $(top_builddir)/src/libbsd.la
check_PROGRAMS = \
headers \
overlay \
bzero \
closefrom \
endian \
humanize \
fgetln \
proctitle \
funopen \
fparseln \
fpurge \
proctitle-init \
strmode \
$(nil)
humanize_LDFLAGS = $(top_builddir)/src/libbsd.la
fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la
proctitle_LDFLAGS = $(top_builddir)/src/libbsd.la
if HAVE_LIBTESTU01
arc4random_LDADD = $(LDADD) $(TESTU01_LIBS)
check_PROGRAMS += arc4random
endif
if BUILD_LIBBSD_CTOR
proctitle_LDFLAGS = \
-Wl,-u,libbsd_init_func \
$(top_builddir)/src/libbsd-ctor.a \
$(top_builddir)/src/libbsd.la \
$(nil)
check_PROGRAMS += proctitle
endif
fgetln_SOURCES = test-stream.c test-stream.h fgetln.c
fgetln_CFLAGS = -Wno-deprecated-declarations
fparseln_SOURCES = test-stream.c test-stream.h fparseln.c
proctitle_init_SOURCES = proctitle.c
proctitle_init_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_USE_SETPROCTITLE_INIT=1
TESTS = $(check_PROGRAMS)

105
test/arc4random.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <testu01/gdef.h>
#include <testu01/unif01.h>
#include <testu01/swrite.h>
#include <testu01/bbattery.h>
#define TEST_OK 0
#define TEST_SKIP 77
#define TEST_DIE 99
#define test_print(msg, ...) \
printf("TEST: " msg "\n", __VA_ARGS__)
#define test_res(idx, name, pval, action) \
test_print("[%4d] (%s) pVal[%d] = %f -> %s", \
idx, name[idx], i, pval[idx], action)
static int test_failed = 0;
static void
test_battery_result(void)
{
char **testNames = bbattery_TestNames;
double *pVal = bbattery_pVal;
double pSuspect = 0.001;
test_print("bbattery_NTests = %d", bbattery_NTests);
for (int i = 0; i < bbattery_NTests; i++) {
/* That test was not done: pVal = -1. */
if (pVal[i] < 0.0) {
test_res(i, testNames, pVal, "SKIP");
continue;
}
/* That test passed or failed. */
if ((pVal[i] >= pSuspect) &&
(pVal[i] <= 1.0 - pSuspect)) {
test_res(i, testNames, pVal, "PASS");
} else {
test_res(i, testNames, pVal, "FAIL");
test_failed++;
}
}
}
int
main(int argc, char **argv)
{
unif01_Gen *gen;
int rc;
gen = unif01_CreateExternGenBits("arc4random", arc4random);
/* XXX: The following battery does not set pVal, so we cannot check
* the results. */
bbattery_FIPS_140_2(gen);
/* XXX: The following battery fails one test. */
bbattery_pseudoDIEHARD(gen);
test_battery_result();
bbattery_Rabbit(gen, 33554432);
test_battery_result();
bbattery_SmallCrush(gen);
test_battery_result();
unif01_DeleteExternGenBits(gen);
if (test_failed) {
test_print("failed tests = %d", test_failed);
/* XXX: We should probably FAIL the test, but we currently
* have one test always failing. */
rc = TEST_SKIP;
}
return rc;
}

47
test/bzero.c Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <string.h>
int
main()
{
unsigned char array[40];
size_t i;
memset(array, 0x3e, sizeof(array));
explicit_bzero(array, 0);
for (i = 0; i < sizeof(array); i++)
assert(array[i] == 0x3e);
explicit_bzero(array, sizeof(array));
for (i = 0; i < sizeof(array); i++)
assert(array[i] == 0);
return 0;
}

53
test/closefrom.c Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int
main()
{
int i;
int fd;
fd = open("/dev/null", O_RDONLY);
for (i = 4; i < 1024; i *= 2)
assert(dup2(fd, i) == i);
if (fd < 4)
close(fd);
closefrom(4);
for (i = 4; i < 1024; i++)
assert(fcntl(i, F_GETFL) == -1 && errno == EBADF);
assert(fcntl(fd, F_GETFL) == -1 && errno == EBADF);
return 0;
}

View File

@@ -24,15 +24,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/wait.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include "test-stream.h"
#define skip(msg) \
do { \
printf("skip: %s\n", (msg)); \
@@ -67,58 +67,6 @@ struct file {
int got_len;
};
static FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
int pipefd[2];
pid_t pid;
rc = pipe(pipefd);
assert(rc >= 0);
pid = fork();
assert(pid >= 0);
if (pid == 0) {
int line;
/* Child writes data to pipe. */
rc = close(pipefd[0]);
assert(rc >= 0);
fp = fdopen(pipefd[1], "w");
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
rc = fprintf(fp, fmt, buf[line]);
assert(rc >= 0);
}
rc = fclose(fp);
assert(rc >= 0);
_exit(0);
} else {
/* Parent gets a FILE and reads from it. */
rc = close(pipefd[1]);
assert(rc >= 0);
fp = fdopen(pipefd[0], "r");
assert(fp);
return fp;
}
}
static void
pipe_close(FILE *fp)
{
fclose(fp);
wait(NULL);
}
static void
test_fgetln_single(void)
{
@@ -149,7 +97,7 @@ test_fgetln_multi(void)
str = strdup("A\n");
str[0] += i;
files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = str;
files[i].lines[1] = str;
files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
@@ -211,7 +159,7 @@ test_fgetwln_multi(void)
wstr = wcsdup(L"A\n");
wstr[0] += i;
files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = wstr;
files[i].lines[1] = wstr;
files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);

92
test/fparseln.c Normal file
View File

@@ -0,0 +1,92 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test-stream.h"
#define TEST_LINES 9
static const char *data_test[] = {
"# This is a test\n",
"line 1\n",
"line 2 \\\n",
"line 3 # Comment\n",
"line 4 \\# Not comment \\\\\\\\\n",
"\n",
"# And a comment \\\n",
"line 5 \\\\\\\n",
"line 6 w/ escape sequences \\b, \\t, \\\\t",
};
#define EXPECT_LINES 5
static size_t lineno_expect[] = { 2, 4, 5, 6, 9 };
static const char *data_parse[] = {
"line 1",
"line 2 line 3 ",
"line 4 \\# Not comment \\\\\\\\",
"",
"line 5 \\\\line 6 w/ escape sequences \\b, \\t, \\\\t",
};
static const char *data_escape[] = {
"line 1",
"line 2 line 3 ",
"line 4 # Not comment \\\\",
"",
"line 5 \\line 6 w/ escape sequences b, t, \\t",
};
static void
test_fparseln(const char **data_expect, int flags)
{
FILE *fp;
size_t i, len, lineno = 0;
fp = pipe_feed("%s", (const void **)data_test, TEST_LINES);
for (i = 0; i < EXPECT_LINES; i++) {
char *str = fparseln(fp, &len, &lineno, NULL, flags);
assert(str);
assert(lineno == lineno_expect[i]);
assert(strcmp(str, data_expect[i]) == 0);
free(str);
}
assert(fparseln(fp, &len, NULL, NULL, 0) == NULL);
pipe_close(fp);
}
int
main(int argc, char **argv)
{
test_fparseln(data_parse, 0);
test_fparseln(data_escape, FPARSELN_UNESCALL);
return 0;
}

48
test/fpurge.c Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright © 2011 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
int
main()
{
static FILE fp_bad;
FILE *fp;
if (fpurge(NULL) == 0)
return 1;
if (fpurge(&fp_bad) == 0)
return 1;
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
fclose(fp);
return 0;
}

178
test/funopen.c Normal file
View File

@@ -0,0 +1,178 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#define ARRAY_SIZE 100
#define TEST_SIZE 50
struct test_cookie {
char array[ARRAY_SIZE];
int index;
};
int
test_readfn(void *cookie, char *buf, int size)
{
struct test_cookie *tc = cookie;
int left_size = sizeof(tc->array) - tc->index;
if (left_size < 0)
size = 0;
else if (left_size < size)
size = left_size;
if (size > 0) {
memcpy(buf, tc->array + tc->index, size);
tc->index += size;
}
return size;
}
int
test_writefn(void *cookie, const char *buf, int size)
{
struct test_cookie *tc = cookie;
int left_size = sizeof(tc->array) - tc->index;
if (left_size < 0)
size = 0;
else if (left_size < size)
size = left_size;
if (size > 0) {
memcpy(tc->array + tc->index, buf, size);
tc->index += size;
}
return size;
}
off_t
test_seekfn(void *cookie, off_t offset, int whence)
{
struct test_cookie *tc = cookie;
switch (whence) {
case SEEK_SET:
tc->index = offset;
break;
case SEEK_CUR:
tc->index += offset;
break;
case SEEK_END:
tc->index = sizeof(tc->array) + offset;
break;
}
return tc->index;
}
int
test_closefn(void *cookie)
{
struct test_cookie *tc = cookie;
memset(tc->array, 0x7f, sizeof(tc->array));
return 0;
}
int
main(int argc, char **argv)
{
struct test_cookie tc;
char data[ARRAY_SIZE];
FILE *fp;
size_t i;
/* Test invalid hooks. */
fp = funopen(&tc, NULL, NULL, NULL, NULL);
assert(fp == NULL);
assert(errno == EINVAL);
/* Test read-only file. */
tc.index = 0;
for (i = 0; i < sizeof(tc.array); i++)
tc.array[i] = i;
fp = fropen(&tc, test_readfn);
assert(fp);
assert(fread(data, 1, TEST_SIZE, fp) == TEST_SIZE);
assert(memcmp(tc.array, data, TEST_SIZE) == 0);
assert(fwrite(data, 1, TEST_SIZE, fp) == 0);
assert(fclose(fp) == 0);
/* Test write-only file. */
memset(&tc, 0, sizeof(tc));
fp = fwopen(&tc, test_writefn);
assert(fp);
setvbuf(fp, NULL, _IONBF, 0);
assert(fwrite(data, 1, TEST_SIZE, fp) == TEST_SIZE);
assert(memcmp(tc.array, data, TEST_SIZE) == 0);
assert(fread(data, 1, TEST_SIZE, fp) == 0);
assert(fclose(fp) == 0);
/* Test seekable file. */
memset(&tc, 0, sizeof(tc));
fp = funopen(&tc, test_readfn, test_writefn, test_seekfn, NULL);
assert(fp);
setvbuf(fp, NULL, _IONBF, 0);
assert(fwrite(data, 1, TEST_SIZE, fp) == TEST_SIZE);
assert(fseek(fp, 0L, SEEK_SET) == 0);
assert(fwrite(data, 1, ARRAY_SIZE, fp) == ARRAY_SIZE);
assert(memcmp(tc.array, data, ARRAY_SIZE) == 0);
assert(fread(data, 1, TEST_SIZE, fp) == 0);
assert(fclose(fp) == 0);
/* Test close hook. */
memset(&tc, 0, sizeof(tc));
fp = funopen(&tc, test_readfn, test_writefn, NULL, test_closefn);
assert(fclose(fp) == 0);
for (i = 0; i < sizeof(tc.array); i++)
assert(tc.array[i] == 0x7f);
return 0;
}

View File

@@ -25,6 +25,7 @@
*/
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
int
@@ -58,7 +59,19 @@ main(int argc, char **argv)
assert(val == 20971520);
assert(dehumanize_number("-3G", &val) == 0);
assert(val == -3221225472);
assert(val == -3221225472LL);
assert(dehumanize_number("9223372036854775807", &val) == 0);
assert(val == INT64_MAX);
assert(dehumanize_number("9223372036854775808", &val) == -1);
assert(errno == ERANGE);
assert(dehumanize_number("-9223372036854775808", &val) == 0);
assert(val == INT64_MIN);
assert(dehumanize_number("-9223372036854775809", &val) == -1);
assert(errno == ERANGE);
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org>
* Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,18 +31,30 @@
#include <string.h>
int
main(int argc, char **argv)
main(int argc, char **argv, char **envp)
{
const char newtitle_base[] = "test arg1 arg2";
char *newtitle_full;
char *envvar;
int rc;
#ifdef TEST_USE_SETPROCTITLE_INIT
setproctitle_init(argc, argv, envp);
#endif
setproctitle("-test %s arg2", "arg1");
assert(strcmp(argv[0], newtitle_base) == 0);
asprintf(&newtitle_full, "%s: %s", getprogname(), newtitle_base);
rc = asprintf(&newtitle_full, "%s: %s", getprogname(), newtitle_base);
assert(rc > 0);
setproctitle("test %s arg2", "arg1");
assert(strcmp(argv[0], newtitle_full) == 0);
free(newtitle_full);
assert(setenv("LIBBSD_TEST", "test value", 1) == 0);
envvar = getenv("LIBBSD_TEST");
assert(envvar != NULL);
assert(strcmp(envvar, "test value") == 0);
return 0;
}

69
test/strmode.c Normal file
View File

@@ -0,0 +1,69 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <string.h>
int
main(int argc, char **argv)
{
char mode_str[12];
strmode(0, mode_str);
assert(strcmp(mode_str, "?--------- ") == 0);
strmode(0777, mode_str);
assert(strcmp(mode_str, "?rwxrwxrwx ") == 0);
strmode(0777 | S_IFREG, mode_str);
assert(strcmp(mode_str, "-rwxrwxrwx ") == 0);
strmode(0777 | S_IFREG | S_ISUID | S_ISGID | S_ISVTX, mode_str);
assert(strcmp(mode_str, "-rwsrwsrwt ") == 0);
strmode(0666 | S_IFREG | S_ISUID | S_ISGID | S_ISVTX, mode_str);
assert(strcmp(mode_str, "-rwSrwSrwT ") == 0);
strmode(0777 | S_IFLNK, mode_str);
assert(strcmp(mode_str, "lrwxrwxrwx ") == 0);
strmode(0777 | S_IFCHR, mode_str);
assert(strcmp(mode_str, "crwxrwxrwx ") == 0);
strmode(0777 | S_IFBLK, mode_str);
assert(strcmp(mode_str, "brwxrwxrwx ") == 0);
strmode(0777 | S_IFDIR, mode_str);
assert(strcmp(mode_str, "drwxrwxrwx ") == 0);
strmode(0777 | S_IFIFO, mode_str);
assert(strcmp(mode_str, "prwxrwxrwx ") == 0);
strmode(0777 | S_IFSOCK, mode_str);
assert(strcmp(mode_str, "srwxrwxrwx ") == 0);
return 0;
}

84
test/test-stream.c Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/wait.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include "test-stream.h"
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
int pipefd[2];
pid_t pid;
rc = pipe(pipefd);
assert(rc >= 0);
pid = fork();
assert(pid >= 0);
if (pid == 0) {
int line;
/* Child writes data to pipe. */
rc = close(pipefd[0]);
assert(rc >= 0);
fp = fdopen(pipefd[1], "w");
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
rc = fprintf(fp, fmt, buf[line]);
assert(rc >= 0);
}
rc = fclose(fp);
assert(rc >= 0);
_exit(0);
} else {
/* Parent gets a FILE and reads from it. */
rc = close(pipefd[1]);
assert(rc >= 0);
fp = fdopen(pipefd[0], "r");
assert(fp);
return fp;
}
}
void
pipe_close(FILE *fp)
{
fclose(fp);
wait(NULL);
}

37
test/test-stream.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSD_TEST_STREAM
#define LIBBSD_TEST_STREAM
#include <stdio.h>
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb);
void
pipe_close(FILE *fp);
#endif