mirror of https://github.com/oxen-io/lokinet
Merge branch 'master' of https://github.com/loki-project/loki-network
This commit is contained in:
commit
4b3b09736b
126
CMakeLists.txt
126
CMakeLists.txt
|
@ -13,22 +13,14 @@ endmacro(add_cxxflags)
|
|||
|
||||
include(CheckCXXCompilerFlag)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
||||
if (MSVC)
|
||||
CHECK_CXX_COMPILER_FLAG("/std:c++17" COMPILER_SUPPORTS_CXX17)
|
||||
else()
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
|
||||
endif()
|
||||
|
||||
option(HAVE_CXX17_FILESYSTEM "Disable if your C++ compiler and runtime library lacks std::[experimental::]filesystem" ON)
|
||||
|
||||
if(COMPILER_SUPPORTS_CXX11 AND NOT HAVE_CXX17_FILESYSTEM)
|
||||
add_cxxflags("-std=c++11")
|
||||
elseif(COMPILER_SUPPORTS_CXX17 AND HAVE_CXX17_FILESYSTEM)
|
||||
if (MSVC)
|
||||
add_cxxflags("/std:c++17")
|
||||
else()
|
||||
add_cxxflags("-std=c++17")
|
||||
endif()
|
||||
add_definitions(-DUSE_CXX17_FILESYSTEM)
|
||||
else()
|
||||
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 or C++17 support. Please use a different C++ compiler.")
|
||||
|
@ -36,30 +28,26 @@ endif()
|
|||
|
||||
add_cxxflags("-fpermissive")
|
||||
|
||||
if (WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE)
|
||||
if (USING_CLANG)
|
||||
add_cxxflags("-Wno-unused-command-line-argument -Wno-c++11-narrowing")
|
||||
add_cflags("-Wno-unused-command-line-argument")
|
||||
# because clang is insane enough to inline whole sections of the C++ library!
|
||||
# May have been fixed in llvm-7.
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-multiple-definition --rtlib=libgcc")
|
||||
endif(USING_CLANG)
|
||||
endif()
|
||||
|
||||
if(DEBIAN)
|
||||
add_definitions(-DDEBIAN)
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
set(THREAD_LIB "-pthread")
|
||||
# finally removed pthread dependency for MSC++
|
||||
elseif(MSVC)
|
||||
set(THREAD_LIB)
|
||||
else()
|
||||
set(THREAD_LIB pthread)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
option (BUILD_AVX2 "Enable AVX2 FPU vector instructions." OFF)
|
||||
if (BUILD_AVX2)
|
||||
add_cflags("/arch:AVX2")
|
||||
add_cxxflags("/arch:AVX2")
|
||||
else()
|
||||
add_cflags("/arch:SSE2")
|
||||
add_cxxflags("/arch:SSE2")
|
||||
endif(BUILD_AVX2)
|
||||
endif()
|
||||
|
||||
if(STATIC_LINK)
|
||||
add_cflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
|
||||
add_cxxflags("-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
|
||||
|
@ -75,18 +63,11 @@ else()
|
|||
set(WITH_STATIC ON)
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
add_cflags("-Wall")
|
||||
add_cxxflags("-Wall")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
set(OPTIMIZE_FLAGS "-Od")
|
||||
set(DEBUG_FLAGS "-ZI")
|
||||
else()
|
||||
set(OPTIMIZE_FLAGS "-O0")
|
||||
set(DEBUG_FLAGS "-g")
|
||||
endif()
|
||||
set(OPTIMIZE_FLAGS "-O3")
|
||||
set(DEBUG_FLAGS "-O0 -g3")
|
||||
|
||||
if(ASAN)
|
||||
set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
|
@ -112,19 +93,15 @@ if(SHADOW)
|
|||
include_directories(${SHADOW_ROOT}/include)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
add_cflags("-wd4996 -wd4244 -MP ${OPTIMIZE_FLAGS}")
|
||||
add_cxxflags("-wd4996 -wd4244 -MP ${OPTIMIZE_FLAGS}")
|
||||
else()
|
||||
add_cflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
|
||||
add_cxxflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
|
||||
set(OPTIMIZE_FLAGS "")
|
||||
add_cflags("${DEBUG_FLAGS}")
|
||||
add_cxxflags("${DEBUG_FLAGS}")
|
||||
endif()
|
||||
|
||||
add_cflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
|
||||
add_cxxflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
|
||||
|
||||
if(SHADOW)
|
||||
add_cflags("-fPIC")
|
||||
add_cxxflags("-fPIC")
|
||||
|
@ -156,6 +133,11 @@ else()
|
|||
)
|
||||
endif()
|
||||
|
||||
# HeapAlloc(2) on Windows was significantly revamped in 2009
|
||||
# but the old algorithm isn't too bad either
|
||||
# this is _the_ system allocator on BSD UNIX
|
||||
# openbsd replaced it with a secure/randomised malloc not too
|
||||
# long ago
|
||||
if(JEMALLOC)
|
||||
set(MALLOC_LIB jemalloc)
|
||||
endif()
|
||||
|
@ -210,16 +192,12 @@ set(LIBTUNTAP_SRC_BASE
|
|||
${LIBTUNTAP_IMPL})
|
||||
|
||||
if (UNIX)
|
||||
set(LIBTUNTAP_SRC
|
||||
set(LIBTUNTAP_SRC
|
||||
${TT_ROOT}/tuntap-unix.c
|
||||
${LIBTUNTAP_SRC_BASE})
|
||||
endif()
|
||||
|
||||
#if(BACKPORT)
|
||||
#else()
|
||||
#set(CPP_BACKPORT_SRC "")
|
||||
#endif()
|
||||
|
||||
else()
|
||||
set(LIBTUNTAP_SRC ${LIBTUNTAP_SRC_BASE})
|
||||
endif(UNIX)
|
||||
set(CPP_BACKPORT_SRC
|
||||
vendor/cppbackport-master/lib/fs/rename.cpp
|
||||
vendor/cppbackport-master/lib/fs/filestatus.cpp
|
||||
|
@ -248,7 +226,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|||
set(ISOLATE_PROC_SRC llarp/linux/netns.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
set(LIB_PLATFORM_SRC
|
||||
# for outpug
|
||||
llarp/logger.cpp
|
||||
|
@ -270,11 +247,9 @@ set(LIB_PLATFORM_SRC
|
|||
${ISOLATE_PROC_SRC}
|
||||
# tun
|
||||
${LIBTUNTAP_SRC}
|
||||
# win32 inline procs
|
||||
# win32 inline code
|
||||
llarp/win32_inet.c
|
||||
llarp/win32_intrnl.c
|
||||
contrib/msc/getopt.c
|
||||
contrib/msc/getopt1.c
|
||||
)
|
||||
|
||||
set(NTRU_AVX_SRC
|
||||
|
@ -332,7 +307,6 @@ set(UTP_SRC
|
|||
libutp/utp_hash.cpp
|
||||
)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
set(UTP_SRC ${UTP_SRC} libutp/libutp_inet_ntop.cpp)
|
||||
endif()
|
||||
|
@ -456,10 +430,6 @@ include_directories(vendor/cppbackport-master/lib)
|
|||
include_directories(/usr/local/include)
|
||||
include_directories(${sodium_INCLUDE_DIR})
|
||||
|
||||
if (MSVC)
|
||||
include_directories(contrib/msc/include)
|
||||
endif()
|
||||
|
||||
set(RC_EXE rcutil)
|
||||
set(DNS_EXE dns)
|
||||
|
||||
|
@ -469,22 +439,14 @@ add_shadow_plugin(shadow-plugin-${SHARED_LIB} ${EXE_SRC} ${LIB_SRC} ${LIB_PLATFO
|
|||
target_link_libraries(shadow-plugin-${SHARED_LIB} ${LIBS})
|
||||
install(TARGETS shadow-plugin-${SHARED_LIB} DESTINATION plugins)
|
||||
else()
|
||||
add_executable(${RC_EXE} ${RC_SRC})
|
||||
add_executable(${RC_EXE} ${RC_SRC})
|
||||
add_executable(${EXE} ${EXE_SRC})
|
||||
add_executable(${CLIENT_EXE} ${CLIENT_SRC})
|
||||
add_executable(${DNS_EXE} ${DNS_SRC})
|
||||
add_executable(${DNS_EXE} ${DNS_SRC})
|
||||
add_subdirectory(${GTEST_DIR})
|
||||
include_directories(${GTEST_DIR}/include ${GTEST_DIR})
|
||||
add_executable(${TEST_EXE} ${TEST_SRC})
|
||||
|
||||
if (MSVC)
|
||||
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ws2_32 iphlpapi)
|
||||
elseif (MINGW)
|
||||
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} stdc++fs iphlpapi ws2_32)
|
||||
else()
|
||||
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB})
|
||||
endif(MSVC)
|
||||
|
||||
if(WITH_STATIC)
|
||||
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
|
||||
if(NOT HAVE_CXX17_FILESYSTEM)
|
||||
|
@ -505,34 +467,28 @@ if(WITH_STATIC)
|
|||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
|
||||
if (MINGW)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
elseif(MSVC)
|
||||
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB})
|
||||
if (WIN32)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
endif(MINGW)
|
||||
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${BACKPORT_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
endif(WIN32)
|
||||
else()
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB})
|
||||
if (MINGW)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
elseif(MSVC)
|
||||
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${PLATFORM_LIB})
|
||||
if (WIN32)
|
||||
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
target_link_libraries(${RC_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
endif(MINGW)
|
||||
target_link_libraries(${TEST_EXE} ${STATIC_LINK_LIBS} gtest_main ${STATIC_LIB} ${PLATFORM_LIB} ws2_32 iphlpapi)
|
||||
endif(WIN32)
|
||||
endif(NOT HAVE_CXX17_FILESYSTEM)
|
||||
if (MINGW)
|
||||
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB} ws2_32 stdc++fs iphlpapi)
|
||||
elseif(WIN32)
|
||||
if (WIN32)
|
||||
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB} ws2_32 iphlpapi)
|
||||
endif(MINGW)
|
||||
endif(WIN32)
|
||||
target_link_libraries(${DNS_EXE} ${STATIC_LIB} ${PLATFORM_LIB} ${THREAD_LIB})
|
||||
endif(NOT WITH_SHARED)
|
||||
endif(WITH_STATIC)
|
||||
|
@ -546,11 +502,9 @@ if(WITH_STATIC)
|
|||
set(LIB_SRC ${LIB_SRC} ${CPP_BACKPORT_SRC})
|
||||
endif(HAVE_CXX17_FILESYSTEM)
|
||||
add_library(${SHARED_LIB} SHARED ${LIB_SRC} ${LIB_PLATFORM_SRC})
|
||||
if (MINGW)
|
||||
set(${LIBS} ${LIBS} ws2_32 stdc++fs iphlpapi)
|
||||
elseif(MSVC)
|
||||
if (WIN32)
|
||||
set(${LIBS} ${LIBS} ws2_32 iphlpapi)
|
||||
endif(MINGW)
|
||||
endif(WIN32)
|
||||
target_link_libraries(${SHARED_LIB} ${LIBS} ${THREAD_LIB})
|
||||
target_link_libraries(${EXE} ${SHARED_LIB})
|
||||
target_link_libraries(${RC_EXE} ${SHARED_LIB})
|
||||
|
|
1050
contrib/msc/getopt.c
1050
contrib/msc/getopt.c
File diff suppressed because it is too large
Load Diff
|
@ -1,190 +0,0 @@
|
|||
#ifdef _MSC_VER
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#if !defined __STDC__ || !__STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#define GETOPT_INTERFACE_VERSION 2
|
||||
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||
#include <gnu-versions.h>
|
||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||
#define ELIDE_CODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ELIDE_CODE
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* Not ELIDE_CODE. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
||||
#endif /* _MSC_VER */
|
|
@ -1,157 +0,0 @@
|
|||
#ifdef _MSC_VER
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
|
||||
#ifndef __need_getopt
|
||||
# define _GETOPT_H 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns -1, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
#ifndef __need_getopt
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
# if defined __STDC__ && __STDC__
|
||||
const char *name;
|
||||
# else
|
||||
char *name;
|
||||
# endif
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
# define no_argument 0
|
||||
# define required_argument 1
|
||||
# define optional_argument 2
|
||||
#endif /* need getopt */
|
||||
|
||||
|
||||
/* Get definitions and prototypes for functions to process the
|
||||
arguments in ARGV (ARGC of them, minus the program name) for
|
||||
options given in OPTS.
|
||||
|
||||
Return the option character from OPTS just read. Return -1 when
|
||||
there are no more options. For unrecognized options, or options
|
||||
missing arguments, `optopt' is set to the option letter, and '?' is
|
||||
returned.
|
||||
|
||||
The OPTS string is a list of characters which are recognized option
|
||||
letters, optionally followed by colons, specifying that that letter
|
||||
takes an argument, to be placed in `optarg'.
|
||||
|
||||
If a letter in OPTS is followed by two colons, its argument is
|
||||
optional. This behavior is specific to the GNU `getopt'.
|
||||
|
||||
The argument `--' causes premature termination of argument
|
||||
scanning, explicitly telling `getopt' that there are no more
|
||||
options.
|
||||
|
||||
If OPTS begins with `--', then non-option arguments are treated as
|
||||
arguments to the option '\0'. This behavior is specific to the GNU
|
||||
`getopt'. */
|
||||
|
||||
/* Many other libraries have conflicting prototypes for getopt, with
|
||||
differences in the consts, in stdlib.h. To avoid compilation
|
||||
errors, only prototype getopt for the GNU C library. */
|
||||
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
|
||||
|
||||
# ifndef __need_getopt
|
||||
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind);
|
||||
extern int getopt_long_only (int __argc, char *const *__argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind);
|
||||
|
||||
/* Internal only. Users should not call this directly. */
|
||||
extern int _getopt_internal (int __argc, char *const *__argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only);
|
||||
# endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure we later can get all the definitions and declarations. */
|
||||
#undef __need_getopt
|
||||
|
||||
#endif /* getopt.h */
|
||||
#endif /* _MSC_VER */
|
|
@ -4,7 +4,9 @@
|
|||
#include <getopt.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#ifndef _MSC_VER
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
#include "fs.hpp"
|
||||
#include "config.hpp" // for ensure_config
|
||||
|
||||
|
@ -29,6 +31,25 @@ printHelp(const char *argv0, int code = 1)
|
|||
return code;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int
|
||||
startWinsock()
|
||||
{
|
||||
WSADATA wsockd;
|
||||
int err;
|
||||
// We used to defer starting winsock until
|
||||
// we got to the iocp event loop
|
||||
// but getaddrinfo(3) requires that winsock be in core already
|
||||
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
|
||||
if(err)
|
||||
{
|
||||
perror("Failed to start Windows Sockets");
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -39,6 +60,11 @@ main(int argc, char *argv[])
|
|||
multiThreaded = false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if(startWinsock())
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
int opt = 0;
|
||||
bool genconfigOnly = false;
|
||||
bool asRouter = true;
|
||||
|
@ -106,7 +132,9 @@ main(int argc, char *argv[])
|
|||
fs::path fpath = basepath / "lokinet.ini";
|
||||
|
||||
std::error_code ec;
|
||||
if(!fs::create_directories(basepath, ec))
|
||||
// These paths are guaranteed to exist - $APPDATA or $HOME
|
||||
// so only create .lokinet/*
|
||||
if(!fs::create_directory(basepath, ec))
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
|
@ -136,6 +164,9 @@ main(int argc, char *argv[])
|
|||
code = llarp_main_run(ctx);
|
||||
llarp_main_free(ctx);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
::WSACleanup();
|
||||
#endif
|
||||
exit(code);
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <llarp/net.hpp> // for llarp::Addr
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
#include <llarp/net.hpp>
|
||||
|
||||
#ifndef _WIN32
|
||||
// unix, linux
|
||||
#include <sys/types.h> // FreeBSD needs this for uchar for ip.h
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#else
|
||||
// windows nt
|
||||
#include <winsock2.h>
|
||||
// Apparently this does not seem to be located _anywhere_ in the windows sdk???
|
||||
// -despair86
|
||||
typedef struct ip_hdr
|
||||
{
|
||||
unsigned char
|
||||
|
@ -46,16 +46,7 @@ typedef struct ip_hdr
|
|||
|
||||
#include <memory>
|
||||
|
||||
#if !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) \
|
||||
&& !defined(__FreeBSD__)
|
||||
#define iphdr ip
|
||||
#define saddr ip_src.s_addr
|
||||
#define daddr ip_dst.s_addr
|
||||
#define ip_version ip_v
|
||||
#define check ip_sum
|
||||
#define ihl ip_hl
|
||||
#endif
|
||||
|
||||
// anything not win32
|
||||
struct ip_header
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
|
|
@ -10,9 +10,16 @@
|
|||
#include <stdlib.h> // for itoa
|
||||
|
||||
// for addrinfo
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <wspiapi.h>
|
||||
#define inet_aton(x, y) inet_pton(AF_INET, x, y)
|
||||
#endif
|
||||
|
||||
bool
|
||||
operator==(const sockaddr& a, const sockaddr& b);
|
||||
|
@ -466,7 +473,7 @@ namespace llarp
|
|||
isOneSevenPrivate(uint32_t byte)
|
||||
{
|
||||
uint8_t byte1 = byte >> 24 & 0xff;
|
||||
uint8_t byte2 = (0x00ff0000 & byte >> 16);
|
||||
uint8_t byte2 = (0x00ff0000 & byte) >> 16;
|
||||
return byte1 == 172 && (byte2 >= 16 || byte2 <= 31);
|
||||
}
|
||||
|
||||
|
@ -474,7 +481,7 @@ namespace llarp
|
|||
isOneNinePrivate(uint32_t byte)
|
||||
{
|
||||
uint8_t byte1 = byte >> 24 & 0xff;
|
||||
uint8_t byte2 = (0x00ff0000 & byte >> 16);
|
||||
uint8_t byte2 = (0x00ff0000 & byte) >> 16;
|
||||
return byte1 == 192 && byte2 == 168;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,11 @@ namespace llarp
|
|||
llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
|
||||
llarp_proto_version_t version;
|
||||
|
||||
bool IsEndpoint(const RouterID & us) const
|
||||
{
|
||||
return info.upstream == us;
|
||||
}
|
||||
|
||||
llarp_time_t
|
||||
ExpireTime() const;
|
||||
llarp::routing::InboundMessageParser m_MessageParser;
|
||||
|
|
|
@ -113,6 +113,12 @@ namespace llarp
|
|||
Path*
|
||||
GetPathByID(const PathID_t& id) const;
|
||||
|
||||
bool
|
||||
GetCurrentIntroductionsWithFilter(
|
||||
std::set< llarp::service::Introduction >& intros,
|
||||
std::function< bool(const llarp::service::Introduction&) > filter)
|
||||
const;
|
||||
|
||||
bool
|
||||
GetCurrentIntroductions(
|
||||
std::set< llarp::service::Introduction >& intros) const;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <llarp/service/tag.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -60,6 +61,7 @@ namespace llarp
|
|||
IntroSet&
|
||||
operator=(const IntroSet& other)
|
||||
{
|
||||
I.clear();
|
||||
A = other.A;
|
||||
I = other.I;
|
||||
K = other.K;
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace llarp
|
|||
llarp_tun_io *
|
||||
getRange();
|
||||
|
||||
bool
|
||||
AddDefaultEndpoint(const std::string & ifaddr, const std::string & ifname);
|
||||
|
||||
/// hint at possible path usage and trigger building early
|
||||
bool
|
||||
Prefetch(const llarp::service::Address &addr);
|
||||
|
|
|
@ -187,6 +187,7 @@ namespace llarp
|
|||
llarp::SharedSecret sharedKey;
|
||||
ServiceInfo remoteIdent;
|
||||
Introduction remoteIntro;
|
||||
ConvoTag currentConvoTag;
|
||||
PathSet* m_PathSet;
|
||||
IDataHandler* m_DataHandler;
|
||||
Endpoint* m_Endpoint;
|
||||
|
@ -351,7 +352,7 @@ namespace llarp
|
|||
|
||||
protected:
|
||||
void
|
||||
RegenAndPublishIntroSet(llarp_time_t now);
|
||||
RegenAndPublishIntroSet(llarp_time_t now, bool forceRebuild = false);
|
||||
|
||||
IServiceLookup*
|
||||
GenerateLookupByTag(const Tag& tag);
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace llarp
|
|||
|
||||
/// determine if this request has timed out
|
||||
bool
|
||||
IsTimedOut(llarp_time_t now, llarp_time_t timeout = 5000) const
|
||||
IsTimedOut(llarp_time_t now, llarp_time_t timeout = 10000) const
|
||||
{
|
||||
if(now <= m_created)
|
||||
return false;
|
||||
|
|
|
@ -92,7 +92,7 @@ typedef struct in6_addr t_tun_in6_addr;
|
|||
* Windows helpers
|
||||
*/
|
||||
#if defined Windows
|
||||
#define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z));
|
||||
//#define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z));
|
||||
#define strdup(x) _strdup(x)
|
||||
#endif
|
||||
|
||||
|
@ -119,10 +119,12 @@ typedef struct in6_addr t_tun_in6_addr;
|
|||
|
||||
/* Handle Windows symbols export */
|
||||
#if defined Windows
|
||||
#if defined(tuntap_EXPORTS) /* CMake generated goo */
|
||||
#if defined(tuntap_EXPORTS) && defined(_USRDLL) /* CMake generated goo */
|
||||
#define TUNTAP_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#elif defined(tuntap_EXPORTS)
|
||||
#define TUNTAP_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define TUNTAP_EXPORT extern
|
||||
#endif
|
||||
#else /* Unix */
|
||||
#define TUNTAP_EXPORT extern
|
||||
|
|
|
@ -30,19 +30,21 @@
|
|||
|
||||
// we already have our own definition of these
|
||||
// -despair
|
||||
namespace {
|
||||
extern "C" {
|
||||
const char* inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
int inet_pton(int af, const char *src, void *dst);
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
const char *libutp::inet_ntop(int af, const void *src, char *dest, size_t length)
|
||||
{
|
||||
return inet_ntop(af, src, dest, length);
|
||||
return ::inet_ntop(af, src, dest, length);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
int libutp::inet_pton(int af, const char* src, void* dest)
|
||||
{
|
||||
return inet_pton(af, src, dest);
|
||||
return ::inet_pton(af, src, dest);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
bool
|
||||
bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz)
|
||||
{
|
||||
if(!llarp_buffer_writef(buff, "%ld:", sz))
|
||||
if(!llarp_buffer_writef(buff, "%zu:", sz))
|
||||
return false;
|
||||
return llarp_buffer_write(buff, data, sz);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ bencode_write_bytestring(llarp_buffer_t* buff, const void* data, size_t sz)
|
|||
bool
|
||||
bencode_write_uint64(llarp_buffer_t* buff, uint64_t i)
|
||||
{
|
||||
return llarp_buffer_writef(buff, "i%lu", i)
|
||||
return llarp_buffer_writef(buff, "i%llu", i)
|
||||
&& llarp_buffer_write(buff, "e", 1);
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result)
|
|||
buffer->cur++;
|
||||
|
||||
numbuf[len] = 0;
|
||||
*result = strtoul(numbuf, nullptr, 10);
|
||||
*result = strtoull(numbuf, nullptr, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,11 @@ llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
|
|||
if(basedir)
|
||||
{
|
||||
basepath = basedir;
|
||||
#ifndef _WIN32
|
||||
basepath += "/";
|
||||
#else
|
||||
basepath += "\\";
|
||||
#endif
|
||||
}
|
||||
|
||||
// abort if client.ini already exists
|
||||
|
@ -94,7 +98,7 @@ llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
|
|||
llarp_generic_ensure_config(f, basepath);
|
||||
if(asRouter)
|
||||
{
|
||||
llarp_ensure_router_config(f);
|
||||
llarp_ensure_router_config(f, basepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -164,24 +168,41 @@ llarp_generic_ensure_config(std::ofstream &f, std::string basepath)
|
|||
}
|
||||
|
||||
void
|
||||
llarp_ensure_router_config(std::ofstream &f)
|
||||
llarp_ensure_router_config(std::ofstream &f, std::string basepath)
|
||||
{
|
||||
f << "# ROUTERS ONLY: router settings block" << std::endl;
|
||||
f << "# router settings block" << std::endl;
|
||||
f << "[router]" << std::endl;
|
||||
f << "# uncomment these to manually set public address and port" << std::endl;
|
||||
f << "# uncomment these to manually set public address and port"
|
||||
<< std::endl;
|
||||
f << "# this is required on providers like AWS because of their firewall "
|
||||
"rules"
|
||||
<< std::endl;
|
||||
f << "# public-address=your.ip.goes.here" << std::endl;
|
||||
f << "# public-port=1090" << std::endl;
|
||||
f << std::endl;
|
||||
f << "# number of crypto worker threads " << std::endl;
|
||||
f << "threads=4" << std::endl;
|
||||
f << "# path to store signed RC" << std::endl;
|
||||
f << "contact-file=" << basepath << "self.signed" << std::endl;
|
||||
f << "# path to store transport private key" << std::endl;
|
||||
f << "transport-privkey=" << basepath << "transport.private" << std::endl;
|
||||
f << "# path to store identity signing key" << std::endl;
|
||||
f << "ident-privkey=" << basepath << "identity.private" << std::endl;
|
||||
f << "# encryption key for onion routing" << std::endl;
|
||||
f << "encryption-privkey=" << basepath << "encryption.private" << std::endl;
|
||||
f << std::endl;
|
||||
f << "# uncomment following line to set router nickname to 'lokinet'"
|
||||
<< std::endl;
|
||||
f << "# nickname=lokinet" << std::endl;
|
||||
f << std::endl << std::endl;
|
||||
|
||||
|
||||
f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic"
|
||||
<< std::endl;
|
||||
f << "[bind]" << std::endl;
|
||||
|
||||
// get ifname
|
||||
std::string ifname;
|
||||
|
||||
if(llarp::GetBestNetIF(ifname, AF_INET))
|
||||
f << ifname << "=1090" << std::endl;
|
||||
else
|
||||
|
@ -195,17 +216,32 @@ bool
|
|||
llarp_ensure_client_config(std::ofstream &f, std::string basepath)
|
||||
{
|
||||
f << "# ROUTERS ONLY: router settings block" << std::endl;
|
||||
f << "# router settings block" << std::endl;
|
||||
f << "[router]" << std::endl;
|
||||
f << "# uncomment these to manually set public address and port" << std::endl;
|
||||
f << "# uncomment these to manually set public address and port"
|
||||
<< std::endl;
|
||||
f << "# this is required on providers like AWS because of their firewall "
|
||||
"rules"
|
||||
<< std::endl;
|
||||
f << "# public-address=your.ip.goes.here" << std::endl;
|
||||
f << "# public-port=1090" << std::endl;
|
||||
f << "#public-address=your.ip.goes.here" << std::endl;
|
||||
f << "#public-port=1090" << std::endl;
|
||||
f << std::endl;
|
||||
|
||||
f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic"
|
||||
f << "# number of crypto worker threads " << std::endl;
|
||||
f << "#threads=4" << std::endl;
|
||||
f << "# path to store signed RC" << std::endl;
|
||||
f << "#contact-file=" << basepath << "self.signed" << std::endl;
|
||||
f << "# path to store transport private key" << std::endl;
|
||||
f << "#transport-privkey=" << basepath << "transport.private" << std::endl;
|
||||
f << "# path to store identity signing key" << std::endl;
|
||||
f << "#ident-privkey=" << basepath << "identity.private" << std::endl;
|
||||
f << "# encryption key for onion routing" << std::endl;
|
||||
f << "#encryption-privkey=" << basepath << "encryption.private" << std::endl;
|
||||
f << std::endl;
|
||||
f << "# uncomment following line to set router nickname to 'lokinet'"
|
||||
<< std::endl;
|
||||
f << "#nickname=lokinet" << std::endl;
|
||||
f << std::endl << std::endl;
|
||||
|
||||
f << "[bind]" << std::endl;
|
||||
std::string ifname;
|
||||
|
||||
|
@ -220,6 +256,13 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
|
|||
f << "client=" << basepath << "client.ini" << std::endl;
|
||||
f << std::endl;
|
||||
|
||||
f << "# network settings " << std::endl;
|
||||
f << "[network]" << std::endl;
|
||||
#ifndef __linux__
|
||||
f << "# ";
|
||||
#endif
|
||||
|
||||
/*
|
||||
// done with fname.ini
|
||||
// start client.ini
|
||||
// write fname ini
|
||||
|
@ -231,6 +274,7 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
|
|||
}
|
||||
clientini_f << "[client-hidden-service-name]" << std::endl;
|
||||
clientini_f << "keyfile=client-keyfile.private" << std::endl;
|
||||
*/
|
||||
|
||||
// pick ip
|
||||
struct privatesInUse ifsInUse = llarp_getPrivateIfs();
|
||||
|
@ -255,7 +299,7 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
|
|||
}
|
||||
llarp::LogDebug("Detected " + ip
|
||||
+ " is available for use, configuring as such");
|
||||
clientini_f << "ifaddr=" << ip << std::endl;
|
||||
//clientini_f << "ifaddr=" << ip << std::endl;
|
||||
// pick interface name
|
||||
uint8_t num = 0;
|
||||
while(num < 255)
|
||||
|
@ -276,12 +320,18 @@ llarp_ensure_client_config(std::ofstream &f, std::string basepath)
|
|||
llarp::LogError("Could not find any free lokitun interface names");
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
clientini_f << "ifname=lokinum" << std::to_string(num) << std::endl;
|
||||
// prefetch-tags=test
|
||||
// enable netns?
|
||||
|
||||
llarp::LogInfo("Generated hidden service client as " + basepath
|
||||
+ "client.ini");
|
||||
*/
|
||||
|
||||
f << "ifname=lokinum" << std::to_string(num) << std::endl;
|
||||
f << "ifaddr=" << ip << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ void
|
|||
llarp_generic_ensure_config(std::ofstream &f, std::string basepath);
|
||||
|
||||
void
|
||||
llarp_ensure_router_config(std::ofstream &f);
|
||||
llarp_ensure_router_config(std::ofstream &f, std::string basepath);
|
||||
|
||||
bool
|
||||
llarp_ensure_client_config(std::ofstream &f, std::string basepath);
|
||||
|
|
|
@ -471,8 +471,8 @@ raw_resolve_host(struct dnsc_context *dnsc, const char *url,
|
|||
llarp::LogInfo("Waiting for recv");
|
||||
|
||||
// Timeout?
|
||||
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0, (struct sockaddr *)&addr,
|
||||
&size);
|
||||
ret = recvfrom(sockfd, (char *)buffer, DNC_BUF_SIZE, 0,
|
||||
(struct sockaddr *)&addr, &size);
|
||||
llarp::LogInfo("recv done ", size);
|
||||
if(ret < 0)
|
||||
{
|
||||
|
|
|
@ -121,5 +121,5 @@ bool
|
|||
llarp_ev_tun_async_write(struct llarp_tun_io *tun, const void *pkt, size_t sz)
|
||||
{
|
||||
// TODO: queue write
|
||||
return static_cast< llarp::ev_io * >(tun->impl)->do_write((void*)pkt, sz);
|
||||
return static_cast< llarp::ev_io * >(tun->impl)->do_write((void *)pkt, sz);
|
||||
}
|
||||
|
|
174
llarp/ev.hpp
174
llarp/ev.hpp
|
@ -1,8 +1,10 @@
|
|||
#ifndef LLARP_EV_HPP
|
||||
#define LLARP_EV_HPP
|
||||
#include <llarp/ev.h>
|
||||
// witev
|
||||
// writev
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
|
@ -42,104 +44,98 @@ namespace llarp
|
|||
sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
|
||||
|
||||
/// used for tun interface
|
||||
bool
|
||||
virtual bool
|
||||
do_write(void* data, size_t sz)
|
||||
{
|
||||
iovec vecs[2];
|
||||
// TODO: IPV6
|
||||
uint32_t t = htonl(AF_INET);
|
||||
vecs[0].iov_base = &t;
|
||||
vecs[0].iov_len = sizeof(t);
|
||||
vecs[1].iov_base = data;
|
||||
vecs[1].iov_len = sz;
|
||||
return writev(fd, vecs, 2) != -1;
|
||||
#ifndef _WIN32
|
||||
return write(fd, data, sz) != -1;
|
||||
#else
|
||||
return WriteFile((void*)fd, data, sz, nullptr, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// called in event loop when fd is ready for writing
|
||||
/// requeues anything not written
|
||||
/// this assumes fd is set to non blocking
|
||||
virtual void
|
||||
flush_write()
|
||||
{
|
||||
m_writeq.Process([&](WriteBuffer& buffer) {
|
||||
// todo: wtf???
|
||||
#ifndef _WIN32
|
||||
do_write(buffer.buf, buffer.bufsz);
|
||||
// if we would block we save the entries for later
|
||||
|
||||
// discard entry
|
||||
#else
|
||||
// writefile
|
||||
|
||||
/// called in event loop when fd is ready for writing
|
||||
/// requeues anything not written
|
||||
/// this assumes fd is set to non blocking
|
||||
virtual void
|
||||
flush_write()
|
||||
{
|
||||
m_writeq.Process([&](WriteBuffer& buffer) {
|
||||
do_write(buffer.buf, buffer.bufsz);
|
||||
// if we would block we save the entries for later
|
||||
// discard entry
|
||||
});
|
||||
/// reset errno
|
||||
errno = 0;
|
||||
#if _WIN32
|
||||
SetLastError(0);
|
||||
#endif
|
||||
});
|
||||
/// reset errno
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
struct WriteBuffer
|
||||
{
|
||||
llarp_time_t timestamp = 0;
|
||||
size_t bufsz;
|
||||
byte_t buf[1500];
|
||||
|
||||
WriteBuffer() = default;
|
||||
|
||||
WriteBuffer(const void* ptr, size_t sz)
|
||||
{
|
||||
if(sz <= sizeof(buf))
|
||||
{
|
||||
bufsz = sz;
|
||||
memcpy(buf, ptr, bufsz);
|
||||
}
|
||||
else
|
||||
bufsz = 0;
|
||||
}
|
||||
|
||||
struct WriteBuffer
|
||||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const WriteBuffer& w) const
|
||||
{
|
||||
llarp_time_t timestamp = 0;
|
||||
size_t bufsz;
|
||||
byte_t buf[1500];
|
||||
|
||||
WriteBuffer() = default;
|
||||
|
||||
WriteBuffer(const void* ptr, size_t sz)
|
||||
{
|
||||
if(sz <= sizeof(buf))
|
||||
{
|
||||
bufsz = sz;
|
||||
memcpy(buf, ptr, bufsz);
|
||||
}
|
||||
else
|
||||
bufsz = 0;
|
||||
}
|
||||
|
||||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const WriteBuffer& w) const
|
||||
{
|
||||
return w.timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
struct PutTime
|
||||
{
|
||||
void
|
||||
operator()(WriteBuffer& w) const
|
||||
{
|
||||
w.timestamp = llarp_time_now_ms();
|
||||
}
|
||||
};
|
||||
|
||||
struct Compare
|
||||
{
|
||||
bool
|
||||
operator()(const WriteBuffer& left, const WriteBuffer& right) const
|
||||
{
|
||||
return left.timestamp < right.timestamp;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
|
||||
WriteBuffer::PutTime, WriteBuffer::Compare,
|
||||
llarp::util::NullMutex, llarp::util::NullLock >
|
||||
m_writeq;
|
||||
|
||||
virtual ~ev_io()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
::close(fd);
|
||||
#else
|
||||
closesocket(fd);
|
||||
#endif
|
||||
};
|
||||
return w.timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace llarp
|
||||
struct PutTime
|
||||
{
|
||||
void
|
||||
operator()(WriteBuffer& w) const
|
||||
{
|
||||
w.timestamp = llarp_time_now_ms();
|
||||
}
|
||||
};
|
||||
|
||||
struct Compare
|
||||
{
|
||||
bool
|
||||
operator()(const WriteBuffer& left, const WriteBuffer& right) const
|
||||
{
|
||||
return left.timestamp < right.timestamp;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
|
||||
WriteBuffer::PutTime, WriteBuffer::Compare,
|
||||
llarp::util::NullMutex, llarp::util::NullLock >
|
||||
m_writeq;
|
||||
|
||||
virtual ~ev_io()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
::close(fd);
|
||||
#else
|
||||
closesocket(fd);
|
||||
#endif
|
||||
};
|
||||
}
|
||||
;
|
||||
}
|
||||
; // namespace llarp
|
||||
|
||||
struct llarp_ev_loop
|
||||
{
|
||||
|
|
|
@ -96,10 +96,10 @@ namespace llarp
|
|||
read(void* buf, size_t sz)
|
||||
{
|
||||
ssize_t ret = tuntap_read(tunif, buf, sz);
|
||||
if(ret > 4 && t->recvpkt)
|
||||
if(ret > 0 && t->recvpkt)
|
||||
{
|
||||
// don't include packet info
|
||||
t->recvpkt(t, ((byte_t*)buf) + 4, ret - 4);
|
||||
// does not have pktinfo
|
||||
t->recvpkt(t, buf, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,19 @@ namespace llarp
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
do_write(void* buf, size_t sz)
|
||||
{
|
||||
iovec vecs[2];
|
||||
// TODO: IPV6
|
||||
uint32_t t = htonl(AF_INET);
|
||||
vecs[0].iov_base = &t;
|
||||
vecs[0].iov_len = sizeof(t);
|
||||
vecs[1].iov_base = buf;
|
||||
vecs[1].iov_len = sz;
|
||||
return writev(fd, vecs, 2) != -1;
|
||||
}
|
||||
|
||||
void
|
||||
flush_write()
|
||||
{
|
||||
|
@ -109,7 +122,7 @@ namespace llarp
|
|||
{
|
||||
ssize_t ret = tuntap_read(tunif, buf, sz);
|
||||
if(ret > 4 && t->recvpkt)
|
||||
t->recvpkt(t, ((byte_t *)buf) + 4, ret - 4);
|
||||
t->recvpkt(t, ((byte_t*)buf) + 4, ret - 4);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,80 @@ namespace llarp
|
|||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct tun : public ev_io
|
||||
{
|
||||
llarp_tun_io* t;
|
||||
device* tunif;
|
||||
tun(llarp_tun_io* tio)
|
||||
: ev_io(-1)
|
||||
, t(tio)
|
||||
, tunif(tuntap_init())
|
||||
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
int
|
||||
sendto(const sockaddr* to, const void* data, size_t sz)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
flush_write()
|
||||
{
|
||||
if(t->before_write)
|
||||
{
|
||||
t->before_write(t);
|
||||
}
|
||||
ev_io::flush_write();
|
||||
}
|
||||
|
||||
int
|
||||
read(void* buf, size_t sz)
|
||||
{
|
||||
ssize_t ret = tuntap_read(tunif, buf, sz);
|
||||
if(ret > 4 && t->recvpkt)
|
||||
// should have pktinfo
|
||||
t->recvpkt(t, ((byte_t*)buf) + 4, ret - 4);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
setup()
|
||||
{
|
||||
llarp::LogDebug("set ifname to ", t->ifname);
|
||||
strncpy(tunif->if_name, t->ifname, sizeof(tunif->if_name));
|
||||
|
||||
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1)
|
||||
{
|
||||
llarp::LogWarn("failed to start interface");
|
||||
return false;
|
||||
}
|
||||
if(tuntap_up(tunif) == -1)
|
||||
{
|
||||
llarp::LogWarn("failed to put interface up: ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
|
||||
{
|
||||
llarp::LogWarn("failed to set ip");
|
||||
return false;
|
||||
}
|
||||
fd = (SOCKET)tunif->tun_fd;
|
||||
if(fd == -1)
|
||||
return false;
|
||||
|
||||
// set non blocking
|
||||
int on = 1;
|
||||
return ioctlsocket(fd, FIONBIO, (u_long*)&on) != -1;
|
||||
}
|
||||
|
||||
~tun()
|
||||
{
|
||||
}
|
||||
};
|
||||
}; // namespace llarp
|
||||
|
||||
struct llarp_win32_loop : public llarp_ev_loop
|
||||
|
@ -93,22 +167,12 @@ struct llarp_win32_loop : public llarp_ev_loop
|
|||
|
||||
llarp_win32_loop() : iocpfd(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WSADATA wsockd;
|
||||
int err;
|
||||
// So, what I was told last time was that we can defer
|
||||
// loading winsock2 up to this point, as we reach this ctor
|
||||
// early on during daemon startup.
|
||||
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
|
||||
if(err)
|
||||
perror("Failed to start Windows Sockets");
|
||||
}
|
||||
|
||||
~llarp_win32_loop()
|
||||
{
|
||||
if(iocpfd != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(iocpfd);
|
||||
|
||||
::WSACleanup();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -287,7 +351,10 @@ struct llarp_win32_loop : public llarp_ev_loop
|
|||
llarp::ev_io*
|
||||
create_tun(llarp_tun_io* tun)
|
||||
{
|
||||
// TODO implement me
|
||||
llarp::tun* t = new llarp::tun(tun);
|
||||
if(t->setup())
|
||||
return t;
|
||||
delete t;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
13
llarp/fs.hpp
13
llarp/fs.hpp
|
@ -1,6 +1,7 @@
|
|||
#ifndef LLARP_FS_HPP
|
||||
#define LLARP_FS_HPP
|
||||
#include <functional>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define PATH_SEP "\\"
|
||||
#else
|
||||
|
@ -8,21 +9,13 @@
|
|||
#endif
|
||||
|
||||
#include "filesystem.h"
|
||||
|
||||
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
|
||||
// win32 is the only one that doesn't use cpp17::filesystem
|
||||
// because cpp17::filesystem is unimplemented for Windows
|
||||
// -despair86
|
||||
#if defined(__MINGW32__) || defined(_MSC_VER) || defined(__sun)
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#else
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#endif // end win32
|
||||
#else
|
||||
// not CPP17 needs this
|
||||
// openbsd needs this
|
||||
// linux gcc 7.2 needs this
|
||||
namespace fs = cpp17::filesystem;
|
||||
#endif
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
namespace llarp
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
#include <llarp/handlers/tun.hpp>
|
||||
#include "router.hpp"
|
||||
#include <sys/types.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#ifndef DNS_PORT
|
||||
#define DNS_PORT (53)
|
||||
|
@ -102,11 +104,11 @@ namespace llarp
|
|||
strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1);
|
||||
|
||||
// set up address in dotLokiLookup
|
||||
struct sockaddr_in s_addr;
|
||||
s_addr.sin_addr.s_addr = inet_addr(tunif.ifaddr);
|
||||
s_addr.sin_family = AF_INET;
|
||||
struct sockaddr_in source_addr;
|
||||
source_addr.sin_addr.s_addr = inet_addr(tunif.ifaddr);
|
||||
source_addr.sin_family = AF_INET;
|
||||
|
||||
llarp::Addr tunIp(s_addr);
|
||||
llarp::Addr tunIp(source_addr);
|
||||
// related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
|
||||
dns_iptracker_setup(tunIp); // claim GW IP to make sure it's not inuse
|
||||
return true;
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
#include <netinet/ip_icmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <wspiapi.h>
|
||||
#endif
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace utp
|
||||
|
@ -342,8 +348,8 @@ namespace llarp
|
|||
static_cast< LinkLayer* >(utp_context_get_userdata(arg->context));
|
||||
llarp::LogDebug("utp_sendto ", Addr(*arg->address), " ", arg->len,
|
||||
" bytes");
|
||||
if(sendto(l->m_udp.fd, arg->buf, arg->len, arg->flags, arg->address,
|
||||
arg->address_len)
|
||||
if(::sendto(l->m_udp.fd, (char*)arg->buf, arg->len, arg->flags,
|
||||
arg->address, arg->address_len)
|
||||
== -1)
|
||||
{
|
||||
llarp::LogError("sendto failed: ", strerror(errno));
|
||||
|
|
|
@ -118,7 +118,9 @@ _llarp_nt_heap_free(void* mem)
|
|||
int
|
||||
llarp_nt_sockaddr_pton(const char* src, struct sockaddr* dst)
|
||||
{
|
||||
struct addrinfo hints = {0}, *result = nullptr;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* result = nullptr;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
@ -261,6 +263,10 @@ _llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
|
|||
ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1);
|
||||
ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next);
|
||||
}
|
||||
else
|
||||
{
|
||||
ift->_ifa.ifa_next = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,7 +872,7 @@ namespace llarp
|
|||
if(i->ifa_addr->sa_family == af)
|
||||
{
|
||||
llarp::Addr a(*i->ifa_addr);
|
||||
if(!(a.isPrivate() || a.isLoopback()))
|
||||
if(!(a.isPrivate() || a.isLoopback() || (a.getHostLong() == 0)))
|
||||
{
|
||||
ifname = i->ifa_name;
|
||||
found = true;
|
||||
|
|
|
@ -96,7 +96,7 @@ struct llarp_nodedb
|
|||
llarp::LogDebug("saving RC.pubkey ", filepath);
|
||||
std::ofstream ofs(
|
||||
filepath,
|
||||
std::ofstream::out & std::ofstream::binary & std::ofstream::trunc);
|
||||
std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
|
||||
ofs.write((char *)buf.base, buf.sz);
|
||||
ofs.close();
|
||||
if(!ofs)
|
||||
|
@ -313,7 +313,7 @@ llarp_nodedb_ensure_dir(const char *dir)
|
|||
std::error_code ec;
|
||||
|
||||
if(!fs::exists(dir, ec))
|
||||
fs::create_directories(path, ec);
|
||||
fs::create_directory(path, ec);
|
||||
|
||||
if(ec)
|
||||
return false;
|
||||
|
|
|
@ -165,6 +165,26 @@ namespace llarp
|
|||
" rx=", path->RXID());
|
||||
}
|
||||
|
||||
bool
|
||||
PathSet::GetCurrentIntroductionsWithFilter(
|
||||
std::set< llarp::service::Introduction >& intros,
|
||||
std::function< bool(const llarp::service::Introduction&) > filter) const
|
||||
{
|
||||
intros.clear();
|
||||
size_t count = 0;
|
||||
auto itr = m_Paths.begin();
|
||||
while(itr != m_Paths.end())
|
||||
{
|
||||
if(itr->second->IsReady() && filter(itr->second->intro))
|
||||
{
|
||||
intros.insert(itr->second->intro);
|
||||
++count;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
PathSet::GetCurrentIntroductions(
|
||||
std::set< llarp::service::Introduction >& intros) const
|
||||
|
|
|
@ -760,6 +760,9 @@ llarp_router::Run()
|
|||
return;
|
||||
}
|
||||
|
||||
// generate default hidden service
|
||||
if(!CreateDefaultHiddenService())
|
||||
return;
|
||||
// delayed connect all for clients
|
||||
uint64_t delay = ((llarp_randint() % 10) * 500) + 500;
|
||||
llarp_logic_call_later(logic, {delay, this, &ConnectAll});
|
||||
|
@ -855,6 +858,12 @@ llarp_router::InitOutboundLink()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_router::CreateDefaultHiddenService()
|
||||
{
|
||||
return hiddenServiceContext.AddDefaultEndpoint(defaultIfAddr, defaultIfName);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_router::HasPendingConnectJob(const llarp::RouterID &remote)
|
||||
{
|
||||
|
@ -1054,6 +1063,17 @@ namespace llarp
|
|||
llarp::LogError("Failed to set up curvecp link");
|
||||
}
|
||||
}
|
||||
else if(StrEq(section, "network"))
|
||||
{
|
||||
if(StrEq(key, "ifaddr"))
|
||||
{
|
||||
self->defaultIfAddr = val;
|
||||
}
|
||||
if(StrEq(key, "ifname"))
|
||||
{
|
||||
self->defaultIfAddr = val;
|
||||
}
|
||||
}
|
||||
else if(StrEq(section, "services"))
|
||||
{
|
||||
if(self->LoadHiddenServiceConfig(val))
|
||||
|
|
|
@ -93,6 +93,13 @@ struct llarp_router
|
|||
|
||||
llarp::service::Context hiddenServiceContext;
|
||||
|
||||
std::string defaultIfAddr = "10.200.0.1/24";
|
||||
std::string defaultIfName = "lokitun0";
|
||||
|
||||
bool
|
||||
CreateDefaultHiddenService();
|
||||
|
||||
|
||||
std::unique_ptr< llarp::ILinkLayer > outboundLink;
|
||||
std::vector< std::unique_ptr< llarp::ILinkLayer > > inboundLinks;
|
||||
|
||||
|
|
|
@ -106,6 +106,12 @@ namespace llarp
|
|||
return tunEndpoint->MapAddress(addr, ip);
|
||||
}
|
||||
|
||||
bool
|
||||
Context::AddDefaultEndpoint(const std::string & ifaddr, const std::string & ifname)
|
||||
{
|
||||
return AddEndpoint({ "default", {{"type", "tun"}, {"ifaddr", ifaddr}, {"ifname", ifname}}});
|
||||
}
|
||||
|
||||
bool
|
||||
Context::AddEndpoint(const Config::section_t &conf)
|
||||
{
|
||||
|
|
|
@ -91,22 +91,25 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
Endpoint::RegenAndPublishIntroSet(llarp_time_t now)
|
||||
Endpoint::RegenAndPublishIntroSet(llarp_time_t now, bool forceRebuild)
|
||||
{
|
||||
std::set< Introduction > I;
|
||||
if(!GetCurrentIntroductions(I))
|
||||
if(!GetCurrentIntroductionsWithFilter(
|
||||
I, [now](const service::Introduction& intro) -> bool {
|
||||
return now < intro.expiresAt
|
||||
&& intro.expiresAt - now > (2 * 60 * 1000);
|
||||
}))
|
||||
{
|
||||
llarp::LogWarn("could not publish descriptors for endpoint ", Name(),
|
||||
" because we couldn't get any introductions");
|
||||
if(ShouldBuildMore())
|
||||
" because we couldn't get enough valid introductions");
|
||||
if(ShouldBuildMore() || forceRebuild)
|
||||
ManualRebuild(1);
|
||||
return;
|
||||
}
|
||||
m_IntroSet.I.clear();
|
||||
for(const auto& intro : I)
|
||||
{
|
||||
if(now < intro.expiresAt && intro.expiresAt - now > 60000)
|
||||
m_IntroSet.I.push_back(intro);
|
||||
m_IntroSet.I.push_back(intro);
|
||||
}
|
||||
if(m_IntroSet.I.size() == 0)
|
||||
{
|
||||
|
@ -760,6 +763,7 @@ namespace llarp
|
|||
if(MarkCurrentIntroBad(llarp_time_now_ms()))
|
||||
llarp::LogInfo(Name(), " switched intros to ", remoteIntro.router,
|
||||
" via ", remoteIntro.pathID);
|
||||
UpdateIntroSet();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -815,7 +819,7 @@ namespace llarp
|
|||
Endpoint::HandlePathDead(void* user)
|
||||
{
|
||||
Endpoint* self = static_cast< Endpoint* >(user);
|
||||
self->RegenAndPublishIntroSet(llarp_time_now_ms());
|
||||
self->RegenAndPublishIntroSet(llarp_time_now_ms(), true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -918,10 +922,18 @@ namespace llarp
|
|||
{
|
||||
if(markedBad)
|
||||
return true;
|
||||
if(i && currentIntroSet.T < i->T)
|
||||
if(i)
|
||||
{
|
||||
if(currentIntroSet.T >= i->T)
|
||||
{
|
||||
llarp::LogInfo("introset is old, dropping");
|
||||
return true;
|
||||
}
|
||||
currentIntroSet = *i;
|
||||
ShiftIntroduction();
|
||||
if(!ShiftIntroduction())
|
||||
{
|
||||
llarp::LogWarn("failed to pick new intro during introset update");
|
||||
}
|
||||
if(GetPathByRouter(remoteIntro.router) == nullptr)
|
||||
BuildOneAlignedTo(remoteIntro.router);
|
||||
}
|
||||
|
@ -1013,42 +1025,13 @@ namespace llarp
|
|||
}
|
||||
++itr;
|
||||
}
|
||||
llarp::LogWarn("No path ready to send yet");
|
||||
// all paths are not ready?
|
||||
return false;
|
||||
}
|
||||
|
||||
// no converstation
|
||||
auto itr = m_PendingTraffic.find(remote);
|
||||
if(itr == m_PendingTraffic.end())
|
||||
{
|
||||
m_PendingTraffic.insert(std::make_pair(remote, PendingBufferQueue()));
|
||||
EnsurePathToService(
|
||||
remote,
|
||||
[&](Address addr, OutboundContext* ctx) {
|
||||
if(ctx)
|
||||
{
|
||||
auto itr = m_PendingTraffic.find(addr);
|
||||
if(itr != m_PendingTraffic.end())
|
||||
{
|
||||
while(itr->second.size())
|
||||
{
|
||||
auto& front = itr->second.front();
|
||||
ctx->AsyncEncryptAndSendTo(front.Buffer(), front.protocol);
|
||||
itr->second.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("failed to obtain outbound context to ", addr,
|
||||
" within timeout");
|
||||
}
|
||||
m_PendingTraffic.erase(addr);
|
||||
},
|
||||
10000);
|
||||
}
|
||||
m_PendingTraffic[remote].emplace(data, t);
|
||||
return true;
|
||||
EnsurePathToService(remote, [](Address, OutboundContext*) {}, 5000);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1090,9 +1073,51 @@ namespace llarp
|
|||
Endpoint::OutboundContext::MarkCurrentIntroBad(llarp_time_t now)
|
||||
{
|
||||
// insert bad intro
|
||||
m_BadIntros.insert(std::make_pair(remoteIntro, now));
|
||||
// shift
|
||||
return ShiftIntroduction();
|
||||
m_BadIntros[remoteIntro] = now;
|
||||
// unconditional shift
|
||||
bool shiftedRouter = false;
|
||||
bool shiftedIntro = false;
|
||||
// try same router
|
||||
for(const auto& intro : currentIntroSet.I)
|
||||
{
|
||||
llarp::LogInfo("have intro: ", intro);
|
||||
if(intro.ExpiresSoon(now))
|
||||
{
|
||||
llarp::LogInfo("skipping intro, expires soon");
|
||||
continue;
|
||||
}
|
||||
auto itr = m_BadIntros.find(intro);
|
||||
if(itr == m_BadIntros.end() && intro.router == remoteIntro.router)
|
||||
{
|
||||
shiftedIntro = true;
|
||||
remoteIntro = intro;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!shiftedIntro)
|
||||
{
|
||||
// try any router
|
||||
for(const auto& intro : currentIntroSet.I)
|
||||
{
|
||||
if(intro.ExpiresSoon(now))
|
||||
continue;
|
||||
auto itr = m_BadIntros.find(intro);
|
||||
if(itr == m_BadIntros.end())
|
||||
{
|
||||
// TODO: this should always be true but idk if it really is
|
||||
shiftedRouter = remoteIntro.router != intro.router;
|
||||
shiftedIntro = true;
|
||||
remoteIntro = intro;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(shiftedRouter)
|
||||
{
|
||||
lastShift = now;
|
||||
ManualRebuild(1);
|
||||
}
|
||||
return shiftedIntro;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1167,11 +1192,13 @@ namespace llarp
|
|||
Introduction remoteIntro;
|
||||
std::function< void(ProtocolFrame&) > hook;
|
||||
IDataHandler* handler;
|
||||
ConvoTag tag;
|
||||
|
||||
AsyncKeyExchange(llarp_logic* l, llarp_crypto* c, const ServiceInfo& r,
|
||||
const Identity& localident,
|
||||
const PQPubKey& introsetPubKey,
|
||||
const Introduction& remote, IDataHandler* h)
|
||||
const Introduction& remote, IDataHandler* h,
|
||||
const ConvoTag& t)
|
||||
: logic(l)
|
||||
, crypto(c)
|
||||
, remote(r)
|
||||
|
@ -1179,6 +1206,7 @@ namespace llarp
|
|||
, introPubKey(introsetPubKey)
|
||||
, remoteIntro(remote)
|
||||
, handler(h)
|
||||
, tag(t)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1215,8 +1243,8 @@ namespace llarp
|
|||
// H (K + PKE(A, B, N))
|
||||
self->crypto->shorthash(self->sharedKey,
|
||||
llarp::StackBuffer< decltype(tmp) >(tmp));
|
||||
// randomize tag
|
||||
self->msg.tag.Randomize();
|
||||
// set tag
|
||||
self->msg.tag = self->tag;
|
||||
// set sender
|
||||
self->msg.sender = self->m_LocalIdentity.pub;
|
||||
// set version
|
||||
|
@ -1238,9 +1266,7 @@ namespace llarp
|
|||
void
|
||||
Endpoint::EnsureReplyPath(const ServiceInfo& ident)
|
||||
{
|
||||
auto itr = m_AddressToService.find(ident.Addr());
|
||||
if(itr == m_AddressToService.end())
|
||||
m_AddressToService.insert(std::make_pair(ident.Addr(), ident));
|
||||
m_AddressToService[ident.Addr()] = ident;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1259,13 +1285,15 @@ namespace llarp
|
|||
return;
|
||||
}
|
||||
}
|
||||
currentConvoTag.Randomize();
|
||||
AsyncKeyExchange* ex = new AsyncKeyExchange(
|
||||
m_Endpoint->RouterLogic(), m_Endpoint->Crypto(), remoteIdent,
|
||||
m_Endpoint->GetIdentity(), currentIntroSet.K, remoteIntro,
|
||||
m_DataHandler, currentConvoTag);
|
||||
|
||||
AsyncKeyExchange* ex =
|
||||
new AsyncKeyExchange(m_Endpoint->RouterLogic(), m_Endpoint->Crypto(),
|
||||
remoteIdent, m_Endpoint->GetIdentity(),
|
||||
currentIntroSet.K, remoteIntro, m_DataHandler);
|
||||
ex->hook = std::bind(&Endpoint::OutboundContext::Send, this,
|
||||
std::placeholders::_1);
|
||||
|
||||
ex->msg.PutBuffer(payload);
|
||||
ex->msg.introReply = path->intro;
|
||||
llarp_threadpool_queue_job(m_Endpoint->Worker(),
|
||||
|
@ -1426,18 +1454,12 @@ namespace llarp
|
|||
Endpoint::SendContext::EncryptAndSendTo(llarp_buffer_t payload,
|
||||
ProtocolType t)
|
||||
{
|
||||
std::set< ConvoTag > tags;
|
||||
if(!m_DataHandler->GetConvoTagsForService(remoteIdent, tags))
|
||||
{
|
||||
llarp::LogError("no open converstations with remote endpoint?");
|
||||
return;
|
||||
}
|
||||
auto crypto = m_Endpoint->Router()->crypto;
|
||||
const byte_t* shared = nullptr;
|
||||
routing::PathTransferMessage msg;
|
||||
ProtocolFrame& f = msg.T;
|
||||
f.N.Randomize();
|
||||
f.T = *tags.begin();
|
||||
f.T = currentConvoTag;
|
||||
f.S = m_Endpoint->GetSeqNoForConvo(f.T);
|
||||
|
||||
auto now = llarp_time_now_ms();
|
||||
|
@ -1486,8 +1508,8 @@ namespace llarp
|
|||
++sequenceNo;
|
||||
if(path->SendRoutingMessage(&msg, m_Endpoint->Router()))
|
||||
{
|
||||
llarp::LogInfo("sent message via ", remoteIntro.pathID, " on ",
|
||||
remoteIntro.router);
|
||||
llarp::LogDebug("sent message via ", remoteIntro.pathID, " on ",
|
||||
remoteIntro.router);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,28 +1,31 @@
|
|||
#include <llarp/time.h>
|
||||
#include <chrono>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
typedef std::chrono::system_clock clock_t;
|
||||
|
||||
template < typename Res, typename IntType >
|
||||
static IntType
|
||||
time_since_epoch()
|
||||
{
|
||||
return std::chrono::duration_cast< Res >(
|
||||
llarp::clock_t::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
} // namespace llarp
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
// these _should_ be 32-bit safe...
|
||||
llarp_time_t
|
||||
llarp_time_now_ms()
|
||||
{
|
||||
return llarp::time_since_epoch< std::chrono::milliseconds, llarp_time_t >();
|
||||
struct timeval tv;
|
||||
struct timezone z;
|
||||
z.tz_minuteswest = 0;
|
||||
time_t t = time(nullptr);
|
||||
z.tz_dsttime = gmtime(&t)->tm_isdst;
|
||||
gettimeofday(&tv, &z);
|
||||
llarp_time_t timeNow =
|
||||
(llarp_time_t)(tv.tv_sec) * 1000 + (llarp_time_t)(tv.tv_usec) / 1000;
|
||||
return timeNow;
|
||||
}
|
||||
|
||||
llarp_seconds_t
|
||||
llarp_time_now_sec()
|
||||
{
|
||||
return llarp::time_since_epoch< std::chrono::seconds, llarp_seconds_t >();
|
||||
struct timeval tv;
|
||||
struct timezone z;
|
||||
z.tz_minuteswest = 0;
|
||||
time_t t = time(nullptr);
|
||||
z.tz_dsttime = gmtime(&t)->tm_isdst;
|
||||
gettimeofday(&tv, &z);
|
||||
llarp_time_t timeNow = tv.tv_sec;
|
||||
return timeNow;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace llarp
|
|||
bool
|
||||
TransitHop::Expired(llarp_time_t now) const
|
||||
{
|
||||
return now - started > lifetime;
|
||||
return now > ExpireTime();
|
||||
}
|
||||
|
||||
llarp_time_t
|
||||
|
@ -54,7 +54,9 @@ namespace llarp
|
|||
TransitHop::SendRoutingMessage(llarp::routing::IMessage* msg,
|
||||
llarp_router* r)
|
||||
{
|
||||
byte_t tmp[MAX_LINK_MSG_SIZE - 1024];
|
||||
if(!IsEndpoint(r->pubkey()))
|
||||
return false;
|
||||
byte_t tmp[MAX_LINK_MSG_SIZE - 128];
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
if(!msg->BEncode(&buf))
|
||||
{
|
||||
|
@ -64,12 +66,14 @@ namespace llarp
|
|||
TunnelNonce N;
|
||||
N.Randomize();
|
||||
buf.sz = buf.cur - buf.base;
|
||||
// pad smaller messages
|
||||
if(buf.sz < MESSAGE_PAD_SIZE)
|
||||
// pad to nearest MESSAGE_PAD_SIZE bytes
|
||||
auto dlt = buf.sz % MESSAGE_PAD_SIZE;
|
||||
if(dlt)
|
||||
{
|
||||
dlt = MESSAGE_PAD_SIZE - dlt;
|
||||
// randomize padding
|
||||
r->crypto.randbytes(buf.cur, MESSAGE_PAD_SIZE - buf.sz);
|
||||
buf.sz = MESSAGE_PAD_SIZE;
|
||||
r->crypto.randbytes(buf.cur, dlt);
|
||||
buf.sz += dlt;
|
||||
}
|
||||
buf.cur = buf.base;
|
||||
return HandleDownstream(buf, N, r);
|
||||
|
@ -94,7 +98,7 @@ namespace llarp
|
|||
llarp_router* r)
|
||||
{
|
||||
r->crypto.xchacha20(buf, pathKey, Y);
|
||||
if(info.upstream == RouterID(r->pubkey()))
|
||||
if(IsEndpoint(r->pubkey()))
|
||||
{
|
||||
return m_MessageParser.ParseMessageBuffer(buf, this, info.rxID, r);
|
||||
}
|
||||
|
@ -166,7 +170,6 @@ namespace llarp
|
|||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// send
|
||||
llarp::LogInfo("Transfer ", buf.sz, " bytes", " to ", msg->P);
|
||||
return path->HandleDownstream(buf, msg->Y, r);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,11 @@ option(gtest_build_tests "Build all of gtest's own tests." OFF)
|
|||
|
||||
option(gtest_build_samples "Build gtest's sample programs." OFF)
|
||||
|
||||
if (NOT WIN32)
|
||||
option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
|
||||
|
||||
# use native windows nt threading even in gcc or clang
|
||||
if (WIN32)
|
||||
option(gtest_disable_pthreads ON)
|
||||
endif(WIN32)
|
||||
else()
|
||||
option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON)
|
||||
endif(NOT WIN32)
|
||||
|
||||
option(
|
||||
gtest_hide_internal_symbols
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#ifndef PBL_CPP_FILESYSTEM_H
|
||||
#define PBL_CPP_FILESYSTEM_H
|
||||
|
||||
#if _MSC_VER >= 1910
|
||||
#if _MSC_VER >= 1900
|
||||
#define CPP17
|
||||
#define CPP11
|
||||
#define CPP14
|
||||
|
@ -39,13 +39,8 @@
|
|||
#include "version.h"
|
||||
|
||||
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
|
||||
#if defined(__MINGW32__) || defined(_MSC_VER) || defined(__sun)
|
||||
// win32 needs experimental
|
||||
#include <experimental/filesystem>
|
||||
#else
|
||||
#include <experimental/filesystem>
|
||||
#endif
|
||||
#else
|
||||
// OpenBSD needs this
|
||||
// MacOS llvm 3.8 needs this
|
||||
#include "fs/absolute.h"
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
/* Copyright (c) 2014, Pollard Banknote Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "basename.h"
|
||||
|
||||
|
@ -33,168 +34,174 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
// the position following the previous occurrence of c (relative to position j),
|
||||
// or 0 if not. In this file, the first letter of a path component.
|
||||
std::size_t after_last(
|
||||
const std::string& s,
|
||||
char c,
|
||||
std::size_t j
|
||||
)
|
||||
{
|
||||
std::size_t i = s.find_last_of(c, j);
|
||||
// the position following the previous occurrence of c (relative to position
|
||||
// j), or 0 if not. In this file, the first letter of a path component.
|
||||
std::size_t
|
||||
after_last(const std::string& s, char c, std::size_t j)
|
||||
{
|
||||
std::size_t i = s.find_last_of(c, j);
|
||||
|
||||
return i == std::string::npos ? 0 : i + 1;
|
||||
}
|
||||
return i == std::string::npos ? 0 : i + 1;
|
||||
}
|
||||
|
||||
// (first character, length) of last path component in s or (0,0) for "."
|
||||
// or (npos, 0) if error
|
||||
std::pair< std::size_t, std::size_t > locate_last_path_component(const std::string& s)
|
||||
{
|
||||
if ( s.empty() )
|
||||
{
|
||||
// (first character, length) of last path component in s or (0,0) for "."
|
||||
// or (npos, 0) if error
|
||||
std::pair< std::size_t, std::size_t >
|
||||
locate_last_path_component(const std::string& s)
|
||||
{
|
||||
if(s.empty())
|
||||
{
|
||||
// error
|
||||
return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
|
||||
}
|
||||
|
||||
// error
|
||||
return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
|
||||
}
|
||||
// j points to the last character in a component
|
||||
std::size_t j = s.find_last_not_of('/');
|
||||
unsigned depth = 0;
|
||||
|
||||
// j points to the last character in a component
|
||||
std::size_t j = s.find_last_not_of('/');
|
||||
unsigned depth = 0;
|
||||
while(j != std::string::npos)
|
||||
{
|
||||
// i points to first character of a component
|
||||
// i <= j, because j never points to a '/'
|
||||
const std::size_t i = after_last(s, '/', j);
|
||||
|
||||
while ( j != std::string::npos )
|
||||
{
|
||||
// i points to first character of a component
|
||||
// i <= j, because j never points to a '/'
|
||||
const std::size_t i = after_last(s, '/', j);
|
||||
if(j - i + 1 == 1 && s[i] == '.')
|
||||
{
|
||||
// component is ".", basically ignore this component
|
||||
}
|
||||
else if(j - i + 1 == 2 && s[i] == '.' && s[i + 1] == '.')
|
||||
{
|
||||
// component is "..", ignore the next component
|
||||
++depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
// found a "normal" path component
|
||||
if(depth == 0)
|
||||
{
|
||||
return std::pair< std::size_t, std::size_t >(i, j - i + 1);
|
||||
}
|
||||
|
||||
if ( j - i + 1 == 1 && s[i] == '.' )
|
||||
{
|
||||
// component is ".", basically ignore this component
|
||||
}
|
||||
else if ( j - i + 1 == 2 && s[i] == '.' && s[i + 1] == '.' )
|
||||
{
|
||||
// component is "..", ignore the next component
|
||||
++depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
// found a "normal" path component
|
||||
if ( depth == 0 )
|
||||
{
|
||||
return std::pair< std::size_t, std::size_t >(i, j - i + 1);
|
||||
}
|
||||
// ..but we're ignoring it
|
||||
--depth;
|
||||
}
|
||||
|
||||
// ..but we're ignoring it
|
||||
--depth;
|
||||
}
|
||||
if(i == 0)
|
||||
{
|
||||
if(depth == 0)
|
||||
{
|
||||
// "."
|
||||
return std::pair< std::size_t, std::size_t >(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// error, path is malformed
|
||||
return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == 0 )
|
||||
{
|
||||
if ( depth == 0 )
|
||||
{
|
||||
j = s.find_last_not_of('/', i - 1);
|
||||
}
|
||||
|
||||
// "."
|
||||
return std::pair< std::size_t, std::size_t >(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// all slashes
|
||||
return std::pair< std::size_t, std::size_t >(0, 1);
|
||||
}
|
||||
|
||||
// error, path is malformed
|
||||
return std::pair< std::size_t, std::size_t >(std::string::npos, 0);
|
||||
}
|
||||
}
|
||||
std::string
|
||||
basename_posix(const std::string& s)
|
||||
{
|
||||
const std::pair< std::size_t, std::size_t > range =
|
||||
locate_last_path_component(s);
|
||||
|
||||
j = s.find_last_not_of('/', i - 1);
|
||||
}
|
||||
if(range.first == std::string::npos)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
// all slashes
|
||||
return std::pair< std::size_t, std::size_t >(0, 1);
|
||||
}
|
||||
if(range.first == 0 && range.second == 0)
|
||||
{
|
||||
return ".";
|
||||
}
|
||||
|
||||
std::string basename_posix(const std::string& s)
|
||||
{
|
||||
const std::pair< std::size_t, std::size_t > range = locate_last_path_component(s);
|
||||
return s.substr(range.first, range.second);
|
||||
}
|
||||
std::string
|
||||
dirname_posix(const std::string& s)
|
||||
{
|
||||
const std::pair< std::size_t, std::size_t > range =
|
||||
locate_last_path_component(s);
|
||||
|
||||
if ( range.first == std::string::npos )
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
// path was malformed
|
||||
if(range.first == std::string::npos)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if ( range.first == 0 && range.second == 0 )
|
||||
{
|
||||
return ".";
|
||||
}
|
||||
if(range.first == 0)
|
||||
{
|
||||
if(range.second == 0)
|
||||
{
|
||||
return "..";
|
||||
}
|
||||
|
||||
return s.substr(range.first, range.second);
|
||||
}
|
||||
// could be '/', or could be a unpathed filename
|
||||
if(s[0] == '/')
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
std::string dirname_posix(const std::string& s)
|
||||
{
|
||||
const std::pair< std::size_t, std::size_t > range = locate_last_path_component(s);
|
||||
return ".";
|
||||
}
|
||||
else
|
||||
{
|
||||
// leading directory
|
||||
return s.substr(0, range.first);
|
||||
}
|
||||
}
|
||||
|
||||
// path was malformed
|
||||
if ( range.first == std::string::npos )
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if ( range.first == 0 )
|
||||
{
|
||||
if ( range.second == 0 )
|
||||
{
|
||||
return "..";
|
||||
}
|
||||
|
||||
// could be '/', or could be a unpathed filename
|
||||
if ( s[0] == '/' )
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
return ".";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// leading directory
|
||||
return s.substr(0, range.first);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace cpp17
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
// Calls the basename_xxx appropriate for this platform
|
||||
std::string basename(const std::string& s)
|
||||
{
|
||||
#ifdef OS_POSIX
|
||||
namespace filesystem
|
||||
{
|
||||
// Calls the basename_xxx appropriate for this platform
|
||||
std::string
|
||||
basename(const std::string& s)
|
||||
{
|
||||
#ifdef OS_POSIX
|
||||
return basename_posix(s);
|
||||
#else
|
||||
std::string t;
|
||||
char fname[_MAX_FNAME], ext[_MAX_EXT];
|
||||
_splitpath(s.c_str(), nullptr, nullptr, fname, ext);
|
||||
t = fname;
|
||||
t += ext;
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
return basename_posix(s);
|
||||
std::string
|
||||
dirname(const std::string& s)
|
||||
{
|
||||
#ifdef OS_POSIX
|
||||
const std::string& t = dirname_posix(s);
|
||||
|
||||
#else
|
||||
#error "No implementation of basename is available for this platform"
|
||||
#endif
|
||||
}
|
||||
if(t == ".")
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
std::string dirname(const std::string& s)
|
||||
{
|
||||
#ifdef OS_POSIX
|
||||
const std::string& t = dirname_posix(s);
|
||||
return cleanpath(t);
|
||||
|
||||
if ( t == "." )
|
||||
{
|
||||
return t;
|
||||
}
|
||||
#else
|
||||
std::string t;
|
||||
char _dirname[_MAX_DIR];
|
||||
_splitpath(s.c_str(), nullptr, _dirname, nullptr, nullptr);
|
||||
t = _dirname;
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
return cleanpath(t);
|
||||
|
||||
#else
|
||||
#error "No implementation of dirname is available for this platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace filesystem
|
||||
} // namespace cpp17
|
||||
|
|
|
@ -1,138 +1,144 @@
|
|||
/* Copyright (c) 2014, Pollard Banknote Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "cleanpath.h"
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
namespace cpp17
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
/// @todo Probably belongs in path.cpp
|
||||
std::string cleanpath(const std::string& s)
|
||||
{
|
||||
std::string t;
|
||||
namespace filesystem
|
||||
{
|
||||
/// @todo Probably belongs in path.cpp
|
||||
std::string
|
||||
cleanpath(const std::string& s)
|
||||
{
|
||||
std::string t;
|
||||
|
||||
if ( s.empty() )
|
||||
{
|
||||
if(s.empty())
|
||||
{
|
||||
// error
|
||||
return t;
|
||||
}
|
||||
|
||||
// error
|
||||
return t;
|
||||
}
|
||||
const std::size_t n = s.length();
|
||||
|
||||
const std::size_t n = s.length();
|
||||
for(std::size_t i = 0; i < n;)
|
||||
{
|
||||
if(s[i] == '/')
|
||||
{
|
||||
// directory separator
|
||||
t.push_back('/');
|
||||
i = s.find_first_not_of('/', i);
|
||||
}
|
||||
else
|
||||
{
|
||||
// path component
|
||||
const std::size_t j = std::min(s.find('/', i), n);
|
||||
|
||||
for ( std::size_t i = 0; i < n;)
|
||||
{
|
||||
if ( s[i] == '/' )
|
||||
{
|
||||
// directory separator
|
||||
t.push_back('/');
|
||||
i = s.find_first_not_of('/', i);
|
||||
}
|
||||
else
|
||||
{
|
||||
// path component
|
||||
const std::size_t j = std::min(s.find('/', i), n);
|
||||
if(s.compare(i, j - i, ".", 1) == 0)
|
||||
{
|
||||
// handle dot
|
||||
if(j < n)
|
||||
{
|
||||
i = s.find_first_not_of('/', j);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = n;
|
||||
}
|
||||
}
|
||||
else if(s.compare(i, j - i, "..", 2) == 0)
|
||||
{
|
||||
// handle dot-dot
|
||||
const std::size_t l = t.length();
|
||||
|
||||
if ( s.compare(i, j - i, ".", 1) == 0 )
|
||||
{
|
||||
// handle dot
|
||||
if ( j < n )
|
||||
{
|
||||
i = s.find_first_not_of('/', j);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = n;
|
||||
}
|
||||
}
|
||||
else if ( s.compare(i, j - i, "..", 2) == 0 )
|
||||
{
|
||||
// handle dot-dot
|
||||
const std::size_t l = t.length();
|
||||
if(l == 0)
|
||||
{
|
||||
// no previous component (ex., "../src")
|
||||
t.assign("..", 2);
|
||||
i = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove previously copied component (unless root)
|
||||
if(l >= 2)
|
||||
{
|
||||
const std::size_t k = t.find_last_of('/', l - 2);
|
||||
|
||||
if ( l == 0 )
|
||||
{
|
||||
// no previous component (ex., "../src")
|
||||
t.assign("..", 2);
|
||||
i = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove previously copied component (unless root)
|
||||
if ( l >= 2 )
|
||||
{
|
||||
const std::size_t k = t.find_last_of('/', l - 2);
|
||||
if(k == std::string::npos)
|
||||
{
|
||||
t.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
t.resize(k + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if ( k == std::string::npos )
|
||||
{
|
||||
t.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
t.resize(k + 1);
|
||||
}
|
||||
}
|
||||
if(j < n)
|
||||
{
|
||||
i = s.find_first_not_of('/', j);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// append path component
|
||||
t.append(s, i, j - i);
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( j < n )
|
||||
{
|
||||
i = s.find_first_not_of('/', j);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// append path component
|
||||
t.append(s, i, j - i);
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(t.empty())
|
||||
{
|
||||
return ".";
|
||||
}
|
||||
|
||||
if ( t.empty() )
|
||||
{
|
||||
return ".";
|
||||
}
|
||||
// drop trailing slashes
|
||||
const std::size_t i = t.find_last_not_of('/');
|
||||
|
||||
// drop trailing slashes
|
||||
const std::size_t i = t.find_last_not_of('/');
|
||||
if(i != std::string::npos)
|
||||
{
|
||||
t.resize(i + 1);
|
||||
}
|
||||
|
||||
if ( i != std::string::npos )
|
||||
{
|
||||
t.resize(i + 1);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace filesystem
|
||||
} // namespace cpp17
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
/* Copyright (c) 2015, Pollard Banknote Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef PBL_CPP_FS_CLEANPATH_H
|
||||
#define PBL_CPP_FS_CLEANPATH_H
|
||||
|
@ -33,29 +34,31 @@
|
|||
|
||||
namespace cpp17
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
/** Return a simplified version of path
|
||||
*
|
||||
* @param path A file system path
|
||||
*
|
||||
* Collapses multiple path separators (ex., as in "/home//user"); replaces
|
||||
* "name/." with "name" and "parent/child/.." with "parent"; removes trailing
|
||||
* slashes.
|
||||
*
|
||||
* The returned path is equivalent to the original path in the sense that it
|
||||
* identifies the same file system object. Specifically, relative paths are
|
||||
* preserved (ex., no simplification is done to the dot-dot in "../here").
|
||||
*
|
||||
* If the path is malformed, the empty string is returned. For this function,
|
||||
* really only the empty string itself is "malformed".
|
||||
*
|
||||
* @note This is a textual operation. It does not validate the string against
|
||||
* the file system or otherwise touch the file system.
|
||||
* @bug foo/bar/../baz may not point to /foo/baz if bar symlinks to flip/flop
|
||||
*/
|
||||
std::string cleanpath(const std::string& path);
|
||||
}
|
||||
}
|
||||
namespace filesystem
|
||||
{
|
||||
/** Return a simplified version of path
|
||||
*
|
||||
* @param path A file system path
|
||||
*
|
||||
* Collapses multiple path separators (ex., as in "/home//user"); replaces
|
||||
* "name/." with "name" and "parent/child/.." with "parent"; removes
|
||||
* trailing slashes.
|
||||
*
|
||||
* The returned path is equivalent to the original path in the sense that it
|
||||
* identifies the same file system object. Specifically, relative paths are
|
||||
* preserved (ex., no simplification is done to the dot-dot in "../here").
|
||||
*
|
||||
* If the path is malformed, the empty string is returned. For this
|
||||
* function, really only the empty string itself is "malformed".
|
||||
*
|
||||
* @note This is a textual operation. It does not validate the string
|
||||
* against the file system or otherwise touch the file system.
|
||||
* @bug foo/bar/../baz may not point to /foo/baz if bar symlinks to
|
||||
* flip/flop
|
||||
*/
|
||||
std::string
|
||||
cleanpath(const std::string& path);
|
||||
} // namespace filesystem
|
||||
} // namespace cpp17
|
||||
|
||||
#endif // PBL_FS_CLEANPATH_H
|
||||
#endif // PBL_FS_CLEANPATH_H
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
/* Copyright (c) 2016, Pollard Banknote Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "create_directory.h"
|
||||
|
||||
|
@ -33,37 +34,43 @@
|
|||
#include "perms.h"
|
||||
#include "filestatus.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#define mkdir(x, y) mkdir(x)
|
||||
#endif
|
||||
|
||||
namespace cpp17
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
bool
|
||||
create_directory(const path& s, std::error_code& ec)
|
||||
{
|
||||
if(s.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool create_directory(const path& s, std::error_code& ec)
|
||||
{
|
||||
if ( s.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ::mkdir(s.c_str(), static_cast< int >(perms::all)) == 0;
|
||||
}
|
||||
|
||||
return ::mkdir( s.c_str(), static_cast< int >( perms::all ) ) == 0;
|
||||
}
|
||||
bool
|
||||
create_directories(const path& s, std::error_code& ec)
|
||||
{
|
||||
path p = s.parent_path();
|
||||
|
||||
bool create_directories(const path& s, std::error_code& ec)
|
||||
{
|
||||
path p = s.parent_path();
|
||||
|
||||
if ( !p.empty() )
|
||||
{
|
||||
if(!p.empty())
|
||||
{
|
||||
std::error_code ec, ec2;
|
||||
if ( !exists(p, ec) && !create_directories(p, ec2) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::error_code ec3;
|
||||
return create_directory(s, ec3);
|
||||
}
|
||||
if(!exists(p, ec) && !create_directories(p, ec2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
std::error_code ec3;
|
||||
return create_directory(s, ec3);
|
||||
}
|
||||
|
||||
} // namespace filesystem
|
||||
} // namespace cpp17
|
||||
|
|
|
@ -1,81 +1,87 @@
|
|||
/* Copyright (c) 2016, Pollard Banknote Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "current_path.h"
|
||||
|
||||
#include <cerrno>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
namespace cpp17
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
path current_path()
|
||||
{
|
||||
char buf[4096];
|
||||
namespace filesystem
|
||||
{
|
||||
path
|
||||
current_path()
|
||||
{
|
||||
char buf[4096];
|
||||
|
||||
if ( ::getcwd( buf, sizeof( buf ) ) )
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
if(::getcwd(buf, sizeof(buf)))
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Dynamically allocate larger buffers until cwd fits
|
||||
std::size_t size = 2 * sizeof( buf );
|
||||
// Dynamically allocate larger buffers until cwd fits
|
||||
std::size_t size = 2 * sizeof(buf);
|
||||
|
||||
while ( true )
|
||||
{
|
||||
char* q = new char[size];
|
||||
while(true)
|
||||
{
|
||||
char* q = new char[size];
|
||||
|
||||
if ( ::getcwd(q, size) )
|
||||
{
|
||||
path p = q;
|
||||
delete[] q;
|
||||
if(::getcwd(q, size))
|
||||
{
|
||||
path p = q;
|
||||
delete[] q;
|
||||
|
||||
return p;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( errno == ERANGE )
|
||||
{
|
||||
delete[] q;
|
||||
size *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(errno == ERANGE)
|
||||
{
|
||||
delete[] q;
|
||||
size *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path();
|
||||
}
|
||||
return path();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace filesystem
|
||||
} // namespace cpp17
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
/* Copyright (c) 2014, Pollard Banknote Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "diriter.h"
|
||||
|
||||
|
@ -33,442 +34,473 @@
|
|||
#include <climits>
|
||||
|
||||
#include <dirent.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include "direntry.h"
|
||||
#include "path.h"
|
||||
|
||||
namespace cpp17
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
|
||||
/// @todo Could save the malloc/free (of e) if we mark end-of-directory
|
||||
class directory_iterator::impl
|
||||
{
|
||||
public:
|
||||
impl()
|
||||
: p(), d(0), e(0), info(), valid_info(false)
|
||||
{
|
||||
//printf("directory_iterator::impl::cstr\n");
|
||||
namespace filesystem
|
||||
{
|
||||
/// @todo Could save the malloc/free (of e) if we mark end-of-directory
|
||||
class directory_iterator::impl
|
||||
{
|
||||
public:
|
||||
impl() : p(), d(0), e(0), info(), valid_info(false)
|
||||
{
|
||||
// printf("directory_iterator::impl::cstr\n");
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
explicit impl(const path& path_)
|
||||
: p(path_), d(0), e(0), info(), valid_info(false)
|
||||
{
|
||||
//printf("directory_iterator::impl::cstr path[%s]\n", path_.c_str());
|
||||
explicit impl(const path& path_)
|
||||
: p(path_), d(0), e(0), info(), valid_info(false)
|
||||
{
|
||||
// printf("directory_iterator::impl::cstr path[%s]\n", path_.c_str());
|
||||
this->cPath = path_;
|
||||
d = ::opendir( path_.c_str() );
|
||||
d = ::opendir(path_.c_str());
|
||||
|
||||
if ( d )
|
||||
{
|
||||
e = acquire();
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
~impl()
|
||||
{
|
||||
//printf("directory_iterator::impl::dstr [%s]\n", this->cPath.c_str());
|
||||
if ( d )
|
||||
{
|
||||
release(); // free e
|
||||
::closedir(d);
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rewind() {
|
||||
//printf("directory_iterator::impl::rewind\n");
|
||||
if ( d )
|
||||
if(d)
|
||||
{
|
||||
release();
|
||||
::closedir(d);
|
||||
e = acquire();
|
||||
next();
|
||||
}
|
||||
d = ::opendir( this->cPath.c_str() );
|
||||
}
|
||||
|
||||
~impl()
|
||||
{
|
||||
// printf("directory_iterator::impl::dstr [%s]\n", this->cPath.c_str());
|
||||
if(d)
|
||||
{
|
||||
release(); // free e
|
||||
::closedir(d);
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rewind()
|
||||
{
|
||||
// printf("directory_iterator::impl::rewind\n");
|
||||
if(d)
|
||||
{
|
||||
release();
|
||||
::closedir(d);
|
||||
}
|
||||
d = ::opendir(this->cPath.c_str());
|
||||
pos = 0;
|
||||
if ( d )
|
||||
if(d)
|
||||
{
|
||||
e = acquire();
|
||||
next();
|
||||
e = acquire();
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
void seek(size_t seekPos) {
|
||||
//printf("directory_iterator::impl::seek\n");
|
||||
}
|
||||
|
||||
void
|
||||
seek(size_t seekPos)
|
||||
{
|
||||
// printf("directory_iterator::impl::seek\n");
|
||||
this->rewind();
|
||||
for(size_t i = 0; i < seekPos; i++) {
|
||||
this->next();
|
||||
for(size_t i = 0; i < seekPos; i++)
|
||||
{
|
||||
this->next();
|
||||
}
|
||||
}
|
||||
|
||||
/** Test if this is an end iterator
|
||||
*/
|
||||
bool is_end() const
|
||||
{
|
||||
//printf("directory_iterator::impl::is_end\n");
|
||||
return !e;
|
||||
}
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
//printf("directory_iterator::impl::next\n");
|
||||
if ( d )
|
||||
{
|
||||
valid_info = false;
|
||||
/** Test if this is an end iterator
|
||||
*/
|
||||
bool
|
||||
is_end() const
|
||||
{
|
||||
// printf("directory_iterator::impl::is_end\n");
|
||||
return !e;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
dirent* ptr = 0;
|
||||
bool
|
||||
next()
|
||||
{
|
||||
// printf("directory_iterator::impl::next\n");
|
||||
if(d)
|
||||
{
|
||||
valid_info = false;
|
||||
|
||||
const int res = ::readdir_r(d, e, &ptr);
|
||||
do
|
||||
{
|
||||
dirent* ptr = 0;
|
||||
|
||||
if ( res != 0 || ptr == 0 )
|
||||
{
|
||||
// error, or end of directory
|
||||
pos = 0;
|
||||
release();
|
||||
const int res = ::readdir_r(d, e, &ptr);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while ( std::strcmp(e->d_name, ".") == 0 || std::strcmp(e->d_name, "..") == 0 );
|
||||
if(res != 0 || ptr == 0)
|
||||
{
|
||||
// error, or end of directory
|
||||
pos = 0;
|
||||
release();
|
||||
|
||||
pos++;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} while(std::strcmp(e->d_name, ".") == 0
|
||||
|| std::strcmp(e->d_name, "..") == 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
pos++;
|
||||
|
||||
path get_path() const
|
||||
{
|
||||
//printf("directory_iterator::impl::get_path\n");
|
||||
return e ? ( p / e->d_name ) : path();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
file_type type() const
|
||||
{
|
||||
//printf("directory_iterator::impl::type\n");
|
||||
if ( e )
|
||||
{
|
||||
switch ( e->d_type )
|
||||
{
|
||||
case DT_FIFO:
|
||||
return false;
|
||||
}
|
||||
|
||||
return file_type::fifo;
|
||||
path
|
||||
get_path() const
|
||||
{
|
||||
// printf("directory_iterator::impl::get_path\n");
|
||||
return e ? (p / e->d_name) : path();
|
||||
}
|
||||
|
||||
case DT_CHR:
|
||||
file_type
|
||||
type() const
|
||||
{
|
||||
// printf("directory_iterator::impl::type\n");
|
||||
if(e)
|
||||
{
|
||||
switch(e->d_type)
|
||||
{
|
||||
case DT_FIFO:
|
||||
|
||||
return file_type::character;
|
||||
return file_type::fifo;
|
||||
|
||||
case DT_DIR:
|
||||
case DT_CHR:
|
||||
|
||||
return file_type::directory;
|
||||
return file_type::character;
|
||||
|
||||
case DT_BLK:
|
||||
case DT_DIR:
|
||||
|
||||
return file_type::block;
|
||||
return file_type::directory;
|
||||
|
||||
case DT_REG:
|
||||
case DT_BLK:
|
||||
|
||||
return file_type::regular;
|
||||
return file_type::block;
|
||||
|
||||
case DT_LNK:
|
||||
case DT_REG:
|
||||
|
||||
return file_type::symlink;
|
||||
return file_type::regular;
|
||||
|
||||
case DT_SOCK:
|
||||
case DT_LNK:
|
||||
|
||||
return file_type::socket;
|
||||
return file_type::symlink;
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
case DT_SOCK:
|
||||
|
||||
}
|
||||
return file_type::socket;
|
||||
|
||||
return file_type::unknown;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
const directory_entry& get_reference()
|
||||
{
|
||||
//printf("directory_iterator::impl::get_reference\n");
|
||||
update();
|
||||
return file_type::unknown;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
const directory_entry&
|
||||
get_reference()
|
||||
{
|
||||
// printf("directory_iterator::impl::get_reference\n");
|
||||
update();
|
||||
|
||||
const directory_entry* get_pointer()
|
||||
{
|
||||
//printf("directory_iterator::impl::get_pointer\n");
|
||||
update();
|
||||
return info;
|
||||
}
|
||||
|
||||
return &info;
|
||||
}
|
||||
const directory_entry*
|
||||
get_pointer()
|
||||
{
|
||||
// printf("directory_iterator::impl::get_pointer\n");
|
||||
update();
|
||||
|
||||
/// Position
|
||||
size_t pos;
|
||||
return &info;
|
||||
}
|
||||
|
||||
// Path to directory
|
||||
path p;
|
||||
|
||||
private:
|
||||
void update()
|
||||
{
|
||||
//printf("directory_iterator::impl::update\n");
|
||||
if ( !valid_info && e )
|
||||
{
|
||||
const path q = p / e->d_name;
|
||||
/// Position
|
||||
size_t pos;
|
||||
|
||||
info.assign(q);
|
||||
valid_info = true;
|
||||
}
|
||||
}
|
||||
// Path to directory
|
||||
path p;
|
||||
|
||||
static dirent* acquire()
|
||||
{
|
||||
//printf("directory_iterator::impl::acquire\n");
|
||||
/* dirent::d_name is required to be at least NAME_MAX + 1 bytes.
|
||||
* However, some implementations use the struct hack and make d_name
|
||||
* 1 byte. Watch for this scenario and adjust accordingly.
|
||||
*/
|
||||
if ( sizeof( static_cast< dirent* >( 0 )->d_name ) < NAME_MAX + 1 )
|
||||
{
|
||||
return static_cast< dirent* >( ::malloc(sizeof( dirent ) + NAME_MAX + 1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast< dirent* >( ::malloc( sizeof( dirent ) ) );
|
||||
}
|
||||
}
|
||||
private:
|
||||
void
|
||||
update()
|
||||
{
|
||||
// printf("directory_iterator::impl::update\n");
|
||||
if(!valid_info && e)
|
||||
{
|
||||
const path q = p / e->d_name;
|
||||
|
||||
void release()
|
||||
{
|
||||
//printf("directory_iterator::impl::release\n");
|
||||
::free(e);
|
||||
e = 0;
|
||||
}
|
||||
info.assign(q);
|
||||
valid_info = true;
|
||||
}
|
||||
}
|
||||
|
||||
// constructor path
|
||||
path cPath;
|
||||
static dirent*
|
||||
acquire()
|
||||
{
|
||||
// printf("directory_iterator::impl::acquire\n");
|
||||
/* dirent::d_name is required to be at least NAME_MAX + 1 bytes.
|
||||
* However, some implementations use the struct hack and make d_name
|
||||
* 1 byte. Watch for this scenario and adjust accordingly.
|
||||
*/
|
||||
if(sizeof(static_cast< dirent* >(0)->d_name) < NAME_MAX + 1)
|
||||
{
|
||||
return static_cast< dirent* >(
|
||||
::malloc(sizeof(dirent) + NAME_MAX + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast< dirent* >(::malloc(sizeof(dirent)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Platform information
|
||||
DIR* d;
|
||||
void
|
||||
release()
|
||||
{
|
||||
// printf("directory_iterator::impl::release\n");
|
||||
::free(e);
|
||||
e = 0;
|
||||
}
|
||||
|
||||
/// Platform information
|
||||
dirent* e;
|
||||
|
||||
directory_entry info;
|
||||
// constructor path
|
||||
path cPath;
|
||||
|
||||
bool valid_info; // info has been populated
|
||||
};
|
||||
|
||||
|
||||
/// Platform information
|
||||
DIR* d;
|
||||
|
||||
directory_iterator::directory_iterator()
|
||||
: pimpl(new impl)
|
||||
{
|
||||
}
|
||||
/// Platform information
|
||||
dirent* e;
|
||||
|
||||
directory_iterator::directory_iterator(const path& path_)
|
||||
: pimpl( new impl(path_) )
|
||||
{
|
||||
}
|
||||
|
||||
// is this right
|
||||
directory_iterator::directory_iterator(directory_iterator const &src)
|
||||
{
|
||||
//printf("directory_iterator::directory_iterator copy - pimpl[%x] from[%s]\n", pimpl, src->path().c_str());
|
||||
if (pimpl)
|
||||
directory_entry info;
|
||||
|
||||
bool valid_info; // info has been populated
|
||||
};
|
||||
|
||||
directory_iterator::directory_iterator() : pimpl(new impl)
|
||||
{
|
||||
//delete pimpl;
|
||||
}
|
||||
pimpl = new impl(src.pimpl->p.c_str());
|
||||
pimpl->seek(src.pimpl->pos);
|
||||
}
|
||||
|
||||
directory_iterator::~directory_iterator()
|
||||
{
|
||||
delete pimpl;
|
||||
}
|
||||
|
||||
directory_iterator::directory_iterator(directory_iterator const &src, int pos) {
|
||||
//printf("directory_iterator::directory_iterator copy at pos - pimpl[%x] from[%s]\n", pimpl, src->path().c_str());
|
||||
pimpl = new impl(src.pimpl->p.c_str());
|
||||
pimpl->seek(pos);
|
||||
}
|
||||
|
||||
bool directory_iterator::operator==(const directory_iterator& i) const
|
||||
{
|
||||
|
||||
// only equal if both are end iterators
|
||||
return pimpl->is_end() && i.pimpl->is_end();
|
||||
}
|
||||
|
||||
bool directory_iterator::operator!=(const directory_iterator& i) const
|
||||
{
|
||||
return !( pimpl->is_end() && i.pimpl->is_end() );
|
||||
}
|
||||
|
||||
directory_iterator& directory_iterator::operator++()
|
||||
{
|
||||
pimpl->next();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const directory_entry& directory_iterator::operator*() const
|
||||
{
|
||||
return pimpl->get_reference();
|
||||
}
|
||||
|
||||
const directory_entry* directory_iterator::operator->() const
|
||||
{
|
||||
return pimpl->get_pointer();
|
||||
}
|
||||
|
||||
file_type directory_iterator::type() const
|
||||
{
|
||||
return pimpl->type();
|
||||
}
|
||||
|
||||
void directory_iterator::swap(directory_iterator& d)
|
||||
{
|
||||
std::swap(pimpl, d.pimpl);
|
||||
}
|
||||
|
||||
// FIXME: this isn't right
|
||||
directory_iterator directory_iterator::begin() {
|
||||
return directory_iterator( *this, 0 );
|
||||
/*
|
||||
printf("directory_iterator::directory_iterator::begin - start\n");
|
||||
size_t cur = pimpl->pos; // backup state
|
||||
printf("directory_iterator::directory_iterator::begin - was at [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
|
||||
pimpl->rewind();
|
||||
directory_iterator *ret = new directory_iterator(*this); // copy ourself
|
||||
pimpl->seek(cur); // restore state
|
||||
printf("directory_iterator::directory_iterator::begin - end\n");
|
||||
return *ret;
|
||||
*/
|
||||
}
|
||||
directory_iterator directory_iterator::end() {
|
||||
//return *(directory_iterator *)endPtr;
|
||||
//printf("directory_iterator::directory_iterator::end - start\n");
|
||||
size_t cur = pimpl->pos; // backup state
|
||||
//printf("directory_iterator::directory_iterator::end - was at [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
|
||||
// spool to the end
|
||||
size_t finalPos = pimpl->pos;
|
||||
while( !pimpl->is_end() )
|
||||
directory_iterator::directory_iterator(const path& path_)
|
||||
: pimpl(new impl(path_))
|
||||
{
|
||||
if (pimpl->next()) {
|
||||
finalPos = pimpl->pos;
|
||||
}
|
||||
|
||||
// is this right
|
||||
directory_iterator::directory_iterator(directory_iterator const& src)
|
||||
{
|
||||
// printf("directory_iterator::directory_iterator copy - pimpl[%x]
|
||||
// from[%s]\n", pimpl, src->path().c_str());
|
||||
if(pimpl)
|
||||
{
|
||||
// delete pimpl;
|
||||
}
|
||||
pimpl = new impl(src.pimpl->p.c_str());
|
||||
pimpl->seek(src.pimpl->pos);
|
||||
}
|
||||
|
||||
directory_iterator::~directory_iterator()
|
||||
{
|
||||
delete pimpl;
|
||||
}
|
||||
|
||||
directory_iterator::directory_iterator(directory_iterator const& src,
|
||||
int pos)
|
||||
{
|
||||
// printf("directory_iterator::directory_iterator copy at pos - pimpl[%x]
|
||||
// from[%s]\n", pimpl, src->path().c_str());
|
||||
pimpl = new impl(src.pimpl->p.c_str());
|
||||
pimpl->seek(pos);
|
||||
}
|
||||
|
||||
bool
|
||||
directory_iterator::operator==(const directory_iterator& i) const
|
||||
{
|
||||
// only equal if both are end iterators
|
||||
return pimpl->is_end() && i.pimpl->is_end();
|
||||
}
|
||||
|
||||
bool
|
||||
directory_iterator::operator!=(const directory_iterator& i) const
|
||||
{
|
||||
return !(pimpl->is_end() && i.pimpl->is_end());
|
||||
}
|
||||
|
||||
directory_iterator&
|
||||
directory_iterator::operator++()
|
||||
{
|
||||
pimpl->next();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const directory_entry& directory_iterator::operator*() const
|
||||
{
|
||||
return pimpl->get_reference();
|
||||
}
|
||||
|
||||
const directory_entry* directory_iterator::operator->() const
|
||||
{
|
||||
return pimpl->get_pointer();
|
||||
}
|
||||
|
||||
file_type
|
||||
directory_iterator::type() const
|
||||
{
|
||||
return pimpl->type();
|
||||
}
|
||||
|
||||
void
|
||||
directory_iterator::swap(directory_iterator& d)
|
||||
{
|
||||
std::swap(pimpl, d.pimpl);
|
||||
}
|
||||
|
||||
// FIXME: this isn't right
|
||||
directory_iterator
|
||||
directory_iterator::begin()
|
||||
{
|
||||
return directory_iterator(*this, 0);
|
||||
/*
|
||||
printf("directory_iterator::directory_iterator::begin - start\n");
|
||||
size_t cur = pimpl->pos; // backup state
|
||||
printf("directory_iterator::directory_iterator::begin - was at
|
||||
[%zu][%s]\n", cur, this->pimpl->get_path().c_str()); pimpl->rewind();
|
||||
directory_iterator *ret = new directory_iterator(*this); // copy ourself
|
||||
pimpl->seek(cur); // restore state
|
||||
printf("directory_iterator::directory_iterator::begin - end\n");
|
||||
return *ret;
|
||||
*/
|
||||
}
|
||||
directory_iterator
|
||||
directory_iterator::end()
|
||||
{
|
||||
// return *(directory_iterator *)endPtr;
|
||||
// printf("directory_iterator::directory_iterator::end - start\n");
|
||||
size_t cur = pimpl->pos; // backup state
|
||||
// printf("directory_iterator::directory_iterator::end - was at
|
||||
// [%zu][%s]\n", cur, this->pimpl->get_path().c_str());
|
||||
// spool to the end
|
||||
size_t finalPos = pimpl->pos;
|
||||
while(!pimpl->is_end())
|
||||
{
|
||||
if(pimpl->next())
|
||||
{
|
||||
finalPos = pimpl->pos;
|
||||
}
|
||||
}
|
||||
// directory_iterator *ret = new directory_iterator(*this); // copy
|
||||
// ourself printf("directory_iterator::directory_iterator::end - now at
|
||||
// [%zu][%s]\n", pimpl->pos, this->pimpl->get_path().c_str());
|
||||
pimpl->seek(cur); // restore state
|
||||
return directory_iterator(*this, finalPos);
|
||||
// printf("directory_iterator::directory_iterator::end - end\n");
|
||||
// return *ret;
|
||||
}
|
||||
|
||||
//
|
||||
// recursive_directory_iterator
|
||||
//
|
||||
|
||||
recursive_directory_iterator::recursive_directory_iterator()
|
||||
{
|
||||
}
|
||||
|
||||
recursive_directory_iterator::recursive_directory_iterator(const path& p)
|
||||
{
|
||||
descend(p);
|
||||
}
|
||||
|
||||
recursive_directory_iterator::~recursive_directory_iterator()
|
||||
{
|
||||
while(!stack.empty())
|
||||
{
|
||||
ascend();
|
||||
}
|
||||
}
|
||||
//directory_iterator *ret = new directory_iterator(*this); // copy ourself
|
||||
//printf("directory_iterator::directory_iterator::end - now at [%zu][%s]\n", pimpl->pos, this->pimpl->get_path().c_str());
|
||||
pimpl->seek(cur); // restore state
|
||||
return directory_iterator( *this, finalPos);
|
||||
//printf("directory_iterator::directory_iterator::end - end\n");
|
||||
//return *ret;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// recursive_directory_iterator
|
||||
//
|
||||
|
||||
recursive_directory_iterator::recursive_directory_iterator()
|
||||
{
|
||||
}
|
||||
bool
|
||||
recursive_directory_iterator::descend(const path& p)
|
||||
{
|
||||
directory_iterator it(p), end;
|
||||
|
||||
recursive_directory_iterator::recursive_directory_iterator(const path& p)
|
||||
{
|
||||
descend(p);
|
||||
}
|
||||
if(it != end)
|
||||
{
|
||||
directory_iterator* jt = new directory_iterator();
|
||||
jt->swap(it);
|
||||
stack.push(jt);
|
||||
|
||||
recursive_directory_iterator::~recursive_directory_iterator()
|
||||
{
|
||||
while ( !stack.empty() )
|
||||
{
|
||||
ascend();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool recursive_directory_iterator::descend(const path& p)
|
||||
{
|
||||
directory_iterator it(p), end;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( it != end )
|
||||
{
|
||||
directory_iterator* jt = new directory_iterator();
|
||||
jt->swap(it);
|
||||
stack.push(jt);
|
||||
void
|
||||
recursive_directory_iterator::ascend()
|
||||
{
|
||||
delete stack.top();
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
const directory_entry& recursive_directory_iterator::operator*() const
|
||||
{
|
||||
return *(*stack.top());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
const directory_entry* recursive_directory_iterator::operator->() const
|
||||
{
|
||||
return stack.top()->operator->();
|
||||
}
|
||||
|
||||
void recursive_directory_iterator::ascend()
|
||||
{
|
||||
delete stack.top();
|
||||
stack.pop();
|
||||
}
|
||||
recursive_directory_iterator&
|
||||
recursive_directory_iterator::operator++()
|
||||
{
|
||||
if(stack.top()->type() == file_type::directory)
|
||||
{
|
||||
// go to directory's first child (if any)
|
||||
if(descend((*stack.top())->path()))
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
const directory_entry& recursive_directory_iterator::operator*() const
|
||||
{
|
||||
return *( *stack.top() );
|
||||
}
|
||||
do
|
||||
{
|
||||
// move to sibling
|
||||
stack.top()->operator++();
|
||||
|
||||
const directory_entry* recursive_directory_iterator::operator->() const
|
||||
{
|
||||
return stack.top()->operator->();
|
||||
}
|
||||
directory_iterator end;
|
||||
|
||||
recursive_directory_iterator& recursive_directory_iterator::operator++()
|
||||
{
|
||||
if ( stack.top()->type() == file_type::directory )
|
||||
{
|
||||
// go to directory's first child (if any)
|
||||
if ( descend( ( *stack.top() )->path() ) )
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
if(*(stack.top()) != end)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// move to sibling
|
||||
stack.top()->operator++();
|
||||
// move to parent
|
||||
ascend();
|
||||
} while(!stack.empty());
|
||||
|
||||
directory_iterator end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if ( *( stack.top() ) != end )
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
bool
|
||||
recursive_directory_iterator::operator==(
|
||||
const recursive_directory_iterator& i) const
|
||||
{
|
||||
return stack.empty() && i.stack.empty();
|
||||
}
|
||||
|
||||
// move to parent
|
||||
ascend();
|
||||
}
|
||||
while ( !stack.empty() );
|
||||
bool
|
||||
recursive_directory_iterator::operator!=(
|
||||
const recursive_directory_iterator& i) const
|
||||
{
|
||||
return !(stack.empty() && i.stack.empty());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool recursive_directory_iterator::operator==(const recursive_directory_iterator& i) const
|
||||
{
|
||||
return stack.empty() && i.stack.empty();
|
||||
}
|
||||
|
||||
bool recursive_directory_iterator::operator!=(const recursive_directory_iterator& i) const
|
||||
{
|
||||
return !( stack.empty() && i.stack.empty() );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace filesystem
|
||||
} // namespace cpp17
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace cpp17
|
||||
{
|
||||
|
|
|
@ -1,281 +1,404 @@
|
|||
/* Copyright (c) 2015, Pollard Banknote Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "filestatus.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "path.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Windows.h>
|
||||
#include <stdint.h>
|
||||
#include <io.h>
|
||||
|
||||
typedef unsigned short mode_t;
|
||||
typedef uint32_t id_t; /* Internal uids/gids are 32-bits */
|
||||
|
||||
typedef SSIZE_T ssize_t;
|
||||
#ifndef _OFF_T_DEFINED
|
||||
typedef DWORD64 off_t;
|
||||
#endif
|
||||
typedef uint32_t uid_t; /* [???] user IDs */
|
||||
|
||||
#ifndef S_IFIFO
|
||||
#define S_IFIFO 0010000 /* [XSI] named pipe (fifo) */
|
||||
#endif
|
||||
|
||||
#ifndef S_IFBLK
|
||||
#define S_IFBLK 0060000 /* [XSI] block special */
|
||||
#endif
|
||||
|
||||
#ifndef S_IFLNK
|
||||
#define S_IFLNK 0120000 /* [XSI] symbolic link */
|
||||
#endif
|
||||
|
||||
#ifndef S_IFSOCK
|
||||
#define S_IFSOCK 0140000 /* [XSI] socket */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISBLK
|
||||
#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block special */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISCHR
|
||||
#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* char special */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISFIFO
|
||||
#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo or socket */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* regular file */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISSOCK
|
||||
#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */
|
||||
#endif
|
||||
|
||||
#ifndef makedev
|
||||
#define makedev(x, y) ((dev_t)(((x) << 24) | (y)))
|
||||
#endif
|
||||
|
||||
#ifndef DT_UNKNOWN
|
||||
#define DT_UNKNOWN 0
|
||||
#endif
|
||||
|
||||
#ifndef DT_FIFO
|
||||
#define DT_FIFO 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_CHR
|
||||
#define DT_CHR 2
|
||||
#endif
|
||||
|
||||
#ifndef DT_DIR
|
||||
#define DT_DIR 4
|
||||
#endif
|
||||
|
||||
#ifndef DT_BLK
|
||||
#define DT_BLK 6
|
||||
#endif
|
||||
|
||||
#ifndef DT_REG
|
||||
#define DT_REG 8
|
||||
#endif
|
||||
|
||||
#ifndef DT_LNK
|
||||
#define DT_LNK 10
|
||||
#endif
|
||||
|
||||
#ifndef DT_SOCK
|
||||
#define DT_SOCK 12
|
||||
#endif
|
||||
|
||||
#ifndef DT_WHT
|
||||
#define DT_WHT 14
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
::cpp17::filesystem::file_status from_mode_t(mode_t m)
|
||||
{
|
||||
::cpp17::filesystem::perms p = static_cast< ::cpp17::filesystem::perms >( m & 0xFFF );
|
||||
::cpp17::filesystem::file_status
|
||||
from_mode_t(mode_t m)
|
||||
{
|
||||
::cpp17::filesystem::perms p =
|
||||
static_cast<::cpp17::filesystem::perms >(m & 0xFFF);
|
||||
|
||||
::cpp17::filesystem::file_type t = file_type::unknown;
|
||||
::cpp17::filesystem::file_type t = file_type::unknown;
|
||||
|
||||
if ( S_ISREG(m) )
|
||||
{
|
||||
t = file_type::regular;
|
||||
}
|
||||
else if ( S_ISDIR(m) )
|
||||
{
|
||||
t = file_type::directory;
|
||||
}
|
||||
else if ( S_ISCHR(m) )
|
||||
{
|
||||
t = file_type::character;
|
||||
}
|
||||
else if ( S_ISBLK(m) )
|
||||
{
|
||||
t = file_type::block;
|
||||
}
|
||||
else if ( S_ISFIFO(m) )
|
||||
{
|
||||
t = file_type::fifo;
|
||||
}
|
||||
if(S_ISREG(m))
|
||||
{
|
||||
t = file_type::regular;
|
||||
}
|
||||
else if(S_ISDIR(m))
|
||||
{
|
||||
t = file_type::directory;
|
||||
}
|
||||
else if(S_ISCHR(m))
|
||||
{
|
||||
t = file_type::character;
|
||||
}
|
||||
else if(S_ISBLK(m))
|
||||
{
|
||||
t = file_type::block;
|
||||
}
|
||||
else if(S_ISFIFO(m))
|
||||
{
|
||||
t = file_type::fifo;
|
||||
}
|
||||
#ifndef _WIN32 // these only work on cygnus or msys2!
|
||||
else if(S_ISLNK(m))
|
||||
{
|
||||
t = file_type::symlink;
|
||||
}
|
||||
else if ( S_ISSOCK(m) )
|
||||
{
|
||||
t = file_type::socket;
|
||||
}
|
||||
else if(S_ISLNK(m))
|
||||
{
|
||||
t = file_type::symlink;
|
||||
}
|
||||
else if(S_ISSOCK(m))
|
||||
{
|
||||
t = file_type::socket;
|
||||
}
|
||||
#endif
|
||||
return ::cpp17::filesystem::file_status(t, p);
|
||||
}
|
||||
return ::cpp17::filesystem::file_status(t, p);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace cpp17
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
file_status::file_status(const file_status& s)
|
||||
: t(s.t), p(s.p)
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
file_status::file_status(const file_status& s) : t(s.t), p(s.p)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
file_status::file_status(file_type t_, perms p_) : t(t_), p(p_)
|
||||
{
|
||||
}
|
||||
|
||||
file_status::file_status(
|
||||
file_type t_,
|
||||
perms p_
|
||||
)
|
||||
: t(t_), p(p_)
|
||||
{
|
||||
file_status&
|
||||
file_status::operator=(const file_status& s)
|
||||
{
|
||||
t = s.t;
|
||||
p = s.p;
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
file_status& file_status::operator=(const file_status& s)
|
||||
{
|
||||
t = s.t;
|
||||
p = s.p;
|
||||
file_type
|
||||
file_status::type() const
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
void
|
||||
file_status::type(file_type t_)
|
||||
{
|
||||
t = t_;
|
||||
}
|
||||
|
||||
file_type file_status::type() const
|
||||
{
|
||||
return t;
|
||||
}
|
||||
perms
|
||||
file_status::permissions() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
void file_status::type(file_type t_)
|
||||
{
|
||||
t = t_;
|
||||
}
|
||||
void
|
||||
file_status::permissions(perms p_)
|
||||
{
|
||||
p = p_;
|
||||
}
|
||||
|
||||
perms file_status::permissions() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const file_status& fs)
|
||||
{
|
||||
os << fs.type() << "; " << fs.permissions();
|
||||
|
||||
void file_status::permissions(perms p_)
|
||||
{
|
||||
p = p_;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(
|
||||
std::ostream& os,
|
||||
const file_status& fs
|
||||
)
|
||||
{
|
||||
os << fs.type() << "; " << fs.permissions();
|
||||
file_status
|
||||
status(const path& path_)
|
||||
{
|
||||
if(!path_.empty())
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
return os;
|
||||
}
|
||||
if(::stat(path_.c_str(), &st) == 0)
|
||||
{
|
||||
return from_mode_t(st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
file_status status(const path& path_)
|
||||
{
|
||||
if ( !path_.empty() )
|
||||
{
|
||||
struct stat st;
|
||||
return file_status();
|
||||
}
|
||||
|
||||
if ( ::stat(path_.c_str(), &st) == 0 )
|
||||
{
|
||||
return from_mode_t(st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
return file_status();
|
||||
}
|
||||
|
||||
file_status symlink_status(const path& path_)
|
||||
{
|
||||
if ( !path_.empty() )
|
||||
{
|
||||
struct stat st;
|
||||
file_status
|
||||
symlink_status(const path& path_)
|
||||
{
|
||||
if(!path_.empty())
|
||||
{
|
||||
struct stat st;
|
||||
#ifndef _WIN32
|
||||
if(::lstat(path_.c_str(), &st) == 0)
|
||||
if(::lstat(path_.c_str(), &st) == 0)
|
||||
#else
|
||||
if(::stat(path_.c_str(), &st) == 0)
|
||||
if(::stat(path_.c_str(), &st) == 0)
|
||||
#endif
|
||||
{
|
||||
return from_mode_t(st.st_mode);
|
||||
}
|
||||
}
|
||||
return file_status();
|
||||
}
|
||||
{
|
||||
return from_mode_t(st.st_mode);
|
||||
}
|
||||
}
|
||||
return file_status();
|
||||
}
|
||||
|
||||
bool status_known(file_status s)
|
||||
{
|
||||
return s.type() != file_type::none;
|
||||
}
|
||||
bool
|
||||
status_known(file_status s)
|
||||
{
|
||||
return s.type() != file_type::none;
|
||||
}
|
||||
|
||||
bool exists(file_status s)
|
||||
{
|
||||
return status_known(s) && s.type() != file_type::not_found;
|
||||
}
|
||||
bool
|
||||
exists(file_status s)
|
||||
{
|
||||
return status_known(s) && s.type() != file_type::not_found;
|
||||
}
|
||||
|
||||
bool exists(const path& p, std::error_code& ec)
|
||||
{
|
||||
return exists( status(p) );
|
||||
}
|
||||
bool
|
||||
exists(const path& p, std::error_code& ec)
|
||||
{
|
||||
return exists(status(p));
|
||||
}
|
||||
|
||||
bool is_block_file(file_status s)
|
||||
{
|
||||
return s.type() == file_type::block;
|
||||
}
|
||||
bool
|
||||
is_block_file(file_status s)
|
||||
{
|
||||
return s.type() == file_type::block;
|
||||
}
|
||||
|
||||
bool is_block_file(const path& p)
|
||||
{
|
||||
return is_block_file( status(p) );
|
||||
}
|
||||
bool
|
||||
is_block_file(const path& p)
|
||||
{
|
||||
return is_block_file(status(p));
|
||||
}
|
||||
|
||||
bool is_character_file(file_status s)
|
||||
{
|
||||
return s.type() == file_type::character;
|
||||
}
|
||||
bool
|
||||
is_character_file(file_status s)
|
||||
{
|
||||
return s.type() == file_type::character;
|
||||
}
|
||||
|
||||
bool is_character_file(const path& p)
|
||||
{
|
||||
return is_character_file( status(p) );
|
||||
}
|
||||
bool
|
||||
is_character_file(const path& p)
|
||||
{
|
||||
return is_character_file(status(p));
|
||||
}
|
||||
|
||||
bool is_fifo(file_status s)
|
||||
{
|
||||
return s.type() == file_type::fifo;
|
||||
}
|
||||
bool
|
||||
is_fifo(file_status s)
|
||||
{
|
||||
return s.type() == file_type::fifo;
|
||||
}
|
||||
|
||||
bool is_fifo(const path& p)
|
||||
{
|
||||
return is_fifo( status(p) );
|
||||
}
|
||||
bool
|
||||
is_fifo(const path& p)
|
||||
{
|
||||
return is_fifo(status(p));
|
||||
}
|
||||
|
||||
bool is_other(file_status s)
|
||||
{
|
||||
return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s);
|
||||
}
|
||||
bool
|
||||
is_other(file_status s)
|
||||
{
|
||||
return exists(s) && !is_regular_file(s) && !is_directory(s)
|
||||
&& !is_symlink(s);
|
||||
}
|
||||
|
||||
bool is_other(const path& p)
|
||||
{
|
||||
return is_other( status(p) );
|
||||
}
|
||||
bool
|
||||
is_other(const path& p)
|
||||
{
|
||||
return is_other(status(p));
|
||||
}
|
||||
|
||||
bool is_regular_file(file_status s)
|
||||
{
|
||||
return s.type() == file_type::regular;
|
||||
}
|
||||
bool
|
||||
is_regular_file(file_status s)
|
||||
{
|
||||
return s.type() == file_type::regular;
|
||||
}
|
||||
|
||||
bool is_regular_file(const path& p)
|
||||
{
|
||||
return is_regular_file( status(p) );
|
||||
}
|
||||
bool
|
||||
is_regular_file(const path& p)
|
||||
{
|
||||
return is_regular_file(status(p));
|
||||
}
|
||||
|
||||
bool is_socket(file_status s)
|
||||
{
|
||||
return s.type() == file_type::socket;
|
||||
}
|
||||
bool
|
||||
is_socket(file_status s)
|
||||
{
|
||||
return s.type() == file_type::socket;
|
||||
}
|
||||
|
||||
bool is_socket(const path& p)
|
||||
{
|
||||
return is_socket( status(p) );
|
||||
}
|
||||
bool
|
||||
is_socket(const path& p)
|
||||
{
|
||||
return is_socket(status(p));
|
||||
}
|
||||
|
||||
bool is_symlink(file_status s)
|
||||
{
|
||||
return s.type() == file_type::symlink;
|
||||
}
|
||||
bool
|
||||
is_symlink(file_status s)
|
||||
{
|
||||
return s.type() == file_type::symlink;
|
||||
}
|
||||
|
||||
bool is_symlink(const path& p)
|
||||
{
|
||||
return is_symlink( status(p) );
|
||||
}
|
||||
bool
|
||||
is_symlink(const path& p)
|
||||
{
|
||||
return is_symlink(status(p));
|
||||
}
|
||||
|
||||
bool is_directory(file_status s)
|
||||
{
|
||||
return s.type() == file_type::directory;
|
||||
}
|
||||
bool
|
||||
is_directory(file_status s)
|
||||
{
|
||||
return s.type() == file_type::directory;
|
||||
}
|
||||
|
||||
bool is_directory(const path& p)
|
||||
{
|
||||
return is_directory( status(p) );
|
||||
}
|
||||
bool
|
||||
is_directory(const path& p)
|
||||
{
|
||||
return is_directory(status(p));
|
||||
}
|
||||
|
||||
std::size_t file_size(const path& p)
|
||||
{
|
||||
if ( !p.empty() )
|
||||
{
|
||||
struct stat st;
|
||||
std::size_t
|
||||
file_size(const path& p)
|
||||
{
|
||||
if(!p.empty())
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if ( ::stat(p.c_str(), &st) == 0 )
|
||||
{
|
||||
return st.st_size;
|
||||
}
|
||||
}
|
||||
if(::stat(p.c_str(), &st) == 0)
|
||||
{
|
||||
return st.st_size;
|
||||
}
|
||||
}
|
||||
|
||||
return std::size_t(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::size_t(-1);
|
||||
}
|
||||
} // namespace filesystem
|
||||
} // namespace cpp17
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -72,7 +72,7 @@ tuntap_sys_start(struct device *dev, int mode, int tun)
|
|||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
|
||||
return -1;
|
||||
}
|
||||
// ifr.ifr_flags |= IFF_NO_PI;
|
||||
ifr.ifr_flags |= IFF_NO_PI;
|
||||
|
||||
if(tun < 0)
|
||||
{
|
||||
|
|
|
@ -135,7 +135,6 @@ tuntap_sys_start(struct device *dev, int mode, int tun) {
|
|||
"Can't get link-layer address");
|
||||
return fd;
|
||||
}
|
||||
(void)memcpy(dev->hwaddr, &addr, ETHER_ADDR_LEN);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -21,353 +21,427 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
/*#include <strsafe.h>*/
|
||||
#include "tuntap.h"
|
||||
|
||||
// DDK macros
|
||||
#define CTL_CODE(DeviceType, Function, Method, Access) \
|
||||
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
|
||||
#define FILE_DEVICE_UNKNOWN 0x00000022
|
||||
#define FILE_ANY_ACCESS 0x00000000
|
||||
#define METHOD_BUFFERED 0
|
||||
|
||||
/* From OpenVPN tap driver, common.h */
|
||||
#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
|
||||
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE (10, METHOD_BUFFERED)
|
||||
#define TAP_CONTROL_CODE(request, method) \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
|
||||
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE(2, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE(3, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE(4, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE(5, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(6, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE(7, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE(8, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE(9, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE(10, METHOD_BUFFERED)
|
||||
|
||||
/* Windows registry crap */
|
||||
#define MAX_KEY_LENGTH 255
|
||||
#define MAX_VALUE_NAME 16383
|
||||
#define NETWORK_ADAPTERS "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
||||
#define NETWORK_ADAPTERS \
|
||||
"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-" \
|
||||
"08002BE10318}"
|
||||
#define ETHER_ADDR_LEN 6
|
||||
|
||||
/* From OpenVPN tap driver, proto.h */
|
||||
typedef unsigned long IPADDR;
|
||||
|
||||
/* This one is from Fabien Pichot, in the tNETacle source code */
|
||||
static LPWSTR
|
||||
formated_error(LPWSTR pMessage, DWORD m, ...) {
|
||||
LPWSTR pBuffer = NULL;
|
||||
formated_error(LPWSTR pMessage, DWORD m, ...)
|
||||
{
|
||||
LPWSTR pBuffer = NULL;
|
||||
|
||||
va_list args = NULL;
|
||||
va_start(args, pMessage);
|
||||
va_list args = NULL;
|
||||
va_start(args, pMessage);
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
pMessage,
|
||||
m,
|
||||
0,
|
||||
(LPSTR)&pBuffer,
|
||||
0,
|
||||
&args);
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
pMessage, m, 0, (LPSTR)&pBuffer, 0, &args);
|
||||
|
||||
va_end(args);
|
||||
va_end(args);
|
||||
|
||||
return pBuffer;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
/* TODO: Rework to be more generic and allow arbitrary key modification (MTU and stuff) */
|
||||
/* TODO: Rework to be more generic and allow arbitrary key modification (MTU and
|
||||
* stuff) */
|
||||
static char *
|
||||
reg_query(char *key_name) {
|
||||
HKEY adapters, adapter;
|
||||
DWORD i, ret, len;
|
||||
char *deviceid = NULL;
|
||||
DWORD sub_keys = 0;
|
||||
reg_query(char *key_name)
|
||||
{
|
||||
HKEY adapters, adapter;
|
||||
DWORD i, ret, len;
|
||||
char *deviceid = NULL;
|
||||
DWORD sub_keys = 0;
|
||||
|
||||
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key_name), 0, KEY_READ, &adapters);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
|
||||
return NULL;
|
||||
}
|
||||
ret =
|
||||
RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(key_name), 0, KEY_READ, &adapters);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = RegQueryInfoKey(adapters, NULL, NULL, NULL, &sub_keys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
|
||||
return NULL;
|
||||
}
|
||||
ret = RegQueryInfoKey(adapters, NULL, NULL, NULL, &sub_keys, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sub_keys <= 0) {
|
||||
tuntap_log(TUNTAP_LOG_DEBUG, "Wrong registry key");
|
||||
return NULL;
|
||||
}
|
||||
if(sub_keys <= 0)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_DEBUG, "Wrong registry key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Walk througt all adapters */
|
||||
for (i = 0; i < sub_keys; i++) {
|
||||
char new_key[MAX_KEY_LENGTH];
|
||||
char data[256];
|
||||
TCHAR key[MAX_KEY_LENGTH];
|
||||
DWORD keylen = MAX_KEY_LENGTH;
|
||||
/* Walk througt all adapters */
|
||||
for(i = 0; i < sub_keys; i++)
|
||||
{
|
||||
char new_key[MAX_KEY_LENGTH];
|
||||
char data[256];
|
||||
TCHAR key[MAX_KEY_LENGTH];
|
||||
DWORD keylen = MAX_KEY_LENGTH;
|
||||
|
||||
/* Get the adapter key name */
|
||||
ret = RegEnumKeyEx(adapters, i, key, &keylen, NULL, NULL, NULL, NULL);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Append it to NETWORK_ADAPTERS and open it */
|
||||
snprintf(new_key, sizeof new_key, "%s\\%s", key_name, key);
|
||||
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(new_key), 0, KEY_READ, &adapter);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
/* Get the adapter key name */
|
||||
ret = RegEnumKeyEx(adapters, i, key, &keylen, NULL, NULL, NULL, NULL);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check its values */
|
||||
len = sizeof data;
|
||||
ret = RegQueryValueEx(adapter, "ComponentId", NULL, NULL, (LPBYTE)data, &len);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
/* This value doesn't exist in this adaptater tree */
|
||||
goto clean;
|
||||
}
|
||||
/* If its a tap adapter, its all good */
|
||||
if (strncmp(data, "tap", 3) == 0) {
|
||||
DWORD type;
|
||||
/* Append it to NETWORK_ADAPTERS and open it */
|
||||
snprintf(new_key, sizeof new_key, "%s\\%s", key_name, key);
|
||||
ret =
|
||||
RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(new_key), 0, KEY_READ, &adapter);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
len = sizeof data;
|
||||
ret = RegQueryValueEx(adapter, "NetCfgInstanceId", NULL, &type, (LPBYTE)data, &len);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
tuntap_log(TUNTAP_LOG_INFO, (const char *)formated_error(L"%1", ret));
|
||||
goto clean;
|
||||
}
|
||||
deviceid = strdup(data);
|
||||
break;
|
||||
}
|
||||
clean:
|
||||
RegCloseKey(adapter);
|
||||
}
|
||||
RegCloseKey(adapters);
|
||||
return deviceid;
|
||||
/* Check its values */
|
||||
len = sizeof data;
|
||||
ret =
|
||||
RegQueryValueEx(adapter, "ComponentId", NULL, NULL, (LPBYTE)data, &len);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
/* This value doesn't exist in this adaptater tree */
|
||||
goto clean;
|
||||
}
|
||||
/* If its a tap adapter, its all good */
|
||||
if(strncmp(data, "tap", 3) == 0)
|
||||
{
|
||||
DWORD type;
|
||||
|
||||
len = sizeof data;
|
||||
ret = RegQueryValueEx(adapter, "NetCfgInstanceId", NULL, &type,
|
||||
(LPBYTE)data, &len);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_INFO, (const char *)formated_error(L"%1", ret));
|
||||
goto clean;
|
||||
}
|
||||
deviceid = strdup(data);
|
||||
break;
|
||||
}
|
||||
clean:
|
||||
RegCloseKey(adapter);
|
||||
}
|
||||
RegCloseKey(adapters);
|
||||
return deviceid;
|
||||
}
|
||||
|
||||
void
|
||||
tuntap_sys_destroy(struct device *dev) {
|
||||
(void)dev;
|
||||
return;
|
||||
tuntap_sys_destroy(struct device *dev)
|
||||
{
|
||||
(void)dev;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_start(struct device *dev, int mode, int tun) {
|
||||
HANDLE tun_fd;
|
||||
char *deviceid;
|
||||
char buf[60];
|
||||
tuntap_start(struct device *dev, int mode, int tun)
|
||||
{
|
||||
HANDLE tun_fd;
|
||||
char *deviceid;
|
||||
char buf[60];
|
||||
|
||||
/* Don't re-initialise a previously started device */
|
||||
if (dev->tun_fd != TUNFD_INVALID_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
/* Don't re-initialise a previously started device */
|
||||
if(dev->tun_fd != TUNFD_INVALID_VALUE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Shift the persistence bit */
|
||||
if (mode & TUNTAP_MODE_PERSIST) {
|
||||
mode &= ~TUNTAP_MODE_PERSIST;
|
||||
}
|
||||
/* Shift the persistence bit */
|
||||
if(mode & TUNTAP_MODE_PERSIST)
|
||||
{
|
||||
mode &= ~TUNTAP_MODE_PERSIST;
|
||||
}
|
||||
|
||||
if (mode == TUNTAP_MODE_TUNNEL) {
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Layer 3 tunneling is not implemented");
|
||||
return -1;
|
||||
}
|
||||
else if (mode != TUNTAP_MODE_ETHERNET) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
|
||||
return -1;
|
||||
}
|
||||
if(mode == TUNTAP_MODE_TUNNEL)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Layer 3 tunneling is not implemented");
|
||||
return -1;
|
||||
}
|
||||
else if(mode != TUNTAP_MODE_ETHERNET)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'mode'");
|
||||
return -1;
|
||||
}
|
||||
|
||||
deviceid = reg_query(NETWORK_ADAPTERS);
|
||||
snprintf(buf, sizeof buf, "\\\\.\\Global\\%s.tap", deviceid);
|
||||
tun_fd = CreateFile(buf, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED, 0);
|
||||
if (tun_fd == TUNFD_INVALID_VALUE) {
|
||||
int errcode = GetLastError();
|
||||
deviceid = reg_query(NETWORK_ADAPTERS);
|
||||
snprintf(buf, sizeof buf, "\\\\.\\Global\\%s.tap", deviceid);
|
||||
tun_fd = CreateFile(buf, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
|
||||
if(tun_fd == TUNFD_INVALID_VALUE)
|
||||
{
|
||||
int errcode = GetLastError();
|
||||
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev->tun_fd = tun_fd;
|
||||
return 0;
|
||||
dev->tun_fd = tun_fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
tuntap_release(struct device *dev) {
|
||||
(void)CloseHandle(dev->tun_fd);
|
||||
free(dev);
|
||||
tuntap_release(struct device *dev)
|
||||
{
|
||||
(void)CloseHandle(dev->tun_fd);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
char *
|
||||
tuntap_get_hwaddr(struct device *dev) {
|
||||
static unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||
DWORD len;
|
||||
tuntap_get_hwaddr(struct device *dev)
|
||||
{
|
||||
static unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||
DWORD len;
|
||||
|
||||
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MAC, &hwaddr, sizeof(hwaddr), &hwaddr, sizeof(hwaddr), &len, NULL) == 0) {
|
||||
int errcode = GetLastError();
|
||||
if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MAC, &hwaddr, sizeof(hwaddr),
|
||||
&hwaddr, sizeof(hwaddr), &len, NULL)
|
||||
== 0)
|
||||
{
|
||||
int errcode = GetLastError();
|
||||
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return NULL;
|
||||
} else {
|
||||
char buf[128];
|
||||
|
||||
(void)_snprintf_s(buf, sizeof buf, sizeof buf, "MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
|
||||
hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]);
|
||||
tuntap_log(TUNTAP_LOG_DEBUG, buf);
|
||||
}
|
||||
return (char *)hwaddr;
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
(void)_snprintf(buf, sizeof buf,
|
||||
"MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", hwaddr[0],
|
||||
hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
|
||||
tuntap_log(TUNTAP_LOG_DEBUG, buf);
|
||||
}
|
||||
return (char *)hwaddr;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_hwaddr(struct device *dev, const char *hwaddr) {
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_hwaddr()");
|
||||
return -1;
|
||||
tuntap_set_hwaddr(struct device *dev, const char *hwaddr)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_hwaddr()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
tuntap_sys_set_updown(struct device *dev, ULONG flag) {
|
||||
DWORD len;
|
||||
tuntap_sys_set_updown(struct device *dev, ULONG flag)
|
||||
{
|
||||
DWORD len;
|
||||
|
||||
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_SET_MEDIA_STATUS, &flag, sizeof(flag), &flag, sizeof(flag), &len, NULL) == 0) {
|
||||
int errcode = GetLastError();
|
||||
if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_SET_MEDIA_STATUS, &flag,
|
||||
sizeof(flag), &flag, sizeof(flag), &len, NULL)
|
||||
== 0)
|
||||
{
|
||||
int errcode = GetLastError();
|
||||
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
} else {
|
||||
char buf[32];
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
(void)_snprintf_s(buf, sizeof buf, sizeof buf, "Status: %s", flag ? "Up" : "Down");
|
||||
tuntap_log(TUNTAP_LOG_DEBUG, buf);
|
||||
return 0;
|
||||
}
|
||||
(void)_snprintf(buf, sizeof buf, "Status: %s",
|
||||
flag ? "Up" : "Down");
|
||||
tuntap_log(TUNTAP_LOG_DEBUG, buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_up(struct device *dev) {
|
||||
ULONG flag;
|
||||
tuntap_up(struct device *dev)
|
||||
{
|
||||
ULONG flag;
|
||||
|
||||
flag = 1;
|
||||
return tuntap_sys_set_updown(dev, flag);
|
||||
flag = 1;
|
||||
return tuntap_sys_set_updown(dev, flag);
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_down(struct device *dev) {
|
||||
ULONG flag;
|
||||
tuntap_down(struct device *dev)
|
||||
{
|
||||
ULONG flag;
|
||||
|
||||
flag = 0;
|
||||
return tuntap_sys_set_updown(dev, flag);
|
||||
flag = 0;
|
||||
return tuntap_sys_set_updown(dev, flag);
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_get_mtu(struct device *dev) {
|
||||
ULONG mtu;
|
||||
DWORD len;
|
||||
tuntap_get_mtu(struct device *dev)
|
||||
{
|
||||
ULONG mtu;
|
||||
DWORD len;
|
||||
|
||||
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MTU, &mtu, sizeof(mtu), &mtu, sizeof(mtu), &len, NULL) == 0) {
|
||||
int errcode = GetLastError();
|
||||
if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_GET_MTU, &mtu, sizeof(mtu), &mtu,
|
||||
sizeof(mtu), &len, NULL)
|
||||
== 0)
|
||||
{
|
||||
int errcode = GetLastError();
|
||||
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_mtu(struct device *dev, int mtu) {
|
||||
(void)dev;
|
||||
(void)mtu;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_mtu()");
|
||||
return -1;
|
||||
tuntap_set_mtu(struct device *dev, int mtu)
|
||||
{
|
||||
(void)dev;
|
||||
(void)mtu;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_mtu()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask) {
|
||||
IPADDR psock[4];
|
||||
DWORD len;
|
||||
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask)
|
||||
{
|
||||
IPADDR psock[4];
|
||||
DWORD len;
|
||||
|
||||
/* Address + Netmask */
|
||||
psock[0] = s->S_un.S_addr;
|
||||
psock[1] = mask;
|
||||
/* DHCP server address (We don't want it) */
|
||||
psock[2] = 0;
|
||||
/* DHCP lease time */
|
||||
psock[3] = 0;
|
||||
/* Address + Netmask */
|
||||
psock[0] = s->S_un.S_addr;
|
||||
psock[1] = mask;
|
||||
/* DHCP server address (We don't want it) */
|
||||
psock[2] = 0;
|
||||
/* DHCP lease time */
|
||||
psock[3] = 0;
|
||||
|
||||
if (DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, &psock, sizeof(psock), &psock, sizeof(psock), &len, NULL) == 0) {
|
||||
int errcode = GetLastError();
|
||||
if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, &psock,
|
||||
sizeof(psock), &psock, sizeof(psock), &len, NULL)
|
||||
== 0)
|
||||
{
|
||||
int errcode = GetLastError();
|
||||
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s, uint32_t mask) {
|
||||
(void)dev;
|
||||
(void)s;
|
||||
(void)mask;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_sys_set_ipv6()");
|
||||
return -1;
|
||||
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s, uint32_t mask)
|
||||
{
|
||||
(void)dev;
|
||||
(void)s;
|
||||
(void)mask;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_sys_set_ipv6()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_read(struct device *dev, void *buf, size_t size) {
|
||||
DWORD len;
|
||||
tuntap_read(struct device *dev, void *buf, size_t size)
|
||||
{
|
||||
DWORD len;
|
||||
|
||||
if (ReadFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0) {
|
||||
int errcode = GetLastError();
|
||||
if(ReadFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0)
|
||||
{
|
||||
int errcode = GetLastError();
|
||||
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_write(struct device *dev, void *buf, size_t size) {
|
||||
DWORD len;
|
||||
tuntap_write(struct device *dev, void *buf, size_t size)
|
||||
{
|
||||
DWORD len;
|
||||
|
||||
if (WriteFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0) {
|
||||
int errcode = GetLastError();
|
||||
if(WriteFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0)
|
||||
{
|
||||
int errcode = GetLastError();
|
||||
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_get_readable(struct device *dev) {
|
||||
(void)dev;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_get_readable()");
|
||||
return -1;
|
||||
tuntap_get_readable(struct device *dev)
|
||||
{
|
||||
(void)dev;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_get_readable()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_nonblocking(struct device *dev, int set) {
|
||||
(void)dev;
|
||||
(void)set;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_nonblocking()");
|
||||
return -1;
|
||||
tuntap_set_nonblocking(struct device *dev, int set)
|
||||
{
|
||||
(void)dev;
|
||||
(void)set;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_nonblocking()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_debug(struct device *dev, int set) {
|
||||
(void)dev;
|
||||
(void)set;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_debug()");
|
||||
return -1;
|
||||
tuntap_set_debug(struct device *dev, int set)
|
||||
{
|
||||
(void)dev;
|
||||
(void)set;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_debug()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_descr(struct device *dev, const char *descr) {
|
||||
(void)dev;
|
||||
(void)descr;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_descr()");
|
||||
return -1;
|
||||
tuntap_set_descr(struct device *dev, const char *descr)
|
||||
{
|
||||
(void)dev;
|
||||
(void)descr;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_descr()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_ifname(struct device *dev, const char *name) {
|
||||
/* TODO: Check Windows API to know how to rename an interface */
|
||||
(void)dev;
|
||||
(void)name;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Your system does not support tuntap_set_ifname()");
|
||||
return -1;
|
||||
tuntap_set_ifname(struct device *dev, const char *name)
|
||||
{
|
||||
/* TODO: Check Windows API to know how to rename an interface */
|
||||
(void)dev;
|
||||
(void)name;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_ifname()");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,12 @@
|
|||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <wspiapi.h>
|
||||
#ifndef _MSC_VER
|
||||
extern "C" int
|
||||
inet_pton(int af, const char *src, void *dst);
|
||||
extern "C" const char *
|
||||
inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
|
Loading…
Reference in New Issue