Merge branch 'next' into newblockstore

This commit is contained in:
Sebastian Messmer 2017-07-07 16:45:52 +02:00
commit c4c0bda6d0
95 changed files with 6728 additions and 3856 deletions

2
vendor/README vendored
View File

@ -1,4 +1,4 @@
This directory contains external projects, taken from the following locations:
scrypt: http://www.tarsnap.com/scrypt.html
googletest: https://github.com/google/googletest/tree/release-1.8.0
spdlog: https://github.com/gabime/spdlog/tree/v0.12.0/include/spdlog
spdlog: https://github.com/gabime/spdlog/tree/v0.13.0/include/spdlog

View File

@ -13,33 +13,33 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
ExternalProject_Add(scrypt_original
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt
CONFIGURE_COMMAND /usr/bin/env CC=${CMAKE_C_COMPILER} CFLAGS=${SCRYPT_CFLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/configure --prefix=${CMAKE_BINARY_DIR}/vendor/scrypt/
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt
CONFIGURE_COMMAND /usr/bin/env CC=${CMAKE_C_COMPILER} CFLAGS=${SCRYPT_CFLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/configure --prefix=${CMAKE_BINARY_DIR}/vendor/scrypt/
PREFIX ${CMAKE_BINARY_DIR}/vendor/scrypt/
BUILD_COMMAND ${MAKE}
)
add_library(${PROJECT_NAME} STATIC
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/lib/crypto/crypto_scrypt.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/lib/crypto/crypto_scrypt_smix.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/util/warnp.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/util/insecure_memzero.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/alg/sha256.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/cpusupport/cpusupport_x86_aesni.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/cpusupport/cpusupport_x86_sse2.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/lib/crypto/crypto_scrypt.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/lib/crypto/crypto_scrypt_smix.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/util/warnp.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/util/insecure_memzero.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/alg/sha256.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/cpusupport/cpusupport_x86_aesni.c
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/cpusupport/cpusupport_x86_sse2.c
)
target_link_libraries(${PROJECT_NAME}
${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/libscrypt_sse2.a
${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/libcperciva_aesni.a
)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/cpusupport
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/alg
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0/scrypt/libcperciva/util
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/cpusupport
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/alg
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/util
)
target_compile_options(${PROJECT_NAME} PRIVATE
-DCONFIG_H_FILE=\"${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/config.h\"
-DCPUSUPPORT_CONFIG_FILE=\"${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/cpusupport-config.h\"
)
add_dependencies(${PROJECT_NAME} scrypt_original)
target_include_directories(${PROJECT_NAME} SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.0)
target_include_directories(${PROJECT_NAME} SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1)

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
AUTOMAKE_OPTIONS= foreign subdir-objects
bin_PROGRAMS= scrypt
dist_man_MANS=$(scrypt_man_MANS)
scrypt_SOURCES= main.c \
libcperciva/alg/sha256.c \
libcperciva/cpusupport/cpusupport_x86_aesni.c \
libcperciva/cpusupport/cpusupport_x86_sse2.c \
libcperciva/crypto/crypto_aes.c \
libcperciva/crypto/crypto_aesctr.c \
libcperciva/crypto/crypto_entropy.c \
libcperciva/util/entropy.c \
libcperciva/util/insecure_memzero.c \
libcperciva/util/readpass.c \
libcperciva/util/warnp.c \
lib/crypto/crypto_scrypt.c \
lib/crypto/crypto_scrypt_smix.c \
lib/scryptenc/scryptenc.c \
lib/scryptenc/scryptenc_cpuperf.c \
lib/util/memlimit.c \
cpusupport-config.h
scrypt_CFLAGS= -I $(srcdir)/libcperciva/alg \
-I $(srcdir)/libcperciva/cpusupport \
-I $(srcdir)/libcperciva/crypto \
-I $(srcdir)/libcperciva/util \
-I $(srcdir)/lib/crypto \
-I $(srcdir)/lib/scryptenc \
-I $(srcdir)/lib/util \
-I . -D CPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\"
scrypt_LDADD= -lcrypto libcperciva_aesni.a libscrypt_sse2.a
scrypt_man_MANS= scrypt.1
cpusupport-config.h:
( export CC="${CC}"; export CFLAGS="${CFLAGS}"; command -p sh $(srcdir)/libcperciva/cpusupport/Build/cpusupport.sh ) > cpusupport-config.h.tmp && command -p mv cpusupport-config.h.tmp cpusupport-config.h
BUILT_SOURCES= cpusupport-config.h
CLEANFILES= cpusupport-config.h cpusupport-config.h.tmp
noinst_LIBRARIES= libcperciva_aesni.a
libcperciva_aesni_a_SOURCES= libcperciva/crypto/crypto_aes_aesni.c
libcperciva_aesni_a_CFLAGS= $(scrypt_CFLAGS) \
`. ./cpusupport-config.h; echo $${CFLAGS_X86_AESNI}`
noinst_LIBRARIES+= libscrypt_sse2.a
libscrypt_sse2_a_SOURCES= lib/crypto/crypto_scrypt_smix_sse2.c
libscrypt_sse2_a_CFLAGS= $(scrypt_CFLAGS) \
`. ./cpusupport-config.h; echo $${CFLAGS_X86_SSE2}`

View File

@ -1,64 +0,0 @@
#ifndef _CPUSUPPORT_H_
#define _CPUSUPPORT_H_
/*
* To enable support for non-portable CPU features at compile time, one or
* more CPUSUPPORT_ARCH_FEATURE macros should be defined. This can be done
* directly on the compiler command line; or a file can be created with the
* necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h
* (or similar) can be provided to include that file here.
*/
#ifdef CPUSUPPORT_CONFIG_FILE
#include CPUSUPPORT_CONFIG_FILE
#endif
/*
* The CPUSUPPORT_FEATURE macro declares the necessary variables and
* functions for detecting CPU feature support at run time. The function
* defined in the macro acts to cache the result of the ..._detect function
* using the ..._present and ..._init variables.
*/
#define CPUSUPPORT_FEATURE(arch, feature) \
extern int cpusupport_ ## arch ## _ ## feature ## _present; \
extern int cpusupport_ ## arch ## _ ## feature ## _init; \
int cpusupport_ ## arch ## _ ## feature ## _detect(void); \
\
static inline int \
cpusupport_ ## arch ## _ ## feature(void) \
{ \
\
if (cpusupport_ ## arch ## _ ## feature ## _present) \
return (1); \
else if (cpusupport_ ## arch ## _ ## feature ## _init) \
return (0); \
cpusupport_ ## arch ## _ ## feature ## _present = \
cpusupport_ ## arch ##_ ## feature ## _detect(); \
cpusupport_ ## arch ## _ ## feature ## _init = 1; \
return (cpusupport_ ## arch ## _ ## feature ## _present); \
} \
struct cpusupport_ ## arch ## _ ## feature ## _dummy
/*
* CPUSUPPORT_FEATURE_DECL(arch, feature):
* Macro which defines variables and provides a function declaration for
* detecting the presence of "feature" on the "arch" architecture. The
* function body following this macro expansion must return nonzero if the
* feature is present, or zero if the feature is not present or the detection
* fails for any reason.
*/
#define CPUSUPPORT_FEATURE_DECL(arch, feature) \
int cpusupport_ ## arch ## _ ## feature ## _present = 0; \
int cpusupport_ ## arch ## _ ## feature ## _init = 0; \
int \
cpusupport_ ## arch ## _ ## feature ## _detect(void)
/*
* Any features listed here must have associated C files compiled and linked
* in, since the macro references symbols which must be defined. Projects
* which do not need to detect certain CPU features may wish to remove lines
* from this list so that the associated C files can be omitted.
*/
CPUSUPPORT_FEATURE(x86, aesni);
CPUSUPPORT_FEATURE(x86, sse2);
#endif /* !_CPUSUPPORT_H_ */

View File

@ -0,0 +1,46 @@
Installing
----------
We strongly recommend that people use the latest official release tarball on
https://www.tarsnap.com/scrypt.html, and build with:
./configure
make
make install
Platform-specific notes
-----------------------
- On OS X, the version of OpenSSL included with the operating
system is outdated (0.9.8) and deprecated, and it is recommended
that scrypt be built with an updated version of OpenSSL. On OS X
10.11 "El Capitan" and higher, OpenSSL was removed entirely. After
installing a newer version of OpenSSL, use
CPPFLAGS="-I /path/to/openssl/headers"
LDFLAGS="-L /path/to/openssl/lib"
to build scrypt.
In particular, if you installed OpenSSL using homebrew, you may
pass the relevant directories directly to ./configure:
./configure CPPFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib"
Alternatively, you may with to add these lines to your $HOME/.profile file:
export CPPFLAGS="-I/usr/local/opt/openssl/include $CPPFLAGS"
export LDFLAGS="-L/usr/local/opt/openssl/lib $LDFLAGS"
and then close & re-open your terminal window.
Building from git
-----------------
For experimental development from git, build with:
autoreconf -i
./configure
make
- You must have automake 1.11.2 or higher.
- In order to support the `AX_CFLAGS_WARN_ALL` autoconf directive, you will
need to install the autoconf archive. On Debian systems, use the
`autoconf-archive` package; on FreeBSD, use `devel/autoconf-archive`.

View File

@ -1,7 +1,8 @@
The code and documentation in this directory ("libcperciva") is distributed
under the following terms:
The included code and documentation ("scrypt") is distributed under the
following terms:
Copyright 2005-2014 Colin Percival. All rights reserved.
Copyright 2005-2016 Colin Percival. All rights reserved.
Copyright 2005-2016 Tarsnap Backup Inc. All rights reserved.
Copyright 2014 Sean Kelly. All rights reserved.
Redistribution and use in source and binary forms, with or without

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
bin_PROGRAMS= scrypt
noinst_PROGRAMS= tests/test_scrypt tests/valgrind/potential-memleaks
dist_man_MANS=$(scrypt_man_MANS)
scrypt_SOURCES= main.c \
libcperciva/alg/sha256.c \
libcperciva/cpusupport/cpusupport_x86_aesni.c \
libcperciva/cpusupport/cpusupport_x86_sse2.c \
libcperciva/crypto/crypto_aes.c \
libcperciva/crypto/crypto_aesctr.c \
libcperciva/crypto/crypto_entropy.c \
libcperciva/util/asprintf.c \
libcperciva/util/entropy.c \
libcperciva/util/getopt.c \
libcperciva/util/humansize.c \
libcperciva/util/insecure_memzero.c \
libcperciva/util/readpass.c \
libcperciva/util/warnp.c \
lib/crypto/crypto_scrypt.c \
lib/crypto/crypto_scrypt_smix.c \
lib/scryptenc/scryptenc.c \
lib/scryptenc/scryptenc_cpuperf.c \
lib/util/memlimit.c \
lib/crypto/crypto_scrypt.h \
lib/crypto/crypto_scrypt_smix.h \
lib/crypto/crypto_scrypt_smix_sse2.h \
lib/scryptenc/scryptenc.h \
lib/scryptenc/scryptenc_cpuperf.h \
lib/util/memlimit.h \
libcperciva/alg/sha256.h \
libcperciva/cpusupport/cpusupport.h \
libcperciva/crypto/crypto_aes.h \
libcperciva/crypto/crypto_aes_aesni.h \
libcperciva/crypto/crypto_aesctr.h \
libcperciva/crypto/crypto_entropy.h \
libcperciva/util/asprintf.h \
libcperciva/util/entropy.h \
libcperciva/util/getopt.h \
libcperciva/util/humansize.h \
libcperciva/util/insecure_memzero.h \
libcperciva/util/readpass.h \
libcperciva/util/sysendian.h \
libcperciva/util/warnp.h \
scrypt_platform.h
AM_CPPFLAGS= -I$(srcdir)/libcperciva/alg \
-I$(srcdir)/libcperciva/cpusupport \
-I$(srcdir)/libcperciva/crypto \
-I$(srcdir)/libcperciva/util \
-I$(srcdir)/lib/crypto \
-I$(srcdir)/lib/scryptenc \
-I$(srcdir)/lib/util \
-DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" \
-D_POSIX_C_SOURCE=200809L
scrypt_LDADD= libcperciva_aesni.a libscrypt_sse2.a
scrypt_man_MANS= scrypt.1
cpusupport-config.h:
( export CC="${CC}"; export CFLAGS="${CFLAGS}"; command -p sh $(srcdir)/libcperciva/cpusupport/Build/cpusupport.sh "$$PATH") > cpusupport-config.h.tmp && command -p mv cpusupport-config.h.tmp cpusupport-config.h
BUILT_SOURCES= cpusupport-config.h
CLEANFILES= cpusupport-config.h cpusupport-config.h.tmp
noinst_LIBRARIES= libcperciva_aesni.a
libcperciva_aesni_a_SOURCES= libcperciva/crypto/crypto_aes_aesni.c
libcperciva_aesni_a_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_X86_AESNI}`
noinst_LIBRARIES+= libscrypt_sse2.a
libscrypt_sse2_a_SOURCES= lib/crypto/crypto_scrypt_smix_sse2.c
libscrypt_sse2_a_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_X86_SSE2}`
EXTRA_DIST = \
COPYRIGHT \
FORMAT \
lib/README \
README.md \
lib/crypto/crypto_scrypt-ref.c \
libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c \
libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c \
libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c \
libcperciva/cpusupport/Build/cpusupport.sh \
tests/test_scrypt.good \
tests/test_scrypt_good.enc \
tests/shared_test_functions.sh \
tests/01-known-values.sh \
tests/02-decrypt-reference-file.sh \
tests/03-encrypt-decrypt-file.sh \
tests/04-force-resources.sh \
tests/05-system-scrypt-encrypt-decrypt.sh \
tests/test_scrypt.sh
tests_test_scrypt_SOURCES = tests/test_scrypt.c \
libcperciva/alg/sha256.c \
libcperciva/alg/sha256.h \
libcperciva/cpusupport/cpusupport_x86_sse2.c \
libcperciva/util/insecure_memzero.c \
libcperciva/util/insecure_memzero.h \
libcperciva/util/warnp.c \
libcperciva/util/warnp.h \
lib/crypto/crypto_scrypt.c \
lib/crypto/crypto_scrypt.h \
lib/crypto/crypto_scrypt_smix.c \
lib/crypto/crypto_scrypt_smix.h
tests_test_scrypt_LDADD= libscrypt_sse2.a
tests_valgrind_potential_memleaks_SOURCES = tests/valgrind/potential-memleaks.c
.PHONY: test
# we can't only build "scrypt tests/test_scrypt" because that won't build
# the BUILT_SOURCES.
test: all
$(top_srcdir)/tests/test_scrypt.sh .

View File

@ -1,17 +1,28 @@
m4_define([SCRYPT_VERS],m4_include([scrypt-version]))
AC_INIT([scrypt],SCRYPT_VERS())
AC_PREREQ([2.69])
AC_INIT([scrypt],1.2.1,
[https://github.com/Tarsnap/scrypt],[scrypt],[http://www.tarsnap.com/scrypt/])
AC_CONFIG_SRCDIR([lib/scryptenc/scryptenc.c])
AC_CONFIG_AUX_DIR([config.aux])
AM_INIT_AUTOMAKE()
AC_PROG_CC
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign subdir-objects -Wall])
# Checks for programs.
AC_PROG_CC_C99
AC_PROG_RANLIB
AM_PROG_AR
# Don't rebuild the configure script. I'm distributing a perfectly good one.
AM_MAINTAINER_MODE
# Checks for libraries.
# Check for clock_gettime. On some systems, this is provided via librt.
AC_CHECK_LIB(rt, clock_gettime)
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_CHECK_FUNCS([clock_gettime])
AC_SEARCH_LIBS([AES_encrypt], [crypto],,
AC_MSG_ERROR([function AES_ENCRYPT not found]))
# Check for a linuxy sysinfo syscall; and while we're doing that, check if
# struct sysinfo is the old version (total RAM == totalmem) or the new
# version (total RAM == totalmem * mem_unit).
@ -25,6 +36,11 @@ AC_CHECK_MEMBERS([struct sysinfo.totalram, struct sysinfo.mem_unit], [], [],
# to work.
AC_CHECK_HEADERS([sys/param.h])
# Check if we have <openssl/aes.h>, to fix the make failing when configure
# passes.
AC_CHECK_HEADERS([openssl/aes.h],,
[AC_MSG_ERROR([Unable to find the openssl/aes.h header])])
# Check for <sys/sysctl.h>. If it exists and it defines HW_USERMEM
# and/or HW_MEMSIZE, we'll try using those as memory limits.
AC_CHECK_HEADERS([sys/sysctl.h])
@ -37,6 +53,17 @@ AC_CHECK_FUNCS([mmap])
AC_SYS_LARGEFILE
# Check whether the user has requested to disable compiler warnings
AC_MSG_CHECKING([compiler_warnings])
AC_ARG_ENABLE(compiler_warnings,
AS_HELP_STRING([--disable-compiler-warnings],
[Do not request compiler warnings. @<:@default=enabled@:>@]),
[ac_compiler_warnings=$enableval],
[ac_compiler_warnings=yes])
AC_MSG_RESULT([${ac_compiler_warnings}])
AS_IF([test x${ac_compiler_warnings} = xyes],
[AX_CFLAGS_WARN_ALL])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@ -0,0 +1,270 @@
#! /bin/sh
# Wrapper for Microsoft lib.exe
me=ar-lib
scriptversion=2012-03-01.08; # UTC
# Copyright (C) 2010-2014 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# func_error message
func_error ()
{
echo "$me: $1" 1>&2
exit 1
}
file_conv=
# func_file_conv build_file
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv in
mingw)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin)
file=`cygpath -m "$file" || echo "$file"`
;;
wine)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_at_file at_file operation archive
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
# for each of them.
# When interpreting the content of the @FILE, do NOT use func_file_conv,
# since the user would need to supply preconverted file names to
# binutils ar, at least for MinGW.
func_at_file ()
{
operation=$2
archive=$3
at_file_contents=`cat "$1"`
eval set x "$at_file_contents"
shift
for member
do
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
done
}
case $1 in
'')
func_error "no command. Try '$0 --help' for more information."
;;
-h | --h*)
cat <<EOF
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
Members may be specified in a file named with @FILE.
EOF
exit $?
;;
-v | --v*)
echo "$me, version $scriptversion"
exit $?
;;
esac
if test $# -lt 3; then
func_error "you must specify a program, an action and an archive"
fi
AR=$1
shift
while :
do
if test $# -lt 2; then
func_error "you must specify a program, an action and an archive"
fi
case $1 in
-lib | -LIB \
| -ltcg | -LTCG \
| -machine* | -MACHINE* \
| -subsystem* | -SUBSYSTEM* \
| -verbose | -VERBOSE \
| -wx* | -WX* )
AR="$AR $1"
shift
;;
*)
action=$1
shift
break
;;
esac
done
orig_archive=$1
shift
func_file_conv "$orig_archive"
archive=$file
# strip leading dash in $action
action=${action#-}
delete=
extract=
list=
quick=
replace=
index=
create=
while test -n "$action"
do
case $action in
d*) delete=yes ;;
x*) extract=yes ;;
t*) list=yes ;;
q*) quick=yes ;;
r*) replace=yes ;;
s*) index=yes ;;
S*) ;; # the index is always updated implicitly
c*) create=yes ;;
u*) ;; # TODO: don't ignore the update modifier
v*) ;; # TODO: don't ignore the verbose modifier
*)
func_error "unknown action specified"
;;
esac
action=${action#?}
done
case $delete$extract$list$quick$replace,$index in
yes,* | ,yes)
;;
yesyes*)
func_error "more than one action specified"
;;
*)
func_error "no action specified"
;;
esac
if test -n "$delete"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
for member
do
case $1 in
@*)
func_at_file "${1#@}" -REMOVE "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
;;
esac
done
elif test -n "$extract"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
if test $# -gt 0; then
for member
do
case $1 in
@*)
func_at_file "${1#@}" -EXTRACT "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
;;
esac
done
else
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
do
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
done
fi
elif test -n "$quick$replace"; then
if test ! -f "$orig_archive"; then
if test -z "$create"; then
echo "$me: creating $orig_archive"
fi
orig_archive=
else
orig_archive=$archive
fi
for member
do
case $1 in
@*)
func_file_conv "${1#@}"
set x "$@" "@$file"
;;
*)
func_file_conv "$1"
set x "$@" "$file"
;;
esac
shift
shift
done
if test -n "$orig_archive"; then
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
else
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
fi
elif test -n "$list"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
$AR -NOLOGO -LIST "$archive" || exit $?
fi

View File

@ -6,15 +6,15 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `rt' library (-lrt). */
#undef HAVE_LIBRT
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mmap' function. */
#undef HAVE_MMAP
/* Define to 1 if you have the <openssl/aes.h> header file. */
#undef HAVE_OPENSSL_AES_H
/* Define to 1 if you have the `posix_memalign' function. */
#undef HAVE_POSIX_MEMALIGN

