Commit f0b41c5d authored by Nikos Mavrogiannopoulos's avatar Nikos Mavrogiannopoulos
Browse files

ecore cli: updated and rewritten to use libev

That removes a lot of code that was not necessary in the gnutls test
suite.

Resolves: #884

Signed-off-by: Nikos Mavrogiannopoulos's avatarNikos Mavrogiannopoulos <nmav@redhat.com>
parent acb025f0
......@@ -265,7 +265,7 @@ threadsan.Fedora.x86_64:
script:
- ./bootstrap
- CFLAGS="-fsanitize=thread -g -O2" CXXFLAGS=$CFLAGS
dash ./configure --disable-gcc-warnings --disable-doc --cache-file cache/config.cache --disable-non-suiteb-curves --disable-guile --enable-fips140-mode
dash ./configure --disable-gcc-warnings --disable-doc --cache-file cache/config.cache --disable-non-suiteb-curves --disable-guile --enable-fips140-mode --disable-full-test-suite
- make -j$(nproc)
- make -C tests check -j$(nproc) SUBDIRS=. TESTS="tls-pthread dtls-pthread fips-mode-pthread rng-pthread" TSAN_OPTIONS="suppressions=$(pwd)/devel/tsan.supp" GNUTLS_SKIP_FIPS_INTEGRITY_CHECKS=1 GNUTLS_FORCE_FIPS_MODE=1
tags:
......
......@@ -87,10 +87,11 @@ and mbedtls.
* [dieharder](https://www.phy.duke.edu/~rgb/General/dieharder.php) (for testing PRNG)
* [lcov](https://linux-test-project.github.io/) (for code coverage)
* [util-linux](https://github.com/karelzak/util-linux) or just [lscpu](https://github.com/NanXiao/lscpu) (for CPU feature detection)
* [libev](hhttp://software.schmorp.de/pkg/libev.html) (for testing)
Debian/Ubuntu:
```
apt-get install -y valgrind nodejs softhsm2 datefudge lcov libssl-dev libcmocka-dev expect
apt-get install -y valgrind nodejs softhsm2 datefudge lcov libssl-dev libcmocka-dev expect libev-dev
apt-get install -y dieharder openssl abigail-tools socat net-tools ppp lockfile-progs util-linux
```
......@@ -102,7 +103,7 @@ apt-get install -y v libubsan0 libasan1
Fedora/RHEL:
```
yum install -y valgrind libasan libasan-static libubsan nodejs softhsm datefudge lcov openssl-devel expect
yum install -y valgrind libasan libasan-static libubsan nodejs softhsm datefudge lcov openssl-devel expect libev-devel
yum install -y dieharder mbedtls-utils openssl libabigail libcmocka-devel socat lockfile-progs util-linux
```
......
......@@ -433,7 +433,7 @@ AC_ARG_ENABLE(full-test-suite,
# test if we are in git master or in release build. In release
# builds we do not use valgrind.
SUITE_FILE="${srcdir}/tests/suite/mini-eagain2.c"
SUITE_FILE="${srcdir}/tests/suite/prime-check.c"
if test "$full_test_suite" = yes && test ! -f "$SUITE_FILE";then
full_test_suite=no
fi
......@@ -450,6 +450,16 @@ fi
AM_CONDITIONAL(ENABLE_OLDGNUTLS_INTEROP, test "$enable_oldgnutls_interop" != "no")
# check for libev - used in full test suite
AC_LIB_HAVE_LINKFLAGS(ev,, [#include <ev.h>], [ev_run(0,0);])
if test "$ac_cv_libev" = yes; then
AC_SUBST([LIBEV_LIBS], [$LIBEV])
elif test "$full_test_suite" = yes;then
AC_MSG_ERROR([[***
*** libev4 was not found.
***]])
fi
dnl GCC warnings to enable
AC_ARG_ENABLE([gcc-warnings],
......
......@@ -27,9 +27,7 @@ AM_CPPFLAGS = \
-I$(top_builddir)/extra/includes \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/tests \
-I$(top_srcdir)/doc/examples \
-I$(top_srcdir)/tests/suite/ecore/src/include \
-I$(top_srcdir)/tests/suite/ecore/src/lib
-I$(top_srcdir)/doc/examples
EXTRA_DIST = cbc-record-check.sh
......@@ -42,49 +40,6 @@ LDADD = ../../lib/libgnutls.la \
prime_check_LDADD = $(LDADD) -lhogweed -lgmp
libecore_la_CPPFLAGS = -I$(top_srcdir)/tests/suite/ecore/ \
-I$(top_srcdir)/tests/suite/ecore/src/include \
-I$(top_srcdir)/tests/suite/ecore/src/lib -DHAVE_CONFIG_H \
-D__UNUSED__= -DVMAJ=1 -D VMIC=0 -DVMIN=0 -DVREV=0 \
-DEFL_HAVE_POSIX_THREADS=1 -DEFL_HAVE_POSIX_THREADS_SPINLOCK=1 \
-DEFL_HAVE_THREADS=1 -DEINA_BUILD_CHAINED_POOL=1 \
-DEINA_STATIC_BUILD_CHAINED_POOL=1 -DHAVE_CLOCK_GETTIME \
-DHAVE_GETTIMEOFDAY -DPACKAGE_LIB_DIR=\"/usr/lib\" \
-DMODULE_ARCH=\"unix\" -DSHARED_LIB_SUFFIX=\".so\"
libecore_la_CFLAGS = -w
nodist_libecore_la_SOURCES = ecore/src/lib/ecore_anim.c \
ecore/src/lib/ecore_app.c ecore/src/lib/ecore.c \
ecore/src/lib/ecore_events.c ecore/src/lib/ecore_exe.c \
ecore/src/lib/ecore_getopt.c ecore/src/lib/ecore_glib.c \
ecore/src/lib/ecore_idle_enterer.c \
ecore/src/lib/ecore_idle_exiter.c ecore/src/lib/ecore_idler.c \
ecore/src/lib/ecore_job.c ecore/src/lib/ecore_main.c \
ecore/src/lib/ecore_pipe.c ecore/src/lib/ecore_poll.c \
ecore/src/lib/ecore_signal.c ecore/src/lib/ecore_thread.c \
ecore/src/lib/ecore_time.c ecore/src/lib/ecore_timer.c \
ecore/src/lib/eina_accessor.c ecore/src/lib/eina_array.c \
ecore/src/lib/eina_benchmark.c ecore/src/lib/eina_binshare.c \
ecore/src/lib/eina_chained_mempool.c \
ecore/src/lib/eina_convert.c ecore/src/lib/eina_counter.c \
ecore/src/lib/eina_cpu.c ecore/src/lib/eina_error.c \
ecore/src/lib/eina_file.c ecore/src/lib/eina_fp.c \
ecore/src/lib/eina_hamster.c ecore/src/lib/eina_hash.c \
ecore/src/lib/eina_inlist.c ecore/src/lib/eina_iterator.c \
ecore/src/lib/eina_lalloc.c ecore/src/lib/eina_list.c \
ecore/src/lib/eina_log.c ecore/src/lib/eina_magic.c \
ecore/src/lib/eina_main.c ecore/src/lib/eina_matrixsparse.c \
ecore/src/lib/eina_mempool.c ecore/src/lib/eina_module.c \
ecore/src/lib/eina_quadtree.c ecore/src/lib/eina_rbtree.c \
ecore/src/lib/eina_rectangle.c \
ecore/src/lib/eina_safety_checks.c ecore/src/lib/eina_sched.c \
ecore/src/lib/eina_share_common.c ecore/src/lib/eina_strbuf.c \
ecore/src/lib/eina_strbuf_common.c ecore/src/lib/eina_str.c \
ecore/src/lib/eina_stringshare.c ecore/src/lib/eina_tiler.c \
ecore/src/lib/eina_unicode.c ecore/src/lib/eina_ustrbuf.c \
ecore/src/lib/eina_ustringshare.c ecore/src/lib/eina_value.c
EXTRA_DIST += testcompat-main-polarssl testcompat-main-openssl \
testcompat-common params.dh tls-fuzzer/tls-fuzzer-common.sh
......@@ -129,11 +84,9 @@ endif
if !MACOSX
if !WINDOWS
noinst_LTLIBRARIES = libecore.la
mini_record_timing_LDADD = -lrt $(LDADD)
eagain_cli_LDADD = libecore.la -lrt -lm $(LIBDL) -lpthread $(LDADD)
nodist_eagain_cli_SOURCES = mini-eagain2.c
eagain_cli_LDADD = $(LIBEV_LIBS) -lrt -lm $(LIBDL) -lpthread $(LDADD)
nodist_eagain_cli_SOURCES = eagain-cli.c
noinst_PROGRAMS = eagain-cli mini-record-timing
......@@ -141,6 +94,8 @@ scripts_to_test += eagain.sh
endif
endif
nodist_prime_check_SOURCES = prime-check.c
nodist_check_SCRIPTS = $(scripts_to_test)
TESTS = $(scripts_to_test) prime-check
......
/*
* Copyright (C) 2008-2012 Free Software Foundation, Inc.
* Copyright (C) 2018-2020 Red Hat, Inc.
* Copyright (C) 2010 Mike Blumenkrantz
*
* This file is part of GnuTLS.
*
* GnuTLS 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 3 of the License, or
* (at your option) any later version.
*
* GnuTLS 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 <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../utils.h"
#include <gnutls/gnutls.h>
#include <assert.h>
#include <sys/time.h>
#include <ev.h>
static int done = 0;
EV_P;
ev_io remote_w;
gnutls_session_t session;
static const char
*SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status)
{
return gnutls_handshake_description_get_name(status);
}
/* Connects to the peer and returns a socket
* descriptor.
*/
static int tcp_connect(void)
{
const char *PORT = getenv("PORT");
const char *SERVER = "127.0.0.1"; //verisign.com
int err, sd;
int flag = 1, curstate = 0;
struct sockaddr_in sa;
/* sets some fd options such as nonblock */
sd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate,
sizeof(curstate));
memset(&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(atoi(PORT));
inet_pton(AF_INET, SERVER, &sa.sin_addr);
err = connect(sd, (struct sockaddr *)&sa, sizeof(sa));
if ((err < 0) && (errno != EINPROGRESS)) {
fprintf(stderr, "Connect error\n");
exit(1);
}
/* lower the send buffers to force EAGAIN */
assert(setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) >= 0);
assert(fcntl(sd, F_SETFL, O_NONBLOCK)>=0);
return sd;
}
static void tcp_close(int sd)
{
shutdown(sd, SHUT_RDWR); /* no more receptions */
close(sd);
}
/* We provide this helper to ensure that we test EAGAIN while writing
* even on a reliable connection */
static ssize_t
_client_push(gnutls_transport_ptr_t tr, const void *data, size_t len)
{
struct timeval tv;
assert(gettimeofday(&tv, NULL) >= 0);
if (tv.tv_usec % 2 == 0) {
errno = EAGAIN;
return -1;
}
return send((unsigned long)tr, data, len, 0);
}
static ssize_t
_client_pull(gnutls_transport_ptr_t tr, void *data, size_t len)
{
struct timeval tv;
assert(gettimeofday(&tv, NULL) >= 0);
if (tv.tv_usec % 2 == 0) {
errno = EAGAIN;
return -1;
}
return recv((unsigned long)tr, data, len, 0);
}
static int _client_pull_timeout(gnutls_transport_ptr_t ptr,
unsigned int ms)
{
return gnutls_system_recv_timeout(ptr, ms);
}
static void _process_data(EV_P_ ev_io * w, int revents)
{
static int ret = -1, lastret = 0;
static unsigned int count = 0;
static int prev_direction;
if (!done && (revents & (EV_WRITE|EV_READ))) {
if (lastret == GNUTLS_E_AGAIN) {
if (revents & EV_WRITE) {
assert(prev_direction == 1);
}
if (revents & EV_READ) {
assert(prev_direction == 0);
}
}
lastret = ret;
ret = gnutls_handshake(session);
count++;
if (gnutls_record_get_direction(session)) {
ev_io_stop(EV_A_ &remote_w);
ev_io_set(&remote_w, gnutls_transport_get_int(session), EV_WRITE);
ev_io_start(EV_A_ &remote_w);
prev_direction = 1;
} else {
ev_io_stop(EV_A_ &remote_w);
ev_io_set(&remote_w, gnutls_transport_get_int(session), EV_READ);
ev_io_start(EV_A_ &remote_w);
prev_direction = 0;
}
/* avoid printing messages infinity times */
if (lastret != ret && ret != 0 && ret != GNUTLS_E_AGAIN) {
fprintf(stderr, "gnutls returned with: %s - %s\n",
gnutls_strerror_name(ret),
gnutls_strerror(ret));
if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
|| (ret == GNUTLS_E_FATAL_ALERT_RECEIVED))
fprintf(stderr, "Also received alert: %s\n",
gnutls_alert_get_name
(gnutls_alert_get(session)));
fprintf(stderr, "last out: %s\n",
SSL_GNUTLS_PRINT_HANDSHAKE_STATUS
(gnutls_handshake_get_last_out(session)));
fprintf(stderr, "last in: %s\n",
SSL_GNUTLS_PRINT_HANDSHAKE_STATUS
(gnutls_handshake_get_last_in(session)));
}
if (gnutls_error_is_fatal(ret)) {
fprintf(stderr, "yarrr this be an error!");
exit(1);
}
}
if (ret == GNUTLS_E_SUCCESS) {
count = 0;
ret = -1;
done = 1;
lastret = 0;
ev_io_stop(EV_A_ & remote_w);
}
return;
}
static void try(const char *name, const char *prio)
{
gnutls_certificate_credentials_t c_certcred;
int sd, i, ret;
global_init();
gnutls_certificate_allocate_credentials(&c_certcred);
printf("%s: testing priority %s\n", name, prio);
loop = EV_DEFAULT;
for (i = 0; i < 4; i++) {
done = 0;
assert(gnutls_init(&session, GNUTLS_CLIENT) >= 0);
gnutls_transport_set_push_function(session, _client_push);
gnutls_transport_set_pull_function(session, _client_pull);
gnutls_transport_set_pull_timeout_function(session, _client_pull_timeout);
gnutls_handshake_set_timeout(session,
GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
assert(gnutls_priority_set_direct(session, prio, NULL) >= 0);
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
c_certcred);
gnutls_server_name_set(session, GNUTLS_NAME_DNS,
"localhost", strlen("localhost"));
sd = tcp_connect();
/* associate gnutls with socket */
gnutls_transport_set_int(session, sd);
/* add a callback for data being available for send/receive on socket */
ev_io_init(&remote_w, _process_data, sd, EV_WRITE);
ev_io_start(EV_A_ & remote_w);
/* begin main loop */
ev_loop(EV_A_ 0);
do {
ret = gnutls_bye(session, GNUTLS_SHUT_RDWR);
} while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
gnutls_deinit(session);
session = NULL;
tcp_close(sd);
}
ev_loop_destroy(loop);
gnutls_certificate_free_credentials(c_certcred);
return;
}
int main(void)
{
try("tls 1.2 (dhe)", "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-RSA");
try("tls 1.2 (rsa)", "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2:-KX-ALL:+RSA");
try("tls 1.3", "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3");
try("default", "NORMAL");
return 0;
}
......@@ -33,7 +33,10 @@ SERV="${SERV} -q"
eval "${GETPORT}"
launch_server $$ --echo --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2:+ANON-DH" --dhparams "${srcdir}/params.dh"
KEY1=${srcdir}/../../doc/credentials/x509/key-rsa.pem
CERT1=${srcdir}/../../doc/credentials/x509/cert-rsa.pem
launch_server $$ --echo --x509keyfile ${KEY1} --x509certfile ${CERT1}
PID=$!
wait_server ${PID}
......
/* EINA - EFL data type library
* Copyright (C) 2008 Cedric Bail
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef EINA_CONFIG_H_
#define EINA_CONFIG_H_
#ifdef EINA_MAGIC_DEBUG
#undef EINA_MAGIC_DEBUG
#endif
#define EINA_MAGIC_DEBUG
#ifdef EINA_DEFAULT_MEMPOOL
#undef EINA_DEFAULT_MEMPOOL
#endif
#ifdef EINA_SAFETY_CHECKS
#undef EINA_SAFETY_CHECKS
#endif
#define EINA_SAFETY_CHECKS
#ifdef EINA_HAVE_INTTYPES_H
#undef EINA_HAVE_INTTYPES_H
#endif
#define EINA_HAVE_INTTYPES_H
#ifdef EINA_HAVE_STDINT_H
#undef EINA_HAVE_STDINT_H
#endif
#define EINA_HAVE_STDINT_H
#ifdef EINA_SIZEOF_WCHAR_T
#undef EINA_SIZEOF_WCHAR_T
#endif
#define EINA_SIZEOF_WCHAR_T 4
#endif /* EINA_CONFIG_H_ */
/* EINA - EFL data type library
* Copyright (C) 2008-2010 Enlightenment Developers:
* Albin "Lutin" Tonnerre <albin.tonnerre@gmail.com>
* Alexandre "diaxen" Becoulet <diaxen@free.fr>
* Andre Dieb <andre.dieb@gmail.com>
* Arnaud de Turckheim "quarium" <quarium@gmail.com>
* Carsten Haitzler <raster@rasterman.com>
* Cedric Bail <cedric.bail@free.fr>
* Corey "atmos" Donohoe <atmos@atmos.org>
* Fabiano Fidêncio <fidencio@profusion.mobi>
* Gustavo Chaves <glima@profusion.mobi>
* Gustavo Sverzut Barbieri <barbieri@gmail.com>
* Jorge Luis "turran" Zapata <jorgeluis.zapata@gmail.com>
* Peter "pfritz" Wehrfritz <peter.wehrfritz@web.de>
* Raphael Kubo da Costa <kubo@profusion.mobi>
* Tilman Sauerbeck <tilman@code-monkey.de>
* Vincent "caro" Torri <vtorri at univ-evry dot fr>
* Tom Hacohen <tom@stosb.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef EINA_H_
#define EINA_H_
/**
* @mainpage Eina
*
* @author Albin "Lutin" Tonnerre <albin.tonnerre@@gmail.com>
* @author Alexandre "diaxen" Becoulet <diaxen@@free.fr>
* @author Andre Dieb <andre.dieb@@gmail.com>
* @author Arnaud de Turckheim "quarium" <quarium@@gmail.com>
* @author Carsten Haitzler <raster@@rasterman.com>
* @author Cedric Bail <cedric.bail@@free.fr>
* @author Corey "atmos" Donohoe <atmos@@atmos.org>
* @author Fabiano Fidêncio <fidencio@@profusion.mobi>
* @author Gustavo Chaves <glima@@profusion.mobi>
* @author Gustavo Sverzut Barbieri <barbieri@@profusion.mobi>
* @author Jorge Luis "turran" Zapata <jorgeluis.zapata@@gmail.com>
* @author Peter "pfritz" Wehrfritz <peter.wehrfritz@@web.de>
* @author Raphael Kubo da Costa <kubo@@profusion.mobi>
* @author Tilman Sauerbeck <tilman@@code-monkey.de>
* @author Vincent "caro" Torri <vtorri at univ-evry dot fr>
* @author Tom Hacohen <tom@@stosb.com>
* @date 2008-2010
*
* @section eina_intro_sec Introduction
*
* The Eina library is a library that implements an API for data types
* in an efficient way. It also provides some useful tools like
* openin shared libraries, errors management, type conversion,
* time accounting and memory pool.
*
* This library is cross-platform and can be compiled and used on
* Linux, BSD, Opensolaris and Windows (XP and CE).
*
* The data types that are available are (see @ref Eina_Data_Types_Group):
* @li @ref Eina_Array_Group standard array of @c void* data.
* @li @ref Eina_Hash_Group standard hash of @c void* data.
* @li @ref Eina_Inline_List_Group list with nodes inlined into user type.
* @li @ref Eina_List_Group standard list of @c void* data.
* @li @ref Eina_Matrixsparse_Group sparse matrix of @c void* data.
* @li @ref Eina_Rbtree_Group red-black tree with nodes inlined into user type.
* @li @ref Eina_String_Buffer_Group mutable string to prepend, insert or append strings to a buffer.
* @li @ref Eina_Stringshare_Group saves memory by sharing read-only string references.
* @li @ref Eina_Tiler_Group split, merge and navigates into 2D tiled regions.
* @li @ref Eina_Trash_Group container of unused but allocated data.
*
* The tools that are available are (see @ref Eina_Tools_Group):
* @li @ref Eina_Benchmark_Group helper to write benchmarks.
* @li @ref Eina_Convert_Group faster conversion from strings to integers, double, etc.
* @li @ref Eina_Counter_Group measures number of calls and their time.
* @li @ref Eina_Error_Group error identifiers.
* @li @ref Eina_File_Group simple file list and path split.
* @li @ref Eina_Lalloc_Group simple lazy allocator.
* @li @ref Eina_Log_Group full-featured logging system.
* @li @ref Eina_Magic_Group provides runtime type checking.
* @li @ref Eina_Memory_Pool_Group abstraction for various memory allocators.
* @li @ref Eina_Module_Group lists, loads and share modules using Eina_Module standard.
* @li @ref Eina_Rectangle_Group rectangle structure and standard manipulation methods.
* @li @ref Eina_Safety_Checks_Group extra checks that will report unexpected conditions and can be disabled at compile time.
* @li @ref Eina_String_Group a set of functions that manages C strings.
*
* @defgroup Eina_Data_Types_Group Data types.
*
* Eina provide easy to use and optimized data types and structures.
*
*
* @defgroup Eina_Containers_Group Containers
*
* Containers are data types that hold data and allow iteration over
* their elements with an @ref Eina_Iterator_Group, or eventually an
* @ref Eina_Accessor_Group.
*
*
* @defgroup Eina_Tools_Group Tools
*
* Eina tools aims to help application development, providing ways to
* make it safer, log errors, manage memory more efficiently and more.
*/
#include <dirent.h>
#ifdef _WIN32
#include <Evil.h>
#endif
#ifdef __cplusplus