mirror of
https://gitlab.freedesktop.org/libbsd/libbsd.git
synced 2025-10-19 21:16:55 +02:00
Compare commits
73 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2fb148a290 | ||
![]() |
c8f0723d2b | ||
![]() |
008316aa29 | ||
![]() |
e4ab2c62cd | ||
![]() |
bf5573f86c | ||
![]() |
229f85794f | ||
![]() |
7a75687541 | ||
![]() |
f84004baf2 | ||
![]() |
cdf998a056 | ||
![]() |
2c77ad593c | ||
![]() |
48ac79b188 | ||
![]() |
290a1ce8f2 | ||
![]() |
6bcb1312f4 | ||
![]() |
da137a0921 | ||
![]() |
d2f59a23d5 | ||
![]() |
01b77f0dcf | ||
![]() |
75729394af | ||
![]() |
8493c7f27d | ||
![]() |
2b030da016 | ||
![]() |
330e211142 | ||
![]() |
874a0e51d3 | ||
![]() |
9a9a8b2dba | ||
![]() |
5f9265f816 | ||
![]() |
1f77cdb40a | ||
![]() |
f3b115540c | ||
![]() |
877732ef4d | ||
![]() |
02bccb0a01 | ||
![]() |
58bef83f41 | ||
![]() |
6e074a2bdc | ||
![]() |
0871daf7b0 | ||
![]() |
02c33d5022 | ||
![]() |
45443583df | ||
![]() |
8641d8aed7 | ||
![]() |
0982dcd98b | ||
![]() |
ee26e59e72 | ||
![]() |
151bc71d64 | ||
![]() |
41ff37bbcc | ||
![]() |
53d989a223 | ||
![]() |
f50b197ea5 | ||
![]() |
54f153414a | ||
![]() |
9688ab26b9 | ||
![]() |
025b44800e | ||
![]() |
a6a101effa | ||
![]() |
32388fe59f | ||
![]() |
30e328cbf1 | ||
![]() |
4cc43915f2 | ||
![]() |
34df142665 | ||
![]() |
3881c4fc68 | ||
![]() |
3a3d87d730 | ||
![]() |
d62f7d8fac | ||
![]() |
cfb4d462a9 | ||
![]() |
205827a2dd | ||
![]() |
c7e01e9884 | ||
![]() |
3267114483 | ||
![]() |
0e4e3ab269 | ||
![]() |
a6fe103c1b | ||
![]() |
02b55488c5 | ||
![]() |
6378351169 | ||
![]() |
e390651b64 | ||
![]() |
e8d3d04177 | ||
![]() |
faa005cb32 | ||
![]() |
36aca8c06e | ||
![]() |
e8f9300355 | ||
![]() |
a88bb8380d | ||
![]() |
8d16c3df67 | ||
![]() |
f41fdcf186 | ||
![]() |
86cbff385a | ||
![]() |
ee04e8de14 | ||
![]() |
61b2dbb8f5 | ||
![]() |
119417462e | ||
![]() |
948bcf1db8 | ||
![]() |
c5b9590287 | ||
![]() |
3077d2fffc |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,6 +7,7 @@ ChangeLog
|
|||||||
*.a
|
*.a
|
||||||
*.log
|
*.log
|
||||||
*.trs
|
*.trs
|
||||||
|
.dirstamp
|
||||||
.deps/
|
.deps/
|
||||||
.libs/
|
.libs/
|
||||||
Makefile
|
Makefile
|
||||||
|
@@ -12,5 +12,5 @@ EXTRA_DIST = \
|
|||||||
dist-hook:
|
dist-hook:
|
||||||
echo $(VERSION) >$(distdir)/.dist-version
|
echo $(VERSION) >$(distdir)/.dist-version
|
||||||
if [ -d .git ]; then \
|
if [ -d .git ]; then \
|
||||||
git log --stat -C >$(distdir)/ChangeLog; \
|
XDG_CONFIG_HOME= HOME= git log --stat -C >$(distdir)/ChangeLog; \
|
||||||
fi
|
fi
|
||||||
|
27
configure.ac
27
configure.ac
@@ -6,11 +6,18 @@ AC_CONFIG_SRCDIR([src/fgetln.c])
|
|||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
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])],
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
|
||||||
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
|
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
|
||||||
|
|
||||||
|
LIBBSD_ABI_MAJOR=0
|
||||||
|
LIBBSD_ABI_MINOR=8
|
||||||
|
LIBBSD_ABI_PATCH=2
|
||||||
|
|
||||||
|
LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH"
|
||||||
|
AC_SUBST([LIBBSD_ABI])
|
||||||
|
|
||||||
# Check and store if we got user supplied variables
|
# Check and store if we got user supplied variables
|
||||||
user_CFLAGS=${CFLAGS-unset}
|
user_CFLAGS=${CFLAGS-unset}
|
||||||
|
|
||||||
@@ -31,9 +38,14 @@ if test "$user_CFLAGS" = unset && test "$GCC" = yes; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Checks for libraries.
|
# 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.
|
# 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.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_TYPE_UID_T
|
AC_TYPE_UID_T
|
||||||
@@ -94,9 +106,8 @@ int main() { return rc; }
|
|||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
if test "$libbsd_cv_gnu_init_array_support" = no; then
|
AM_CONDITIONAL([BUILD_LIBBSD_CTOR],
|
||||||
AC_MSG_ERROR([missing required GNU .init_array section support])
|
[test "$libbsd_cv_gnu_init_array_support" = yes])
|
||||||
fi
|
|
||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
AC_MSG_CHECKING([for program_invocation_short_name])
|
AC_MSG_CHECKING([for program_invocation_short_name])
|
||||||
@@ -117,7 +128,10 @@ AC_LINK_IFELSE(
|
|||||||
AC_MSG_RESULT([yes])],
|
AC_MSG_RESULT([yes])],
|
||||||
[AC_MSG_RESULT([no])])
|
[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([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
@@ -125,6 +139,7 @@ AC_CONFIG_FILES([
|
|||||||
man/Makefile
|
man/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/libbsd.pc
|
src/libbsd.pc
|
||||||
|
src/libbsd-ctor.pc
|
||||||
src/libbsd-overlay.pc
|
src/libbsd-overlay.pc
|
||||||
test/Makefile
|
test/Makefile
|
||||||
])
|
])
|
||||||
|
@@ -19,6 +19,8 @@ nobase_include_HEADERS = \
|
|||||||
bsd/stdio.h \
|
bsd/stdio.h \
|
||||||
bsd/stdlib.h \
|
bsd/stdlib.h \
|
||||||
bsd/string.h \
|
bsd/string.h \
|
||||||
|
bsd/stringlist.h \
|
||||||
|
bsd/timeconv.h \
|
||||||
bsd/unistd.h \
|
bsd/unistd.h \
|
||||||
bsd/vis.h \
|
bsd/vis.h \
|
||||||
bsd/wchar.h \
|
bsd/wchar.h \
|
||||||
|
@@ -27,10 +27,12 @@
|
|||||||
#ifndef LIBBSD_H
|
#ifndef LIBBSD_H
|
||||||
#define LIBBSD_H
|
#define LIBBSD_H
|
||||||
|
|
||||||
|
#ifdef LIBBSD_OVERLAY
|
||||||
|
#warning "This header is meant to be used w/o the libbsd overlay."
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
* Include all bsd compat headers.
|
* Include all bsd compat headers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <bsd/sys/cdefs.h>
|
#include <bsd/sys/cdefs.h>
|
||||||
#include <bsd/sys/queue.h>
|
#include <bsd/sys/queue.h>
|
||||||
#include <bsd/sys/tree.h>
|
#include <bsd/sys/tree.h>
|
||||||
@@ -40,5 +42,6 @@
|
|||||||
#include <bsd/err.h>
|
#include <bsd/err.h>
|
||||||
#include <bsd/getopt.h>
|
#include <bsd/getopt.h>
|
||||||
#include <bsd/md5.h>
|
#include <bsd/md5.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -34,15 +34,23 @@
|
|||||||
#ifndef LIBBSD_ERR_H
|
#ifndef LIBBSD_ERR_H
|
||||||
#define LIBBSD_ERR_H
|
#define LIBBSD_ERR_H
|
||||||
|
|
||||||
|
#ifdef LIBBSD_OVERLAY
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
#else
|
||||||
|
#include <bsd/sys/cdefs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
extern void warnc (int code, const char *format, ...);
|
void warnc(int code, const char *format, ...)
|
||||||
extern void vwarnc (int code, const char *format, va_list ap);
|
__printflike(2, 3);
|
||||||
extern void errc (int status, int code, const char *format, ...);
|
void vwarnc(int code, const char *format, va_list ap)
|
||||||
extern void verrc (int status, 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
|
__END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -15,26 +15,29 @@
|
|||||||
#ifndef _MD5_H_
|
#ifndef _MD5_H_
|
||||||
#define _MD5_H_
|
#define _MD5_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define MD5_BLOCK_LENGTH 64
|
#define MD5_BLOCK_LENGTH 64
|
||||||
#define MD5_DIGEST_LENGTH 16
|
#define MD5_DIGEST_LENGTH 16
|
||||||
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
|
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
|
||||||
|
|
||||||
typedef struct MD5Context {
|
typedef struct MD5Context {
|
||||||
u_int32_t state[4]; /* state */
|
uint32_t state[4]; /* state */
|
||||||
u_int64_t count; /* number of bits, mod 2^64 */
|
uint64_t count; /* number of bits, mod 2^64 */
|
||||||
u_int8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
|
uint8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
|
||||||
} MD5_CTX;
|
} MD5_CTX;
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
void MD5Init(MD5_CTX *);
|
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)));
|
__attribute__((__bounded__(__string__,2,3)));
|
||||||
void MD5Pad(MD5_CTX *);
|
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)));
|
__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__,1,4)))
|
||||||
__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));
|
__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));
|
||||||
char *MD5End(MD5_CTX *, char *)
|
char *MD5End(MD5_CTX *, char *)
|
||||||
@@ -43,7 +46,7 @@ char *MD5File(const char *, char *)
|
|||||||
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
|
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
|
||||||
char *MD5FileChunk(const char *, char *, off_t, off_t)
|
char *MD5FileChunk(const char *, char *, off_t, off_t)
|
||||||
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
|
__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__(__string__,1,2)))
|
||||||
__attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH)));
|
__attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH)));
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@@ -24,12 +24,17 @@
|
|||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(__need_FILE) || defined(__need___FILE)
|
||||||
|
#define LIBBSD_STDIO_H_SKIP
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LIBBSD_OVERLAY
|
#ifdef LIBBSD_OVERLAY
|
||||||
#include_next <stdio.h>
|
#include_next <stdio.h>
|
||||||
#else
|
#else
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LIBBSD_STDIO_H_SKIP
|
||||||
#ifndef LIBBSD_STDIO_H
|
#ifndef LIBBSD_STDIO_H
|
||||||
#define LIBBSD_STDIO_H
|
#define LIBBSD_STDIO_H
|
||||||
|
|
||||||
@@ -39,9 +44,33 @@
|
|||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
const char *fmtcheck(const char *, const char *);
|
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);
|
int fpurge(FILE *fp);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
#undef LIBBSD_STDIO_H_SKIP
|
||||||
|
@@ -47,11 +47,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
u_int32_t arc4random();
|
uint32_t arc4random(void);
|
||||||
void arc4random_stir();
|
void arc4random_stir(void);
|
||||||
void arc4random_addrandom(u_char *dat, int datlen);
|
void arc4random_addrandom(u_char *dat, int datlen);
|
||||||
void arc4random_buf(void *_buf, size_t n);
|
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);
|
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);
|
const unsigned char *table, unsigned endbyte);
|
||||||
|
|
||||||
void *reallocf(void *ptr, size_t size);
|
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,
|
long long strtonum(const char *nptr, long long minval, long long maxval,
|
||||||
const char **errstr);
|
const char **errstr);
|
||||||
|
|
||||||
|
char *getbsize(int *headerlenp, long *blocksizep);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -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);
|
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||||
char *strnstr(const char *str, const char *find, size_t str_len);
|
char *strnstr(const char *str, const char *find, size_t str_len);
|
||||||
void strmode(mode_t mode, char *str);
|
void strmode(mode_t mode, char *str);
|
||||||
|
|
||||||
|
void explicit_bzero(void *buf, size_t len);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
54
include/bsd/stringlist.h
Normal file
54
include/bsd/stringlist.h
Normal 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 */
|
@@ -114,6 +114,47 @@
|
|||||||
# define __bounded__(x, y, z)
|
# define __bounded__(x, y, z)
|
||||||
#endif
|
#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
|
#ifndef __RCSID
|
||||||
# define __RCSID(x)
|
# define __RCSID(x)
|
||||||
#endif
|
#endif
|
||||||
@@ -138,4 +179,16 @@
|
|||||||
# define __COPYRIGHT(x)
|
# define __COPYRIGHT(x)
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2011 Guillem Jover <guillem@hadrons.org>
|
* Copyright © 2011 Guillem Jover <guillem@hadrons.org>
|
||||||
*
|
*
|
||||||
|
* Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
@@ -9,19 +12,18 @@
|
|||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 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,
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef LIBBSD_OVERLAY
|
#ifdef LIBBSD_OVERLAY
|
||||||
@@ -49,32 +51,6 @@
|
|||||||
#define _PDP_ENDIAN __PDP_ENDIAN
|
#define _PDP_ENDIAN __PDP_ENDIAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
|
|
||||||
* 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 <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
|
/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
|
||||||
|
@@ -65,7 +65,7 @@
|
|||||||
* so that an arbitrary element can be removed without a need to
|
* so that an arbitrary element can be removed without a need to
|
||||||
* traverse the list. New elements can be added to the list before
|
* 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
|
* 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
|
* 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
|
* list and the other to the tail of the list. The elements are doubly
|
||||||
@@ -85,12 +85,16 @@
|
|||||||
* _EMPTY + + + +
|
* _EMPTY + + + +
|
||||||
* _FIRST + + + +
|
* _FIRST + + + +
|
||||||
* _NEXT + + + +
|
* _NEXT + + + +
|
||||||
* _PREV - - - +
|
* _PREV - + - +
|
||||||
* _LAST - - + +
|
* _LAST - - + +
|
||||||
* _FOREACH + + + +
|
* _FOREACH + + + +
|
||||||
|
* _FOREACH_FROM + + + +
|
||||||
* _FOREACH_SAFE + + + +
|
* _FOREACH_SAFE + + + +
|
||||||
|
* _FOREACH_FROM_SAFE + + + +
|
||||||
* _FOREACH_REVERSE - - - +
|
* _FOREACH_REVERSE - - - +
|
||||||
|
* _FOREACH_REVERSE_FROM - - - +
|
||||||
* _FOREACH_REVERSE_SAFE - - - +
|
* _FOREACH_REVERSE_SAFE - - - +
|
||||||
|
* _FOREACH_REVERSE_FROM_SAFE - - - +
|
||||||
* _INSERT_HEAD + + + +
|
* _INSERT_HEAD + + + +
|
||||||
* _INSERT_BEFORE - + - +
|
* _INSERT_BEFORE - + - +
|
||||||
* _INSERT_AFTER + + + +
|
* _INSERT_AFTER + + + +
|
||||||
@@ -99,19 +103,22 @@
|
|||||||
* _REMOVE_AFTER + - + -
|
* _REMOVE_AFTER + - + -
|
||||||
* _REMOVE_HEAD + - + -
|
* _REMOVE_HEAD + - + -
|
||||||
* _REMOVE + + + +
|
* _REMOVE + + + +
|
||||||
|
* _SWAP + + + +
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifdef QUEUE_MACRO_DEBUG
|
#ifdef QUEUE_MACRO_DEBUG
|
||||||
/* Store the last 2 places the queue element or head was altered */
|
/* Store the last 2 places the queue element or head was altered */
|
||||||
struct qm_trace {
|
struct qm_trace {
|
||||||
char * lastfile;
|
unsigned long lastline;
|
||||||
int lastline;
|
unsigned long prevline;
|
||||||
char * prevfile;
|
const char *lastfile;
|
||||||
int prevline;
|
const char *prevfile;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TRACEBUF struct qm_trace trace;
|
#define TRACEBUF struct qm_trace trace;
|
||||||
|
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
|
||||||
#define TRASHIT(x) do {(x) = (void *)-1;} while (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 { \
|
#define QMD_TRACE_HEAD(head) do { \
|
||||||
(head)->trace.prevline = (head)->trace.lastline; \
|
(head)->trace.prevline = (head)->trace.lastline; \
|
||||||
@@ -130,7 +137,9 @@ struct qm_trace {
|
|||||||
#else
|
#else
|
||||||
#define QMD_TRACE_ELEM(elem)
|
#define QMD_TRACE_ELEM(elem)
|
||||||
#define QMD_TRACE_HEAD(head)
|
#define QMD_TRACE_HEAD(head)
|
||||||
|
#define QMD_SAVELINK(name, link)
|
||||||
#define TRACEBUF
|
#define TRACEBUF
|
||||||
|
#define TRACEBUF_INITIALIZER
|
||||||
#define TRASHIT(x)
|
#define TRASHIT(x)
|
||||||
#endif /* QUEUE_MACRO_DEBUG */
|
#endif /* QUEUE_MACRO_DEBUG */
|
||||||
|
|
||||||
@@ -162,11 +171,21 @@ struct { \
|
|||||||
(var); \
|
(var); \
|
||||||
(var) = SLIST_NEXT((var), field))
|
(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) \
|
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
for ((var) = SLIST_FIRST((head)); \
|
for ((var) = SLIST_FIRST((head)); \
|
||||||
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
||||||
(var) = (tvar))
|
(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) \
|
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
|
||||||
for ((varp) = &SLIST_FIRST((head)); \
|
for ((varp) = &SLIST_FIRST((head)); \
|
||||||
((var) = *(varp)) != NULL; \
|
((var) = *(varp)) != NULL; \
|
||||||
@@ -189,6 +208,7 @@ struct { \
|
|||||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||||
|
|
||||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||||
|
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
|
||||||
if (SLIST_FIRST((head)) == (elm)) { \
|
if (SLIST_FIRST((head)) == (elm)) { \
|
||||||
SLIST_REMOVE_HEAD((head), field); \
|
SLIST_REMOVE_HEAD((head), field); \
|
||||||
} \
|
} \
|
||||||
@@ -198,7 +218,7 @@ struct { \
|
|||||||
curelm = SLIST_NEXT(curelm, field); \
|
curelm = SLIST_NEXT(curelm, field); \
|
||||||
SLIST_REMOVE_AFTER(curelm, field); \
|
SLIST_REMOVE_AFTER(curelm, field); \
|
||||||
} \
|
} \
|
||||||
TRASHIT((elm)->field.sle_next); \
|
TRASHIT(*oldnext); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SLIST_REMOVE_AFTER(elm, field) do { \
|
#define SLIST_REMOVE_AFTER(elm, field) do { \
|
||||||
@@ -210,6 +230,12 @@ struct { \
|
|||||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define SLIST_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.
|
* Singly-linked Tail queue declarations.
|
||||||
*/
|
*/
|
||||||
@@ -247,12 +273,21 @@ struct { \
|
|||||||
(var); \
|
(var); \
|
||||||
(var) = STAILQ_NEXT((var), field))
|
(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) \
|
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
for ((var) = STAILQ_FIRST((head)); \
|
for ((var) = STAILQ_FIRST((head)); \
|
||||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||||
(var) = (tvar))
|
(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 { \
|
#define STAILQ_INIT(head) do { \
|
||||||
STAILQ_FIRST((head)) = NULL; \
|
STAILQ_FIRST((head)) = NULL; \
|
||||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||||
@@ -277,14 +312,13 @@ struct { \
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define STAILQ_LAST(head, type, field) \
|
#define STAILQ_LAST(head, type, field) \
|
||||||
(STAILQ_EMPTY((head)) ? \
|
(STAILQ_EMPTY((head)) ? NULL : \
|
||||||
NULL : \
|
__containerof((head)->stqh_last, struct type, field.stqe_next))
|
||||||
((struct type *)(void *) \
|
|
||||||
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
|
|
||||||
|
|
||||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||||
|
|
||||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||||
|
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
|
||||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||||
STAILQ_REMOVE_HEAD((head), field); \
|
STAILQ_REMOVE_HEAD((head), field); \
|
||||||
} \
|
} \
|
||||||
@@ -294,13 +328,7 @@ struct { \
|
|||||||
curelm = STAILQ_NEXT(curelm, field); \
|
curelm = STAILQ_NEXT(curelm, field); \
|
||||||
STAILQ_REMOVE_AFTER(head, curelm, field); \
|
STAILQ_REMOVE_AFTER(head, curelm, field); \
|
||||||
} \
|
} \
|
||||||
TRASHIT((elm)->field.stqe_next); \
|
TRASHIT(*oldnext); \
|
||||||
} 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)
|
} while (0)
|
||||||
|
|
||||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
||||||
@@ -309,6 +337,12 @@ struct { \
|
|||||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||||
} while (0)
|
} 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 { \
|
#define STAILQ_SWAP(head1, head2, type) do { \
|
||||||
struct type *swap_first = STAILQ_FIRST(head1); \
|
struct type *swap_first = STAILQ_FIRST(head1); \
|
||||||
struct type **swap_last = (head1)->stqh_last; \
|
struct type **swap_last = (head1)->stqh_last; \
|
||||||
@@ -378,11 +412,21 @@ struct { \
|
|||||||
(var); \
|
(var); \
|
||||||
(var) = LIST_NEXT((var), field))
|
(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) \
|
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
for ((var) = LIST_FIRST((head)); \
|
for ((var) = LIST_FIRST((head)); \
|
||||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||||
(var) = (tvar))
|
(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 { \
|
#define LIST_INIT(head) do { \
|
||||||
LIST_FIRST((head)) = NULL; \
|
LIST_FIRST((head)) = NULL; \
|
||||||
} while (0)
|
} while (0)
|
||||||
@@ -414,15 +458,21 @@ struct { \
|
|||||||
|
|
||||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||||
|
|
||||||
|
#define LIST_PREV(elm, head, type, field) \
|
||||||
|
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
|
||||||
|
__containerof((elm)->field.le_prev, struct type, field.le_next))
|
||||||
|
|
||||||
#define LIST_REMOVE(elm, field) do { \
|
#define LIST_REMOVE(elm, field) do { \
|
||||||
|
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
|
||||||
|
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
|
||||||
QMD_LIST_CHECK_NEXT(elm, field); \
|
QMD_LIST_CHECK_NEXT(elm, field); \
|
||||||
QMD_LIST_CHECK_PREV(elm, field); \
|
QMD_LIST_CHECK_PREV(elm, field); \
|
||||||
if (LIST_NEXT((elm), field) != NULL) \
|
if (LIST_NEXT((elm), field) != NULL) \
|
||||||
LIST_NEXT((elm), field)->field.le_prev = \
|
LIST_NEXT((elm), field)->field.le_prev = \
|
||||||
(elm)->field.le_prev; \
|
(elm)->field.le_prev; \
|
||||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||||
TRASHIT((elm)->field.le_next); \
|
TRASHIT(*oldnext); \
|
||||||
TRASHIT((elm)->field.le_prev); \
|
TRASHIT(*oldprev); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LIST_SWAP(head1, head2, type, field) do { \
|
#define LIST_SWAP(head1, head2, type, field) do { \
|
||||||
@@ -446,7 +496,7 @@ struct name { \
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||||
{ NULL, &(head).tqh_first }
|
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
|
||||||
|
|
||||||
#define TAILQ_ENTRY(type) \
|
#define TAILQ_ENTRY(type) \
|
||||||
struct { \
|
struct { \
|
||||||
@@ -509,21 +559,41 @@ struct { \
|
|||||||
(var); \
|
(var); \
|
||||||
(var) = TAILQ_NEXT((var), field))
|
(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) \
|
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
for ((var) = TAILQ_FIRST((head)); \
|
for ((var) = TAILQ_FIRST((head)); \
|
||||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||||
(var) = (tvar))
|
(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) \
|
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||||
for ((var) = TAILQ_LAST((head), headname); \
|
for ((var) = TAILQ_LAST((head), headname); \
|
||||||
(var); \
|
(var); \
|
||||||
(var) = TAILQ_PREV((var), headname, field))
|
(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) \
|
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
|
||||||
for ((var) = TAILQ_LAST((head), headname); \
|
for ((var) = TAILQ_LAST((head), headname); \
|
||||||
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
||||||
(var) = (tvar))
|
(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 { \
|
#define TAILQ_INIT(head) do { \
|
||||||
TAILQ_FIRST((head)) = NULL; \
|
TAILQ_FIRST((head)) = NULL; \
|
||||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||||
@@ -587,6 +657,8 @@ struct { \
|
|||||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||||
|
|
||||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
#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_NEXT(elm, field); \
|
||||||
QMD_TAILQ_CHECK_PREV(elm, field); \
|
QMD_TAILQ_CHECK_PREV(elm, field); \
|
||||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||||
@@ -597,8 +669,8 @@ struct { \
|
|||||||
QMD_TRACE_HEAD(head); \
|
QMD_TRACE_HEAD(head); \
|
||||||
} \
|
} \
|
||||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||||
TRASHIT((elm)->field.tqe_next); \
|
TRASHIT(*oldnext); \
|
||||||
TRASHIT((elm)->field.tqe_prev); \
|
TRASHIT(*oldprev); \
|
||||||
QMD_TRACE_ELEM(&(elm)->field); \
|
QMD_TRACE_ELEM(&(elm)->field); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
57
include/bsd/timeconv.h
Normal file
57
include/bsd/timeconv.h
Normal 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_ */
|
@@ -34,7 +34,11 @@
|
|||||||
#ifndef LIBBSD_UNISTD_H
|
#ifndef LIBBSD_UNISTD_H
|
||||||
#define LIBBSD_UNISTD_H
|
#define LIBBSD_UNISTD_H
|
||||||
|
|
||||||
|
#ifdef LIBBSD_OVERLAY
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
#else
|
||||||
|
#include <bsd/sys/cdefs.h>
|
||||||
|
#endif
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifndef S_ISTXT
|
#ifndef S_ISTXT
|
||||||
@@ -56,7 +60,12 @@ void *setmode(const char *mode_str);
|
|||||||
|
|
||||||
void closefrom(int lowfd);
|
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);
|
int getpeereid(int s, uid_t *euid, gid_t *egid);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@@ -24,12 +24,18 @@
|
|||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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
|
#ifdef LIBBSD_OVERLAY
|
||||||
#include_next <wchar.h>
|
#include_next <wchar.h>
|
||||||
#else
|
#else
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LIBBSD_WCHAR_H_SKIP
|
||||||
#ifndef LIBBSD_WCHAR_H
|
#ifndef LIBBSD_WCHAR_H
|
||||||
#define 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
|
__END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
#undef LIBBSD_WCHAR_H_SKIP
|
||||||
|
@@ -23,11 +23,14 @@ dist_man_MANS = \
|
|||||||
closefrom.3 \
|
closefrom.3 \
|
||||||
dehumanize_number.3 \
|
dehumanize_number.3 \
|
||||||
expand_number.3 \
|
expand_number.3 \
|
||||||
|
explicit_bzero.3 \
|
||||||
fgetln.3 \
|
fgetln.3 \
|
||||||
fgetwln.3 \
|
fgetwln.3 \
|
||||||
flopen.3 \
|
flopen.3 \
|
||||||
fmtcheck.3 \
|
fmtcheck.3 \
|
||||||
fparseln.3 \
|
fparseln.3 \
|
||||||
|
funopen.3bsd \
|
||||||
|
getbsize.3 \
|
||||||
getmode.3 \
|
getmode.3 \
|
||||||
getpeereid.3 \
|
getpeereid.3 \
|
||||||
getprogname.3 \
|
getprogname.3 \
|
||||||
@@ -40,11 +43,13 @@ dist_man_MANS = \
|
|||||||
queue.3bsd \
|
queue.3bsd \
|
||||||
radixsort.3 \
|
radixsort.3 \
|
||||||
readpassphrase.3 \
|
readpassphrase.3 \
|
||||||
|
reallocarray.3 \
|
||||||
reallocf.3 \
|
reallocf.3 \
|
||||||
setmode.3 \
|
setmode.3 \
|
||||||
setproctitle.3 \
|
setproctitle.3 \
|
||||||
setprogname.3 \
|
setprogname.3 \
|
||||||
sradixsort.3 \
|
sradixsort.3 \
|
||||||
|
stringlist.3 \
|
||||||
strlcat.3 \
|
strlcat.3 \
|
||||||
strlcpy.3 \
|
strlcpy.3 \
|
||||||
strnstr.3 \
|
strnstr.3 \
|
||||||
|
108
man/arc4random.3
108
man/arc4random.3
@@ -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>
|
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@@ -28,9 +29,8 @@
|
|||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" Manual page, using -mandoc macros
|
.\" Manual page, using -mandoc macros
|
||||||
.\" $FreeBSD$
|
|
||||||
.\"
|
.\"
|
||||||
.Dd April 15, 1997
|
.Dd $Mdocdate: July 19 2014 $
|
||||||
.Dt ARC4RANDOM 3
|
.Dt ARC4RANDOM 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -45,56 +45,70 @@
|
|||||||
.Lb libbsd
|
.Lb libbsd
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.In bsd/stdlib.h
|
.In bsd/stdlib.h
|
||||||
.Ft u_int32_t
|
.Ft uint32_t
|
||||||
.Fn arc4random "void"
|
.Fn arc4random "void"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn arc4random_buf "void *buf" "size_t nbytes"
|
.Fn arc4random_buf "void *buf" "size_t nbytes"
|
||||||
.Ft u_int32_t
|
.Ft uint32_t
|
||||||
.Fn arc4random_uniform "u_int32_t upper_bound"
|
.Fn arc4random_uniform "uint32_t upper_bound"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn arc4random_stir "void"
|
.Fn arc4random_stir "void"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
|
.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
This family of functions provides higher quality data than those
|
||||||
.Fn arc4random
|
described in
|
||||||
function uses the key stream generator employed by the
|
.Xr rand 3 ,
|
||||||
arc4 cipher, which uses 8*8 8 bit S-Boxes.
|
.Xr random 3 ,
|
||||||
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
|
|
||||||
and
|
and
|
||||||
.Xr random 3 .
|
.Xr rand48 3 .
|
||||||
.Pp
|
.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
|
.Fn arc4random_buf
|
||||||
function fills the region
|
function fills the region
|
||||||
.Fa buf
|
.Fa buf
|
||||||
of length
|
of length
|
||||||
.Fa nbytes
|
.Fa nbytes
|
||||||
with ARC4-derived random data.
|
with random data.
|
||||||
.Pp
|
.Pp
|
||||||
.Fn arc4random_uniform
|
.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 .
|
.Fa upper_bound .
|
||||||
.Fn arc4random_uniform
|
This is recommended over constructions like
|
||||||
is recommended over constructions like
|
|
||||||
.Dq Li arc4random() % upper_bound
|
.Dq Li arc4random() % upper_bound
|
||||||
as it avoids "modulo bias" when the upper bound is not a power of two.
|
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
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn arc4random_stir
|
.Fn arc4random_stir
|
||||||
function reads data from
|
function reads data from
|
||||||
.Pa /dev/urandom
|
.Xr getentropy 2
|
||||||
and uses it to permute the S-Boxes via
|
and uses it to re-seed the subsystem via
|
||||||
.Fn arc4random_addrandom .
|
.Fn arc4random_addrandom .
|
||||||
.Pp
|
.Pp
|
||||||
There is no need to call
|
There is no need to call
|
||||||
@@ -103,26 +117,22 @@ before using
|
|||||||
.Fn arc4random
|
.Fn arc4random
|
||||||
functions family, since
|
functions family, since
|
||||||
they automatically initialize themselves.
|
they automatically initialize themselves.
|
||||||
.Sh EXAMPLES
|
.Sh RETURN VALUES
|
||||||
The following produces a drop-in replacement for the traditional
|
These functions are always successful, and no return value is
|
||||||
.Fn rand
|
reserved to indicate an error.
|
||||||
and
|
|
||||||
.Fn random
|
|
||||||
functions using
|
|
||||||
.Fn arc4random :
|
|
||||||
.Pp
|
|
||||||
.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
|
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr rand 3 ,
|
.Xr rand 3 ,
|
||||||
.Xr random 3 ,
|
.Xr rand48 3 ,
|
||||||
.Xr srandomdev 3
|
.Xr random 3
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
.Pa RC4
|
These functions first appeared in
|
||||||
has been designed by RSA Data Security, Inc.
|
.Ox 2.1 .
|
||||||
It was posted anonymously
|
.Pp
|
||||||
to the USENET and was confirmed to be equivalent by several sources who
|
The original version of this random number generator used the
|
||||||
had access to the original cipher.
|
RC4 (also known as ARC4) algorithm.
|
||||||
Since
|
In
|
||||||
.Pa RC4
|
.Ox 5.5
|
||||||
used to be a trade secret, the cipher is now referred to as
|
it was replaced with the ChaCha20 cipher, and it may be replaced
|
||||||
.Pa ARC4 .
|
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
72
man/explicit_bzero.3
Normal 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 .
|
@@ -126,9 +126,9 @@ is returned.
|
|||||||
The
|
The
|
||||||
.Fn fparseln
|
.Fn fparseln
|
||||||
function uses internally
|
function uses internally
|
||||||
.Xr fgetln 3 ,
|
.Xr getline 3 ,
|
||||||
so all error conditions that apply to
|
so all error conditions that apply to
|
||||||
.Xr fgetln 3 ,
|
.Xr getline 3 ,
|
||||||
apply to
|
apply to
|
||||||
.Fn fparseln .
|
.Fn fparseln .
|
||||||
In addition
|
In addition
|
||||||
@@ -141,7 +141,7 @@ and return
|
|||||||
.Dv NULL
|
.Dv NULL
|
||||||
if it runs out of memory.
|
if it runs out of memory.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr fgetln 3
|
.Xr getline 3
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Fn fparseln
|
.Fn fparseln
|
||||||
|
191
man/funopen.3bsd
Normal file
191
man/funopen.3bsd
Normal 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
95
man/getbsize.3
Normal 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 .
|
@@ -32,13 +32,13 @@
|
|||||||
.Ft void
|
.Ft void
|
||||||
.Fn MDXInit "MDX_CTX *context"
|
.Fn MDXInit "MDX_CTX *context"
|
||||||
.Ft void
|
.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
|
.Ft void
|
||||||
.Fn MDXPad "MDX_CTX *context"
|
.Fn MDXPad "MDX_CTX *context"
|
||||||
.Ft void
|
.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
|
.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 *"
|
.Ft "char *"
|
||||||
.Fn MDXEnd "MDX_CTX *context" "char *buf"
|
.Fn MDXEnd "MDX_CTX *context" "char *buf"
|
||||||
.Ft "char *"
|
.Ft "char *"
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
.Ft "char *"
|
.Ft "char *"
|
||||||
.Fn MDXFileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
|
.Fn MDXFileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
|
||||||
.Ft "char *"
|
.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
|
.Sh DESCRIPTION
|
||||||
The MDX functions calculate a 128-bit cryptographic checksum (digest)
|
The MDX functions calculate a 128-bit cryptographic checksum (digest)
|
||||||
for any number of input bytes.
|
for any number of input bytes.
|
||||||
|
186
man/queue.3bsd
186
man/queue.3bsd
@@ -9,7 +9,7 @@
|
|||||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
.\" notice, this list of conditions and the following disclaimer in the
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
.\" documentation and/or other materials provided with the distribution.
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
.\" 4. Neither the name of the University nor the names of its contributors
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
.\" may be used to endorse or promote products derived from this software
|
.\" may be used to endorse or promote products derived from this software
|
||||||
.\" without specific prior written permission.
|
.\" without specific prior written permission.
|
||||||
.\"
|
.\"
|
||||||
@@ -28,15 +28,17 @@
|
|||||||
.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
|
.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd May 13, 2011
|
.Dd June 17, 2013
|
||||||
.Dt QUEUE 3bsd
|
.Dt QUEUE 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm SLIST_EMPTY ,
|
.Nm SLIST_EMPTY ,
|
||||||
.Nm SLIST_ENTRY ,
|
.Nm SLIST_ENTRY ,
|
||||||
.Nm SLIST_FIRST ,
|
.Nm SLIST_FIRST ,
|
||||||
.Nm SLIST_FOREACH ,
|
.Nm SLIST_FOREACH ,
|
||||||
|
.Nm SLIST_FOREACH_FROM ,
|
||||||
.Nm SLIST_FOREACH_SAFE ,
|
.Nm SLIST_FOREACH_SAFE ,
|
||||||
|
.Nm SLIST_FOREACH_FROM_SAFE ,
|
||||||
.Nm SLIST_HEAD ,
|
.Nm SLIST_HEAD ,
|
||||||
.Nm SLIST_HEAD_INITIALIZER ,
|
.Nm SLIST_HEAD_INITIALIZER ,
|
||||||
.Nm SLIST_INIT ,
|
.Nm SLIST_INIT ,
|
||||||
@@ -52,7 +54,9 @@
|
|||||||
.Nm STAILQ_ENTRY ,
|
.Nm STAILQ_ENTRY ,
|
||||||
.Nm STAILQ_FIRST ,
|
.Nm STAILQ_FIRST ,
|
||||||
.Nm STAILQ_FOREACH ,
|
.Nm STAILQ_FOREACH ,
|
||||||
|
.Nm STAILQ_FOREACH_FROM ,
|
||||||
.Nm STAILQ_FOREACH_SAFE ,
|
.Nm STAILQ_FOREACH_SAFE ,
|
||||||
|
.Nm STAILQ_FOREACH_FROM_SAFE ,
|
||||||
.Nm STAILQ_HEAD ,
|
.Nm STAILQ_HEAD ,
|
||||||
.Nm STAILQ_HEAD_INITIALIZER ,
|
.Nm STAILQ_HEAD_INITIALIZER ,
|
||||||
.Nm STAILQ_INIT ,
|
.Nm STAILQ_INIT ,
|
||||||
@@ -69,7 +73,9 @@
|
|||||||
.Nm LIST_ENTRY ,
|
.Nm LIST_ENTRY ,
|
||||||
.Nm LIST_FIRST ,
|
.Nm LIST_FIRST ,
|
||||||
.Nm LIST_FOREACH ,
|
.Nm LIST_FOREACH ,
|
||||||
|
.Nm LIST_FOREACH_FROM ,
|
||||||
.Nm LIST_FOREACH_SAFE ,
|
.Nm LIST_FOREACH_SAFE ,
|
||||||
|
.Nm LIST_FOREACH_FROM_SAFE ,
|
||||||
.Nm LIST_HEAD ,
|
.Nm LIST_HEAD ,
|
||||||
.Nm LIST_HEAD_INITIALIZER ,
|
.Nm LIST_HEAD_INITIALIZER ,
|
||||||
.Nm LIST_INIT ,
|
.Nm LIST_INIT ,
|
||||||
@@ -77,6 +83,7 @@
|
|||||||
.Nm LIST_INSERT_BEFORE ,
|
.Nm LIST_INSERT_BEFORE ,
|
||||||
.Nm LIST_INSERT_HEAD ,
|
.Nm LIST_INSERT_HEAD ,
|
||||||
.Nm LIST_NEXT ,
|
.Nm LIST_NEXT ,
|
||||||
|
.Nm LIST_PREV ,
|
||||||
.Nm LIST_REMOVE ,
|
.Nm LIST_REMOVE ,
|
||||||
.Nm LIST_SWAP ,
|
.Nm LIST_SWAP ,
|
||||||
.Nm TAILQ_CONCAT ,
|
.Nm TAILQ_CONCAT ,
|
||||||
@@ -84,9 +91,13 @@
|
|||||||
.Nm TAILQ_ENTRY ,
|
.Nm TAILQ_ENTRY ,
|
||||||
.Nm TAILQ_FIRST ,
|
.Nm TAILQ_FIRST ,
|
||||||
.Nm TAILQ_FOREACH ,
|
.Nm TAILQ_FOREACH ,
|
||||||
|
.Nm TAILQ_FOREACH_FROM ,
|
||||||
.Nm TAILQ_FOREACH_SAFE ,
|
.Nm TAILQ_FOREACH_SAFE ,
|
||||||
|
.Nm TAILQ_FOREACH_FROM_SAFE ,
|
||||||
.Nm TAILQ_FOREACH_REVERSE ,
|
.Nm TAILQ_FOREACH_REVERSE ,
|
||||||
|
.Nm TAILQ_FOREACH_REVERSE_FROM ,
|
||||||
.Nm TAILQ_FOREACH_REVERSE_SAFE ,
|
.Nm TAILQ_FOREACH_REVERSE_SAFE ,
|
||||||
|
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE ,
|
||||||
.Nm TAILQ_HEAD ,
|
.Nm TAILQ_HEAD ,
|
||||||
.Nm TAILQ_HEAD_INITIALIZER ,
|
.Nm TAILQ_HEAD_INITIALIZER ,
|
||||||
.Nm TAILQ_INIT ,
|
.Nm TAILQ_INIT ,
|
||||||
@@ -108,7 +119,9 @@ lists and tail queues
|
|||||||
.Fn SLIST_ENTRY "TYPE"
|
.Fn SLIST_ENTRY "TYPE"
|
||||||
.Fn SLIST_FIRST "SLIST_HEAD *head"
|
.Fn SLIST_FIRST "SLIST_HEAD *head"
|
||||||
.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
|
.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
|
||||||
|
.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
|
||||||
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
|
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
|
||||||
|
.Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
|
||||||
.Fn SLIST_HEAD "HEADNAME" "TYPE"
|
.Fn SLIST_HEAD "HEADNAME" "TYPE"
|
||||||
.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
|
.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
|
||||||
.Fn SLIST_INIT "SLIST_HEAD *head"
|
.Fn SLIST_INIT "SLIST_HEAD *head"
|
||||||
@@ -125,7 +138,9 @@ lists and tail queues
|
|||||||
.Fn STAILQ_ENTRY "TYPE"
|
.Fn STAILQ_ENTRY "TYPE"
|
||||||
.Fn STAILQ_FIRST "STAILQ_HEAD *head"
|
.Fn STAILQ_FIRST "STAILQ_HEAD *head"
|
||||||
.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
|
.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
|
||||||
|
.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
|
||||||
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
|
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||||
|
.Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
|
||||||
.Fn STAILQ_HEAD "HEADNAME" "TYPE"
|
.Fn STAILQ_HEAD "HEADNAME" "TYPE"
|
||||||
.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
|
.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
|
||||||
.Fn STAILQ_INIT "STAILQ_HEAD *head"
|
.Fn STAILQ_INIT "STAILQ_HEAD *head"
|
||||||
@@ -143,7 +158,9 @@ lists and tail queues
|
|||||||
.Fn LIST_ENTRY "TYPE"
|
.Fn LIST_ENTRY "TYPE"
|
||||||
.Fn LIST_FIRST "LIST_HEAD *head"
|
.Fn LIST_FIRST "LIST_HEAD *head"
|
||||||
.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
|
.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
|
||||||
|
.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
|
||||||
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
|
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
|
||||||
|
.Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
|
||||||
.Fn LIST_HEAD "HEADNAME" "TYPE"
|
.Fn LIST_HEAD "HEADNAME" "TYPE"
|
||||||
.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
|
.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
|
||||||
.Fn LIST_INIT "LIST_HEAD *head"
|
.Fn LIST_INIT "LIST_HEAD *head"
|
||||||
@@ -151,6 +168,7 @@ lists and tail queues
|
|||||||
.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
|
.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_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
|
||||||
.Fn LIST_NEXT "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_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
|
||||||
.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
|
.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
|
||||||
.\"
|
.\"
|
||||||
@@ -159,9 +177,13 @@ lists and tail queues
|
|||||||
.Fn TAILQ_ENTRY "TYPE"
|
.Fn TAILQ_ENTRY "TYPE"
|
||||||
.Fn TAILQ_FIRST "TAILQ_HEAD *head"
|
.Fn TAILQ_FIRST "TAILQ_HEAD *head"
|
||||||
.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
|
.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
|
||||||
|
.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
|
||||||
.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
|
.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 "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_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 "HEADNAME" "TYPE"
|
||||||
.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
|
.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
|
||||||
.Fn TAILQ_INIT "TAILQ_HEAD *head"
|
.Fn TAILQ_INIT "TAILQ_HEAD *head"
|
||||||
@@ -244,8 +266,18 @@ Code size and execution time of operations (except for removal) is about
|
|||||||
twice that of the singly-linked data-structures.
|
twice that of the singly-linked data-structures.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Linked lists are the simplest of the doubly linked data structures and support
|
Linked lists are the simplest of the doubly linked data structures.
|
||||||
only the above functionality over singly-linked lists.
|
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
|
.Pp
|
||||||
Tail queues add the following functionality:
|
Tail queues add the following functionality:
|
||||||
.Bl -enum -compact -offset indent
|
.Bl -enum -compact -offset indent
|
||||||
@@ -349,6 +381,19 @@ turn to
|
|||||||
.Fa var .
|
.Fa var .
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm SLIST_FOREACH_SAFE
|
||||||
traverses the list referenced by
|
traverses the list referenced by
|
||||||
.Fa head
|
.Fa head
|
||||||
@@ -363,6 +408,19 @@ as well as free it from within the loop safely without interfering with the
|
|||||||
traversal.
|
traversal.
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm SLIST_INIT
|
||||||
initializes the list referenced by
|
initializes the list referenced by
|
||||||
.Fa head .
|
.Fa head .
|
||||||
@@ -388,7 +446,8 @@ The macro
|
|||||||
.Nm SLIST_REMOVE_AFTER
|
.Nm SLIST_REMOVE_AFTER
|
||||||
removes the element after
|
removes the element after
|
||||||
.Fa elm
|
.Fa elm
|
||||||
from the list. Unlike
|
from the list.
|
||||||
|
Unlike
|
||||||
.Fa SLIST_REMOVE ,
|
.Fa SLIST_REMOVE ,
|
||||||
this macro does not traverse the entire list.
|
this macro does not traverse the entire list.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -528,6 +587,19 @@ in turn to
|
|||||||
.Fa var .
|
.Fa var .
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm STAILQ_FOREACH_SAFE
|
||||||
traverses the tail queue referenced by
|
traverses the tail queue referenced by
|
||||||
.Fa head
|
.Fa head
|
||||||
@@ -542,6 +614,19 @@ as well as free it from within the loop safely without interfering with the
|
|||||||
traversal.
|
traversal.
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm STAILQ_INIT
|
||||||
initializes the tail queue referenced by
|
initializes the tail queue referenced by
|
||||||
.Fa head .
|
.Fa head .
|
||||||
@@ -579,7 +664,8 @@ The macro
|
|||||||
.Nm STAILQ_REMOVE_AFTER
|
.Nm STAILQ_REMOVE_AFTER
|
||||||
removes the element after
|
removes the element after
|
||||||
.Fa elm
|
.Fa elm
|
||||||
from the tail queue. Unlike
|
from the tail queue.
|
||||||
|
Unlike
|
||||||
.Fa STAILQ_REMOVE ,
|
.Fa STAILQ_REMOVE ,
|
||||||
this macro does not traverse the entire tail queue.
|
this macro does not traverse the entire tail queue.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -717,6 +803,19 @@ in the forward direction, assigning each element in turn to
|
|||||||
.Fa var .
|
.Fa var .
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm LIST_FOREACH_SAFE
|
||||||
traverses the list referenced by
|
traverses the list referenced by
|
||||||
.Fa head
|
.Fa head
|
||||||
@@ -730,6 +829,19 @@ as well as free it from within the loop safely without interfering with the
|
|||||||
traversal.
|
traversal.
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm LIST_INIT
|
||||||
initializes the list referenced by
|
initializes the list referenced by
|
||||||
.Fa head .
|
.Fa head .
|
||||||
@@ -759,6 +871,14 @@ The macro
|
|||||||
returns the next element in the list, or NULL if this is the last.
|
returns the next element in the list, or NULL if this is the last.
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm LIST_REMOVE
|
||||||
removes the element
|
removes the element
|
||||||
.Fa elm
|
.Fa elm
|
||||||
@@ -894,12 +1014,38 @@ is set to
|
|||||||
if the loop completes normally, or if there were no elements.
|
if the loop completes normally, or if there were no elements.
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm TAILQ_FOREACH_REVERSE
|
||||||
traverses the tail queue referenced by
|
traverses the tail queue referenced by
|
||||||
.Fa head
|
.Fa head
|
||||||
in the reverse direction, assigning each element in turn to
|
in the reverse direction, assigning each element in turn to
|
||||||
.Fa var .
|
.Fa var .
|
||||||
.Pp
|
.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
|
The macros
|
||||||
.Nm TAILQ_FOREACH_SAFE
|
.Nm TAILQ_FOREACH_SAFE
|
||||||
and
|
and
|
||||||
@@ -919,6 +1065,32 @@ as well as free it from within the loop safely without interfering with the
|
|||||||
traversal.
|
traversal.
|
||||||
.Pp
|
.Pp
|
||||||
The macro
|
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
|
.Nm TAILQ_INIT
|
||||||
initializes the tail queue referenced by
|
initializes the tail queue referenced by
|
||||||
.Fa head .
|
.Fa head .
|
||||||
|
102
man/reallocarray.3
Normal file
102
man/reallocarray.3
Normal 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 .
|
@@ -33,6 +33,8 @@
|
|||||||
.In sys/types.h
|
.In sys/types.h
|
||||||
.In bsd/unistd.h
|
.In bsd/unistd.h
|
||||||
.Ft void
|
.Ft void
|
||||||
|
.Fn setproctitle_init "int argc" "char *argv[]" "char *envp[]"
|
||||||
|
.Ft void
|
||||||
.Fn setproctitle "const char *fmt" "..."
|
.Fn setproctitle "const char *fmt" "..."
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
@@ -41,6 +43,15 @@ library routine sets the process title that appears on the
|
|||||||
.Xr ps 1
|
.Xr ps 1
|
||||||
command.
|
command.
|
||||||
.Pp
|
.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
|
The title is set from the executable's name, followed by the
|
||||||
result of a
|
result of a
|
||||||
.Xr printf 3
|
.Xr printf 3
|
||||||
@@ -101,6 +112,11 @@ first appeared in
|
|||||||
.Fx 2.2 .
|
.Fx 2.2 .
|
||||||
Other operating systems have
|
Other operating systems have
|
||||||
similar functions.
|
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
|
.Sh AUTHORS
|
||||||
.An -nosplit
|
.An -nosplit
|
||||||
.An Peter Wemm Aq peter@FreeBSD.org
|
.An Peter Wemm Aq peter@FreeBSD.org
|
||||||
|
147
man/stringlist.3
Normal file
147
man/stringlist.3
Normal 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 .
|
@@ -7,11 +7,23 @@ AM_CPPFLAGS = \
|
|||||||
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
|
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
|
||||||
-D__REENTRANT
|
-D__REENTRANT
|
||||||
|
|
||||||
|
libbsd_la_included_sources = \
|
||||||
|
hash/helper.c \
|
||||||
|
getentropy_aix.c \
|
||||||
|
getentropy_bsd.c \
|
||||||
|
getentropy_hpux.c \
|
||||||
|
getentropy_hurd.c \
|
||||||
|
getentropy_linux.c \
|
||||||
|
getentropy_osx.c \
|
||||||
|
getentropy_solaris.c \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
libbsd.map \
|
libbsd.map \
|
||||||
libbsd.pc.in \
|
libbsd.pc.in \
|
||||||
|
libbsd-ctor.pc.in \
|
||||||
libbsd-overlay.pc.in \
|
libbsd-overlay.pc.in \
|
||||||
hash/helper.c \
|
$(libbsd_la_included_sources) \
|
||||||
$(nil)
|
$(nil)
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
@@ -25,56 +37,88 @@ pkgconfig_DATA = \
|
|||||||
$(nil)
|
$(nil)
|
||||||
|
|
||||||
lib_LTLIBRARIES = libbsd.la
|
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
|
hash/md5hl.c: $(srcdir)/hash/helper.c
|
||||||
$(AM_V_at) $(MKDIR_P) hash
|
$(AM_V_at) $(MKDIR_P) hash
|
||||||
$(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@
|
$(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@
|
||||||
|
|
||||||
libbsd_la_DEPENDENCIES = \
|
libbsd_la_DEPENDENCIES = \
|
||||||
|
$(libbsd_la_included_sources) \
|
||||||
libbsd.map
|
libbsd.map
|
||||||
libbsd_la_LDFLAGS = \
|
libbsd_la_LDFLAGS = \
|
||||||
-Wl,--version-script=$(srcdir)/libbsd.map \
|
-Wl,--version-script=$(srcdir)/libbsd.map \
|
||||||
-version-number 0:5:2
|
-version-number $(LIBBSD_ABI)
|
||||||
libbsd_la_SOURCES = \
|
libbsd_la_SOURCES = \
|
||||||
arc4random.c \
|
arc4random.c \
|
||||||
|
arc4random.h \
|
||||||
|
arc4random_unix.h \
|
||||||
|
arc4random_openbsd.h \
|
||||||
|
arc4random_uniform.c \
|
||||||
bsd_getopt.c \
|
bsd_getopt.c \
|
||||||
|
chacha_private.h \
|
||||||
closefrom.c \
|
closefrom.c \
|
||||||
dehumanize_number.c \
|
dehumanize_number.c \
|
||||||
err.c \
|
err.c \
|
||||||
expand_number.c \
|
expand_number.c \
|
||||||
|
explicit_bzero.c \
|
||||||
fgetln.c \
|
fgetln.c \
|
||||||
fgetwln.c \
|
fgetwln.c \
|
||||||
flopen.c \
|
flopen.c \
|
||||||
fmtcheck.c \
|
fmtcheck.c \
|
||||||
fparseln.c \
|
fparseln.c \
|
||||||
fpurge.c \
|
fpurge.c \
|
||||||
|
funopen.c \
|
||||||
|
getbsize.c \
|
||||||
getpeereid.c \
|
getpeereid.c \
|
||||||
hash/md5.c \
|
hash/md5.c \
|
||||||
hash/md5hl.c \
|
hash/md5hl.c \
|
||||||
|
hash/sha512.h \
|
||||||
|
hash/sha512c.c \
|
||||||
heapsort.c \
|
heapsort.c \
|
||||||
humanize_number.c \
|
humanize_number.c \
|
||||||
inet_net_pton.c \
|
inet_net_pton.c \
|
||||||
local-elf.h \
|
local-elf.h \
|
||||||
|
local-link.h \
|
||||||
merge.c \
|
merge.c \
|
||||||
nlist.c \
|
nlist.c \
|
||||||
pidfile.c \
|
pidfile.c \
|
||||||
progname.c \
|
progname.c \
|
||||||
radixsort.c \
|
radixsort.c \
|
||||||
readpassphrase.c \
|
readpassphrase.c \
|
||||||
|
reallocarray.c \
|
||||||
reallocf.c \
|
reallocf.c \
|
||||||
setmode.c \
|
setmode.c \
|
||||||
setproctitle.c \
|
setproctitle.c \
|
||||||
strlcat.c \
|
strlcat.c \
|
||||||
strlcpy.c \
|
strlcpy.c \
|
||||||
|
stringlist.c \
|
||||||
strmode.c \
|
strmode.c \
|
||||||
strnstr.c \
|
strnstr.c \
|
||||||
strtonum.c \
|
strtonum.c \
|
||||||
|
timeconv.c \
|
||||||
unvis.c \
|
unvis.c \
|
||||||
vis.c \
|
vis.c \
|
||||||
wcslcat.c \
|
wcslcat.c \
|
||||||
wcslcpy.c \
|
wcslcpy.c \
|
||||||
$(nil)
|
$(nil)
|
||||||
|
|
||||||
|
if !HAVE_GETENTROPY
|
||||||
|
libbsd_la_SOURCES += \
|
||||||
|
getentropy.c \
|
||||||
|
$(nil)
|
||||||
|
endif
|
||||||
|
|
||||||
|
libbsd_ctor_a_SOURCES = \
|
||||||
|
setproctitle_ctor.c \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
runtimelibdir = $(libdir)
|
runtimelibdir = $(libdir)
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
|
374
src/arc4random.c
374
src/arc4random.c
@@ -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) 1996, David Mazieres <dm@uun.org>
|
||||||
* Copyright (c) 2008, Damien Miller <djm@openbsd.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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -16,281 +21,192 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Arc4 random number generator for OpenBSD.
|
* ChaCha based 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <fcntl.h>
|
||||||
__FBSDID("$FreeBSD$");
|
#include <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
struct arc4_stream {
|
#define KEYSTREAM_ONLY
|
||||||
u_int8_t i;
|
#include "chacha_private.h"
|
||||||
u_int8_t j;
|
|
||||||
u_int8_t s[256];
|
|
||||||
};
|
|
||||||
|
|
||||||
#define RANDOMDEV "/dev/urandom"
|
#define minimum(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#define KEYSIZE 128
|
|
||||||
|
|
||||||
#ifdef __REENTRANT
|
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||||
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
|
#define inline __inline
|
||||||
#define THREAD_LOCK() pthread_mutex_lock(&arc4random_mtx)
|
#else /* __GNUC__ || _MSC_VER */
|
||||||
#define THREAD_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
|
#define inline
|
||||||
#else
|
#endif /* !__GNUC__ && !_MSC_VER */
|
||||||
#define THREAD_LOCK()
|
|
||||||
#define THREAD_UNLOCK()
|
#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
|
#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;
|
m = minimum(datlen, KEYSZ + IVSZ);
|
||||||
static int rs_initialized;
|
for (i = 0; i < m; i++)
|
||||||
static int rs_stired;
|
rsx->rs_buf[i] ^= dat[i];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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
|
static void
|
||||||
arc4_stir(void)
|
_rs_stir(void)
|
||||||
{
|
{
|
||||||
int done, fd, n;
|
u_char rnd[KEYSZ + IVSZ];
|
||||||
struct {
|
|
||||||
struct timeval tv;
|
|
||||||
pid_t pid;
|
|
||||||
u_int8_t rnd[KEYSIZE];
|
|
||||||
} rdat;
|
|
||||||
|
|
||||||
fd = open(RANDOMDEV, O_RDONLY, 0);
|
if (getentropy(rnd, sizeof rnd) == -1)
|
||||||
done = 0;
|
_getentropy_fail();
|
||||||
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... */
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
||||||
|
|
||||||
/*
|
/* invalidate rs_buf */
|
||||||
* Throw away the first N bytes of output, as suggested in the
|
rs->rs_have = 0;
|
||||||
* paper "Weaknesses in the Key Scheduling Algorithm of RC4"
|
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
|
||||||
* by Fluher, Mantin, and Shamir. N=1024 is based on
|
|
||||||
* suggestions in the paper "(Not So) Random Shuffles of RC4"
|
rs->rs_count = 1600000;
|
||||||
* by Ilya Mironov.
|
|
||||||
*/
|
|
||||||
for (n = 0; n < 1024; n++)
|
|
||||||
(void) arc4_getbyte();
|
|
||||||
arc4_count = 1600000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u_int8_t
|
static inline void
|
||||||
arc4_getbyte(void)
|
_rs_stir_if_needed(size_t len)
|
||||||
{
|
{
|
||||||
u_int8_t si, sj;
|
_rs_forkdetect();
|
||||||
|
if (!rs || rs->rs_count <= len)
|
||||||
rs.i = (rs.i + 1);
|
_rs_stir();
|
||||||
si = rs.s[rs.i];
|
if (rs->rs_count <= len)
|
||||||
rs.j = (rs.j + si);
|
rs->rs_count = 0;
|
||||||
sj = rs.s[rs.j];
|
else
|
||||||
rs.s[rs.i] = sj;
|
rs->rs_count -= len;
|
||||||
rs.s[rs.j] = si;
|
|
||||||
|
|
||||||
return (rs.s[(si + sj) & 0xff]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u_int32_t
|
static inline void
|
||||||
arc4_getword(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;
|
_rs_stir_if_needed(n);
|
||||||
val |= arc4_getbyte() << 16;
|
while (n > 0) {
|
||||||
val |= arc4_getbyte() << 8;
|
if (rs->rs_have > 0) {
|
||||||
val |= arc4_getbyte();
|
m = minimum(n, rs->rs_have);
|
||||||
|
keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
|
||||||
return (val);
|
- rs->rs_have;
|
||||||
}
|
memcpy(buf, keystream, m);
|
||||||
|
memset(keystream, 0, m);
|
||||||
static void
|
buf += m;
|
||||||
arc4_check_init(void)
|
n -= m;
|
||||||
{
|
rs->rs_have -= m;
|
||||||
if (!rs_initialized) {
|
}
|
||||||
arc4_init();
|
if (rs->rs_have == 0)
|
||||||
rs_initialized = 1;
|
_rs_rekey(NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
arc4_check_stir(void)
|
_rs_random_u32(uint32_t *val)
|
||||||
{
|
{
|
||||||
if (!rs_stired || arc4_count <= 0) {
|
u_char *keystream;
|
||||||
arc4_stir();
|
|
||||||
rs_stired = 1;
|
_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
|
void
|
||||||
arc4random_stir(void)
|
arc4random_stir(void)
|
||||||
{
|
{
|
||||||
THREAD_LOCK();
|
_ARC4_LOCK();
|
||||||
arc4_check_init();
|
_rs_stir();
|
||||||
arc4_stir();
|
_ARC4_UNLOCK();
|
||||||
rs_stired = 1;
|
|
||||||
THREAD_UNLOCK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
arc4random_addrandom(u_char *dat, int datlen)
|
arc4random_addrandom(u_char *dat, int datlen)
|
||||||
{
|
{
|
||||||
THREAD_LOCK();
|
_ARC4_LOCK();
|
||||||
arc4_check_init();
|
_rs_stir_if_needed(datlen);
|
||||||
arc4_check_stir();
|
_rs_rekey(dat, datlen);
|
||||||
arc4_addrandom(dat, datlen);
|
_ARC4_UNLOCK();
|
||||||
THREAD_UNLOCK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int32_t
|
uint32_t
|
||||||
arc4random(void)
|
arc4random(void)
|
||||||
{
|
{
|
||||||
u_int32_t rnd;
|
uint32_t val;
|
||||||
|
|
||||||
THREAD_LOCK();
|
_ARC4_LOCK();
|
||||||
arc4_check_init();
|
_rs_random_u32(&val);
|
||||||
arc4_check_stir();
|
_ARC4_UNLOCK();
|
||||||
rnd = arc4_getword();
|
return val;
|
||||||
arc4_count -= 4;
|
|
||||||
THREAD_UNLOCK();
|
|
||||||
|
|
||||||
return (rnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
arc4random_buf(void *_buf, size_t n)
|
arc4random_buf(void *buf, size_t n)
|
||||||
{
|
{
|
||||||
u_char *buf = (u_char *)_buf;
|
_ARC4_LOCK();
|
||||||
|
_rs_random_buf(buf, n);
|
||||||
THREAD_LOCK();
|
_ARC4_UNLOCK();
|
||||||
arc4_check_init();
|
|
||||||
while (n--) {
|
|
||||||
arc4_check_stir();
|
|
||||||
buf[n] = arc4_getbyte();
|
|
||||||
arc4_count--;
|
|
||||||
}
|
|
||||||
THREAD_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
|
|
||||||
|
41
src/arc4random.h
Normal file
41
src/arc4random.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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_ARC4RANDOM_H
|
||||||
|
#define LIBBSD_ARC4RANDOM_H
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
getentropy(void *buf, size_t len);
|
||||||
|
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
#include "arc4random_openbsd.h"
|
||||||
|
#else
|
||||||
|
#include "arc4random_unix.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
61
src/arc4random_openbsd.h
Normal file
61
src/arc4random_openbsd.h
Normal 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
57
src/arc4random_uniform.c
Normal 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);
|
92
src/arc4random_unix.h
Normal file
92
src/arc4random_unix.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/* $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
|
||||||
|
/*
|
||||||
|
* 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))
|
||||||
|
#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);
|
||||||
|
}
|
222
src/chacha_private.h
Normal file
222
src/chacha_private.h
Normal 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
|
||||||
|
}
|
||||||
|
}
|
152
src/closefrom.c
152
src/closefrom.c
@@ -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>
|
* Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifdef STDC_HEADERS
|
#ifdef STDC_HEADERS
|
||||||
@@ -30,20 +29,26 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif /* STDC_HEADERS */
|
#endif /* STDC_HEADERS */
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#ifdef HAVE_DIRENT_H
|
#include <limits.h>
|
||||||
# include <dirent.h>
|
#ifdef HAVE_PSTAT_GETPROC
|
||||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
# include <sys/param.h>
|
||||||
|
# include <sys/pstat.h>
|
||||||
#else
|
#else
|
||||||
# define dirent direct
|
# ifdef HAVE_DIRENT_H
|
||||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
# include <dirent.h>
|
||||||
# ifdef HAVE_SYS_NDIR_H
|
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||||
# include <sys/ndir.h>
|
# else
|
||||||
# endif
|
# define dirent direct
|
||||||
# ifdef HAVE_SYS_DIR_H
|
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||||
# include <sys/dir.h>
|
# ifdef HAVE_SYS_NDIR_H
|
||||||
# endif
|
# include <sys/ndir.h>
|
||||||
# ifdef HAVE_NDIR_H
|
# endif
|
||||||
# include <ndir.h>
|
# ifdef HAVE_SYS_DIR_H
|
||||||
|
# include <sys/dir.h>
|
||||||
|
# endif
|
||||||
|
# ifdef HAVE_NDIR_H
|
||||||
|
# include <ndir.h>
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -51,15 +56,24 @@
|
|||||||
# define OPEN_MAX 256
|
# define OPEN_MAX 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_FCNTL_CLOSEM
|
#if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)
|
||||||
# ifndef HAVE_DIRFD
|
# define closefrom closefrom_fallback
|
||||||
# define closefrom_fallback closefrom
|
|
||||||
# endif
|
|
||||||
#endif
|
#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.
|
* Close all file descriptors greater than or equal to lowfd.
|
||||||
* This is the expensive (ballback) method.
|
* This is the expensive (fallback) method.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
closefrom_fallback(int lowfd)
|
closefrom_fallback(int lowfd)
|
||||||
@@ -80,43 +94,99 @@ closefrom_fallback(int lowfd)
|
|||||||
maxfd = OPEN_MAX;
|
maxfd = OPEN_MAX;
|
||||||
|
|
||||||
for (fd = lowfd; fd < maxfd; fd++)
|
for (fd = lowfd; fd < maxfd; fd++)
|
||||||
(void)close((int)fd);
|
closefrom_close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close all file descriptors greater than or equal to lowfd.
|
* Close all file descriptors greater than or equal to lowfd.
|
||||||
* We try the fast way first, falling back on the slow method.
|
* We try the fast way first, falling back on the slow method.
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_FCNTL_CLOSEM
|
#if defined(HAVE_FCNTL_CLOSEM)
|
||||||
void
|
void
|
||||||
closefrom(int lowfd)
|
closefrom(int lowfd)
|
||||||
{
|
{
|
||||||
if (fcntl(lowfd, F_CLOSEM, 0) == -1)
|
if (fcntl(lowfd, F_CLOSEM, 0) == -1)
|
||||||
closefrom_fallback(lowfd);
|
closefrom_fallback(lowfd);
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(HAVE_PSTAT_GETPROC)
|
||||||
# ifdef HAVE_DIRFD
|
|
||||||
void
|
void
|
||||||
closefrom(int lowfd)
|
closefrom(int lowfd)
|
||||||
{
|
{
|
||||||
struct dirent *dent;
|
struct pst_status pstat;
|
||||||
DIR *dirp;
|
int fd;
|
||||||
char *endp;
|
|
||||||
long fd;
|
|
||||||
|
|
||||||
/* Use /proc/self/fd directory if it exists. */
|
if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1) {
|
||||||
dirp = opendir("/proc/self/fd");
|
for (fd = lowfd; fd <= pstat.pst_highestfd; fd++)
|
||||||
if (dirp != NULL) {
|
(void)close(fd);
|
||||||
while ((dent = readdir(dirp)) != NULL) {
|
} else {
|
||||||
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
|
|
||||||
closefrom_fallback(lowfd);
|
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(__FreeBSD_kernel__) || 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 */
|
#endif /* HAVE_FCNTL_CLOSEM */
|
||||||
|
@@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@@ -35,8 +35,8 @@
|
|||||||
int
|
int
|
||||||
dehumanize_number(const char *buf, int64_t *num)
|
dehumanize_number(const char *buf, int64_t *num)
|
||||||
{
|
{
|
||||||
uint64_t rval;
|
uint64_t rval, rmax;
|
||||||
int sign = 1;
|
int sign = +1;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* The current expand_number() implementation uses bit shifts, so
|
/* 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);
|
rc = expand_number(buf, &rval);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
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;
|
errno = ERANGE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
19
src/explicit_bzero.c
Normal file
19
src/explicit_bzero.c
Normal 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);
|
||||||
|
}
|
10
src/fgetln.c
10
src/fgetln.c
@@ -30,6 +30,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "local-link.h"
|
||||||
|
|
||||||
#ifdef HAVE_GETLINE
|
#ifdef HAVE_GETLINE
|
||||||
struct filebuf {
|
struct filebuf {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@@ -48,6 +50,8 @@ fgetln(FILE *stream, size_t *len)
|
|||||||
struct filebuf *fb;
|
struct filebuf *fb;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
|
|
||||||
|
flockfile(stream);
|
||||||
|
|
||||||
/* Try to diminish the possibility of several fgetln() calls being
|
/* Try to diminish the possibility of several fgetln() calls being
|
||||||
* used on different streams, by using a pool of buffers per file. */
|
* used on different streams, by using a pool of buffers per file. */
|
||||||
fb = &fb_pool[fb_pool_cur];
|
fb = &fb_pool[fb_pool_cur];
|
||||||
@@ -59,6 +63,9 @@ fgetln(FILE *stream, size_t *len)
|
|||||||
fb->fp = stream;
|
fb->fp = stream;
|
||||||
|
|
||||||
nread = getline(&fb->buf, &fb->len, stream);
|
nread = getline(&fb->buf, &fb->len, stream);
|
||||||
|
|
||||||
|
funlockfile(stream);
|
||||||
|
|
||||||
/* Note: the getdelim/getline API ensures nread != 0. */
|
/* Note: the getdelim/getline API ensures nread != 0. */
|
||||||
if (nread == -1) {
|
if (nread == -1) {
|
||||||
*len = 0;
|
*len = 0;
|
||||||
@@ -68,6 +75,9 @@ fgetln(FILE *stream, size_t *len)
|
|||||||
return fb->buf;
|
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
|
#else
|
||||||
#error "Function fgetln() needs to be ported."
|
#error "Function fgetln() needs to be ported."
|
||||||
#endif
|
#endif
|
||||||
|
@@ -60,7 +60,7 @@ fgetwln(FILE *stream, size_t *lenp)
|
|||||||
fb->fp = stream;
|
fb->fp = stream;
|
||||||
|
|
||||||
while ((wc = fgetwc(stream)) != WEOF) {
|
while ((wc = fgetwc(stream)) != WEOF) {
|
||||||
if (!fb->len || wused > fb->len) {
|
if (!fb->len || wused >= fb->len) {
|
||||||
wchar_t *wp;
|
wchar_t *wp;
|
||||||
|
|
||||||
if (fb->len)
|
if (fb->len)
|
||||||
@@ -68,7 +68,7 @@ fgetwln(FILE *stream, size_t *lenp)
|
|||||||
else
|
else
|
||||||
fb->len = FILEWBUF_INIT_LEN;
|
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) {
|
if (wp == NULL) {
|
||||||
wused = 0;
|
wused = 0;
|
||||||
break;
|
break;
|
||||||
|
@@ -35,8 +35,6 @@ __RCSID("$NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $");
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define FLOCKFILE(fp)
|
|
||||||
#define FUNLOCKFILE(fp)
|
|
||||||
#define _DIAGASSERT(t)
|
#define _DIAGASSERT(t)
|
||||||
|
|
||||||
static int isescaped(const char *, const char *, int);
|
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] = { '\\', '\\', '#' };
|
static const char dstr[3] = { '\\', '\\', '#' };
|
||||||
|
|
||||||
size_t s, len;
|
ssize_t s;
|
||||||
|
size_t len, ptrlen;
|
||||||
char *buf;
|
char *buf;
|
||||||
char *ptr, *cp;
|
char *ptr, *cp;
|
||||||
int cnt;
|
int cnt;
|
||||||
@@ -87,6 +86,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
|
|||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
|
ptrlen = 0;
|
||||||
|
ptr = NULL;
|
||||||
cnt = 1;
|
cnt = 1;
|
||||||
|
|
||||||
if (str == NULL)
|
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];
|
com = str[2];
|
||||||
/*
|
/*
|
||||||
* XXX: it would be cool to be able to specify the newline character,
|
* 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';
|
nl = '\n';
|
||||||
|
|
||||||
FLOCKFILE(fp);
|
flockfile(fp);
|
||||||
|
|
||||||
while (cnt) {
|
while (cnt) {
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
@@ -109,7 +110,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
|
|||||||
if (lineno)
|
if (lineno)
|
||||||
(*lineno)++;
|
(*lineno)++;
|
||||||
|
|
||||||
if ((ptr = fgetln(fp, &s)) == NULL)
|
s = getline(&ptr, &ptrlen, fp);
|
||||||
|
if (s < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (s && com) { /* Check and eliminate comments */
|
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) {
|
if ((cp = realloc(buf, len + s + 1)) == NULL) {
|
||||||
FUNLOCKFILE(fp);
|
funlockfile(fp);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
free(ptr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buf = cp;
|
buf = cp;
|
||||||
@@ -158,7 +161,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
|
|||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNLOCKFILE(fp);
|
funlockfile(fp);
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
|
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
|
||||||
strchr(buf, esc) != 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;
|
*size = len;
|
||||||
return buf;
|
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 */
|
|
||||||
|
20
src/fpurge.c
20
src/fpurge.c
@@ -44,23 +44,3 @@ fpurge(FILE *fp)
|
|||||||
#else
|
#else
|
||||||
#error "Function fpurge() needs to be ported."
|
#error "Function fpurge() needs to be ported."
|
||||||
#endif
|
#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
142
src/funopen.c
Normal 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
102
src/getbsize.c
Normal 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);
|
||||||
|
}
|
45
src/getentropy.c
Normal file
45
src/getentropy.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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(__GNU__)
|
||||||
|
#include "getentropy_hurd.c"
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
#include "getentropy_bsd.c"
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
#include "getentropy_bsd.c"
|
||||||
|
#elif defined(__sun)
|
||||||
|
#include "getentropy_solaris.c"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include "getentropy_osx.c"
|
||||||
|
#elif defined(_AIX)
|
||||||
|
#include "getentropy_aix.c"
|
||||||
|
#elif defined(__hpux)
|
||||||
|
#include "getentropy_hpux.c"
|
||||||
|
#else
|
||||||
|
#error "No getentropy hooks defined for this platform."
|
||||||
|
#endif
|
425
src/getentropy_aix.c
Normal file
425
src/getentropy_aix.c
Normal 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 "hash/sha512.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
62
src/getentropy_bsd.c
Normal 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);
|
||||||
|
}
|
420
src/getentropy_hpux.c
Normal file
420
src/getentropy_hpux.c
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
/* $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 "hash/sha512.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);
|
||||||
|
}
|
446
src/getentropy_hurd.c
Normal file
446
src/getentropy_hurd.c
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
/* $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>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <sys/socket.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 "hash/sha512.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);
|
||||||
|
static int getentropy_urandom(void *buf, size_t len);
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* 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 has 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 Hurd
|
||||||
|
* does not provide a failsafe API for entropy collection.
|
||||||
|
*
|
||||||
|
* We hope this demonstrates that Hurd should either get a
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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);
|
||||||
|
}
|
548
src/getentropy_linux.c
Normal file
548
src/getentropy_linux.c
Normal file
@@ -0,0 +1,548 @@
|
|||||||
|
/* $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 "hash/sha512.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
429
src/getentropy_osx.c
Normal 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
445
src/getentropy_solaris.c
Normal 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);
|
||||||
|
}
|
@@ -27,7 +27,7 @@ char *
|
|||||||
HASHEnd(HASH_CTX *ctx, char *buf)
|
HASHEnd(HASH_CTX *ctx, char *buf)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u_int8_t digest[HASH_DIGEST_LENGTH];
|
uint8_t digest[HASH_DIGEST_LENGTH];
|
||||||
#ifdef HASH_DIGEST_UPPERCASE
|
#ifdef HASH_DIGEST_UPPERCASE
|
||||||
static const char hex[] = "0123456789ABCDEF";
|
static const char hex[] = "0123456789ABCDEF";
|
||||||
#else
|
#else
|
||||||
|
@@ -37,7 +37,7 @@
|
|||||||
(cp)[1] = (value) >> 8; \
|
(cp)[1] = (value) >> 8; \
|
||||||
(cp)[0] = (value); } while (0)
|
(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,
|
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
|
||||||
@@ -71,7 +71,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
|
|||||||
need = MD5_BLOCK_LENGTH - have;
|
need = MD5_BLOCK_LENGTH - have;
|
||||||
|
|
||||||
/* Update bitcount */
|
/* Update bitcount */
|
||||||
ctx->count += (u_int64_t)len << 3;
|
ctx->count += (uint64_t)len << 3;
|
||||||
|
|
||||||
if (len >= need) {
|
if (len >= need) {
|
||||||
if (have != 0) {
|
if (have != 0) {
|
||||||
@@ -102,7 +102,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
|
|||||||
void
|
void
|
||||||
MD5Pad(MD5_CTX *ctx)
|
MD5Pad(MD5_CTX *ctx)
|
||||||
{
|
{
|
||||||
u_int8_t count[8];
|
uint8_t count[8];
|
||||||
size_t padlen;
|
size_t padlen;
|
||||||
|
|
||||||
/* Convert count to 8 bytes in little endian order. */
|
/* 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.
|
* the data and converts bytes into longwords for this routine.
|
||||||
*/
|
*/
|
||||||
void
|
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
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
memcpy(in, block, sizeof(in));
|
memcpy(in, block, sizeof(in));
|
||||||
#else
|
#else
|
||||||
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
|
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
|
||||||
in[a] = (u_int32_t)(
|
in[a] = (uint32_t)(
|
||||||
(u_int32_t)(block[a * 4 + 0]) |
|
(uint32_t)(block[a * 4 + 0]) |
|
||||||
(u_int32_t)(block[a * 4 + 1]) << 8 |
|
(uint32_t)(block[a * 4 + 1]) << 8 |
|
||||||
(u_int32_t)(block[a * 4 + 2]) << 16 |
|
(uint32_t)(block[a * 4 + 2]) << 16 |
|
||||||
(u_int32_t)(block[a * 4 + 3]) << 24);
|
(uint32_t)(block[a * 4 + 3]) << 24);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
53
src/hash/sha512.h
Normal file
53
src/hash/sha512.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright 2005 Colin Percival
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SHA512_H_
|
||||||
|
#define _SHA512_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define SHA512_DIGEST_LENGTH 64
|
||||||
|
|
||||||
|
typedef struct SHA512Context {
|
||||||
|
uint64_t state[8];
|
||||||
|
uint64_t count[2];
|
||||||
|
unsigned char buf[128];
|
||||||
|
} SHA512_CTX;
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
void SHA512_Init(SHA512_CTX *);
|
||||||
|
void SHA512_Update(SHA512_CTX *, const void *, size_t);
|
||||||
|
void SHA512_Final(unsigned char [64], SHA512_CTX *);
|
||||||
|
char *SHA512_End(SHA512_CTX *, char *);
|
||||||
|
char *SHA512_File(const char *, char *);
|
||||||
|
char *SHA512_FileChunk(const char *, char *, off_t, off_t);
|
||||||
|
char *SHA512_Data(const void *, unsigned int, char *);
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* !_SHA512_H_ */
|
320
src/hash/sha512c.c
Normal file
320
src/hash/sha512c.c
Normal 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));
|
||||||
|
}
|
@@ -130,10 +130,8 @@
|
|||||||
* only advantage over quicksort is that it requires little additional memory.
|
* only advantage over quicksort is that it requires little additional memory.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
heapsort(vbase, nmemb, size, compar)
|
heapsort(void *vbase, size_t nmemb, size_t size,
|
||||||
void *vbase;
|
int (*compar)(const void *, const void *))
|
||||||
size_t nmemb, size;
|
|
||||||
int (*compar)(const void *, const void *);
|
|
||||||
{
|
{
|
||||||
size_t cnt, i, j, l;
|
size_t cnt, i, j, l;
|
||||||
char tmp, *tmp1, *tmp2;
|
char tmp, *tmp1, *tmp2;
|
||||||
|
@@ -55,11 +55,7 @@ static int inet_net_pton_ipv4(const char *src, u_char *dst, size_t size);
|
|||||||
* Paul Vixie (ISC), June 1996
|
* Paul Vixie (ISC), June 1996
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
inet_net_pton(af, src, dst, size)
|
inet_net_pton(int af, const char *src, void *dst, size_t size)
|
||||||
int af;
|
|
||||||
const char *src;
|
|
||||||
void *dst;
|
|
||||||
size_t size;
|
|
||||||
{
|
{
|
||||||
switch (af) {
|
switch (af) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
@@ -87,10 +83,7 @@ inet_net_pton(af, src, dst, size)
|
|||||||
* Paul Vixie (ISC), June 1996
|
* Paul Vixie (ISC), June 1996
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
inet_net_pton_ipv4(src, dst, size)
|
inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
|
||||||
const char *src;
|
|
||||||
u_char *dst;
|
|
||||||
size_t size;
|
|
||||||
{
|
{
|
||||||
static const char
|
static const char
|
||||||
xdigits[] = "0123456789abcdef",
|
xdigits[] = "0123456789abcdef",
|
||||||
|
12
src/libbsd-ctor.pc.in
Normal file
12
src/libbsd-ctor.pc.in
Normal 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
|
@@ -105,3 +105,34 @@ LIBBSD_0.5 {
|
|||||||
wcslcat;
|
wcslcat;
|
||||||
wcslcpy;
|
wcslcpy;
|
||||||
} LIBBSD_0.4;
|
} 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;
|
||||||
|
@@ -134,6 +134,12 @@
|
|||||||
#define ELF_TARG_DATA ELFDATA2LSB
|
#define ELF_TARG_DATA ELFDATA2LSB
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__nios2__)
|
||||||
|
|
||||||
|
#define ELF_TARG_MACH EM_ALTERA_NIOS2
|
||||||
|
#define ELF_TARG_CLASS ELFCLASS32
|
||||||
|
#define ELF_TARG_DATA ELFDATA2LSB
|
||||||
|
|
||||||
#elif defined(__powerpc__)
|
#elif defined(__powerpc__)
|
||||||
|
|
||||||
#define ELF_TARG_MACH EM_PPC
|
#define ELF_TARG_MACH EM_PPC
|
||||||
@@ -179,6 +185,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#define ELF_TARG_DATA ELFDATA2MSB
|
#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
|
#else
|
||||||
|
|
||||||
#error Unknown ELF machine type
|
#error Unknown ELF machine type
|
||||||
|
33
src/local-link.h
Normal file
33
src/local-link.h
Normal 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
|
21
src/merge.c
21
src/merge.c
@@ -95,11 +95,8 @@ static void insertionsort(u_char *, size_t, size_t,
|
|||||||
* Arguments are as for qsort.
|
* Arguments are as for qsort.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mergesort(base, nmemb, size, cmp)
|
mergesort(void *base, size_t nmemb, size_t size,
|
||||||
void *base;
|
int (*cmp)(const void *, const void *))
|
||||||
size_t nmemb;
|
|
||||||
size_t size;
|
|
||||||
int (*cmp)(const void *, const void *);
|
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
int sense;
|
int sense;
|
||||||
@@ -258,11 +255,9 @@ COPY: b = t;
|
|||||||
* when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
|
* when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
|
||||||
* is defined. Otherwise simple pairwise merging is used.)
|
* is defined. Otherwise simple pairwise merging is used.)
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
setup(list1, list2, n, size, cmp)
|
setup(u_char *list1, u_char *list2, size_t n, size_t size,
|
||||||
size_t n, size;
|
int (*cmp)(const void *, const void *))
|
||||||
int (*cmp)(const void *, const void *);
|
|
||||||
u_char *list1, *list2;
|
|
||||||
{
|
{
|
||||||
int i, length, size2, tmp, sense;
|
int i, length, size2, tmp, sense;
|
||||||
u_char *f1, *f2, *s, *l2, *last, *p2;
|
u_char *f1, *f2, *s, *l2, *last, *p2;
|
||||||
@@ -333,10 +328,8 @@ setup(list1, list2, n, size, cmp)
|
|||||||
* last 4 elements.
|
* last 4 elements.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
insertionsort(a, n, size, cmp)
|
insertionsort(u_char *a, size_t n, size_t size,
|
||||||
u_char *a;
|
int (*cmp)(const void *, const void *))
|
||||||
size_t n, size;
|
|
||||||
int (*cmp)(const void *, const void *);
|
|
||||||
{
|
{
|
||||||
u_char *ai, *s, *t, *u, tmp;
|
u_char *ai, *s, *t, *u, tmp;
|
||||||
int i;
|
int i;
|
||||||
|
25
src/nlist.c
25
src/nlist.c
@@ -70,9 +70,7 @@ static int __elf_fdnlist(int, struct nlist *);
|
|||||||
int __fdnlist(int, struct nlist *);
|
int __fdnlist(int, struct nlist *);
|
||||||
|
|
||||||
int
|
int
|
||||||
nlist(name, list)
|
nlist(const char *name, struct nlist *list)
|
||||||
const char *name;
|
|
||||||
struct nlist *list;
|
|
||||||
{
|
{
|
||||||
int fd, n;
|
int fd, n;
|
||||||
|
|
||||||
@@ -96,9 +94,7 @@ static struct nlist_handlers {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
__fdnlist(fd, list)
|
__fdnlist(int fd, struct nlist *list)
|
||||||
int fd;
|
|
||||||
struct nlist *list;
|
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
int n = -1;
|
int n = -1;
|
||||||
@@ -115,9 +111,7 @@ __fdnlist(fd, list)
|
|||||||
|
|
||||||
#ifdef _NLIST_DO_AOUT
|
#ifdef _NLIST_DO_AOUT
|
||||||
static int
|
static int
|
||||||
__aout_fdnlist(fd, list)
|
__aout_fdnlist(int fd, struct nlist *list)
|
||||||
int fd;
|
|
||||||
struct nlist *list;
|
|
||||||
{
|
{
|
||||||
struct nlist *p, *symtab;
|
struct nlist *p, *symtab;
|
||||||
caddr_t strtab, a_out_mmap;
|
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.
|
* as such its use should be restricted.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
__elf_is_okay__(ehdr)
|
__elf_is_okay__(Elf_Ehdr *ehdr)
|
||||||
Elf_Ehdr *ehdr;
|
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
/*
|
/*
|
||||||
@@ -244,9 +237,7 @@ __elf_is_okay__(ehdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__elf_fdnlist(fd, list)
|
__elf_fdnlist(int fd, struct nlist *list)
|
||||||
int fd;
|
|
||||||
struct nlist *list;
|
|
||||||
{
|
{
|
||||||
struct nlist *p;
|
struct nlist *p;
|
||||||
Elf_Off symoff = 0, symstroff = 0;
|
Elf_Off symoff = 0, symstroff = 0;
|
||||||
@@ -386,11 +377,7 @@ __elf_fdnlist(fd, list)
|
|||||||
* n_value and n_type members.
|
* n_value and n_type members.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
elf_sym_to_nlist(nl, s, shdr, shnum)
|
elf_sym_to_nlist(struct nlist *nl, Elf_Sym *s, Elf_Shdr *shdr, int shnum)
|
||||||
struct nlist *nl;
|
|
||||||
Elf_Sym *s;
|
|
||||||
Elf_Shdr *shdr;
|
|
||||||
int shnum;
|
|
||||||
{
|
{
|
||||||
nl->n_value = s->st_value;
|
nl->n_value = s->st_value;
|
||||||
|
|
||||||
|
@@ -118,7 +118,8 @@ sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
|
|||||||
if (n < THRESHOLD)
|
if (n < THRESHOLD)
|
||||||
simplesort(a, n, 0, tr, endch);
|
simplesort(a, n, 0, tr, endch);
|
||||||
else {
|
else {
|
||||||
if ((ta = malloc(n * sizeof(a))) == NULL)
|
ta = reallocarray(NULL, n, sizeof(a));
|
||||||
|
if (ta == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
r_sort_b(a, ta, n, 0, tr, endch);
|
r_sort_b(a, ta, n, 0, tr, endch);
|
||||||
free(ta);
|
free(ta);
|
||||||
|
38
src/reallocarray.c
Normal file
38
src/reallocarray.c
Normal 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);
|
||||||
|
}
|
@@ -154,7 +154,7 @@ common: if (set->cmd2 & CMD2_CLR) {
|
|||||||
if (set >= endset) { \
|
if (set >= endset) { \
|
||||||
BITCMD *newset; \
|
BITCMD *newset; \
|
||||||
setlen += SET_LEN_INCR; \
|
setlen += SET_LEN_INCR; \
|
||||||
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
|
newset = reallocarray(saveset, setlen, sizeof(BITCMD)); \
|
||||||
if (newset == NULL) \
|
if (newset == NULL) \
|
||||||
goto out; \
|
goto out; \
|
||||||
set = newset + (set - saveset); \
|
set = newset + (set - saveset); \
|
||||||
@@ -197,7 +197,8 @@ setmode(const char *p)
|
|||||||
|
|
||||||
setlen = SET_LEN + 2;
|
setlen = SET_LEN + 2;
|
||||||
|
|
||||||
if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
|
set = reallocarray(NULL, setlen, sizeof(BITCMD));
|
||||||
|
if (set == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
saveset = set;
|
saveset = set;
|
||||||
endset = set + (setlen - 2);
|
endset = set + (setlen - 2);
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <err.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ static struct {
|
|||||||
/* Pointer to original nul character within base. */
|
/* Pointer to original nul character within base. */
|
||||||
char *nul;
|
char *nul;
|
||||||
|
|
||||||
|
bool warned;
|
||||||
bool reset;
|
bool reset;
|
||||||
int error;
|
int error;
|
||||||
} SPT;
|
} SPT;
|
||||||
@@ -153,8 +155,8 @@ spt_copyargs(int argc, char *argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
spt_init(int argc, char *argv[], char *envp[])
|
setproctitle_init(int argc, char *argv[], char *envp[])
|
||||||
{
|
{
|
||||||
char *base, *end, *nul, *tmp;
|
char *base, *end, *nul, *tmp;
|
||||||
int i, envc, error;
|
int i, envc, error;
|
||||||
@@ -215,14 +217,6 @@ spt_init(int argc, char *argv[], char *envp[])
|
|||||||
SPT.end = end;
|
SPT.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Force spt_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 (*spt_init_func)(int argc, char *argv[], char *envp[])
|
|
||||||
__attribute__((section(".init_array"))) = spt_init;
|
|
||||||
|
|
||||||
#ifndef SPT_MAXTITLE
|
#ifndef SPT_MAXTITLE
|
||||||
#define SPT_MAXTITLE 255
|
#define SPT_MAXTITLE 255
|
||||||
#endif
|
#endif
|
||||||
@@ -236,8 +230,14 @@ setproctitle_impl(const char *fmt, ...)
|
|||||||
char *nul;
|
char *nul;
|
||||||
int len;
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
if (fmt[0] == '-') {
|
if (fmt[0] == '-') {
|
||||||
|
52
src/setproctitle_ctor.c
Normal file
52
src/setproctitle_ctor.c
Normal 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
155
src/stringlist.c
Normal 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;
|
||||||
|
}
|
@@ -37,9 +37,7 @@ static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
strmode(mode, p)
|
strmode(mode_t mode, char *p)
|
||||||
mode_t mode;
|
|
||||||
char *p;
|
|
||||||
{
|
{
|
||||||
/* print type */
|
/* print type */
|
||||||
switch (mode & S_IFMT) {
|
switch (mode & S_IFMT) {
|
||||||
|
119
src/timeconv.c
Normal file
119
src/timeconv.c
Normal 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);
|
||||||
|
}
|
10
test/.gitignore
vendored
10
test/.gitignore
vendored
@@ -1,6 +1,14 @@
|
|||||||
|
arc4random
|
||||||
|
bzero
|
||||||
|
closefrom
|
||||||
endian
|
endian
|
||||||
fgetln
|
fgetln
|
||||||
headers
|
funopen
|
||||||
|
fparseln
|
||||||
|
fpurge
|
||||||
|
headers-gen.c
|
||||||
humanize
|
humanize
|
||||||
overlay
|
overlay
|
||||||
|
proctitle-init
|
||||||
proctitle
|
proctitle
|
||||||
|
strmode
|
||||||
|
@@ -1,23 +1,69 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
HEADERS_CPPFLAGS = \
|
||||||
-I$(top_builddir) \
|
-I$(top_builddir) \
|
||||||
-isystem $(top_srcdir)/include/bsd/ \
|
|
||||||
-include $(top_builddir)/config.h \
|
-include $(top_builddir)/config.h \
|
||||||
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
|
-DLIBBSD_DISABLE_DEPRECATED \
|
||||||
-D__REENTRANT
|
-D__REENTRANT
|
||||||
|
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-isystem $(top_srcdir)/include/bsd/ \
|
||||||
|
$(HEADERS_CPPFLAGS) \
|
||||||
|
-DLIBBSD_OVERLAY
|
||||||
|
|
||||||
|
AM_TESTS_ENVIRONMENT = \
|
||||||
|
export CC="$(CC)"; \
|
||||||
|
export CPPFLAGS="$(HEADERS_CPPFLAGS)"; \
|
||||||
|
export top_srcdir="$(top_srcdir)"; \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
|
LDADD = $(top_builddir)/src/libbsd.la
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
headers-overlay.sh \
|
||||||
|
headers-system.sh \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
|
check_SCRIPTS = \
|
||||||
|
headers-overlay.sh \
|
||||||
|
headers-system.sh \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
check_PROGRAMS = \
|
check_PROGRAMS = \
|
||||||
headers \
|
|
||||||
overlay \
|
overlay \
|
||||||
|
bzero \
|
||||||
|
closefrom \
|
||||||
endian \
|
endian \
|
||||||
humanize \
|
humanize \
|
||||||
fgetln \
|
fgetln \
|
||||||
proctitle \
|
funopen \
|
||||||
|
fparseln \
|
||||||
|
fpurge \
|
||||||
|
proctitle-init \
|
||||||
|
strmode \
|
||||||
$(nil)
|
$(nil)
|
||||||
|
|
||||||
humanize_LDFLAGS = $(top_builddir)/src/libbsd.la
|
if HAVE_LIBTESTU01
|
||||||
fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la
|
arc4random_LDADD = $(LDADD) $(TESTU01_LIBS)
|
||||||
proctitle_LDFLAGS = $(top_builddir)/src/libbsd.la
|
|
||||||
|
|
||||||
TESTS = $(check_PROGRAMS)
|
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_SCRIPTS) $(check_PROGRAMS)
|
||||||
|
107
test/arc4random.c
Normal file
107
test/arc4random.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
} else {
|
||||||
|
rc = TEST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
47
test/bzero.c
Normal file
47
test/bzero.c
Normal 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
53
test/closefrom.c
Normal 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;
|
||||||
|
}
|
@@ -24,15 +24,15 @@
|
|||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include "test-stream.h"
|
||||||
|
|
||||||
#define skip(msg) \
|
#define skip(msg) \
|
||||||
do { \
|
do { \
|
||||||
printf("skip: %s\n", (msg)); \
|
printf("skip: %s\n", (msg)); \
|
||||||
@@ -67,58 +67,6 @@ struct file {
|
|||||||
int got_len;
|
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
|
static void
|
||||||
test_fgetln_single(void)
|
test_fgetln_single(void)
|
||||||
{
|
{
|
||||||
@@ -149,7 +97,7 @@ test_fgetln_multi(void)
|
|||||||
str = strdup("A\n");
|
str = strdup("A\n");
|
||||||
str[0] += i;
|
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[0] = str;
|
||||||
files[i].lines[1] = str;
|
files[i].lines[1] = str;
|
||||||
files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
|
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 = wcsdup(L"A\n");
|
||||||
wstr[0] += i;
|
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[0] = wstr;
|
||||||
files[i].lines[1] = wstr;
|
files[i].lines[1] = wstr;
|
||||||
files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);
|
files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);
|
||||||
|
92
test/fparseln.c
Normal file
92
test/fparseln.c
Normal 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
48
test/fpurge.c
Normal 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
178
test/funopen.c
Normal 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;
|
||||||
|
}
|
25
test/headers-overlay.sh
Executable file
25
test/headers-overlay.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
echo "$@"
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
incdir="${top_srcdir}/include/bsd"
|
||||||
|
CPPFLAGS="$CPPFLAGS -DLIBBSD_OVERLAY"
|
||||||
|
|
||||||
|
for inc in $(cd $incdir; find -name '*.h' | sort | cut -c3-); do
|
||||||
|
cat >headers-overlay-gen.c <<SOURCE
|
||||||
|
#include <$inc>
|
||||||
|
int main() { return 0; }
|
||||||
|
SOURCE
|
||||||
|
|
||||||
|
echo "testing header $inc"
|
||||||
|
run $CC -isystem "$incdir" $CPPFLAGS headers-overlay-gen.c -o /dev/null
|
||||||
|
echo
|
||||||
|
|
||||||
|
rm -f headers-overlay-gen*
|
||||||
|
done
|
24
test/headers-system.sh
Executable file
24
test/headers-system.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
echo "$@"
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
incdir="${top_srcdir}/include"
|
||||||
|
|
||||||
|
for inc in $(cd $incdir; find -name '*.h' | sort | cut -c3-); do
|
||||||
|
cat >headers-system-gen.c <<SOURCE
|
||||||
|
#include <$inc>
|
||||||
|
int main() { return 0; }
|
||||||
|
SOURCE
|
||||||
|
|
||||||
|
echo "testing header $inc"
|
||||||
|
run $CC -isystem "$incdir" $CPPFLAGS headers-system-gen.c -o /dev/null
|
||||||
|
echo
|
||||||
|
|
||||||
|
rm -f headers-system-gen.*
|
||||||
|
done
|
@@ -1,25 +0,0 @@
|
|||||||
/* Check that all libbsd overlayed headers preprocess. */
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include <sys/endian.h>
|
|
||||||
#include <sys/bitstring.h>
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#include <sys/tree.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
|
|
||||||
#include <err.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <libutil.h>
|
|
||||||
#include <md5.h>
|
|
||||||
#include <nlist.h>
|
|
||||||
#include <readpassphrase.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <vis.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -60,5 +61,17 @@ main(int argc, char **argv)
|
|||||||
assert(dehumanize_number("-3G", &val) == 0);
|
assert(dehumanize_number("-3G", &val) == 0);
|
||||||
assert(val == -3221225472LL);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2012 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 system headers that are “known” to pull bits selectively from
|
/* Include system headers that are “known” to pull bits selectively from
|
||||||
* other headers through magic macros, to check that the overlay is working
|
* other headers through magic macros, to check that the overlay is working
|
||||||
* properly. */
|
* properly. */
|
||||||
|
@@ -31,16 +31,22 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
const char newtitle_base[] = "test arg1 arg2";
|
const char newtitle_base[] = "test arg1 arg2";
|
||||||
char *newtitle_full;
|
char *newtitle_full;
|
||||||
char *envvar;
|
char *envvar;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
#ifdef TEST_USE_SETPROCTITLE_INIT
|
||||||
|
setproctitle_init(argc, argv, envp);
|
||||||
|
#endif
|
||||||
|
|
||||||
setproctitle("-test %s arg2", "arg1");
|
setproctitle("-test %s arg2", "arg1");
|
||||||
assert(strcmp(argv[0], newtitle_base) == 0);
|
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");
|
setproctitle("test %s arg2", "arg1");
|
||||||
assert(strcmp(argv[0], newtitle_full) == 0);
|
assert(strcmp(argv[0], newtitle_full) == 0);
|
||||||
free(newtitle_full);
|
free(newtitle_full);
|
||||||
|
70
test/strmode.c
Normal file
70
test/strmode.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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 <sys/stat.h>
|
||||||
|
#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
84
test/test-stream.c
Normal 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
37
test/test-stream.h
Normal 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
|
Reference in New Issue
Block a user