View File

@ -1,6 +1,8 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for scrypt 1.2.0.
# Generated by GNU Autoconf 2.69 for scrypt 1.2.1.
#
# Report bugs to <https://github.com/Tarsnap/scrypt>.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -264,7 +266,8 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
$as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
$as_echo "$0: Please tell bug-autoconf@gnu.org and
$0: https://github.com/Tarsnap/scrypt about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@ -577,11 +580,12 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='scrypt'
PACKAGE_TARNAME='scrypt'
PACKAGE_VERSION='1.2.0'
PACKAGE_STRING='scrypt 1.2.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
PACKAGE_VERSION='1.2.1'
PACKAGE_STRING='scrypt 1.2.1'
PACKAGE_BUGREPORT='https://github.com/Tarsnap/scrypt'
PACKAGE_URL='http://www.tarsnap.com/scrypt/'
ac_unique_file="lib/scryptenc/scryptenc.c"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
@ -628,6 +632,8 @@ CPP
MAINT
MAINTAINER_MODE_FALSE
MAINTAINER_MODE_TRUE
ac_ct_AR
AR
RANLIB
am__fastdepCC_FALSE
am__fastdepCC_TRUE
@ -718,6 +724,7 @@ enable_silent_rules
enable_dependency_tracking
enable_maintainer_mode
enable_largefile
enable_compiler_warnings
'
ac_precious_vars='build_alias
host_alias
@ -1268,7 +1275,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures scrypt 1.2.0 to adapt to many kinds of systems.
\`configure' configures scrypt 1.2.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1334,7 +1341,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of scrypt 1.2.0:";;
short | recursive ) echo "Configuration of scrypt 1.2.1:";;
esac
cat <<\_ACEOF
@ -1352,6 +1359,8 @@ Optional Features:
enable make rules and dependencies not useful (and
sometimes confusing) to the casual installer
--disable-largefile omit support for large files
--disable-compiler-warnings
Do not request compiler warnings. [default=enabled]
Some influential environment variables:
CC C compiler command
@ -1366,7 +1375,8 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to the package provider.
Report bugs to <https://github.com/Tarsnap/scrypt>.
scrypt home page: <http://www.tarsnap.com/scrypt/>.
_ACEOF
ac_status=$?
fi
@ -1429,7 +1439,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
scrypt configure 1.2.0
scrypt configure 1.2.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1701,6 +1711,10 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
( $as_echo "## ------------------------------------------------ ##
## Report this to https://github.com/Tarsnap/scrypt ##
## ------------------------------------------------ ##"
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
@ -1905,7 +1919,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by scrypt $as_me 1.2.0, which was
It was created by scrypt $as_me 1.2.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2253,6 +2267,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_aux_dir=
for ac_dir in config.aux "$srcdir"/config.aux; do
if test -f "$ac_dir/install-sh"; then
@ -2282,6 +2297,7 @@ ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
am__api_version='1.15'
# Find a good install program. We prefer a C program (faster),
@ -2768,7 +2784,7 @@ fi
# Define the identity of the package.
PACKAGE='scrypt'
VERSION='1.2.0'
VERSION='1.2.1'
cat >>confdefs.h <<_ACEOF
@ -2861,6 +2877,71 @@ END
fi
fi
# Checks for programs.
DEPDIR="${am__leading_dot}deps"
ac_config_commands="$ac_config_commands depfiles"
am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo this is the am__doit target
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
$as_echo_n "checking for style of include used by $am_make... " >&6; }
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
$as_echo "$_am_result" >&6; }
rm -f confinc confmf
# Check whether --enable-dependency-tracking was given.
if test "${enable_dependency_tracking+set}" = set; then :
enableval=$enable_dependency_tracking;
fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
AMDEP_FALSE='#'
else
AMDEP_TRUE='#'
AMDEP_FALSE=
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@ -3708,69 +3789,6 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
DEPDIR="${am__leading_dot}deps"
ac_config_commands="$ac_config_commands depfiles"
am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo this is the am__doit target
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
$as_echo_n "checking for style of include used by $am_make... " >&6; }
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
$as_echo "$_am_result" >&6; }
rm -f confinc confmf
# Check whether --enable-dependency-tracking was given.
if test "${enable_dependency_tracking+set}" = set; then :
enableval=$enable_dependency_tracking;
fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
AMDEP_FALSE='#'
else
AMDEP_TRUE='#'
AMDEP_FALSE=
fi
depcc="$CC" am_compiler_list=
@ -3900,6 +3918,183 @@ else
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
if ${ac_cv_prog_cc_c99+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdio.h>
// Check varargs macros. These examples are taken from C99 6.10.3.5.
#define debug(...) fprintf (stderr, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
int x = 1234;
int y = 5678;
debug ("Flag");
debug ("X = %d\n", x);
showlist (The first, second, and third items.);
report (x>y, "x is %d but y is %d", x, y);
}
// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
your preprocessor is broken;
#endif
#if BIG_OK
#else
your preprocessor is broken;
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;
struct incomplete_array
{
int datasize;
double data[];
};
struct named_init {
int number;
const wchar_t *name;
double average;
};
typedef const char *ccp;
static inline int
test_restrict (ccp restrict text)
{
// See if C++-style comments work.
// Iterate through items via the restricted pointer.
// Also check for declarations in for loops.
for (unsigned int i = 0; *(text+i) != '\0'; ++i)
continue;
return 0;
}
// Check varargs and va_copy.
static void
test_varargs (const char *format, ...)
{
va_list args;
va_start (args, format);
va_list args_copy;
va_copy (args_copy, args);
const char *str;
int number;
float fnumber;
while (*format)
{
switch (*format++)
{
case 's': // string
str = va_arg (args_copy, const char *);
break;
case 'd': // int
number = va_arg (args_copy, int);
break;
case 'f': // float
fnumber = va_arg (args_copy, double);
break;
default:
break;
}
}
va_end (args_copy);
va_end (args);
}
int
main ()
{
// Check bool.
_Bool success = false;
// Check restrict.
if (test_restrict ("String literal") == 0)
success = true;
char *restrict newvar = "Another string";
// Check varargs.
test_varargs ("s, d' f .", "string", 65, 34.234);
test_varargs_macros ();
// Check flexible array members.
struct incomplete_array *ia =
malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
ia->datasize = 10;
for (int i = 0; i < ia->datasize; ++i)
ia->data[i] = i * 1.234;
// Check named initializers.
struct named_init ni = {
.number = 34,
.name = L"Test wide string",
.average = 543.34343,
};
ni.number = 58;
int dynamic_array[ni.number];
dynamic_array[ni.number - 1] = 543;
// work around unused variable warnings
return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
|| dynamic_array[ni.number - 1] != 543);
;
return 0;
}
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c99" in
x)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
xno)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
*)
CC="$CC $ac_cv_prog_cc_c99"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
esac
if test "x$ac_cv_prog_cc_c99" != xno; then :
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
@ -3993,6 +4188,178 @@ else
fi
if test -n "$ac_tool_prefix"; then
for ac_prog in ar lib "link -lib"
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_AR+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
$as_echo "$AR" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$AR" && break
done
fi
if test -z "$AR"; then
ac_ct_AR=$AR
for ac_prog in ar lib "link -lib"
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_AR+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_AR"; then
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_AR="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
$as_echo "$ac_ct_AR" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$ac_ct_AR" && break
done
if test "x$ac_ct_AR" = x; then
AR="false"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
AR=$ac_ct_AR
fi
fi
: ${AR=ar}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
$as_echo_n "checking the archiver ($AR) interface... " >&6; }
if ${am_cv_ar_interface+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
am_cv_ar_interface=ar
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int some_variable = 0;
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
(eval $am_ar_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if test "$ac_status" -eq 0; then
am_cv_ar_interface=ar
else
am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
(eval $am_ar_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if test "$ac_status" -eq 0; then
am_cv_ar_interface=lib
else
am_cv_ar_interface=unknown
fi
fi
rm -f conftest.lib libconftest.a
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
$as_echo "$am_cv_ar_interface" >&6; }
case $am_cv_ar_interface in
ar)
;;
lib)
# Microsoft lib, so override with the ar-lib wrapper script.
# FIXME: It is wrong to rewrite AR.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__AR in this case,
# and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
# similar.
AR="$am_aux_dir/ar-lib $AR"
;;
unknown)
as_fn_error $? "could not determine $AR interface" "$LINENO" 5
;;
esac
# Don't rebuild the configure script. I'm distributing a perfectly good one.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
@ -4018,15 +4385,15 @@ fi
# Check for clock_gettime. On some systems, this is provided via librt.
# Checks for libraries.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
if ${ac_cv_lib_rt_clock_gettime+:} false; then :
# Check for clock_gettime. On some systems, this is provided via librt.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
$as_echo_n "checking for library containing clock_gettime... " >&6; }
if ${ac_cv_search_clock_gettime+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@ -4045,23 +4412,35 @@ return clock_gettime ();
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_rt_clock_gettime=yes
else
ac_cv_lib_rt_clock_gettime=no
for ac_lib in '' rt; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_clock_gettime=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
conftest$ac_exeext
if ${ac_cv_search_clock_gettime+:} false; then :
break
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBRT 1
_ACEOF
done
if ${ac_cv_search_clock_gettime+:} false; then :
LIBS="-lrt $LIBS"
else
ac_cv_search_clock_gettime=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
$as_echo "$ac_cv_search_clock_gettime" >&6; }
ac_res=$ac_cv_search_clock_gettime
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
@ -4077,6 +4456,65 @@ fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing AES_encrypt" >&5
$as_echo_n "checking for library containing AES_encrypt... " >&6; }
if ${ac_cv_search_AES_encrypt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char AES_encrypt ();
int
main ()
{
return AES_encrypt ();
;
return 0;
}
_ACEOF
for ac_lib in '' crypto; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_AES_encrypt=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_AES_encrypt+:} false; then :
break
fi
done
if ${ac_cv_search_AES_encrypt+:} false; then :
else
ac_cv_search_AES_encrypt=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_AES_encrypt" >&5
$as_echo "$ac_cv_search_AES_encrypt" >&6; }
ac_res=$ac_cv_search_AES_encrypt
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
else
as_fn_error $? "function AES_ENCRYPT not found" "$LINENO" 5
fi
# Check for a linuxy sysinfo syscall; and while we're doing that, check if
# struct sysinfo is the old version (total RAM == totalmem) or the new
# version (total RAM == totalmem * mem_unit).
@ -4548,6 +4986,23 @@ fi
done
# Check if we have <openssl/aes.h>, to fix the make failing when configure
# passes.
for ac_header in openssl/aes.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "openssl/aes.h" "ac_cv_header_openssl_aes_h" "$ac_includes_default"
if test "x$ac_cv_header_openssl_aes_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_OPENSSL_AES_H 1
_ACEOF
else
as_fn_error $? "Unable to find the openssl/aes.h header" "$LINENO" 5
fi
done
# Check for <sys/sysctl.h>. If it exists and it defines HW_USERMEM
# and/or HW_MEMSIZE, we'll try using those as memory limits.
for ac_header in sys/sysctl.h
@ -4790,6 +5245,103 @@ rm -rf conftest*
fi
# Check whether the user has requested to disable compiler warnings
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler_warnings" >&5
$as_echo_n "checking compiler_warnings... " >&6; }
# Check whether --enable-compiler_warnings was given.
if test "${enable_compiler_warnings+set}" = set; then :
enableval=$enable_compiler_warnings; ac_compiler_warnings=$enableval
else
ac_compiler_warnings=yes
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_compiler_warnings}" >&5
$as_echo "${ac_compiler_warnings}" >&6; }
if test x${ac_compiler_warnings} = xyes; then :
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking CFLAGS for maximum warnings" >&5
$as_echo_n "checking CFLAGS for maximum warnings... " >&6; }
if ${ac_cv_cflags_warn_all+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_cflags_warn_all="no, unknown"
ac_save_CFLAGS="$CFLAGS"
for ac_arg in "-warn all % -warn all" "-pedantic % -Wall" "-xstrconst % -v" "-std1 % -verbose -w0 -warnprotos" "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" "-ansi -ansiE % -fullwarn" "+ESlit % +w1" "-Xc % -pvctl,fullmsg" "-h conform % -h msglevel 2" #
do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_cflags_warn_all=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
CFLAGS="$ac_save_CFLAGS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags_warn_all" >&5
$as_echo "$ac_cv_cflags_warn_all" >&6; }
case ".$ac_cv_cflags_warn_all" in
.ok|.ok,*) ;;
.|.no|.no,*) ;;
*)
if ${CFLAGS+:} false; then :
case " $CFLAGS " in #(
*" $ac_cv_cflags_warn_all "*) :
{ { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$ac_cv_cflags_warn_all"; } >&5
(: CFLAGS already contains $ac_cv_cflags_warn_all) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } ;; #(
*) :
as_fn_append CFLAGS " $ac_cv_cflags_warn_all"
{ { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
(: CFLAGS="$CFLAGS") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
;;
esac
else
CFLAGS=$ac_cv_cflags_warn_all
{ { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
(: CFLAGS="$CFLAGS") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
fi
;;
esac
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
fi
ac_config_headers="$ac_config_headers config.h"
ac_config_files="$ac_config_files Makefile"
@ -5328,7 +5880,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by scrypt $as_me 1.2.0, which was
This file was extended by scrypt $as_me 1.2.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -5388,13 +5940,14 @@ $config_headers
Configuration commands:
$config_commands
Report bugs to the package provider."
Report bugs to <https://github.com/Tarsnap/scrypt>.
scrypt home page: <http://www.tarsnap.com/scrypt/>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
scrypt config.status 1.2.0
scrypt config.status 1.2.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -97,7 +97,7 @@ _crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
goto err1;
XY = (uint32_t *)(XY0);
#if !defined(MAP_ANON) || !defined(HAVE_MMAP)
if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
if ((errno = posix_memalign(&V0, 64, (size_t)(128 * r * N))) != 0)
goto err2;
V = (uint32_t *)(V0);
#endif

View File

@ -27,9 +27,7 @@
* online backup system.
*/
#include <stdint.h>
#include <string.h>
#include "sha256.h"
#include "sysendian.h"
#include "crypto_scrypt_smix.h"

View File

@ -1,6 +1,9 @@
#ifndef _CRYPTO_SCRYPT_SMIX_H_
#define _CRYPTO_SCRYPT_SMIX_H_
#include <stddef.h>
#include <stdint.h>
/**
* crypto_scrypt_smix(B, r, N, V, XY):
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;

View File

@ -165,6 +165,7 @@ blockmix_salsa8(const __m128i * Bin, __m128i * Bout, __m128i * X, size_t r)
/**
* integerify(B, r):
* Return the result of parsing B_{2r-1} as a little-endian integer.
* Note that B's layout is permuted compared to the generic implementation.
*/
static uint64_t
integerify(const void * B, size_t r)

View File

@ -1,6 +1,9 @@
#ifndef _CRYPTO_SCRYPT_SMIX_SSE2_H_
#define _CRYPTO_SCRYPT_SMIX_SSE2_H_
#include <stddef.h>
#include <stdint.h>
/**
* crypto_scrypt_smix_sse2(B, r, N, V, XY):
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;

View File

@ -28,16 +28,17 @@
*/
#include "scrypt_platform.h"
#include <errno.h>
#include <fcntl.h>
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "crypto_aes.h"
#include "crypto_aesctr.h"
#include "crypto_entropy.h"
#include "humansize.h"
#include "insecure_memzero.h"
#include "sha256.h"
#include "sysendian.h"
@ -51,12 +52,34 @@
#define ENCBLOCK 65536
static int pickparams(size_t, double, double,
int *, uint32_t *, uint32_t *);
static int checkparams(size_t, double, double, int, uint32_t, uint32_t);
int *, uint32_t *, uint32_t *, int);
static int checkparams(size_t, double, double, int, uint32_t, uint32_t, int,
int);
static void
display_params(int logN, uint32_t r, uint32_t p, size_t memlimit,
double opps, double maxtime)
{
uint64_t N = (uint64_t)(1) << logN;
uint64_t mem_minimum = 128 * r * N;
double expected_seconds = 4 * N * p / opps;
char * human_memlimit = humansize(memlimit);
char * human_mem_minimum = humansize(mem_minimum);
fprintf(stderr, "Parameters used: N = %" PRIu64 "; r = %" PRIu32
"; p = %" PRIu32 ";\n", N, r, p);
fprintf(stderr, " This requires at least %s bytes of memory "
"(%s available),\n", human_mem_minimum, human_memlimit);
fprintf(stderr, " and will take approximately %.1f seconds "
"(limit: %.1f seconds).\n", expected_seconds, maxtime);
free(human_memlimit);
free(human_mem_minimum);
}
static int
pickparams(size_t maxmem, double maxmemfrac, double maxtime,
int * logN, uint32_t * r, uint32_t * p)
int * logN, uint32_t * r, uint32_t * p, int verbose)
{
size_t memlimit;
double opps;
@ -89,7 +112,7 @@ pickparams(size_t maxmem, double maxmemfrac, double maxtime,
fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n",
memlimit, opslimit);
#endif
if (opslimit < memlimit/32) {
if (opslimit < (double)memlimit / 32) {
/* Set p = 1 and choose N based on the CPU limit. */
*p = 1;
maxN = opslimit / (*r * 4);
@ -112,10 +135,8 @@ pickparams(size_t maxmem, double maxmemfrac, double maxtime,
*p = (uint32_t)(maxrp) / *r;
}
#ifdef DEBUG
fprintf(stderr, "N = %zu r = %d p = %d\n",
(size_t)(1) << *logN, (int)(*r), (int)(*p));
#endif
if (verbose)
display_params(*logN, *r, *p, memlimit, opps, maxtime);
/* Success! */
return (0);
@ -123,7 +144,7 @@ pickparams(size_t maxmem, double maxmemfrac, double maxtime,
static int
checkparams(size_t maxmem, double maxmemfrac, double maxtime,
int logN, uint32_t r, uint32_t p)
int logN, uint32_t r, uint32_t p, int verbose, int force)
{
size_t memlimit;
double opps;
@ -131,27 +152,37 @@ checkparams(size_t maxmem, double maxmemfrac, double maxtime,
uint64_t N;
int rc;
/* Figure out the maximum amount of memory we can use. */
if (memtouse(maxmem, maxmemfrac, &memlimit))
return (1);
/* Figure out how fast the CPU is. */
if ((rc = scryptenc_cpuperf(&opps)) != 0)
return (rc);
opslimit = opps * maxtime;
/* Sanity-check values. */
if ((logN < 1) || (logN > 63))
return (7);
if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000)
return (7);
/* Check limits. */
N = (uint64_t)(1) << logN;
if ((memlimit / N) / r < 128)
return (9);
if ((opslimit / N) / (r * p) < 4)
return (10);
/* Are we forcing decryption, regardless of resource limits? */
if (!force) {
/* Figure out the maximum amount of memory we can use. */
if (memtouse(maxmem, maxmemfrac, &memlimit))
return (1);
/* Figure out how fast the CPU is. */
if ((rc = scryptenc_cpuperf(&opps)) != 0)
return (rc);
opslimit = opps * maxtime;
/* Check limits. */
N = (uint64_t)(1) << logN;
if ((memlimit / N) / r < 128)
return (9);
if ((opslimit / N) / (r * p) < 4)
return (10);
} else {
/* We have no limit. */
memlimit = 0;
opps = 0;
}
if (verbose)
display_params(logN, r, p, memlimit, opps, maxtime);
/* Success! */
return (0);
@ -160,7 +191,7 @@ checkparams(size_t maxmem, double maxmemfrac, double maxtime,
static int
scryptenc_setup(uint8_t header[96], uint8_t dk[64],
const uint8_t * passwd, size_t passwdlen,
size_t maxmem, double maxmemfrac, double maxtime)
size_t maxmem, double maxmemfrac, double maxtime, int verbose)
{
uint8_t salt[32];
uint8_t hbuf[32];
@ -175,10 +206,13 @@ scryptenc_setup(uint8_t header[96], uint8_t dk[64],
/* Pick values for N, r, p. */
if ((rc = pickparams(maxmem, maxmemfrac, maxtime,
&logN, &r, &p)) != 0)
&logN, &r, &p, verbose)) != 0)
return (rc);
N = (uint64_t)(1) << logN;
/* Sanity check. */
assert((logN > 0) && (logN < 256));
/* Get some salt. */
if (crypto_entropy_read(salt, 32))
return (4);
@ -190,7 +224,7 @@ scryptenc_setup(uint8_t header[96], uint8_t dk[64],
/* Construct the file header. */
memcpy(header, "scrypt", 6);
header[6] = 0;
header[7] = logN;
header[7] = logN & 0xff;
be32enc(&header[8], r);
be32enc(&header[12], p);
memcpy(&header[16], salt, 32);
@ -214,7 +248,8 @@ scryptenc_setup(uint8_t header[96], uint8_t dk[64],
static int
scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
const uint8_t * passwd, size_t passwdlen,
size_t maxmem, double maxmemfrac, double maxtime)
size_t maxmem, double maxmemfrac, double maxtime, int verbose,
int force)
{
uint8_t salt[32];
uint8_t hbuf[32];
@ -243,9 +278,10 @@ scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
/*
* Check whether the provided parameters are valid and whether the
* key derivation function can be computed within the allowed memory
* and CPU time.
* and CPU time, unless the user chose to disable this test.
*/
if ((rc = checkparams(maxmem, maxmemfrac, maxtime, logN, r, p)) != 0)
if ((rc = checkparams(maxmem, maxmemfrac, maxtime, logN, r, p,
verbose, force)) != 0)
return (rc);
/* Compute the derived keys. */
@ -266,14 +302,14 @@ scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
/**
* scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose):
* Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
* bytes to outbuf.
*/
int
scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
const uint8_t * passwd, size_t passwdlen,
size_t maxmem, double maxmemfrac, double maxtime)
size_t maxmem, double maxmemfrac, double maxtime, int verbose)
{
uint8_t dk[64];
uint8_t hbuf[32];
@ -287,7 +323,7 @@ scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
/* Generate the header and derived key. */
if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
maxmem, maxmemfrac, maxtime)) != 0)
maxmem, maxmemfrac, maxtime, verbose)) != 0)
return (rc);
/* Copy header into output buffer. */
@ -317,15 +353,17 @@ scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
/**
* scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose, force):
* Decrypt inbuflen bytes from inbuf, writing the result into outbuf and the
* decrypted data length to outlen. The allocated length of outbuf must
* be at least inbuflen.
* be at least inbuflen. If ${force} is 1, do not check whether
* decryption will exceed the estimated available memory or time.
*/
int
scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
size_t * outlen, const uint8_t * passwd, size_t passwdlen,
size_t maxmem, double maxmemfrac, double maxtime)
size_t maxmem, double maxmemfrac, double maxtime, int verbose,
int force)
{
uint8_t hbuf[32];
uint8_t dk[64];
@ -353,7 +391,7 @@ scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
/* Parse the header and generate derived keys. */
if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
maxmem, maxmemfrac, maxtime)) != 0)
maxmem, maxmemfrac, maxtime, verbose, force)) != 0)
return (rc);
/* Decrypt data. */
@ -382,14 +420,14 @@ scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
/**
* scryptenc_file(infile, outfile, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose):
* Read a stream from infile and encrypt it, writing the resulting stream to
* outfile.
*/
int
scryptenc_file(FILE * infile, FILE * outfile,
const uint8_t * passwd, size_t passwdlen,
size_t maxmem, double maxmemfrac, double maxtime)
size_t maxmem, double maxmemfrac, double maxtime, int verbose)
{
uint8_t buf[ENCBLOCK];
uint8_t dk[64];
@ -405,7 +443,7 @@ scryptenc_file(FILE * infile, FILE * outfile,
/* Generate the header and derived key. */
if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
maxmem, maxmemfrac, maxtime)) != 0)
maxmem, maxmemfrac, maxtime, verbose)) != 0)
return (rc);
/* Hash and write the header. */
@ -453,14 +491,16 @@ scryptenc_file(FILE * infile, FILE * outfile,
/**
* scryptdec_file(infile, outfile, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose, force):
* Read a stream from infile and decrypt it, writing the resulting stream to
* outfile.
* outfile. If ${force} is 1, do not check whether decryption
* will exceed the estimated available memory or time.
*/
int
scryptdec_file(FILE * infile, FILE * outfile,
const uint8_t * passwd, size_t passwdlen,
size_t maxmem, double maxmemfrac, double maxtime)
size_t maxmem, double maxmemfrac, double maxtime, int verbose,
int force)
{
uint8_t buf[ENCBLOCK + 32];
uint8_t header[96];
@ -505,7 +545,7 @@ scryptdec_file(FILE * infile, FILE * outfile,
/* Parse the header and generate derived keys. */
if ((rc = scryptdec_setup(header, dk, passwd, passwdlen,
maxmem, maxmemfrac, maxtime)) != 0)
maxmem, maxmemfrac, maxtime, verbose, force)) != 0)
return (rc);
/* Start hashing with the header. */

View File

@ -36,7 +36,7 @@
* NOTE: This file provides prototypes for routines which encrypt/decrypt data
* using a key derived from a password by using the scrypt key derivation
* function. If you are just trying to "hash" a password for user logins,
* this is not the code you are looking for. You want to use the crypt_scrypt
* this is not the code you are looking for. You want to use the crypto_scrypt
* function directly.
*/
@ -82,39 +82,41 @@
/**
* scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose):
* Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
* bytes to outbuf.
*/
int scryptenc_buf(const uint8_t *, size_t, uint8_t *,
const uint8_t *, size_t, size_t, double, double);
const uint8_t *, size_t, size_t, double, double, int);
/**
* scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose, force):
* Decrypt inbuflen bytes from inbuf, writing the result into outbuf and the
* decrypted data length to outlen. The allocated length of outbuf must
* be at least inbuflen.
* be at least inbuflen. If ${force} is 1, do not check whether
* decryption will exceed the estimated available memory or time.
*/
int scryptdec_buf(const uint8_t *, size_t, uint8_t *, size_t *,
const uint8_t *, size_t, size_t, double, double);
const uint8_t *, size_t, size_t, double, double, int, int);
/**
* scryptenc_file(infile, outfile, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose):
* Read a stream from infile and encrypt it, writing the resulting stream to
* outfile.
*/
int scryptenc_file(FILE *, FILE *, const uint8_t *, size_t,
size_t, double, double);
size_t, double, double, int);
/**
* scryptdec_file(infile, outfile, passwd, passwdlen,
* maxmem, maxmemfrac, maxtime):
* maxmem, maxmemfrac, maxtime, verbose, force):
* Read a stream from infile and decrypt it, writing the resulting stream to
* outfile.
* outfile. If ${force} is 1, do not check whether decryption
* will exceed the estimated available memory or time.
*/
int scryptdec_file(FILE *, FILE *, const uint8_t *, size_t,
size_t, double, double);
size_t, double, double, int, int);
#endif /* !_SCRYPTENC_H_ */

View File

@ -40,7 +40,7 @@
#ifdef HAVE_CLOCK_GETTIME
static clock_t clocktouse;
static clockid_t clocktouse;
static int
getclockres(double * resd)

View File

@ -26,6 +26,10 @@
* This file was originally written by Colin Percival as part of the Tarsnap
* online backup system.
*/
/* We use non-POSIX functionality in this file. */
#undef _POSIX_C_SOURCE
#include "scrypt_platform.h"
#include <sys/types.h>
@ -92,7 +96,7 @@ memlimit_sysctl_hw(size_t * memlimit, int mibleaf)
if (sysctlval > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = sysctlval;
*memlimit = (size_t)sysctlval;
#else
*memlimit = sysctlval;
#endif
@ -134,7 +138,7 @@ memlimit_sysinfo(size_t * memlimit)
if (totalmem > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = totalmem;
*memlimit = (size_t)totalmem;
#else
*memlimit = totalmem;
#endif
@ -159,7 +163,7 @@ memlimit_rlimit(size_t * memlimit)
return (1);
if ((rl.rlim_cur != RLIM_INFINITY) &&
((uint64_t)rl.rlim_cur < memrlimit))
memrlimit = rl.rlim_cur;
memrlimit = (uint64_t)rl.rlim_cur;
#endif
/* ... RLIMIT_DATA... */
@ -167,7 +171,7 @@ memlimit_rlimit(size_t * memlimit)
return (1);
if ((rl.rlim_cur != RLIM_INFINITY) &&
((uint64_t)rl.rlim_cur < memrlimit))
memrlimit = rl.rlim_cur;
memrlimit = (uint64_t)rl.rlim_cur;
/* ... and RLIMIT_RSS. */
#ifdef RLIMIT_RSS
@ -175,7 +179,7 @@ memlimit_rlimit(size_t * memlimit)
return (1);
if ((rl.rlim_cur != RLIM_INFINITY) &&
((uint64_t)rl.rlim_cur < memrlimit))
memrlimit = rl.rlim_cur;
memrlimit = (uint64_t)rl.rlim_cur;
#endif
/* Return the value, but clamp to SIZE_MAX if necessary. */
@ -183,7 +187,7 @@ memlimit_rlimit(size_t * memlimit)
if (memrlimit > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = memrlimit;
*memlimit = (size_t)memrlimit;
#else
*memlimit = memrlimit;
#endif
@ -212,8 +216,11 @@ memlimit_sysconf(size_t * memlimit)
/* Read the two limits. */
if (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) ||
((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) {
/* Did an error occur? */
if (errno != 0)
/*
* Did an error occur? OS X may return EINVAL due to not
* supporting _SC_PHYS_PAGES in spite of defining it.
*/
if (errno != 0 && errno != EINVAL)
return (1);
/* If not, there is no limit. */
@ -228,7 +235,7 @@ memlimit_sysconf(size_t * memlimit)
if (totalmem > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = totalmem;
*memlimit = (size_t)totalmem;
#else
*memlimit = totalmem;
#endif
@ -298,7 +305,7 @@ memtouse(size_t maxmem, double maxmemfrac, size_t * memlimit)
/* Only use the specified fraction of the available memory. */
if ((maxmemfrac > 0.5) || (maxmemfrac == 0.0))
maxmemfrac = 0.5;
memavail = maxmemfrac * memlimit_min;
memavail = (size_t)(maxmemfrac * memlimit_min);
/* Don't use more than the specified maximum. */
if ((maxmem > 0) && (memavail > maxmem))

View File

@ -41,6 +41,26 @@ be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len)
dst[i] = be32dec(src + i * 4);
}
/* SHA256 round constants. */
static const uint32_t Krnd[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/* Elementary functions used by SHA256 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
@ -53,117 +73,84 @@ be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len)
/* SHA256 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;
h += S1(e) + Ch(e, f, g) + k; \
d += h; \
h += S0(a) + Maj(a, b, c);
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, k) \
#define RNDr(S, W, i, ii) \
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
S[(66 - i) % 8], S[(67 - i) % 8], \
S[(68 - i) % 8], S[(69 - i) % 8], \
S[(70 - i) % 8], S[(71 - i) % 8], \
W[i] + k)
W[i + ii] + Krnd[i + ii])
/* Message schedule computation */
#define MSCH(W, ii, i) \
W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
/*
* SHA256 block compression function. The 256-bit state is transformed via
* the 512-bit input block to produce a new state.
*/
static void
SHA256_Transform(uint32_t * state, const uint8_t block[64])
SHA256_Transform(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64],
uint32_t W[static restrict 64], uint32_t S[static restrict 8])
{
uint32_t W[64];
uint32_t S[8];
uint32_t t0, t1;
int i;
/* 1. Prepare message schedule W. */
/* 1. Prepare the first part of the message schedule W. */
be32dec_vect(W, block, 64);
for (i = 16; i < 64; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 32);
/* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98);
RNDr(S, W, 1, 0x71374491);
RNDr(S, W, 2, 0xb5c0fbcf);
RNDr(S, W, 3, 0xe9b5dba5);
RNDr(S, W, 4, 0x3956c25b);
RNDr(S, W, 5, 0x59f111f1);
RNDr(S, W, 6, 0x923f82a4);
RNDr(S, W, 7, 0xab1c5ed5);
RNDr(S, W, 8, 0xd807aa98);
RNDr(S, W, 9, 0x12835b01);
RNDr(S, W, 10, 0x243185be);
RNDr(S, W, 11, 0x550c7dc3);
RNDr(S, W, 12, 0x72be5d74);
RNDr(S, W, 13, 0x80deb1fe);
RNDr(S, W, 14, 0x9bdc06a7);
RNDr(S, W, 15, 0xc19bf174);
RNDr(S, W, 16, 0xe49b69c1);
RNDr(S, W, 17, 0xefbe4786);
RNDr(S, W, 18, 0x0fc19dc6);
RNDr(S, W, 19, 0x240ca1cc);
RNDr(S, W, 20, 0x2de92c6f);
RNDr(S, W, 21, 0x4a7484aa);
RNDr(S, W, 22, 0x5cb0a9dc);
RNDr(S, W, 23, 0x76f988da);
RNDr(S, W, 24, 0x983e5152);
RNDr(S, W, 25, 0xa831c66d);
RNDr(S, W, 26, 0xb00327c8);
RNDr(S, W, 27, 0xbf597fc7);
RNDr(S, W, 28, 0xc6e00bf3);
RNDr(S, W, 29, 0xd5a79147);
RNDr(S, W, 30, 0x06ca6351);
RNDr(S, W, 31, 0x14292967);
RNDr(S, W, 32, 0x27b70a85);
RNDr(S, W, 33, 0x2e1b2138);
RNDr(S, W, 34, 0x4d2c6dfc);
RNDr(S, W, 35, 0x53380d13);
RNDr(S, W, 36, 0x650a7354);
RNDr(S, W, 37, 0x766a0abb);
RNDr(S, W, 38, 0x81c2c92e);
RNDr(S, W, 39, 0x92722c85);
RNDr(S, W, 40, 0xa2bfe8a1);
RNDr(S, W, 41, 0xa81a664b);
RNDr(S, W, 42, 0xc24b8b70);
RNDr(S, W, 43, 0xc76c51a3);
RNDr(S, W, 44, 0xd192e819);
RNDr(S, W, 45, 0xd6990624);
RNDr(S, W, 46, 0xf40e3585);
RNDr(S, W, 47, 0x106aa070);
RNDr(S, W, 48, 0x19a4c116);
RNDr(S, W, 49, 0x1e376c08);
RNDr(S, W, 50, 0x2748774c);
RNDr(S, W, 51, 0x34b0bcb5);
RNDr(S, W, 52, 0x391c0cb3);
RNDr(S, W, 53, 0x4ed8aa4a);
RNDr(S, W, 54, 0x5b9cca4f);
RNDr(S, W, 55, 0x682e6ff3);
RNDr(S, W, 56, 0x748f82ee);
RNDr(S, W, 57, 0x78a5636f);
RNDr(S, W, 58, 0x84c87814);
RNDr(S, W, 59, 0x8cc70208);
RNDr(S, W, 60, 0x90befffa);
RNDr(S, W, 61, 0xa4506ceb);
RNDr(S, W, 62, 0xbef9a3f7);
RNDr(S, W, 63, 0xc67178f2);
for (i = 0; i < 64; i += 16) {
RNDr(S, W, 0, i);
RNDr(S, W, 1, i);
RNDr(S, W, 2, i);
RNDr(S, W, 3, i);
RNDr(S, W, 4, i);
RNDr(S, W, 5, i);
RNDr(S, W, 6, i);
RNDr(S, W, 7, i);
RNDr(S, W, 8, i);
RNDr(S, W, 9, i);
RNDr(S, W, 10, i);
RNDr(S, W, 11, i);
RNDr(S, W, 12, i);
RNDr(S, W, 13, i);
RNDr(S, W, 14, i);
RNDr(S, W, 15, i);
if (i == 48)
break;
MSCH(W, 0, i);
MSCH(W, 1, i);
MSCH(W, 2, i);
MSCH(W, 3, i);
MSCH(W, 4, i);
MSCH(W, 5, i);
MSCH(W, 6, i);
MSCH(W, 7, i);
MSCH(W, 8, i);
MSCH(W, 9, i);
MSCH(W, 10, i);
MSCH(W, 11, i);
MSCH(W, 12, i);
MSCH(W, 13, i);
MSCH(W, 14, i);
MSCH(W, 15, i);
}
/* 4. Mix local working variables into global state. */
for (i = 0; i < 8; i++)
state[i] += S[i];
/* Clean the stack. */
insecure_memzero(W, 256);
insecure_memzero(S, 32);
insecure_memzero(&t0, sizeof(uint32_t));
insecure_memzero(&t1, sizeof(uint32_t));
}
static uint8_t PAD[64] = {
static const uint8_t PAD[64] = {
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,
@ -172,28 +159,35 @@ static uint8_t PAD[64] = {
/* Add padding and terminating bit-count. */
static void
SHA256_Pad(SHA256_CTX * ctx)
SHA256_Pad(SHA256_CTX * ctx, uint32_t tmp32[static restrict 72])
{
uint8_t len[8];
uint32_t r, plen;
size_t r;
/*
* Convert length to a vector of bytes -- we do this now rather
* than later because the length will change after we pad.
*/
be64enc(len, ctx->count);
/* Add 1--64 bytes so that the resulting length is 56 mod 64. */
/* Figure out how many bytes we have buffered. */
r = (ctx->count >> 3) & 0x3f;
plen = (r < 56) ? (56 - r) : (120 - r);
SHA256_Update(ctx, PAD, (size_t)plen);
/* Pad to 56 mod 64, transforming if we finish a block en route. */
if (r < 56) {
/* Pad to 56 mod 64. */
memcpy(&ctx->buf[r], PAD, 56 - r);
} else {
/* Finish the current block and mix. */
memcpy(&ctx->buf[r], PAD, 64 - r);
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
/* The start of the final block is all zeroes. */
memset(&ctx->buf[0], 0, 56);
}
/* Add the terminating bit-count. */
SHA256_Update(ctx, len, 8);
be64enc(&ctx->buf[56], ctx->count);
/* Mix in the final block. */
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
}
/* Magic initialization constants. */
static const uint32_t initstate[8] = {
static const uint32_t initial_state[8] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};
@ -210,15 +204,16 @@ SHA256_Init(SHA256_CTX * ctx)
ctx->count = 0;
/* Initialize state. */
memcpy(ctx->state, initstate, sizeof(initstate));
memcpy(ctx->state, initial_state, sizeof(initial_state));
}
/**
* SHA256_Update(ctx, in, len):
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
*/
void
SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)
static void
_SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len,
uint32_t tmp32[static restrict 72])
{
uint32_t r;
const uint8_t * src = in;
@ -241,13 +236,13 @@ SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)
/* Finish the current block. */
memcpy(&ctx->buf[r], src, 64 - r);
SHA256_Transform(ctx->state, ctx->buf);
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
src += 64 - r;
len -= 64 - r;
/* Perform complete blocks. */
while (len >= 64) {
SHA256_Transform(ctx->state, src);
SHA256_Transform(ctx->state, src, &tmp32[0], &tmp32[64]);
src += 64;
len -= 64;
}
@ -256,37 +251,69 @@ SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)
memcpy(ctx->buf, src, len);
}
/* Wrapper function for intermediate-values sanitization. */
void
SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)
{
uint32_t tmp32[72];
/* Call the real function. */
_SHA256_Update(ctx, in, len, tmp32);
/* Clean the stack. */
insecure_memzero(tmp32, 288);
}
/**
* SHA256_Final(digest, ctx):
* Output the SHA256 hash of the data input to the context ${ctx} into the
* buffer ${digest}.
*/
void
SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx)
static void
_SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx,
uint32_t tmp32[static restrict 72])
{
/* Add padding. */
SHA256_Pad(ctx);
SHA256_Pad(ctx, tmp32);
/* Write the hash. */
be32enc_vect(digest, ctx->state, 32);
}
/* Wrapper function for intermediate-values sanitization. */
void
SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx)
{
uint32_t tmp32[72];
/* Call the real function. */
_SHA256_Final(digest, ctx, tmp32);
/* Clear the context state. */
insecure_memzero(ctx, sizeof(SHA256_CTX));
/* Clean the stack. */
insecure_memzero(tmp32, 288);
}
/**
* SHA256_Buf(in, len, digest):
* Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}.
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
*/
void
SHA256_Buf(const void * in, size_t len, uint8_t digest[32])
{
SHA256_CTX ctx;
uint32_t tmp32[72];
SHA256_Init(&ctx);
SHA256_Update(&ctx, in, len);
SHA256_Final(digest, &ctx);
_SHA256_Update(&ctx, in, len, tmp32);
_SHA256_Final(digest, &ctx, tmp32);
/* Clean the stack. */
insecure_memzero(&ctx, sizeof(SHA256_CTX));
insecure_memzero(tmp32, 288);
}
/**
@ -294,19 +321,19 @@ SHA256_Buf(const void * in, size_t len, uint8_t digest[32])
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
* ${K}.
*/
void
HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
static void
_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen,
uint32_t tmp32[static restrict 72], uint8_t pad[static restrict 64],
uint8_t khash[static restrict 32])
{
uint8_t pad[64];
uint8_t khash[32];
const uint8_t * K = _K;
size_t i;
/* If Klen > 64, the key is really SHA256(K). */
if (Klen > 64) {
SHA256_Init(&ctx->ictx);
SHA256_Update(&ctx->ictx, K, Klen);
SHA256_Final(khash, &ctx->ictx);
_SHA256_Update(&ctx->ictx, K, Klen, tmp32);
_SHA256_Final(khash, &ctx->ictx, tmp32);
K = khash;
Klen = 32;
}
@ -316,16 +343,29 @@ HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
memset(pad, 0x36, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
SHA256_Update(&ctx->ictx, pad, 64);
_SHA256_Update(&ctx->ictx, pad, 64, tmp32);
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
SHA256_Init(&ctx->octx);
memset(pad, 0x5c, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
SHA256_Update(&ctx->octx, pad, 64);
_SHA256_Update(&ctx->octx, pad, 64, tmp32);
}
/* Wrapper function for intermediate-values sanitization. */
void
HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
{
uint32_t tmp32[72];
uint8_t pad[64];
uint8_t khash[32];
/* Call the real function. */
_HMAC_SHA256_Init(ctx, _K, Klen, tmp32, pad, khash);
/* Clean the stack. */
insecure_memzero(tmp32, 288);
insecure_memzero(khash, 32);
insecure_memzero(pad, 64);
}
@ -334,12 +374,26 @@ HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
* HMAC_SHA256_Update(ctx, in, len):
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
*/
void
HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len)
static void
_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len,
uint32_t tmp32[static restrict 72])
{
/* Feed data to the inner SHA256 operation. */
SHA256_Update(&ctx->ictx, in, len);
_SHA256_Update(&ctx->ictx, in, len, tmp32);
}
/* Wrapper function for intermediate-values sanitization. */
void
HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len)
{
uint32_t tmp32[72];
/* Call the real function. */
_HMAC_SHA256_Update(ctx, in, len, tmp32);
/* Clean the stack. */
insecure_memzero(tmp32, 288);
}
/**
@ -347,21 +401,33 @@ HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len)
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
* buffer ${digest}.
*/
static void
_HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx,
uint32_t tmp32[static restrict 72], uint8_t ihash[static restrict 32])
{
/* Finish the inner SHA256 operation. */
_SHA256_Final(ihash, &ctx->ictx, tmp32);
/* Feed the inner hash to the outer SHA256 operation. */
_SHA256_Update(&ctx->octx, ihash, 32, tmp32);
/* Finish the outer SHA256 operation. */
_SHA256_Final(digest, &ctx->octx, tmp32);
}
/* Wrapper function for intermediate-values sanitization. */
void
HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx)
{
uint32_t tmp32[72];
uint8_t ihash[32];
/* Finish the inner SHA256 operation. */
SHA256_Final(ihash, &ctx->ictx);
/* Feed the inner hash to the outer SHA256 operation. */
SHA256_Update(&ctx->octx, ihash, 32);
/* Finish the outer SHA256 operation. */
SHA256_Final(digest, &ctx->octx);
/* Call the real function. */
_HMAC_SHA256_Final(digest, ctx, tmp32, ihash);
/* Clean the stack. */
insecure_memzero(tmp32, 288);
insecure_memzero(ihash, 32);
}
@ -375,10 +441,17 @@ HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len,
uint8_t digest[32])
{
HMAC_SHA256_CTX ctx;
uint32_t tmp32[72];
uint8_t tmp8[96];
HMAC_SHA256_Init(&ctx, K, Klen);
HMAC_SHA256_Update(&ctx, in, len);
HMAC_SHA256_Final(digest, &ctx);
_HMAC_SHA256_Init(&ctx, K, Klen, tmp32, &tmp8[0], &tmp8[64]);
_HMAC_SHA256_Update(&ctx, in, len, tmp32);
_HMAC_SHA256_Final(digest, &ctx, tmp32, &tmp8[0]);
/* Clean the stack. */
insecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(tmp32, 288);
insecure_memzero(tmp8, 96);
}
/**
@ -390,7 +463,9 @@ void
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
{
HMAC_SHA256_CTX PShctx, hctx;
HMAC_SHA256_CTX Phctx, PShctx, hctx;
uint32_t tmp32[72];
uint8_t tmp8[96];
size_t i;
uint8_t ivec[4];
uint8_t U[32];
@ -402,9 +477,13 @@ PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
/* Sanity-check. */
assert(dkLen <= 32 * (size_t)(UINT32_MAX));
/* Compute HMAC state after processing P. */
_HMAC_SHA256_Init(&Phctx, passwd, passwdlen,
tmp32, &tmp8[0], &tmp8[64]);
/* Compute HMAC state after processing P and S. */
HMAC_SHA256_Init(&PShctx, passwd, passwdlen);
HMAC_SHA256_Update(&PShctx, salt, saltlen);
memcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX));
_HMAC_SHA256_Update(&PShctx, salt, saltlen, tmp32);
/* Iterate through the blocks. */
for (i = 0; i * 32 < dkLen; i++) {
@ -413,17 +492,17 @@ PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
/* Compute U_1 = PRF(P, S || INT(i)). */
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
HMAC_SHA256_Update(&hctx, ivec, 4);
HMAC_SHA256_Final(U, &hctx);
_HMAC_SHA256_Update(&hctx, ivec, 4, tmp32);
_HMAC_SHA256_Final(U, &hctx, tmp32, tmp8);
/* T_i = U_1 ... */
memcpy(T, U, 32);
for (j = 2; j <= c; j++) {
/* Compute U_j. */
HMAC_SHA256_Init(&hctx, passwd, passwdlen);
HMAC_SHA256_Update(&hctx, U, 32);
HMAC_SHA256_Final(U, &hctx);
memcpy(&hctx, &Phctx, sizeof(HMAC_SHA256_CTX));
_HMAC_SHA256_Update(&hctx, U, 32, tmp32);
_HMAC_SHA256_Final(U, &hctx, tmp32, tmp8);
/* ... xor U_j ... */
for (k = 0; k < 32; k++)
@ -437,6 +516,12 @@ PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
memcpy(&buf[i * 32], T, clen);
}
/* Clean PShctx, since we never called _Final on it. */
/* Clean the stack. */
insecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(tmp32, 288);
insecure_memzero(tmp8, 96);
insecure_memzero(U, 32);
insecure_memzero(T, 32);
}

View File

@ -47,7 +47,7 @@ void SHA256_Final(uint8_t[32], SHA256_CTX *);
/**
* SHA256_Buf(in, len, digest):
* Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}.
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
*/
void SHA256_Buf(const void *, size_t, uint8_t[32]);

View File

@ -0,0 +1,106 @@
#ifndef _CPUSUPPORT_H_
#define _CPUSUPPORT_H_
/*
* To enable support for non-portable CPU features at compile time, one or
* more CPUSUPPORT_ARCH_FEATURE macros should be defined. This can be done
* directly on the compiler command line via -D CPUSUPPORT_ARCH_FEATURE or
* -D CPUSUPPORT_ARCH_FEATURE=1; or a file can be created with the
* necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h
* (or similar) can be provided to include that file here.
*/
#ifdef CPUSUPPORT_CONFIG_FILE
#include CPUSUPPORT_CONFIG_FILE
#endif
/**
* The CPUSUPPORT_FEATURE macro declares the necessary variables and
* functions for detecting CPU feature support at run time. The function
* defined in the macro acts to cache the result of the ..._detect function
* using the ..._present and ..._init variables. The _detect function and the
* _present and _init variables are turn defined by CPUSUPPORT_FEATURE_DECL in
* appropriate cpusupport_foo_bar.c file.
*
* In order to allow CPUSUPPORT_FEATURE to be used for features which do not
* have corresponding CPUSUPPORT_FEATURE_DECL blocks in another source file,
* we abuse the C preprocessor: If CPUSUPPORT_${enabler} is defined to 1, then
* we access _present_1, _init_1, and _detect_1; but if it is not defined, we
* access _present_CPUSUPPORT_${enabler} etc., which we define as static, thus
* preventing the compiler from emitting a reference to an external symbol.
*
* In this way, it becomes possible to issue CPUSUPPORT_FEATURE invocations
* for nonexistent features without running afoul of the requirement that
* "If an identifier declared with external linkage is used... in the entire
* program there shall be exactly one external definition" (C99 standard, 6.9
* paragraph 5). In practice, this means that users of the cpusupport code
* can omit build and runtime detection files without changing the framework
* code.
*/
#define CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled) \
static int cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \
static int cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \
static inline int cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler(void) { return (0); } \
extern int cpusupport_ ## arch_feature ## _present_ ## enabled; \
extern int cpusupport_ ## arch_feature ## _init_ ## enabled; \
int cpusupport_ ## arch_feature ## _detect_ ## enabled(void); \
\
static inline int \
cpusupport_ ## arch_feature(void) \
{ \
\
if (cpusupport_ ## arch_feature ## _present_ ## enabled) \
return (1); \
else if (cpusupport_ ## arch_feature ## _init_ ## enabled) \
return (0); \
cpusupport_ ## arch_feature ## _present_ ## enabled = \
cpusupport_ ## arch_feature ## _detect_ ## enabled(); \
cpusupport_ ## arch_feature ## _init_ ## enabled = 1; \
return (cpusupport_ ## arch_feature ## _present_ ## enabled); \
} \
static void (* cpusupport_ ## arch_feature ## _dummyptr)(void); \
static inline void \
cpusupport_ ## arch_feature ## _dummyfunc(void) \
{ \
\
(void)cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \
(void)cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \
(void)cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler; \
(void)cpusupport_ ## arch_feature ## _present_ ## enabled; \
(void)cpusupport_ ## arch_feature ## _init_ ## enabled; \
(void)cpusupport_ ## arch_feature ## _detect_ ## enabled; \
(void)cpusupport_ ## arch_feature ## _dummyptr; \
} \
static void (* cpusupport_ ## arch_feature ## _dummyptr)(void) = cpusupport_ ## arch_feature ## _dummyfunc; \
struct cpusupport_ ## arch_feature ## _dummy
#define CPUSUPPORT_FEATURE_(arch_feature, enabler, enabled) \
CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled)
#define CPUSUPPORT_FEATURE(arch, feature, enabler) \
CPUSUPPORT_FEATURE_(arch ## _ ## feature, enabler, CPUSUPPORT_ ## enabler)
/*
* CPUSUPPORT_FEATURE_DECL(arch, feature):
* Macro which defines variables and provides a function declaration for
* detecting the presence of "feature" on the "arch" architecture. The
* function body following this macro expansion must return nonzero if the
* feature is present, or zero if the feature is not present or the detection
* fails for any reason.
*/
#define CPUSUPPORT_FEATURE_DECL(arch, feature) \
int cpusupport_ ## arch ## _ ## feature ## _present_1 = 0; \
int cpusupport_ ## arch ## _ ## feature ## _init_1 = 0; \
int cpusupport_ ## arch ## _ ## feature ## _detect_1(void); \
int \
cpusupport_ ## arch ## _ ## feature ## _detect_1(void)
/*
* List of features. If a feature here is not enabled by the appropriate
* CPUSUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the
* relevant macro may be defined (e.g., by Build/cpusupport.sh successfully
* compiling Build/cpusupport-ARCH-FEATURE.c) then the C file containing the
* corresponding run-time detection code (cpusupport_arch_feature.c) must be
* compiled and linked in.
*/
CPUSUPPORT_FEATURE(x86, aesni, X86_AESNI);
CPUSUPPORT_FEATURE(x86, sse2, X86_SSE2);
#endif /* !_CPUSUPPORT_H_ */

View File

@ -2,9 +2,9 @@
#ifdef CPUSUPPORT_X86_CPUID
#include <cpuid.h>
#endif
#define CPUID_AESNI_BIT (1 << 25)
#endif
CPUSUPPORT_FEATURE_DECL(x86, aesni)
{
@ -22,7 +22,7 @@ CPUSUPPORT_FEATURE_DECL(x86, aesni)
goto unsupported;
/* Return the relevant feature bit. */
return (ecx & CPUID_AESNI_BIT);
return ((ecx & CPUID_AESNI_BIT) ? 1 : 0);
unsupported:
#endif

View File

@ -2,9 +2,9 @@
#ifdef CPUSUPPORT_X86_CPUID
#include <cpuid.h>
#endif
#define CPUID_SSE2_BIT (1 << 26)
#endif
CPUSUPPORT_FEATURE_DECL(x86, sse2)
{
@ -22,7 +22,7 @@ CPUSUPPORT_FEATURE_DECL(x86, sse2)
goto unsupported;
/* Return the relevant feature bit. */
return (edx & CPUID_SSE2_BIT);
return ((edx & CPUID_SSE2_BIT) ? 1 : 0);
unsupported:
#endif

View File

@ -23,16 +23,19 @@ struct crypto_aes_key;
#ifdef CPUSUPPORT_X86_AESNI
/* Test whether OpenSSL and AESNI code produce the same AES ciphertext. */
static int
aesnitest(uint8_t ptext[16], uint8_t * key, size_t keylen)
aesnitest(uint8_t ptext[16], uint8_t * key, size_t len)
{
AES_KEY kexp_openssl;
void * kexp_aesni;
uint8_t ctext_openssl[16];
uint8_t ctext_aesni[16];
/* Sanity-check. */
assert((len == 16) || (len == 32));
/* Expand the key. */
AES_set_encrypt_key(key, keylen * 8, &kexp_openssl);
if ((kexp_aesni = crypto_aes_key_expand_aesni(key, keylen)) == NULL)
AES_set_encrypt_key(key, (int)(len * 8), &kexp_openssl);
if ((kexp_aesni = crypto_aes_key_expand_aesni(key, len)) == NULL)
goto err0;
/* Encrypt the block. */
@ -70,9 +73,9 @@ useaesni(void)
/* Test cases: key is 0x00010203..., ptext is 0x00112233... */
for (i = 0; i < 16; i++)
ptext[i] = 0x11 * i;
ptext[i] = (0x11 * i) & 0xff;
for (i = 0; i < 32; i++)
key[i] = i;
key[i] = i & 0xff;
/* Test that AESNI and OpenSSL produce the same results. */
if (aesnitest(ptext, key, 16) || aesnitest(ptext, key, 32)) {
@ -112,7 +115,7 @@ crypto_aes_key_expand(const uint8_t * key, size_t len)
goto err0;
/* Expand the key. */
AES_set_encrypt_key(key, len * 8, kexp);
AES_set_encrypt_key(key, (int)(len * 8), kexp);
/* Success! */
return ((void *)kexp);
@ -158,6 +161,10 @@ crypto_aes_key_free(struct crypto_aes_key * key)
}
#endif
/* Behave consistently with free(NULL). */
if (key == NULL)
return;
/* Attempt to zero the expanded key. */
insecure_memzero(key, sizeof(AES_KEY));

View File

@ -3,7 +3,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wmmintrin.h>
#include "insecure_memzero.h"
@ -226,6 +225,10 @@ void
crypto_aes_key_free_aesni(void * key)
{
/* Behave consistently with free(NULL). */
if (key == NULL)
return;
/* Attempt to zero the expanded key. */
insecure_memzero(key, sizeof(struct crypto_aes_key_aesni));

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include "crypto_aes.h"
#include "insecure_memzero.h"
#include "sysendian.h"
#include "crypto_aesctr.h"
@ -82,16 +83,13 @@ crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf,
void
crypto_aesctr_free(struct crypto_aesctr * stream)
{
int i;
/* Be compatible with free(NULL). */
/* Behave consistently with free(NULL). */
if (stream == NULL)
return;
/* Zero potentially sensitive information. */
for (i = 0; i < 16; i++)
stream->buf[i] = 0;
stream->bytectr = stream->nonce = 0;
insecure_memzero(stream, sizeof(struct crypto_aesctr));
/* Free the stream. */
free(stream);
@ -99,7 +97,7 @@ crypto_aesctr_free(struct crypto_aesctr * stream)
/**
* crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen):
* Equivalent to init(key, nonce); stream(inbuf, outbuf, buflen); free.
* Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free().
*/
void
crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce,
@ -107,7 +105,6 @@ crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce,
{
struct crypto_aesctr stream_rec;
struct crypto_aesctr * stream = &stream_rec;
int i;
/* Initialize values. */
stream->key = key;
@ -118,7 +115,5 @@ crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce,
crypto_aesctr_stream(stream, inbuf, outbuf, buflen);
/* Zero potentially sensitive information. */
for (i = 0; i < 16; i++)
stream->buf[i] = 0;
stream->bytectr = stream->nonce = 0;
insecure_memzero(stream, sizeof(struct crypto_aesctr));
}

View File

@ -4,8 +4,9 @@
#include <stddef.h>
#include <stdint.h>
/* Opaque type. */
/* Opaque types. */
struct crypto_aes_key;
struct crypto_aesctr;
/**
* crypto_aesctr_init(key, nonce):
@ -33,7 +34,7 @@ void crypto_aesctr_free(struct crypto_aesctr *);
/**
* crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen):
* Equivalent to init(key, nonce); stream(inbuf, outbuf, buflen); free.
* Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free().
*/
void crypto_aesctr_buf(const struct crypto_aes_key *, uint64_t,
const uint8_t *, uint8_t *, size_t);

View File

@ -0,0 +1,49 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "asprintf.h"
/**
* asprintf(ret, format, ...):
* Do asprintf(3) like GNU and BSD do.
*/
int
asprintf(char ** ret, const char * format, ...)
{
va_list ap;
int len;
size_t buflen;
/* Figure out how long the string needs to be. */
va_start(ap, format);
len = vsnprintf(NULL, 0, format, ap);
va_end(ap);
/* Did we fail? */
if (len < 0)
goto err0;
buflen = (size_t)(len) + 1;
/* Allocate memory. */
if ((*ret = malloc(buflen)) == NULL)
goto err0;
/* Actually generate the string. */
va_start(ap, format);
len = vsnprintf(*ret, buflen, format, ap);
va_end(ap);
/* Did we fail? */
if (len < 0)
goto err1;
/* Success! */
return (len);
err1:
free(*ret);
err0:
/* Failure! */
return (-1);
}

View File

@ -0,0 +1,16 @@
#ifndef _ASPRINTF_H_
#define _ASPRINTF_H_
/* Avoid namespace collisions with BSD/GNU asprintf. */
#ifdef asprintf
#undef asprintf
#endif
#define asprintf libcperciva_asprintf
/**
* asprintf(ret, format, ...):
* Do asprintf(3) like GNU and BSD do.
*/
int asprintf(char **, const char *, ...);
#endif /* !_ASPRINTF_H_ */

View File

@ -1,3 +1,4 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
@ -53,8 +54,8 @@ entropy_read(uint8_t * buf, size_t buflen)
}
/* We've filled a portion of the buffer. */
buf += lenread;
buflen -= lenread;
buf += (size_t)lenread;
buflen -= (size_t)lenread;
}
/* Close the device. */

View File

@ -0,0 +1,358 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
/*
* Standard getopt global variables. optreset starts as non-zero in order to
* trigger initialization behaviour.
*/
const char * optarg = NULL;
int optind = 1;
int opterr = 1;
int optreset = 1;
/*
* Quasi-internal global variables -- these are used via GETOPT macros.
*/
const char * getopt_dummy = "(dummy)";
int getopt_initialized = 0;
/*
* Internal variables.
*/
static const char * cmdname = NULL;
static struct opt {
const char * os;
size_t olen;
int hasarg;
} * opts = NULL;
static size_t nopts;
static size_t opt_missing;
static size_t opt_default;
static size_t opt_found;
static const char * packedopts;
static char popt[3];
static int atexit_registered = 0;
/* Print a message. */
#define PRINTMSG(...) do { \
if (cmdname != NULL) \
fprintf(stderr, "%s: ", cmdname); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while (0)
/* Print an error message and die. */
#define DIE(...) do { \
PRINTMSG(__VA_ARGS__); \
abort(); \
} while (0)
/* Print a warning, if warnings are enabled. */
#define WARN(...) do { \
if (opterr == 0) \
break; \
if (opt_missing != opt_default) \
break; \
PRINTMSG(__VA_ARGS__); \
} while (0)
/* Free allocated options array. */
static void
atexit_handler(void)
{
free(opts);
opts = NULL;
}
/* Reset internal state. */
static void
reset(int argc, char * const argv[])
{
const char * p;
/* If we have arguments, stash argv[0] for error messages. */
if (argc > 0) {
/* Find the basename, without leading directories. */
for (p = cmdname = argv[0]; *p != '\0'; p++) {
if (*p == '/')
cmdname = p + 1;
}
}
/* Discard any registered command-line options. */
free(opts);
opts = NULL;
/* Register atexit handler if we haven't done so already. */
if (!atexit_registered) {
atexit(atexit_handler);
atexit_registered = 1;
}
/* We will start scanning from the first option. */
optind = 1;
/* We're not in the middle of any packed options. */
packedopts = NULL;
/* We haven't found any option yet. */
opt_found = (size_t)(-1);
/* We're not initialized yet. */
getopt_initialized = 0;
/* Finished resetting state. */
optreset = 0;
}
/* Search for an option string. */
static size_t
searchopt(const char * os)
{
size_t i;
/* Scan the array of options. */
for (i = 0; i < nopts; i++) {
/* Is there an option in this slot? */
if (opts[i].os == NULL)
continue;
/* Does this match up to the length of the option string? */
if (strncmp(opts[i].os, os, opts[i].olen))
continue;
/* Do we have <option>\0 or <option>= ? */
if ((os[opts[i].olen] == '\0') || (os[opts[i].olen] == '='))
return (i);
}
/* Not found. */
return (opt_default);
}
const char *
getopt(int argc, char * const argv[])
{
const char * os = NULL;
const char * canonical_os = NULL;
/* No argument yet. */
optarg = NULL;
/* Reset the getopt state if needed. */
if (optreset)
reset(argc, argv);
/* If not initialized, return dummy option. */
if (!getopt_initialized)
return (GETOPT_DUMMY);
/* If we've run out of arguments, we're done. */
if (optind >= argc)
return (NULL);
/*
* If we're not already in the middle of a packed single-character
* options, see if we should start.
*/
if ((packedopts == NULL) && (argv[optind][0] == '-') &&
(argv[optind][1] != '-') && (argv[optind][1] != '\0')) {
/* We have one or more single-character options. */
packedopts = &argv[optind][1];
}
/* If we're processing single-character options, fish one out. */
if (packedopts != NULL) {
/* Construct the option string. */
popt[0] = '-';
popt[1] = *packedopts;
popt[2] = '\0';
os = popt;
/* We've done this character. */
packedopts++;
/* Are we done with this string? */
if (*packedopts == '\0') {
packedopts = NULL;
optind++;
}
}
/* If we don't have an option yet, do we have dash-dash? */
if ((os == NULL) && (argv[optind][0] == '-') &&
(argv[optind][1] == '-')) {
/* If this is not "--\0", it's an option. */
if (argv[optind][2] != '\0')
os = argv[optind];
/* Either way, we want to eat the string. */
optind++;
}
/* If we have found nothing which looks like an option, we're done. */
if (os == NULL)
return (NULL);
/* Search for the potential option. */
opt_found = searchopt(os);
/* If the option is not registered, give up now. */
if (opt_found == opt_default) {
WARN("unknown option: %s", os);
return (os);
}
/* The canonical option string is the one registered. */
canonical_os = opts[opt_found].os;
/* Does the option take an argument? */
if (opts[opt_found].hasarg) {
/*
* If we're processing packed single-character options, the
* rest of the string is the argument to this option.
*/
if (packedopts != NULL) {
optarg = packedopts;
packedopts = NULL;
optind++;
}
/*
* If the option string is <option>=<value>, extract that
* value as the option argument.
*/
if (os[opts[opt_found].olen] == '=')
optarg = &os[opts[opt_found].olen + 1];
/*
* If we don't have an argument yet, take one from the
* remaining command line.
*/
if ((optarg == NULL) && (optind < argc))
optarg = argv[optind++];
/* If we still have no option, declare it MIA. */
if (optarg == NULL) {
WARN("option requires an argument: %s",
opts[opt_found].os);
opt_found = opt_missing;
}
} else {
/* If we have --foo=bar, something went wrong. */
if (os[opts[opt_found].olen] == '=') {
WARN("option doesn't take an argument: %s",
opts[opt_found].os);
opt_found = opt_default;
}
}
/* Return the canonical option string. */
return (canonical_os);
}
size_t
getopt_lookup(const char * os)
{
/* Can't reset here. */
if (optreset)
DIE("Can't reset in the middle of getopt loop");
/* We should only be called after initialization is complete. */
assert(getopt_initialized);
/* GETOPT_DUMMY should never get passed back to us. */
assert(os != GETOPT_DUMMY);
/*
* Make sure the option passed back to us corresponds to the one we
* found earlier.
*/
assert((opt_found == opt_missing) || (opt_found == opt_default) ||
((opt_found < nopts) && (strcmp(os, opts[opt_found].os) == 0)));
/* Return the option number we identified earlier. */
return (opt_found);
}
void
getopt_register_opt(const char * os, size_t ln, int hasarg)
{
/* Can't reset here. */
if (optreset)
DIE("Can't reset in the middle of getopt loop");
/* We should only be called during initialization. */
assert(!getopt_initialized);
/* We should have space allocated for registering options. */
assert(opts != NULL);
/* We should not have registered an option here yet. */
assert(opts[ln].os == NULL);
/* Options should be "-X" or "--foo". */
if ((os[0] != '-') || (os[1] == '\0') ||
((os[1] == '-') && (os[2] == '\0')) ||
((os[1] != '-') && (os[2] != '\0')))
DIE("Not a valid command-line option: %s", os);
/* Make sure we haven't already registered this option. */
if (searchopt(os) != opt_default)
DIE("Command-line option registered twice: %s", os);
/* Record option. */
opts[ln].os = os;
opts[ln].olen = strlen(os);
opts[ln].hasarg = hasarg;
}
void
getopt_register_missing(size_t ln)
{
/* Can't reset here. */
if (optreset)
DIE("Can't reset in the middle of getopt loop");
/* We should only be called during initialization. */
assert(!getopt_initialized);
/* Record missing-argument value. */
opt_missing = ln;
}
void
getopt_setrange(size_t ln)
{
size_t i;
/* Can't reset here. */
if (optreset)
DIE("Can't reset in the middle of getopt loop");
/* We should only be called during initialization. */
assert(!getopt_initialized);
/* Allocate space for options. */
opts = malloc(ln * sizeof(struct opt));
if ((ln > 0) && (opts == NULL))
DIE("Failed to allocate memory in getopt");
/* Initialize options. */
for (i = 0; i < ln; i++)
opts[i].os = NULL;
/* Record the number of (potential) options. */
nopts = ln;
/* Record default missing-argument and no-such-option values. */
opt_missing = opt_default = ln + 1;
}

View File

@ -0,0 +1,175 @@
#ifndef _GETOPT_H_
#define _GETOPT_H_
#include <setjmp.h>
#include <stddef.h>
/**
* This getopt implementation parses options of the following forms:
* -a -b -c foo (single-character options)
* -abc foo (packed single-character options)
* -abcfoo (packed single-character options and an argument)
* --foo bar (long option)
* --foo=bar (long option and argument separated by '=')
*
* It does not support abbreviated options (e.g., interpreting --foo as
* --foobar when there are no other --foo* options) since that misfeature
* results in breakage when new options are added. It also does not support
* options appearing after non-options (e.g., "cp foo bar -R") since that is
* a horrible GNU perversion.
*/
/* Work around LLVM bug. */
#ifdef __clang__
#warning Working around bug in LLVM optimizer
#warning For more details see https://llvm.org/bugs/show_bug.cgi?id=27190
#define DO_SETJMP _DO_SETJMP(__LINE__)
#define _DO_SETJMP(x) __DO_SETJMP(x)
#define __DO_SETJMP(x) \
void * getopt_initloop = && getopt_initloop_ ## x; \
getopt_initloop_ ## x:
#define DO_LONGJMP \
goto *getopt_initloop
#else
#define DO_SETJMP \
sigjmp_buf getopt_initloop; \
if (!getopt_initialized) \
sigsetjmp(getopt_initloop, 0)
#define DO_LONGJMP \
siglongjmp(getopt_initloop, 1)
#endif
/* Avoid namespace collisions with libc getopt. */
#define getopt libcperciva_getopt
#define optarg libcperciva_optarg
#define optind libcperciva_optind
#define opterr libcperciva_opterr
#define optreset libcperciva_optreset
/* Standard getopt global variables. */
extern const char * optarg;
extern int optind, opterr, optreset;
/* Dummy option string, equal to "(dummy)". */
#define GETOPT_DUMMY getopt_dummy
/**
* GETOPT(argc, argv):
* When called for the first time (or the first time after optreset is set to
* a nonzero value), return GETOPT_DUMMY, aka. "(dummy)". Thereafter, return
* the next option string and set optarg / optind appropriately; abort if not
* properly initialized when not being called for the first time.
*/
#define GETOPT(argc, argv) getopt(argc, argv)
/**
* GETOPT_SWITCH(ch):
* Jump to the appropriate GETOPT_OPT, GETOPT_OPTARG, GETOPT_MISSING_ARG, or
* GETOPT_DEFAULT based on the option string ${ch}. When called for the first
* time, perform magic to index the options.
*
* GETOPT_SWITCH(ch) is equivalent to "switch (ch)" in a standard getopt loop.
*/
#define GETOPT_SWITCH(ch) \
volatile size_t getopt_ln_min = __LINE__; \
volatile size_t getopt_ln = getopt_ln_min - 1; \
volatile int getopt_default_missing = 0; \
DO_SETJMP; \
switch (getopt_initialized ? getopt_lookup(ch) + getopt_ln_min : getopt_ln++)
/**
* GETOPT_OPT(os):
* Jump to this point when the option string ${os} is passed to GETOPT_SWITCH.
*
* GETOPT_OPT("-x") is equivalent to "case 'x'" in a standard getopt loop
* which has an optstring containing "x".
*/
#define GETOPT_OPT(os) _GETOPT_OPT(os, __LINE__)
#define _GETOPT_OPT(os, ln) __GETOPT_OPT(os, ln)
#define __GETOPT_OPT(os, ln) \
case ln: \
if (getopt_initialized) \
goto getopt_skip_ ## ln; \
getopt_register_opt(os, ln - getopt_ln_min, 0); \
DO_LONGJMP; \
getopt_skip_ ## ln
/**
* GETOPT_OPTARG(os):
* Jump to this point when the option string ${os} is passed to GETOPT_SWITCH,
* unless no argument is available, in which case jump to GETOPT_MISSING_ARG
* (if present) or GETOPT_DEFAULT (if not).
*
* GETOPT_OPTARG("-x") is equivalent to "case 'x'" in a standard getopt loop
* which has an optstring containing "x:".
*/
#define GETOPT_OPTARG(os) _GETOPT_OPTARG(os, __LINE__)
#define _GETOPT_OPTARG(os, ln) __GETOPT_OPTARG(os, ln)
#define __GETOPT_OPTARG(os, ln) \
case ln: \
if (getopt_initialized) \
goto getopt_skip_ ## ln; \
getopt_register_opt(os, ln - getopt_ln_min, 1); \
DO_LONGJMP; \
getopt_skip_ ## ln
/**
* GETOPT_MISSING_ARG:
* Jump to this point if an option string specified in GETOPT_OPTARG is seen
* but no argument is available.
*
* GETOPT_MISSING_ARG is equivalent to "case ':'" in a standard getopt loop
* which has an optstring starting with ":". As such, it also has the effect
* of disabling warnings about invalid options, as if opterr had been zeroed.
*/
#define GETOPT_MISSING_ARG _GETOPT_MISSING_ARG(__LINE__)
#define _GETOPT_MISSING_ARG(ln) __GETOPT_MISSING_ARG(ln)
#define __GETOPT_MISSING_ARG(ln) \
case ln: \
if (getopt_initialized) \
goto getopt_skip_ ## ln; \
getopt_register_missing(ln - getopt_ln_min); \
DO_LONGJMP; \
getopt_skip_ ## ln
/**
* GETOPT_DEFAULT:
* Jump to this point if an unrecognized option is seen or if an option
* specified in GETOPT_OPTARG is seen, no argument is available, and there is
* no GETOPT_MISSING_ARG label.
*
* GETOPT_DEFAULT is equivalent to "case '?'" in a standard getopt loop.
*
* NOTE: This MUST be present in the GETOPT_SWITCH statement, and MUST occur
* after all other GETOPT_* labels.
*/
#define GETOPT_DEFAULT _GETOPT_DEFAULT(__LINE__)
#define _GETOPT_DEFAULT(ln) __GETOPT_DEFAULT(ln)
#define __GETOPT_DEFAULT(ln) \
goto getopt_skip_ ## ln; \
case ln: \
getopt_initialized = 1; \
break; \
default: \
if (getopt_initialized) \
goto getopt_skip_ ## ln; \
if (!getopt_default_missing) { \
getopt_setrange(ln - getopt_ln_min); \
getopt_default_missing = 1; \
} \
DO_LONGJMP; \
getopt_skip_ ## ln
/*
* The back-end implementation. These should be considered internal
* interfaces and not used directly.
*/
const char * getopt(int, char * const []);
size_t getopt_lookup(const char *);
void getopt_register_opt(const char *, size_t, int);
void getopt_register_missing(size_t);
void getopt_setrange(size_t);
extern const char * getopt_dummy;
extern int getopt_initialized;
#endif /* !_GETOPT_H_ */

View File

@ -0,0 +1,165 @@
#include <stdio.h>
#include "asprintf.h"
#include "warnp.h"
#include "humansize.h"
/**
* humansize(size):
* Given a size in bytes, allocate and return a string of the form "<N> B"
* for 0 <= N <= 999 or "<X> <prefix>B" where either 10 <= X <= 999 or
* 1.0 <= X <= 9.9 and <prefix> is "k", "M", "G", "T", "P", or "E"; and where
* the value returned is the largest valid value <= the provided size.
*/
char *
humansize(uint64_t size)
{
char * s;
char prefix;
int shiftcnt;
int rc;
/* Special-case for size < 1000. */
if (size < 1000) {
rc = asprintf(&s, "%d B", (int)size);
} else {
/* Keep 10 * size / 1000^(3n) in size. */
for (size /= 100, shiftcnt = 1; size >= 10000; shiftcnt++)
size /= 1000;
/*
* Figure out what prefix to use. Since 1 EB = 10^18 B and
* the maximum value of a uint64_t is 2^64 which is roughly
* 18.4 * 10^18, this cannot reference beyond the end of the
* string.
*/
prefix = " kMGTPE"[shiftcnt];
/* Construct the string. */
if (size < 100)
rc = asprintf(&s, "%d.%d %cB", (int)size / 10,
(int)size % 10, prefix);
else
rc = asprintf(&s, "%d %cB", (int)size / 10, prefix);
}
if (rc == -1) {
warnp("asprintf");
goto err0;
}
/* Success! */
return (s);
err0:
/* Failure! */
return (NULL);
}
/**
* humansize_parse(s, size):
* Parse a string matching /[0-9]+ ?[kMGTPE]?B?/ as a size in bytes.
*/
int
humansize_parse(const char * s, uint64_t * size)
{
int state = 0;
uint64_t multiplier = 1;
do {
switch (state) {
case -1:
/* Error state. */
break;
case 0:
/* Initial state. */
*size = 0;
/* We must start with at least one digit. */
if ((*s < '0') || (*s > '9')) {
state = -1;
break;
}
/* FALLTHROUGH */
case 1:
/* We're now processing digits. */
state = 1;
/* Digit-parsing state. */
if (('0' <= *s) && (*s <= '9')) {
if (*size > UINT64_MAX / 10)
state = -1;
else
*size *= 10;
if (*size > UINT64_MAX - (uint64_t)(*s - '0'))
state = -1;
else
*size += (uint64_t)(*s - '0');
break;
}
/* FALLTHROUGH */
case 2:
/* We move into state 3 after an optional ' '. */
state = 3;
if (*s == ' ')
break;
/* FALLTHROUGH */
case 3:
/* We may have one SI prefix. */
switch (*s) {
case 'E':
multiplier *= 1000;
/* FALLTHROUGH */
case 'P':
multiplier *= 1000;
/* FALLTHROUGH */
case 'T':
multiplier *= 1000;
/* FALLTHROUGH */
case 'G':
multiplier *= 1000;
/* FALLTHROUGH */
case 'M':
multiplier *= 1000;
/* FALLTHROUGH */
case 'k':
multiplier *= 1000;
break;
}
/* We move into state 4 after the optional prefix. */
state = 4;
if (multiplier != 1)
break;
/* FALLTHROUGH */
case 4:
/* We move into state 5 after an optional 'B'. */
state = 5;
if (*s == 'B')
break;
/* FALLTHROUGH */
case 5:
/* We have trailing garbage. */
state = -1;
break;
}
/* Move on to the next character. */
s++;
} while (*s != '\0');
/* Multiply by multiplier. */
if (*size > UINT64_MAX / multiplier)
state = -1;
else
*size *= multiplier;
/* Anything other than state -1 is success. */
return ((state == -1) ? -1 : 0);
}

View File

@ -0,0 +1,21 @@
#ifndef _HUMANSIZE_H_
#define _HUMANSIZE_H_
#include <stdint.h>
/**
* humansize(size):
* Given a size in bytes, allocate and return a string of the form "<N> B"
* for 0 <= N <= 999 or "<X> <prefix>B" where either 10 <= X <= 999 or
* 1.0 <= X <= 9.9 and <prefix> is "k", "M", "G", "T", "P", or "E"; and where
* the value returned is the largest valid value <= the provided size.
*/
char * humansize(uint64_t);
/**
* humansize_parse(s, size):
* Parse a string matching /[0-9]+ ?[kMGTPE]?B?/ as a size in bytes.
*/
int humansize_parse(const char *, uint64_t *);
#endif /* !_HUMANSIZE_H_ */

View File

@ -1,6 +1,5 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
@ -38,6 +37,23 @@ handle(int sig)
gotsig[sig] = 1;
}
/* Restore old signals and re-issue intercepted signals. */
static void
resetsigs(struct sigaction savedsa[NSIGS])
{
size_t i;
/* Restore old signals. */
for (i = 0; i < NSIGS; i++)
sigaction(badsigs[i], &savedsa[i], NULL);
/* If we intercepted a signal, re-issue it. */
for (i = 0; i < NSIGS; i++) {
if (gotsig[badsigs[i]])
raise(badsigs[i]);
}
}
/**
* readpass(passwd, prompt, confirmprompt, devtty)
* If ${devtty} is non-zero, read a password from /dev/tty if possible; if
@ -90,7 +106,7 @@ readpass(char ** passwd, const char * prompt,
goto err2;
}
memcpy(&term, &term_old, sizeof(struct termios));
term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL;
term.c_lflag = (term.c_lflag & ~((tcflag_t)ECHO)) | ECHONL;
if (tcsetattr(fileno(readfrom), TCSANOW, &term)) {
warnp("Cannot set terminal settings");
goto err2;
@ -104,7 +120,10 @@ retry:
/* Read the password. */
if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) {
warnp("Cannot read password");
if (feof(readfrom))
warn0("EOF reading password");
else
warnp("Cannot read password");
goto err3;
}
@ -113,7 +132,10 @@ retry:
if (usingtty)
fprintf(stderr, "%s: ", confirmprompt);
if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) {
warnp("Cannot read password");
if (feof(readfrom))
warn0("EOF reading password");
else
warnp("Cannot read password");
goto err3;
}
if (strcmp(passbuf, confpassbuf)) {
@ -130,15 +152,8 @@ retry:
if (usingtty)
tcsetattr(fileno(readfrom), TCSANOW, &term_old);
/* Restore old signals. */
for (i = 0; i < NSIGS; i++)
sigaction(badsigs[i], &savedsa[i], NULL);
/* If we intercepted a signal, re-issue it. */
for (i = 0; i < NSIGS; i++) {
if (gotsig[badsigs[i]])
raise(badsigs[i]);
}
/* Restore old signals and re-issue intercepted signals. */
resetsigs(savedsa);
/* Close /dev/tty if we opened it. */
if (readfrom != stdin)
@ -174,6 +189,9 @@ err2:
/* Close /dev/tty if we opened it. */
if (readfrom != stdin)
fclose(readfrom);
/* Restore old signals and re-issue intercepted signals. */
resetsigs(savedsa);
err1:
/* Zero any stored passwords. */
insecure_memzero(passbuf, MAXPASSLEN);

View File

@ -22,7 +22,7 @@ be16dec(const void * pp)
{
const uint8_t * p = (uint8_t const *)pp;
return ((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8));
return (uint16_t)((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8));
}
static inline void
@ -85,7 +85,7 @@ le16dec(const void * pp)
{
const uint8_t * p = (uint8_t const *)pp;
return ((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8));
return (uint16_t)((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8));
}
static inline void

View File

@ -2,6 +2,7 @@
#define _WARNP_H_
#include <errno.h>
#include <stddef.h>
/* Avoid namespace collisions with BSD <err.h>. */
#define warn libcperciva_warn

View File

@ -25,13 +25,13 @@
*/
#include "scrypt_platform.h"
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "getopt.h"
#include "humansize.h"
#include "insecure_memzero.h"
#include "readpass.h"
#include "scryptenc.h"
@ -42,7 +42,10 @@ usage(void)
{
fprintf(stderr,
"usage: scrypt {enc | dec} [...] infile [outfile]\n");
"usage: scrypt {enc | dec} [-f] [-M maxmem]"
" [-m maxmemfrac]\n"
" [-t maxtime] [-v] [-P] infile [outfile]\n"
" scrypt --version\n");
exit(1);
}
@ -51,13 +54,17 @@ main(int argc, char *argv[])
{
FILE * infile;
FILE * outfile;
int devtty = 1;
int dec = 0;
size_t maxmem = 0;
int force_resources = 0;
uint64_t maxmem64;
double maxmemfrac = 0.5;
double maxtime = 300.0;
int ch;
const char * ch;
char * passwd;
int rc;
int verbose = 0;
WARNP_INIT;
@ -70,24 +77,50 @@ main(int argc, char *argv[])
maxtime = 5.0;
} else if (strcmp(argv[1], "dec") == 0) {
dec = 1;
} else
} else if (strcmp(argv[1], "--version") == 0) {
fprintf(stdout, "scrypt %s\n", PACKAGE_VERSION);
exit(0);
} else {
warn0("First argument must be 'enc' or 'dec'.\n");
usage();
}
argc--;
argv++;
/* Parse arguments. */
while ((ch = getopt(argc, argv, "hm:M:t:")) != -1) {
switch (ch) {
case 'M':
maxmem = strtoumax(optarg, NULL, 0);
while ((ch = GETOPT(argc, argv)) != NULL) {
GETOPT_SWITCH(ch) {
GETOPT_OPT("-f"):
force_resources = 1;
break;
case 'm':
GETOPT_OPTARG("-M"):
if (humansize_parse(optarg, &maxmem64)) {
warn0("Could not parse the parameter to -M.");
exit(1);
}
if (maxmem64 > SIZE_MAX) {
warn0("The parameter to -M is too large.");
exit(1);
}
maxmem = (size_t)maxmem64;
break;
GETOPT_OPTARG("-m"):
maxmemfrac = strtod(optarg, NULL);
break;
case 't':
GETOPT_OPTARG("-t"):
maxtime = strtod(optarg, NULL);
break;
default:
GETOPT_OPT("-v"):
verbose = 1;
break;
GETOPT_OPT("-P"):
devtty = 0;
break;
GETOPT_MISSING_ARG:
warn0("Missing argument to %s\n", ch);
usage();
GETOPT_DEFAULT:
warn0("illegal option -- %s\n", ch);
usage();
}
}
@ -120,21 +153,28 @@ main(int argc, char *argv[])
/* Prompt for a password. */
if (readpass(&passwd, "Please enter passphrase",
dec ? NULL : "Please confirm passphrase", 1))
(dec || !devtty) ? NULL : "Please confirm passphrase", devtty))
exit(1);
/* Encrypt or decrypt. */
if (dec)
rc = scryptdec_file(infile, outfile, (uint8_t *)passwd,
strlen(passwd), maxmem, maxmemfrac, maxtime);
strlen(passwd), maxmem, maxmemfrac, maxtime, verbose,
force_resources);
else
rc = scryptenc_file(infile, outfile, (uint8_t *)passwd,
strlen(passwd), maxmem, maxmemfrac, maxtime);
strlen(passwd), maxmem, maxmemfrac, maxtime, verbose);
/* Zero and free the password. */
insecure_memzero(passwd, strlen(passwd));
free(passwd);
/* Close any files we opened. */
if (infile != stdin)
fclose(infile);
if (outfile != stdout)
fclose(outfile);
/* If we failed, print the right error message and exit. */
if (rc != 0) {
switch (rc) {

View File

@ -21,7 +21,7 @@
.\" 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 24, 2009
.Dd February 10, 2017
.Dt SCRYPT 1
.Os
.Sh NAME
@ -30,11 +30,15 @@
.Sh SYNOPSIS
.Nm
.Brq Cm enc | Cm dec
.Op Fl f
.Op Fl M Ar maxmem
.Op Fl m Ar maxmemfrac
.Op Fl t Ar maxtime
.Op Fl P
.Ar infile
.Op Ar outfile
.Nm
.Fl -version
.Sh DESCRIPTION
.Nm Cm enc
encrypts
@ -53,8 +57,24 @@ and writes the result to
if specified, or the standard output otherwise.
The user will be prompted to enter the passphrase used at
encryption time to generate the derived encryption key.
.Pp
If
.Fl P
is not given,
.Nm
reads passphrases from its controlling terminal, or failing that,
from stdin. Prompts are only printed when
.Nm
is reading passphrases from some terminal. If
.Fl P
is given, then
.Nm
does not print any prompts, and reads a passphrase from stdin.
.Sh OPTIONS
.Bl -tag -width "-m maxmemfrac"
.It Fl f
Force the decryption to proceed even if it is anticipated to
require an excessive amount of memory or CPU time.
.It Fl M Ar maxmem
Use at most
.Ar maxmem
@ -67,6 +87,11 @@ of the available RAM to compute the derived encryption key.
Use at most
.Ar maxtime
seconds of CPU time to compute the derived encryption key.
.It Fl P
Always read passphrase from stdin, and do so only once even
when encrypting.
.It Fl -version
Print version of scrypt, and exit.
.El
.Pp
In

View File

@ -0,0 +1,26 @@
#!/bin/sh
### Constants
# The scenario command requires a lot of memory, so valgrind is only enabled
# if $USE_VALGRIND > 1.
c_valgrind_min=2
test_output="${s_basename}-stdout.txt"
reference="${scriptdir}/test_scrypt.good"
### Actual command
scenario_cmd() {
# Run the binary which tests known input/output strings.
setup_check_variables
(
${c_valgrind_cmd} ${bindir}/tests/test_scrypt 1> ${test_output}
echo $? > ${c_exitfile}
)
# The generated values should match the known good values.
setup_check_variables
if cmp -s ${test_output} ${reference}; then
echo "0"
else
echo "1"
fi > ${c_exitfile}
}

View File

@ -0,0 +1,26 @@
#!/bin/sh
### Constants
c_valgrind_min=1
reference_file="${scriptdir}/test_scrypt.good"
encrypted_reference_file="${scriptdir}/test_scrypt_good.enc"
decrypted_reference_file="${out}/attempt_reference.txt"
scenario_cmd() {
# Decrypt a reference file.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
dec -P ${encrypted_reference_file} \
${decrypted_reference_file}
echo $? > ${c_exitfile}
)
# The decrypted reference file should match the reference.
setup_check_variables
if cmp -s ${decrypted_reference_file} ${reference_file}; then
echo "0"
else
echo "1"
fi > ${c_exitfile}
}

View File

@ -0,0 +1,44 @@
#!/bin/sh
### Constants
c_valgrind_min=1
reference_file="${scriptdir}/test_scrypt.good"
encrypted_file="${out}/attempt.enc"
decrypted_file="${out}/attempt.txt"
scenario_cmd() {
# Encrypt a file.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
enc -P -t 1 ${reference_file} ${encrypted_file}
echo $? > ${c_exitfile}
)
# The encrypted file should be different from the original file.
# We cannot check against the "reference" encrypted file, because
# encrypted files include random salt. If successful, don't delete
# ${encrypted_file} yet; we need it for the next test.
setup_check_variables
if cmp -s ${encrypted_file} ${reference_file}; then
echo "1"
else
echo "0"
fi > ${c_exitfile}
# Decrypt the file we just encrypted.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
dec -P ${encrypted_file} ${decrypted_file}
echo $? > ${c_exitfile}
)
# The decrypted file should match the reference.
setup_check_variables
if cmp -s ${decrypted_file} ${reference_file}; then
echo "0"
else
echo "1"
fi > ${c_exitfile}
}

View File

@ -0,0 +1,57 @@
#!/bin/sh
### Constants
c_valgrind_min=1
reference_file="${scriptdir}/test_scrypt.good"
longwait_encrypted_file="${out}/longwait.enc"
longwait_decrypted_file="${out}/longwait.txt"
longwait_failed_log="${out}/longwait-failed.log"
scenario_cmd() {
# Encrypt file which should take a long time to decrypt.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
enc -P -t 10 ${reference_file} \
${longwait_encrypted_file}
echo $? > ${c_exitfile}
)
# Attempt to decrypt it with limited time. We want this
# command to fail, so we negate the normal return code.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
dec -P -t 1 ${longwait_encrypted_file} \
${longwait_decrypted_file} \
2> ${longwait_failed_log}
test ! $? -eq 0
echo $? > ${c_exitfile}
)
# We should have received an error message.
setup_check_variables
if grep -q "scrypt: Decrypting file would take too much CPU time" \
${longwait_failed_log}; then
echo "0"
else
echo "1"
fi > ${c_exitfile}
# Attempt to decrypt it with limited time, but force success.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
dec -P -t 1 -f ${longwait_encrypted_file} \
${longwait_decrypted_file}
echo $? > ${c_exitfile}
)
# The decrypted reference file should match the reference.
setup_check_variables
if cmp -s ${longwait_decrypted_file} ${reference_file}; then
echo "0"
else
echo "1"
fi > ${c_exitfile}
}

View File

@ -0,0 +1,69 @@
#!/bin/sh
### Constants
c_valgrind_min=1
reference_file="${scriptdir}/test_scrypt.good"
encrypted_file_1="${out}/sys-scrypt.enc"
decrypted_file_1="${out}/sys-scrypt.txt"
encrypted_file_2="${out}/our-scrypt.enc"
decrypted_file_2="${out}/our-scrypt.txt"
scenario_cmd() {
if [ -z "${system_scrypt}" ]; then
printf "no suitable system scrypt: "
# Inform test suite that we are skipping.
setup_check_variables
echo "-1" > ${c_exitfile}
return
fi
# Encrypt a file with our scrypt.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
enc -P -t 1 ${reference_file} ${encrypted_file_1}
echo $? > ${c_exitfile}
)
# Use the system scrypt to decrypt the file we just
# encrypted. Don't use valgrind for this.
setup_check_variables
(
echo ${password} | ${system_scrypt} \
dec -P ${encrypted_file_1} ${decrypted_file_1}
echo $? > ${c_exitfile}
)
# The decrypted file should match the reference.
setup_check_variables
if cmp -s ${decrypted_file_1} ${reference_file}; then
echo "0"
else
echo "1"
fi > ${c_exitfile}
# Encrypt a file with the system scrypt. Don't use
# valgrind for this.
setup_check_variables
(
echo ${password} | ${system_scrypt} \
enc -P -t 1 ${reference_file} ${encrypted_file_2}
echo $? > ${c_exitfile}
)
# Use our scrypt to decrypt the file we just encrypted.
setup_check_variables
(
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
dec -P ${encrypted_file_2} ${decrypted_file_2}
echo $? > ${c_exitfile}
)
# The decrypted file should match the reference.
setup_check_variables
if cmp -s ${decrypted_file_2} ${reference_file}; then
echo "0"
else
echo "1"
fi > ${c_exitfile}
}

View File

@ -0,0 +1,268 @@
#!/bin/sh
### Definitions
#
# This test suite uses the following terminology:
# - scenario: a series of commands to test. Each must be in a
# separate file, and must be completely self-contained
# (other than the variables listed below).
# - check: a series of commands that produces an exit code which
# the test suite should check. A scenario may contain any
# number of checks.
#
### Design
#
# The main function is scenario_runner(scenario_filename), which
# takes a scenario file as the argument, and runs a
# scenario_cmd()
# function which was defined in that file.
#
### Variables
#
# Wherever possible, this suite uses local variables and
# explicitly-passed arguments, with the following exceptions:
# - s_basename: this is the basename for the scenario's temporary
# and log files.
# - s_val_basename: this is the basename for the scenario's
# valgrind log files.
# - s_count: this is the count of the scenario's checks (so that
# each check can have distinct files).
# - s_retval: this is the overall exit code of the scenario.
# - c_exitfile: this contains the exit code of each check.
# - c_valgrind_min: this is the minimum value of USE_VALGRIND
# which will enable valgrind checking for this check.
# - c_valgrind_cmd: this is the valgrind command (including
# appropriate log file) if necessary, or is "" otherwise.
set -o nounset
### Constants
out="tests-output"
out_valgrind="tests-valgrind"
valgrind_suppressions="${out_valgrind}/suppressions"
valgrind_suppressions_log="${out_valgrind}/suppressions.pre"
# Keep the user-specified ${USE_VALGRIND}, or initialize to 0.
USE_VALGRIND=${USE_VALGRIND:-0}
# A non-zero value unlikely to be used as an exit code by the programs being
# tested.
valgrind_exit_code=108
## prepare_directories():
# Delete any old directories, and create new ones as necessary. Must be run
# after check_optional_valgrind().
prepare_directories() {
# Clean up previous directories.
if [ -d "${out}" ]; then
rm -rf ${out}
fi
if [ -d "${out_valgrind}" ]; then
rm -rf ${out_valgrind}
fi
# Make new directories.
mkdir ${out}
if [ "$USE_VALGRIND" -gt 0 ]; then
mkdir ${out_valgrind}
fi
}
## find_system (cmd, args...):
# Looks for ${cmd} in the $PATH, and ensure that it supports ${args}.
find_system() {
cmd=$1
cmd_with_args=$@
# Look for ${cmd}.
system_binary=`command -v ${cmd}`
if [ -z "${system_binary}" ]; then
system_binary=""
printf "System ${cmd} not found.\n" 1>&2
# If the command exists, check it ensures the ${args}.
elif ${cmd_with_args} 2>&1 >/dev/null | \
grep -qE "(invalid|illegal) option"; then
system_binary=""
printf "Cannot use system ${cmd}; does not" 1>&2
printf " support necessary arguments.\n" 1>&2
fi
echo "${system_binary}"
}
## check_optional_valgrind ():
# Return a $USE_VALGRIND variable defined; if it was previously defined and
# was greater than 0, then check that valgrind is available in the $PATH.
check_optional_valgrind() {
if [ "$USE_VALGRIND" -gt 0 ]; then
# Look for valgrind in $PATH.
if ! command -v valgrind >/dev/null 2>&1; then
printf "valgrind not found\n" 1>&2
exit 1
fi
fi
}
## ensure_valgrind_suppresssion (potential_memleaks_binary):
# Runs the ${potential_memleaks_binary} through valgrind, keeping
# track of any apparent memory leak in order to suppress reporting
# those leaks when testing other binaries.
ensure_valgrind_suppression() {
potential_memleaks_binary=$1
# Quit if we're not using valgrind.
if [ ! "$USE_VALGRIND" -gt 0 ]; then
return
fi;
printf "Generating valgrind suppressions... "
# Run valgrind on the binary, sending it a "\n" so that
# a test which uses STDIN will not wait for user input.
printf "\n" | (valgrind --leak-check=full --show-leak-kinds=all \
--gen-suppressions=all \
--log-file=${valgrind_suppressions_log} \
${potential_memleaks_binary})
# Strip out useless parts from the log file, as well as
# removing references to the main and "pl_*" ("potential
# loss") functions so that the suppressions can apply to
# other binaries.
(grep -v "^==" ${valgrind_suppressions_log} \
| grep -v " fun:pl_" - \
| grep -v " fun:main" - \
> ${valgrind_suppressions} )
# Clean up
rm -f ${valgrind_suppressions_log}
printf "done.\n"
}
## setup_check_variables ():
# Set up the "check" variables ${c_exitfile} and ${c_valgrind_cmd}, the
# latter depending on the previously-defined ${c_valgrind_min}.
# Advances the number of checks ${s_count} so that the next call to this
# function will set up new filenames.
setup_check_variables() {
# Set up the "exit" file.
c_exitfile="${s_basename}-`printf %02d ${s_count}`.exit"
# If we don't have a suppressions file, don't try to use it.
if [ ! -e ${valgrind_suppressions} ]; then
valgrind_suppressions=/dev/null
fi
# Set up the valgrind command if $USE_VALGRIND is greater
# than or equal to ${valgrind_min}; otherwise, produce an
# empty string. Using --error-exitcode means that if
# there is a serious problem (such that scrypt calls
# exit(1)) *and* a memory leak, the test suite reports an
# exit value of ${valgrind_exit_code}. However, if there
# is a serious problem but no memory leak, we still
# receive a non-zero exit code. The most important thing
# is that we only receive an exit code of 0 if both the
# program and valgrind are happy.
if [ "$USE_VALGRIND" -ge "${c_valgrind_min}" ]; then
val_logfilename=${s_val_basename}-`printf %02d ${s_count}`.log
c_valgrind_cmd="valgrind \
--log-file=${val_logfilename} \
--leak-check=full --show-leak-kinds=all \
--errors-for-leak-kinds=all \
--suppressions=${valgrind_suppressions} \
--error-exitcode=${valgrind_exit_code} "
else
c_valgrind_cmd=""
fi
# Advances the number of checks.
s_count=$((s_count + 1))
}
## get_val_logfile (val_basename, exitfile):
# Return the valgrind logfile corresponding to ${exitfile}.
get_val_logfile() {
val_basename=$1
exitfile=$2
num=`echo "${exitfile}" | rev | cut -c 1-7 | rev | cut -c 1-2 `
echo "${val_basename}-${num}.log"
}
## notify_success_or_fail (log_basename, val_log_basename):
# Examine all "exit code" files beginning with ${log_basename} and
# print "SUCCESS!" or "FAILED!" as appropriate. If the test failed
# with the code ${valgrind_exit_code}, output the appropriate
# valgrind logfile to stdout.
notify_success_or_fail() {
log_basename=$1
val_log_basename=$2
# Check each exitfile.
for exitfile in `ls ${log_basename}-*.exit | sort`; do
ret=`cat ${exitfile}`
if [ "${ret}" -lt 0 ]; then
echo "SKIP!"
return
fi
if [ "${ret}" -gt 0 ]; then
echo "FAILED!"
retval=${ret}
if [ "${ret}" -eq "${valgrind_exit_code}" ]; then
val_logfilename=$( get_val_logfile \
${val_log_basename} ${exitfile} )
cat ${val_logfilename}
fi
s_retval=${ret}
return
fi
done
echo "SUCCESS!"
}
## scenario_runner (scenario_filename):
# Runs a test scenario from ${scenario_filename}.
scenario_runner() {
scenario_filename=$1
basename=`basename ${scenario_filename} .sh`
printf " ${basename}... " 1>&2
# Initialize "scenario" and "check" variables.
s_basename=${out}/${basename}
s_val_basename=${out_valgrind}/${basename}
s_count=0
c_exitfile=/dev/null
c_valgrind_min=9
c_valgrind_cmd=""
# Load scenario_cmd() from the scenario file.
unset scenario_cmd
. ${scenario_filename}
if ! command -v scenario_cmd 1>/dev/null ; then
printf "ERROR: scenario_cmd() is not defined in\n"
printf " ${scenario_filename}\n"
exit 1
fi
# Run the scenario command.
scenario_cmd
# Print PASS or FAIL, and return result.
s_retval=0
notify_success_or_fail ${s_basename} ${s_val_basename}
return "${s_retval}"
}
## run_scenarios (scenario_filenames):
# Runs all scenarios matching ${scenario_filenames}.
run_scenarios() {
printf -- "Running tests\n"
printf -- "-------------\n"
scenario_filenames=$@
for scenario in ${scenario_filenames}; do
# We can't call this function with $( ... ) because we
# want to allow it to echo values to stdout.
scenario_runner ${scenario}
retval=$?
if [ ${retval} -gt 0 ]; then
exit ${retval}
fi
done
}

View File

@ -0,0 +1,51 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "crypto_scrypt.h"
#include "warnp.h"
static struct scrypt_test {
const char * passwd;
const char * salt;
uint64_t N;
uint32_t r;
uint32_t p;
} tests[4] = {
{ "", "", 16, 1, 1 },
{ "password", "NaCl", 1024, 8, 16 },
{ "pleaseletmein", "SodiumChloride", 16384, 8, 1 },
{ "pleaseletmein", "SodiumChloride", 1048576, 8, 1 }
};
int
main(int argc, char * argv[])
{
struct scrypt_test * test;
char kbuf[64];
size_t i;
WARNP_INIT;
(void)argc; /* UNUSED */
(void)argv; /* UNUSED */
for (test = tests;
test < tests + sizeof(tests) / sizeof(tests[0]);
test++) {
crypto_scrypt((const uint8_t *)test->passwd,
strlen(test->passwd), (const uint8_t *)test->salt,
strlen(test->salt), test->N, test->r, test->p,
(uint8_t *)kbuf, 64);
printf("scrypt(\"%s\", \"%s\", %u, %u, %u, 64) =\n",
test->passwd, test->salt, (unsigned int)test->N,
(unsigned int)(test->r), (unsigned int)test->p);
for (i = 0; i < 64; i++) {
printf("%02x ", (uint8_t)kbuf[i]);
if ((i % 16) == 15)
printf("\n");
}
}
return (0);
}

View File

@ -0,0 +1,20 @@
scrypt("", "", 16, 1, 1, 64) =
77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97
f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42
fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17
e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06
scrypt("password", "NaCl", 1024, 8, 16, 64) =
fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe
7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62
2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da
c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40
scrypt("pleaseletmein", "SodiumChloride", 16384, 8, 1, 64) =
70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb
fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2
d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9
e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87
scrypt("pleaseletmein", "SodiumChloride", 1048576, 8, 1, 64) =
21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81
ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47
8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3
37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4

View File

@ -0,0 +1,34 @@
#!/bin/sh
# Build directory (allowing flexible out-of-tree builds).
bindir=$1
# Constants used in multiple scenarios.
password="hunter2"
# Find script directory and load helper functions.
scriptdir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
. ${scriptdir}/shared_test_functions.sh
# We need a ${bindir}.
if [ -z ${bindir} ]; then
printf "Warning: Scrypt binary directory not given.\n"
printf "Attempting to use default values for in-source-tree build.\n"
bindir=".."
fi
# Find system scrypt, and ensure it supports -P.
system_scrypt=$( find_system scrypt enc -P )
# Check for optional valgrind.
check_optional_valgrind
# Clean up previous directories, and create new ones.
prepare_directories
# Generate valgrind suppression file if it is required. Must be
# done after preparing directories.
ensure_valgrind_suppression ${bindir}/tests/valgrind/potential-memleaks
# Run the test scenarios; this will exit on the first failure.
run_scenarios ${scriptdir}/??-*.sh

Binary file not shown.

View File

@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdlib.h>
#define FGETS_BUFSIZE 64
/* Problem with FreeBSD 10.3 fgets() with stdin. */
static void
pl_freebsd_fgets()
{
char buf[FGETS_BUFSIZE];
if (fgets(buf, FGETS_BUFSIZE, stdin) == NULL)
exit(1);
}
int
main()
{
/* Test potential memory leaks. */
pl_freebsd_fgets();
/* Success! */
exit(0);
}

View File

@ -63,6 +63,11 @@ public:
//Wait for the queue to be empty, and flush synchronously
//Warning: this can potentialy last forever as we wait it to complete
void flush() override;
// Error handler
virtual void set_error_handler(log_err_handler) override;
virtual log_err_handler error_handler() override;
protected:
void _sink_it(details::log_msg& msg) override;
void _set_formatter(spdlog::formatter_ptr msg_formatter) override;

View File

@ -66,7 +66,7 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
msg_type(std::move(other.msg_type))
{}
async_msg(async_msg_type m_type) :msg_type(m_type)
async_msg(async_msg_type m_type):msg_type(m_type)
{}
async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT
@ -85,7 +85,7 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
async_msg& operator=(const async_msg& other) = delete;
// construct from log_msg
async_msg(const details::log_msg& m) :
async_msg(const details::log_msg& m):
level(m.level),
time(m.time),
thread_id(m.thread_id),
@ -135,6 +135,7 @@ public:
void flush(bool wait_for_q);
void set_error_handler(spdlog::log_err_handler err_handler);
private:
formatter_ptr _formatter;
@ -221,7 +222,8 @@ inline spdlog::details::async_log_helper::~async_log_helper()
_worker_thread.join();
}
catch (...) // don't crash in destructor
{}
{
}
}
@ -250,28 +252,34 @@ inline void spdlog::details::async_log_helper::push_msg(details::async_log_helpe
inline void spdlog::details::async_log_helper::flush(bool wait_for_q)
{
push_msg(async_msg(async_msg_type::flush));
if(wait_for_q)
if (wait_for_q)
wait_empty_q(); //return only make after the above flush message was processed
}
inline void spdlog::details::async_log_helper::worker_loop()
{
try
if (_worker_warmup_cb) _worker_warmup_cb();
auto last_pop = details::os::now();
auto last_flush = last_pop;
auto active = true;
while (active)
{
if (_worker_warmup_cb) _worker_warmup_cb();
auto last_pop = details::os::now();
auto last_flush = last_pop;
while(process_next_msg(last_pop, last_flush));
if (_worker_teardown_cb) _worker_teardown_cb();
}
catch (const std::exception &ex)
{
_err_handler(ex.what());
}
catch (...)
{
_err_handler("Unknown exception");
try
{
active = process_next_msg(last_pop, last_flush);
}
catch (const std::exception &ex)
{
_err_handler(ex.what());
}
catch (...)
{
_err_handler("Unknown exception");
}
}
if (_worker_teardown_cb) _worker_teardown_cb();
}
// process next message in the queue
@ -300,7 +308,7 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
_formatter->format(incoming_log_msg);
for (auto &s : _sinks)
{
if(s->should_log( incoming_log_msg.level))
if (s->should_log(incoming_log_msg.level))
{
s->log(incoming_log_msg);
}
@ -374,5 +382,10 @@ inline void spdlog::details::async_log_helper::wait_empty_q()
}
}
inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler)
{
_err_handler = err_handler;
}

View File

@ -57,6 +57,19 @@ inline void spdlog::async_logger::flush()
_async_log_helper->flush(true);
}
// Error handler
inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_handler)
{
_err_handler = err_handler;
_async_log_helper->set_error_handler(err_handler);
}
inline spdlog::log_err_handler spdlog::async_logger::error_handler()
{
return _err_handler;
}
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
{
_formatter = msg_formatter;

View File

@ -121,44 +121,42 @@ inline void spdlog::logger::log(level::level_enum lvl, const T& msg)
}
template <typename... Args>
inline void spdlog::logger::trace(const char* fmt, const Args&... args)
template <typename Arg1, typename... Args>
inline void spdlog::logger::trace(const char* fmt, const Arg1 &arg1, const Args&... args)
{
log(level::trace, fmt, args...);
log(level::trace, fmt, arg1, args...);
}
template <typename... Args>
inline void spdlog::logger::debug(const char* fmt, const Args&... args)
template <typename Arg1, typename... Args>
inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args)
{
log(level::debug, fmt, args...);
log(level::debug, fmt, arg1, args...);
}
template <typename... Args>
inline void spdlog::logger::info(const char* fmt, const Args&... args)
template <typename Arg1, typename... Args>
inline void spdlog::logger::info(const char* fmt, const Arg1 &arg1, const Args&... args)
{
log(level::info, fmt, args...);
log(level::info, fmt, arg1, args...);
}
template <typename... Args>
inline void spdlog::logger::warn(const char* fmt, const Args&... args)
template <typename Arg1, typename... Args>
inline void spdlog::logger::warn(const char* fmt, const Arg1 &arg1, const Args&... args)
{
log(level::warn, fmt, args...);
log(level::warn, fmt, arg1, args...);
}
template <typename... Args>
inline void spdlog::logger::error(const char* fmt, const Args&... args)
template <typename Arg1, typename... Args>
inline void spdlog::logger::error(const char* fmt, const Arg1 &arg1, const Args&... args)
{
log(level::err, fmt, args...);
log(level::err, fmt, arg1, args...);
}
template <typename... Args>
inline void spdlog::logger::critical(const char* fmt, const Args&... args)
template <typename Arg1, typename... Args>
inline void spdlog::logger::critical(const char* fmt, const Arg1 &arg1, const Args&... args)
{
log(level::critical, fmt, args...);
log(level::critical, fmt, arg1, args...);
}
template<typename T>
inline void spdlog::logger::trace(const T& msg)
{

View File

@ -82,7 +82,7 @@ static int to12h(const tm& t)
using days_array = std::array<std::string, 7>;
static const days_array& days()
{
static const days_array arr{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static const days_array arr{ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } };
return arr;
}
class a_formatter:public flag_formatter
@ -96,7 +96,7 @@ class a_formatter:public flag_formatter
//Full weekday name
static const days_array& full_days()
{
static const days_array arr{ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
static const days_array arr{ { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } };
return arr;
}
class A_formatter:public flag_formatter
@ -111,7 +111,7 @@ class A_formatter:public flag_formatter
using months_array = std::array<std::string, 12>;
static const months_array& months()
{
static const months_array arr{ "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" };
static const months_array arr{ { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" } };
return arr;
}
class b_formatter:public flag_formatter
@ -125,7 +125,7 @@ class b_formatter:public flag_formatter
//Full month name
static const months_array& full_months()
{
static const months_array arr{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
static const months_array arr{ { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" } };
return arr;
}
class B_formatter:public flag_formatter

View File

@ -61,23 +61,23 @@ inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string
// Create multi/single threaded rotating file logger
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
{
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files);
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
}
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
{
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files);
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files);
}
// Create file logger which creates new file at midnight):
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute)
{
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute);
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, hour, minute);
}
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute)
{
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute);
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, hour, minute);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,43 @@
/*
Formatting library for C++ - std::ostream support
Formatting library for C++ - std::ostream support
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
For the license information refer to format.h.
*/
#include "ostream.h"
namespace fmt {
namespace internal {
FMT_FUNC void write(std::ostream &os, Writer &w)
{
const char *data = w.data();
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
UnsignedStreamSize size = w.size();
UnsignedStreamSize max_size =
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
do {
UnsignedStreamSize n = size <= max_size ? size : max_size;
os.write(data, static_cast<std::streamsize>(n));
data += n;
size -= n;
} while (size != 0);
}
}
namespace {
// Write the content of w to os.
void write(std::ostream &os, Writer &w) {
const char *data = w.data();
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
UnsignedStreamSize size = w.size();
UnsignedStreamSize max_size =
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
do {
UnsignedStreamSize n = size <= max_size ? size : max_size;
os.write(data, static_cast<std::streamsize>(n));
data += n;
size -= n;
} while (size != 0);
}
}
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args)
{
MemoryWriter w;
w.write(format_str, args);
internal::write(os, w);
}
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
MemoryWriter w;
w.write(format_str, args);
write(os, w);
}
FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
write(os, w);
return static_cast<int>(w.size());
}
} // namespace fmt

View File

@ -1,17 +1,16 @@
/*
Formatting library for C++ - std::ostream support
Formatting library for C++ - std::ostream support
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
For the license information refer to format.h.
*/
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
// commented out by spdlog
// #include "format.h"
#include "format.h"
#include <ostream>
namespace fmt
@ -21,7 +20,7 @@ namespace internal
{
template <class Char>
class FormatBuf: public std::basic_streambuf<Char>
class FormatBuf : public std::basic_streambuf<Char>
{
private:
typedef typename std::basic_streambuf<Char>::int_type int_type;
@ -31,7 +30,7 @@ private:
Char *start_;
public:
FormatBuf(Buffer<Char> &buffer): buffer_(buffer), start_(&buffer[0])
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0])
{
this->setp(start_, start_ + buffer_.capacity());
}
@ -46,7 +45,7 @@ public:
start_ = &buffer_[0];
start_[buf_size] = traits_type::to_char_type(ch);
this->setp(start_ + buf_size + 1, start_ + buf_size * 2);
this->setp(start_+ buf_size + 1, start_ + buf_size * 2);
}
return ch;
}
@ -59,7 +58,7 @@ public:
Yes &convert(std::ostream &);
struct DummyStream: std::ostream
struct DummyStream : std::ostream
{
DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
@ -77,15 +76,12 @@ struct ConvertToIntImpl<T, true>
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
};
};
// Write the content of w to os.
void write(std::ostream &os, Writer &w);
} // namespace internal
// Formats a value.
template <typename Char, typename ArgFormatter, typename T>
void format_arg(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value)
void format(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value)
{
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
@ -99,16 +95,28 @@ void format_arg(BasicFormatter<Char, ArgFormatter> &f,
}
/**
\rst
Prints formatted data to the stream *os*.
\rst
Prints formatted data to the stream *os*.
**Example**::
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
print(cerr, "Don't {}!", "panic");
\endrst
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt
#ifdef FMT_HEADER_ONLY

View File

@ -0,0 +1,238 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
// Disable bogus MSVC warnings.
#ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif
#include "posix.h"
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef _WIN32
# include <unistd.h>
#else
# include <windows.h>
# include <io.h>
# define O_CREAT _O_CREAT
# define O_TRUNC _O_TRUNC
# ifndef S_IRUSR
# define S_IRUSR _S_IREAD
# endif
# ifndef S_IWUSR
# define S_IWUSR _S_IWRITE
# endif
# ifdef __MINGW32__
# define _SH_DENYNO 0x40
# endif
#endif // _WIN32
#ifdef fileno
# undef fileno
#endif
namespace {
#ifdef _WIN32
// Return type of read and write functions.
typedef int RWResult;
// On Windows the count argument to read and write is unsigned, so convert
// it from size_t preventing integer overflow.
inline unsigned convert_rwcount(std::size_t count) {
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
}
#else
// Return type of read and write functions.
typedef ssize_t RWResult;
inline std::size_t convert_rwcount(std::size_t count) { return count; }
#endif
}
fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
fmt::report_system_error(errno, "cannot close file");
}
fmt::BufferedFile::BufferedFile(
fmt::CStringRef filename, fmt::CStringRef mode) {
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
if (!file_)
FMT_THROW(SystemError(errno, "cannot open file {}", filename));
}
void fmt::BufferedFile::close() {
if (!file_)
return;
int result = FMT_SYSTEM(fclose(file_));
file_ = 0;
if (result != 0)
FMT_THROW(SystemError(errno, "cannot close file"));
}
// A macro used to prevent expansion of fileno on broken versions of MinGW.
#define FMT_ARGS
int fmt::BufferedFile::fileno() const {
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
if (fd == -1)
FMT_THROW(SystemError(errno, "cannot get file descriptor"));
return fd;
}
fmt::File::File(fmt::CStringRef path, int oflag) {
int mode = S_IRUSR | S_IWUSR;
#if defined(_WIN32) && !defined(__MINGW32__)
fd_ = -1;
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
#else
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
#endif
if (fd_ == -1)
FMT_THROW(SystemError(errno, "cannot open file {}", path));
}
fmt::File::~File() FMT_NOEXCEPT {
// Don't retry close in case of EINTR!
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
fmt::report_system_error(errno, "cannot close file");
}
void fmt::File::close() {
if (fd_ == -1)
return;
// Don't retry close in case of EINTR!
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
int result = FMT_POSIX_CALL(close(fd_));
fd_ = -1;
if (result != 0)
FMT_THROW(SystemError(errno, "cannot close file"));
}
fmt::LongLong fmt::File::size() const {
#ifdef _WIN32
// Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
// is less than 0x0500 as is the case with some default MinGW builds.
// Both functions support large file sizes.
DWORD size_upper = 0;
HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));
DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
if (size_lower == INVALID_FILE_SIZE) {
DWORD error = GetLastError();
if (error != NO_ERROR)
FMT_THROW(WindowsError(GetLastError(), "cannot get file size"));
}
fmt::ULongLong long_size = size_upper;
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
#else
typedef struct stat Stat;
Stat file_stat = Stat();
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
FMT_THROW(SystemError(errno, "cannot get file attributes"));
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
"return type of File::size is not large enough");
return file_stat.st_size;
#endif
}
std::size_t fmt::File::read(void *buffer, std::size_t count) {
RWResult result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
if (result < 0)
FMT_THROW(SystemError(errno, "cannot read from file"));
return internal::to_unsigned(result);
}
std::size_t fmt::File::write(const void *buffer, std::size_t count) {
RWResult result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
if (result < 0)
FMT_THROW(SystemError(errno, "cannot write to file"));
return internal::to_unsigned(result);
}
fmt::File fmt::File::dup(int fd) {
// Don't retry as dup doesn't return EINTR.
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
int new_fd = FMT_POSIX_CALL(dup(fd));
if (new_fd == -1)
FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {}", fd));
return File(new_fd);
}
void fmt::File::dup2(int fd) {
int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1) {
FMT_THROW(SystemError(errno,
"cannot duplicate file descriptor {} to {}", fd_, fd));
}
}
void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT {
int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1)
ec = ErrorCode(errno);
}
void fmt::File::pipe(File &read_end, File &write_end) {
// Close the descriptors first to make sure that assignments don't throw
// and there are no leaks.
read_end.close();
write_end.close();
int fds[2] = {};
#ifdef _WIN32
// Make the default pipe capacity same as on Linux 2.6.11+.
enum { DEFAULT_CAPACITY = 65536 };
int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
#else
// Don't retry as the pipe function doesn't return EINTR.
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
int result = FMT_POSIX_CALL(pipe(fds));
#endif
if (result != 0)
FMT_THROW(SystemError(errno, "cannot create pipe"));
// The following assignments don't throw because read_fd and write_fd
// are closed.
read_end = File(fds[0]);
write_end = File(fds[1]);
}
fmt::BufferedFile fmt::File::fdopen(const char *mode) {
// Don't retry as fdopen doesn't return EINTR.
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
if (!f)
FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor"));
BufferedFile file(f);
fd_ = -1;
return file;
}
long fmt::getpagesize() {
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwPageSize;
#else
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
if (size < 0)
FMT_THROW(SystemError(errno, "cannot get memory page size"));
return size;
#endif
}

443
vendor/spdlog/spdlog/fmt/bundled/posix.h vendored Normal file
View File

@ -0,0 +1,443 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_POSIX_H_
#define FMT_POSIX_H_
#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
# undef __STRICT_ANSI__
#endif
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__)
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_POSIX
# if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
# define FMT_POSIX(call) _##call
# else
# define FMT_POSIX(call) call
# endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
# define FMT_SYSTEM(call) call
# ifdef _WIN32
// Fix warnings about deprecated symbols.
# define FMT_POSIX_CALL(call) ::_##call
# else
# define FMT_POSIX_CALL(call) ::call
# endif
#endif
#if FMT_GCC_VERSION >= 407
# define FMT_UNUSED __attribute__((unused))
#else
# define FMT_UNUSED
#endif
#ifndef FMT_USE_STATIC_ASSERT
# define FMT_USE_STATIC_ASSERT 0
#endif
#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
#else
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
# define FMT_STATIC_ASSERT(cond, message) \
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
#endif
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
# define FMT_RETRY_VAL(result, expression, error_result) \
do { \
result = (expression); \
} while (result == error_result && errno == EINTR)
#else
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
namespace fmt
{
// An error code.
class ErrorCode
{
private:
int value_;
public:
explicit ErrorCode(int value = 0) FMT_NOEXCEPT :
value_(value) {}
int get() const FMT_NOEXCEPT
{
return value_;
}
};
// A buffered file.
class BufferedFile
{
private:
FILE *file_;
friend class File;
explicit BufferedFile(FILE *f) : file_(f) {}
public:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT :
file_(0) {}
// Destroys the object closing the file it represents if any.
~BufferedFile() FMT_NOEXCEPT;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct Proxy
{
FILE *file;
};
public:
// A "move constructor" for moving from a temporary.
BufferedFile(Proxy p) FMT_NOEXCEPT :
file_(p.file) {}
// A "move constructor" for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT :
file_(f.file_)
{
f.file_ = 0;
}
// A "move assignment operator" for moving from a temporary.
BufferedFile &operator=(Proxy p)
{
close();
file_ = p.file;
return *this;
}
// A "move assignment operator" for moving from an lvalue.
BufferedFile &operator=(BufferedFile &other)
{
close();
file_ = other.file_;
other.file_ = 0;
return *this;
}
// Returns a proxy object for moving from a temporary:
// BufferedFile file = BufferedFile(...);
operator Proxy() FMT_NOEXCEPT
{
Proxy p = {file_};
file_ = 0;
return p;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT :
file_(other.file_)
{
other.file_ = 0;
}
BufferedFile& operator=(BufferedFile &&other)
{
close();
file_ = other.file_;
other.file_ = 0;
return *this;
}
#endif
// Opens a file.
BufferedFile(CStringRef filename, CStringRef mode);
// Closes the file.
void close();
// Returns the pointer to a FILE object representing this file.
FILE *get() const FMT_NOEXCEPT
{
return file_;
}
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
int (fileno)() const;
void print(CStringRef format_str, const ArgList &args)
{
fmt::print(file_, format_str, args);
}
FMT_VARIADIC(void, print, CStringRef)
};
// A file. Closed file is represented by a File object with descriptor -1.
// Methods that are not declared with FMT_NOEXCEPT may throw
// fmt::SystemError in case of failure. Note that some errors such as
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
class File
{
private:
int fd_; // File descriptor.
// Constructs a File object with a given descriptor.
explicit File(int fd) : fd_(fd) {}
public:
// Possible values for the oflag argument to the constructor.
enum
{
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
};
// Constructs a File object which doesn't represent any file.
File() FMT_NOEXCEPT :
fd_(-1) {}
// Opens a file and constructs a File object representing this file.
File(CStringRef path, int oflag);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct Proxy
{
int fd;
};
public:
// A "move constructor" for moving from a temporary.
File(Proxy p) FMT_NOEXCEPT :
fd_(p.fd) {}
// A "move constructor" for moving from an lvalue.
File(File &other) FMT_NOEXCEPT :
fd_(other.fd_)
{
other.fd_ = -1;
}
// A "move assignment operator" for moving from a temporary.
File &operator=(Proxy p)
{
close();
fd_ = p.fd;
return *this;
}
// A "move assignment operator" for moving from an lvalue.
File &operator=(File &other)
{
close();
fd_ = other.fd_;
other.fd_ = -1;
return *this;
}
// Returns a proxy object for moving from a temporary:
// File file = File(...);
operator Proxy() FMT_NOEXCEPT
{
Proxy p = {fd_};
fd_ = -1;
return p;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN(File);
public:
File(File &&other) FMT_NOEXCEPT :
fd_(other.fd_)
{
other.fd_ = -1;
}
File& operator=(File &&other)
{
close();
fd_ = other.fd_;
other.fd_ = -1;
return *this;
}
#endif
// Destroys the object closing the file it represents if any.
~File() FMT_NOEXCEPT;
// Returns the file descriptor.
int descriptor() const FMT_NOEXCEPT
{
return fd_;
}
// Closes the file.
void close();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
LongLong size() const;
// Attempts to read count bytes from the file into the specified buffer.
std::size_t read(void *buffer, std::size_t count);
// Attempts to write count bytes from the specified buffer to the file.
std::size_t write(const void *buffer, std::size_t count);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
static File dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
static void pipe(File &read_end, File &write_end);
// Creates a BufferedFile object associated with this file and detaches
// this File object from the file.
BufferedFile fdopen(const char *mode);
};
// Returns the memory page size.
long getpagesize();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
!defined(__ANDROID__) && !defined(__CYGWIN__)
# define FMT_LOCALE
#endif
#ifdef FMT_LOCALE
// A "C" numeric locale.
class Locale
{
private:
# ifdef _MSC_VER
typedef _locale_t locale_t;
enum { LC_NUMERIC_MASK = LC_NUMERIC };
static locale_t newlocale(int category_mask, const char *locale, locale_t)
{
return _create_locale(category_mask, locale);
}
static void freelocale(locale_t locale)
{
_free_locale(locale);
}
static double strtod_l(const char *nptr, char **endptr, _locale_t locale)
{
return _strtod_l(nptr, endptr, locale);
}
# endif
locale_t locale_;
FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
public:
typedef locale_t Type;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL))
{
if (!locale_)
FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
}
~Locale()
{
freelocale(locale_);
}
Type get() const
{
return locale_;
}
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double strtod(const char *&str) const
{
char *end = 0;
double result = strtod_l(str, &end, locale_);
str = end;
return result;
}
};
#endif // FMT_LOCALE
} // namespace fmt
#if !FMT_USE_RVALUE_REFERENCES
namespace std
{
// For compatibility with C++98.
inline fmt::BufferedFile &move(fmt::BufferedFile &f)
{
return f;
}
inline fmt::File &move(fmt::File &f)
{
return f;
}
}
#endif
#endif // FMT_POSIX_H_

View File

@ -1,658 +0,0 @@
/*
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include "ostream.h"
namespace fmt
{
namespace internal
{
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template <bool IsSigned>
struct IntChecker
{
template <typename T>
static bool fits_in_int(T value)
{
unsigned max = std::numeric_limits<int>::max();
return value <= max;
}
static bool fits_in_int(bool)
{
return true;
}
};
template <>
struct IntChecker<true>
{
template <typename T>
static bool fits_in_int(T value)
{
return value >= std::numeric_limits<int>::min() &&
value <= std::numeric_limits<int>::max();
}
static bool fits_in_int(int)
{
return true;
}
};
class PrecisionHandler: public ArgVisitor<PrecisionHandler, int>
{
public:
void report_unhandled_arg()
{
FMT_THROW(FormatError("precision is not integer"));
}
template <typename T>
int visit_any_int(T value)
{
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(FormatError("number is too big"));
return static_cast<int>(value);
}
};
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class IsZeroInt: public ArgVisitor<IsZeroInt, bool>
{
public:
template <typename T>
bool visit_any_int(T value)
{
return value == 0;
}
};
template <typename T, typename U>
struct is_same
{
enum
{
value = 0
};
};
template <typename T>
struct is_same<T, T>
{
enum
{
value = 1
};
};
// An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template <typename T = void>
class ArgConverter: public ArgVisitor<ArgConverter<T>, void>
{
private:
internal::Arg &arg_;
wchar_t type_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
public:
ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type)
{}
void visit_bool(bool value)
{
if (type_ != 's')
visit_any_int(value);
}
template <typename U>
void visit_any_int(U value)
{
bool is_signed = type_ == 'd' || type_ == 'i';
using internal::Arg;
typedef typename internal::Conditional<
is_same<T, void>::value, U, T>::type TargetType;
if (sizeof(TargetType) <= sizeof(int))
{
// Extra casts are used to silence warnings.
if (is_signed)
{
arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
}
else
{
arg_.type = Arg::UINT;
typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
}
}
else
{
if (is_signed)
{
arg_.type = Arg::LONG_LONG;
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_.long_long_value = static_cast<LongLong>(value);
}
else
{
arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value =
static_cast<typename internal::MakeUnsigned<U>::Type>(value);
}
}
}
};
// Converts an integer argument to char for printf.
class CharConverter: public ArgVisitor<CharConverter, void>
{
private:
internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public:
explicit CharConverter(internal::Arg &arg): arg_(arg)
{}
template <typename T>
void visit_any_int(T value)
{
arg_.type = internal::Arg::CHAR;
arg_.int_value = static_cast<char>(value);
}
};
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class WidthHandler: public ArgVisitor<WidthHandler, unsigned>
{
private:
FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public:
explicit WidthHandler(FormatSpec &spec): spec_(spec)
{}
void report_unhandled_arg()
{
FMT_THROW(FormatError("width is not integer"));
}
template <typename T>
unsigned visit_any_int(T value)
{
typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType width = static_cast<UnsignedType>(value);
if (internal::is_negative(value))
{
spec_.align_ = ALIGN_LEFT;
width = 0 - width;
}
unsigned int_max = std::numeric_limits<int>::max();
if (width > int_max)
FMT_THROW(FormatError("number is too big"));
return static_cast<unsigned>(width);
}
};
} // namespace internal
/**
\rst
A ``printf`` argument formatter based on the `curiously recurring template
pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
or all of the visit methods with the same signatures as the methods in
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
Pass the subclass as the *Impl* template parameter. When a formatting
function processes an argument, it will dispatch to a visit method
specific to the argument type. For example, if the argument type is
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
will be called. If the subclass doesn't contain a method with this signature,
then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
superclass will be called.
\endrst
*/
template <typename Impl, typename Char>
class BasicPrintfArgFormatter: public internal::ArgFormatterBase<Impl, Char>
{
private:
void write_null_pointer()
{
this->spec().type_ = 0;
this->write("(nil)");
}
typedef internal::ArgFormatterBase<Impl, Char> Base;
public:
/**
\rst
Constructs an argument formatter object.
*writer* is a reference to the output writer and *spec* contains format
specifier information for standard argument types.
\endrst
*/
BasicPrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: internal::ArgFormatterBase<Impl, Char>(w, s)
{}
/** Formats an argument of type ``bool``. */
void visit_bool(bool value)
{
FormatSpec &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return this->visit_any_int(value);
fmt_spec.type_ = 0;
this->write(value);
}
/** Formats a character. */
void visit_char(int value)
{
const FormatSpec &fmt_spec = this->spec();
BasicWriter<Char> &w = this->writer();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
w.write_int(value, fmt_spec);
typedef typename BasicWriter<Char>::CharPtr CharPtr;
CharPtr out = CharPtr();
if (fmt_spec.width_ > 1)
{
Char fill = ' ';
out = w.grow_buffer(fmt_spec.width_);
if (fmt_spec.align_ != ALIGN_LEFT)
{
std::fill_n(out, fmt_spec.width_ - 1, fill);
out += fmt_spec.width_ - 1;
}
else
{
std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
}
}
else
{
out = w.grow_buffer(1);
}
*out = static_cast<Char>(value);
}
/** Formats a null-terminated C string. */
void visit_cstring(const char *value)
{
if (value)
Base::visit_cstring(value);
else if (this->spec().type_ == 'p')
write_null_pointer();
else
this->write("(null)");
}
/** Formats a pointer. */
void visit_pointer(const void *value)
{
if (value)
return Base::visit_pointer(value);
this->spec().type_ = 0;
write_null_pointer();
}
/** Formats an argument of a custom (user-defined) type. */
void visit_custom(internal::Arg::CustomValue c)
{
BasicFormatter<Char> formatter(ArgList(), this->writer());
const Char format_str[] = { '}', 0 };
const Char *format = format_str;
c.format(&formatter, c.value, &format);
}
};
/** The default printf argument formatter. */
template <typename Char>
class PrintfArgFormatter
: public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>
{
public:
/** Constructs an argument formatter object. */
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s)
{}
};
/** This template formats data and writes the output to a writer. */
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
class PrintfFormatter: private internal::FormatterBase
{
private:
BasicWriter<Char> &writer_;
void parse_flags(FormatSpec &spec, const Char *&s);
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
internal::Arg get_arg(
const Char *s,
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
// Parses argument index, flags and width and returns the argument index.
unsigned parse_header(const Char *&s, FormatSpec &spec);
public:
/**
\rst
Constructs a ``PrintfFormatter`` object. References to the arguments and
the writer are stored in the formatter object so make sure they have
appropriate lifetimes.
\endrst
*/
explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
: FormatterBase(al), writer_(w)
{}
/** Formats stored arguments and writes the output to the writer. */
FMT_API void format(BasicCStringRef<Char> format_str);
};
template <typename Char, typename AF>
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
{
for (;;)
{
switch (*s++)
{
case '-':
spec.align_ = ALIGN_LEFT;
break;
case '+':
spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
break;
case '0':
spec.fill_ = '0';
break;
case ' ':
spec.flags_ |= SIGN_FLAG;
break;
case '#':
spec.flags_ |= HASH_FLAG;
break;
default:
--s;
return;
}
}
}
template <typename Char, typename AF>
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
unsigned arg_index)
{
(void)s;
const char *error = FMT_NULL;
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
if (error)
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
return arg;
}
template <typename Char, typename AF>
unsigned PrintfFormatter<Char, AF>::parse_header(
const Char *&s, FormatSpec &spec)
{
unsigned arg_index = std::numeric_limits<unsigned>::max();
Char c = *s;
if (c >= '0' && c <= '9')
{
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
unsigned value = internal::parse_nonnegative_int(s);
if (*s == '$') // value is an argument index
{
++s;
arg_index = value;
}
else
{
if (c == '0')
spec.fill_ = '0';
if (value != 0)
{
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
spec.width_ = value;
return arg_index;
}
}
}
parse_flags(spec, s);
// Parse width.
if (*s >= '0' && *s <= '9')
{
spec.width_ = internal::parse_nonnegative_int(s);
}
else if (*s == '*')
{
++s;
spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
}
return arg_index;
}
template <typename Char, typename AF>
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
{
const Char *start = format_str.c_str();
const Char *s = start;
while (*s)
{
Char c = *s++;
if (c != '%') continue;
if (*s == c)
{
write(writer_, start, s);
start = ++s;
continue;
}
write(writer_, start, s - 1);
FormatSpec spec;
spec.align_ = ALIGN_RIGHT;
// Parse argument index, flags and width.
unsigned arg_index = parse_header(s, spec);
// Parse precision.
if (*s == '.')
{
++s;
if ('0' <= *s && *s <= '9')
{
spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
}
else if (*s == '*')
{
++s;
spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
}
}
using internal::Arg;
Arg arg = get_arg(s, arg_index);
if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
if (spec.fill_ == '0')
{
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
spec.align_ = ALIGN_NUMERIC;
else
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
}
// Parse length and convert the argument to the required type.
using internal::ArgConverter;
switch (*s++)
{
case 'h':
if (*s == 'h')
ArgConverter<signed char>(arg, *++s).visit(arg);
else
ArgConverter<short>(arg, *s).visit(arg);
break;
case 'l':
if (*s == 'l')
ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
else
ArgConverter<long>(arg, *s).visit(arg);
break;
case 'j':
ArgConverter<intmax_t>(arg, *s).visit(arg);
break;
case 'z':
ArgConverter<std::size_t>(arg, *s).visit(arg);
break;
case 't':
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
break;
case 'L':
// printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break;
default:
--s;
ArgConverter<void>(arg, *s).visit(arg);
}
// Parse type.
if (!*s)
FMT_THROW(FormatError("invalid format string"));
spec.type_ = static_cast<char>(*s++);
if (arg.type <= Arg::LAST_INTEGER_TYPE)
{
// Normalize type.
switch (spec.type_)
{
case 'i':
case 'u':
spec.type_ = 'd';
break;
case 'c':
// TODO: handle wchar_t
internal::CharConverter(arg).visit(arg);
break;
}
}
start = s;
// Format argument.
AF(writer_, spec).visit(arg);
}
write(writer_, start, s);
}
template <typename Char>
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args)
{
PrintfFormatter<Char>(args, w).format(format);
}
/**
\rst
Formats arguments and returns the result as a string.
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
inline std::string sprintf(CStringRef format, ArgList args)
{
MemoryWriter w;
printf(w, format, args);
return w.str();
}
FMT_VARIADIC(std::string, sprintf, CStringRef)
inline std::wstring sprintf(WCStringRef format, ArgList args)
{
WMemoryWriter w;
printf(w, format, args);
return w.str();
}
FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
/**
\rst
Prints formatted data to the file *f*.
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
/**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
inline int printf(CStringRef format, ArgList args)
{
return fprintf(stdout, format, args);
}
FMT_VARIADIC(int, printf, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args)
{
MemoryWriter w;
printf(w, format_str, args);
internal::write(os, w);
return static_cast<int>(w.size());
}
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt
#ifdef FMT_HEADER_ONLY
# include "printf.cc"
#endif
#endif // FMT_PRINTF_H_

58
vendor/spdlog/spdlog/fmt/bundled/time.h vendored Normal file
View File

@ -0,0 +1,58 @@
/*
Formatting library for C++ - time formatting
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_TIME_H_
#define FMT_TIME_H_
#include "format.h"
#include <ctime>
namespace fmt
{
template <typename ArgFormatter>
void format(BasicFormatter<char, ArgFormatter> &f,
const char *&format_str, const std::tm &tm)
{
if (*format_str == ':')
++format_str;
const char *end = format_str;
while (*end && *end != '}')
++end;
if (*end != '}')
FMT_THROW(FormatError("missing '}' in format string"));
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format;
format.append(format_str, end + 1);
format[format.size() - 1] = '\0';
Buffer<char> &buffer = f.writer().buffer();
std::size_t start = buffer.size();
for (;;)
{
std::size_t size = buffer.capacity() - start;
std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm);
if (count != 0)
{
buffer.resize(start + count);
break;
}
if (size >= format.size() * 256)
{
// If the buffer is 256 times larger than the format string, assume
// that `strftime` gives an empty result. There doesn't seem to be a
// better way to distinguish the two cases:
// https://github.com/fmtlib/fmt/issues/367
break;
}
const std::size_t MIN_GROWTH = 10;
buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
}
format_str = end + 1;
}
}
#endif // FMT_TIME_H_

View File

@ -37,12 +37,12 @@ public:
template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args);
template <typename... Args> void log(level::level_enum lvl, const char* msg);
template <typename... Args> void trace(const char* fmt, const Args&... args);
template <typename... Args> void debug(const char* fmt, const Args&... args);
template <typename... Args> void info(const char* fmt, const Args&... args);
template <typename... Args> void warn(const char* fmt, const Args&... args);
template <typename... Args> void error(const char* fmt, const Args&... args);
template <typename... Args> void critical(const char* fmt, const Args&... args);
template <typename Arg1, typename... Args> void trace(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void debug(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void info(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void warn(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void error(const char* fmt, const Arg1&, const Args&... args);
template <typename Arg1, typename... Args> void critical(const char* fmt, const Arg1&, const Args&... args);
template <typename T> void log(level::level_enum lvl, const T&);
template <typename T> void trace(const T&);
@ -59,10 +59,6 @@ public:
void set_pattern(const std::string&);
void set_formatter(formatter_ptr);
// error handler
void set_error_handler(log_err_handler);
log_err_handler error_handler();
// automatically call flush() if message level >= log_level
void flush_on(level::level_enum log_level);
@ -70,6 +66,10 @@ public:
const std::vector<sink_ptr>& sinks() const;
// error handler
virtual void set_error_handler(log_err_handler);
virtual log_err_handler error_handler();
protected:
virtual void _sink_it(details::log_msg&);
virtual void _set_pattern(const std::string&);

View File

@ -64,16 +64,15 @@ template<class Mutex>
class rotating_file_sink : public base_sink < Mutex >
{
public:
rotating_file_sink(const filename_t &base_filename, const filename_t &extension,
std::size_t max_size, std::size_t max_files ) :
rotating_file_sink(const filename_t &base_filename,
std::size_t max_size, std::size_t max_files) :
_base_filename(base_filename),
_extension(extension),
_max_size(max_size),
_max_files(max_files),
_current_size(0),
_file_helper()
{
_file_helper.open(calc_filename(_base_filename, 0, _extension));
_file_helper.open(calc_filename(_base_filename, 0));
_current_size = _file_helper.size(); //expensive. called only once
}
@ -95,21 +94,21 @@ protected:
}
private:
static filename_t calc_filename(const filename_t& filename, std::size_t index, const filename_t& extension)
static filename_t calc_filename(const filename_t& filename, std::size_t index)
{
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
if (index)
w.write(SPDLOG_FILENAME_T("{}.{}.{}"), filename, index, extension);
w.write(SPDLOG_FILENAME_T("{}.{}"), filename, index);
else
w.write(SPDLOG_FILENAME_T("{}.{}"), filename, extension);
w.write(SPDLOG_FILENAME_T("{}"), filename);
return w.str();
}
// Rotate files:
// log.txt -> log.1.txt
// log.1.txt -> log2.txt
// log.2.txt -> log3.txt
// log.3.txt -> delete
// log.txt -> log.txt.1
// log.txt.1 -> log.txt.2
// log.txt.2 -> log.txt.3
// lo3.txt.3 -> delete
void _rotate()
{
@ -117,8 +116,8 @@ private:
_file_helper.close();
for (auto i = _max_files; i > 0; --i)
{
filename_t src = calc_filename(_base_filename, i - 1, _extension);
filename_t target = calc_filename(_base_filename, i, _extension);
filename_t src = calc_filename(_base_filename, i - 1);
filename_t target = calc_filename(_base_filename, i);
if (details::file_helper::file_exists(target))
{
@ -135,7 +134,6 @@ private:
_file_helper.reopen(true);
}
filename_t _base_filename;
filename_t _extension;
std::size_t _max_size;
std::size_t _max_files;
std::size_t _current_size;
@ -150,27 +148,27 @@ typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
*/
struct default_daily_file_name_calculator
{
// Create filename for the form basename.YYYY-MM-DD_hh-mm.extension
static filename_t calc_filename(const filename_t& basename, const filename_t& extension)
// Create filename for the form basename.YYYY-MM-DD_hh-mm
static filename_t calc_filename(const filename_t& basename)
{
std::tm tm = spdlog::details::os::localtime();
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
return w.str();
}
};
/*
* Generator of daily log file names in format basename.YYYY-MM-DD.extension
* Generator of daily log file names in format basename.YYYY-MM-DD
*/
struct dateonly_daily_file_name_calculator
{
// Create filename for the form basename.YYYY-MM-DD.extension
static filename_t calc_filename(const filename_t& basename, const filename_t& extension)
// Create filename for the form basename.YYYY-MM-DD
static filename_t calc_filename(const filename_t& basename)
{
std::tm tm = spdlog::details::os::localtime();
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, extension);
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
return w.str();
}
};
@ -185,17 +183,15 @@ public:
//create daily file sink which rotates on given time
daily_file_sink(
const filename_t& base_filename,
const filename_t& extension,
int rotation_hour,
int rotation_minute) : _base_filename(base_filename),
_extension(extension),
_rotation_h(rotation_hour),
_rotation_m(rotation_minute)
{
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
_rotation_tp = _next_rotation_tp();
_file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension));
_file_helper.open(FileNameCalc::calc_filename(_base_filename));
}
void flush() override
@ -208,7 +204,7 @@ protected:
{
if (std::chrono::system_clock::now() >= _rotation_tp)
{
_file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension));
_file_helper.open(FileNameCalc::calc_filename(_base_filename));
_rotation_tp = _next_rotation_tp();
}
_file_helper.write(msg);
@ -231,7 +227,6 @@ private:
}
filename_t _base_filename;
filename_t _extension;
int _rotation_h;
int _rotation_m;
std::chrono::system_clock::time_point _rotation_tp;

View File

@ -7,7 +7,7 @@
#pragma once
#define SPDLOG_VERSION "0.12.0"
#define SPDLOG_VERSION "0.13.0"
#include <spdlog/tweakme.h>
#include <spdlog/common.h>
@ -124,7 +124,7 @@ std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_b
// Create and register a logger with templated sink type
// Example:
// spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename", "txt");
// spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename");
template <typename Sink, typename... Args>
std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...);