diff --git a/CMakeLists.txt b/CMakeLists.txt index d56f86d..7b0db49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,31 +3,47 @@ PROJECT( fc ) CMAKE_MINIMUM_REQUIRED( VERSION 2.8.0 ) SET( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}" ) +SET( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}" ) INCLUDE( VersionMacros ) INCLUDE( SetupTargetMacros ) +INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ) +INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include ) +INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/vendor/boost_1_51/include ) SET( DEFAULT_HEADER_INSTALL_DIR include/\${target} ) SET( DEFAULT_LIBRARY_INSTALL_DIR lib/ ) SET( DEFAULT_EXECUTABLE_INSTALL_DIR bin/ ) SET( CMAKE_DEBUG_POSTFIX _debug ) -#SET( BUILD_SHARED_LIBS NO ) - +SET( BUILD_SHARED_LIBS NO ) SET(Boost_USE_STATIC_LIBS ON) FIND_PACKAGE(Boost 1.51 COMPONENTS thread date_time system filesystem program_options signals serialization chrono unit_test_framework context ) +if( WIN32 ) + set( RPCRT4 Rpcrt4 ) + set( OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl" ) + if ( NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/lib" ) + file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/out32dll" DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/cmakefun") + file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/cmakefun/out32dll" "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/lib") + endif( NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vendor/openssl/lib" ) +endif( WIN32 ) - -INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ) LINK_DIRECTORIES( ${Boost_LIBRARY_DIRS} ) IF( WIN32 ) + ADD_DEFINITIONS( -DWIN32 ) ADD_DEFINITIONS( -DBOOST_CONTEXT_NO_LIB ) ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) ADD_DEFINITIONS( -D_WIN32_WINNT=0x0501 ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) + ADD_DEFINITIONS( -DBOOST_ALL_NO_LIB -DBOOST_THREAD_BUILD_LIB) + ADD_DEFINITIONS( -DWIN32) + # Activate C++ exception handling + IF (NOT CMAKE_CXX_FLAGS MATCHES "/EHsc") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") + ENDIF() ELSE(WIN32) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wno-unused-local-typedefs -fmax-errors=3" ) ENDIF(WIN32) if( UNIX ) @@ -40,82 +56,144 @@ endif() option( UNITY_BUILD OFF ) FIND_PACKAGE( OpenSSL ) -FIND_PACKAGE( ZLIB ) -include_directories( vendor/zlib-1.2.7/) -include_directories( vendor/libssh2-1.4.2/include ) +include_directories( vendor/boost_1.51/include ) include_directories( ${Boost_INCLUDE_DIR} ) include_directories( ${OPENSSL_INCLUDE_DIR} ) -include_directories( include ) -set( sources - src/logger.cpp - src/console_appender.cpp - src/file_appender.cpp - src/appender.cpp - src/logger_config.cpp - src/ssh.cpp - src/url.cpp - src/process.cpp - src/http_connection.cpp - src/http_server.cpp - src/json_rpc_connection.cpp - src/json_rpc_stream_connection.cpp - src/json_rpc_tcp_connection.cpp - src/json_rpc_tcp_server.cpp - src/json_rpc_error_object.cpp - src/error_report.cpp - src/value.cpp - src/lexical_cast.cpp - src/spin_lock.cpp - src/spin_yield_lock.cpp - src/task.cpp - src/future.cpp - src/shared_ptr.cpp - src/string.cpp - src/json.cpp - src/log.cpp - src/time.cpp - src/iostream.cpp - src/fstream.cpp - src/sstream.cpp - src/exception.cpp - src/thread.cpp - src/hex.cpp - src/sha1.cpp - src/sha256.cpp - src/filesystem.cpp - src/ip.cpp - src/bigint.cpp - src/mutex.cpp - src/pke.cpp - src/base64.cpp - src/base58.cpp - src/blowfish.cpp - src/dh.cpp - src/udp_socket.cpp - src/tcp_socket.cpp - src/asio.cpp - src/super_fast_hash.cpp - src/file_mapping.cpp - src/reflect.cpp -# src/program_options.cpp +SET( ALL_OPENSSL_LIBRARIES + ${OPENSSL_LIBRARIES} + ${SSL_EAY_RELEASE} + ${LIB_EAY_RELEASE} + ) + +set( fc_sources + src/variant.cpp + src/exception.cpp + src/variant_object.cpp + src/thread/thread.cpp + src/thread/future.cpp + src/thread/task.cpp + src/thread/spin_lock.cpp + src/thread/spin_yield_lock.cpp + src/thread/mutex.cpp + src/asio.cpp + src/string.cpp + src/shared_ptr.cpp + src/time.cpp + src/io/iostream.cpp + src/io/datastream.cpp + src/io/buffered_iostream.cpp + src/io/fstream.cpp + src/io/sstream.cpp + src/io/json.cpp + src/io/varint.cpp + src/filesystem.cpp + src/interprocess/process.cpp + src/interprocess/file_mapping.cpp + src/rpc/json_connection.cpp + src/log/log_message.cpp + src/log/logger.cpp + src/log/appender.cpp + src/log/console_appender.cpp + src/log/file_appender.cpp + src/log/logger_config.cpp + src/crypto/base36.cpp + src/crypto/bigint.cpp + src/crypto/base64.cpp + src/crypto/base58.cpp + src/crypto/hex.cpp + src/crypto/sha1.cpp + src/crypto/sha256.cpp + src/crypto/dh.cpp + src/crypto/blowfish.cpp + src/network/tcp_socket.cpp + src/network/udp_socket.cpp + src/network/http/http_connection.cpp + src/network/http/http_server.cpp + src/network/ip.cpp + src/network/resolve.cpp + src/network/url.cpp +# src/ssh/client.cpp +# src/ssh/process.cpp + ) + +IF( UNIX ) + IF( ENABLE_ARM ) + SET_PROPERTY( SOURCE + vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S + PROPERTY LANGUAGE C) + SET( boost_context_sources vendor/boost_1.51/libs/context/protected_stack_posix.cpp + vendor/boost_1.51/libs/context/stack_helper_posix.cpp + vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S + ) + ELSE() + + IF( APPLE ) + SET_PROPERTY( SOURCE + vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S + PROPERTY LANGUAGE C) + SET( boost_context_sources vendor/boost_1.51/libs/context/stack_utils_posix.cpp + vendor/boost_1.51/libs/context/stack_allocator_posix.cpp + vendor/boost_1.51/libs/context/fcontext.cpp + vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S + ) + ELSE (APPLE) + IF( CMAKE_SIZEOF_VOID_P EQUAL 4 ) + SET_PROPERTY( SOURCE + vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S + PROPERTY LANGUAGE C) + SET( fcontext_asm vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S ) + ELSE( ) + SET( fcontext_asm vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S ) + SET_PROPERTY( SOURCE + vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S + PROPERTY LANGUAGE C) + ENDIF( ) + + SET( boost_context_sources vendor/boost_1.51/libs/context/stack_utils_posix.cpp + vendor/boost_1.51/libs/context/stack_allocator_posix.cpp + vendor/boost_1.51/libs/context/fcontext.cpp + ${fcontext_asm} + ) + ENDIF(APPLE) + + ENDIF() +ENDIF( UNIX ) + +IF( WIN32 ) + ENABLE_LANGUAGE(ASM_MASM) +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa" ) + + SET( boost_context_sources vendor/boost_1.51/libs/context/fcontext.cpp + vendor/boost_1.51/libs/context/seh.cpp + vendor/boost_1.51/libs/context/stack_allocator_windows.cpp + vendor/boost_1.51/libs/context/stack_utils_windows.cpp + vendor/boost_1.51/libs/context/seh.cpp + ) + IF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) + SET( boost_context_sources ${boost_context_sources} + vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm ) + ELSE() # 32bit + SET( boost_context_sources ${boost_context_sources} + vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm ) + SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO" ) + message(STATUS "") + message(STATUS "Note for Visual Studio 2012 projects:") + message(STATUS " Each time CMake regenerates your projects, you will need to:") + message(STATUS " Right-click on the 'fc' project and select 'Build Customizations', and") + message(STATUS " check the 'masm' customization.") + message(STATUS " then, go to the 'Properties' for the fcontext*.asm file, and change its ") + message(STATUS " item type from 'Does not participate in build' to 'Microsoft Macro Assembler'") + ENDIF() + +ENDIF(WIN32) + +set( sources + ${fc_sources} + ${boost_context_sources} ) -add_subdirectory(vendor) +setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC ) -#add_executable( date t.cpp ) -#target_link_libraries( date fc ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ${Boost_DATE_TIME_LIBRARY}) -setup_library( fc SOURCES ${sources} ) - -#setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES fc ${ZLIB_LIBRARY} ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ${Boost_DATE_TIME_LIBRARY}) -setup_executable( ssh_test SOURCES tests/ssh.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ssh2 ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY}) - -setup_executable( logger_test SOURCES tests/logger.cpp LIBRARIES fc ${pthread_library} ${rt_library} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${rt_library} ssh2 ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY}) - -#add_executable( test_vec tests/vector_test.cpp ) -#target_link_libraries( test_vec fc ${Boost_SYSTEM_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ) - -#add_executable( unit_tests tests/unit.cpp ) -#target_link_libraries( unit_tests fc ${Boost_CHRONO_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_CONTEXT_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) diff --git a/CMakeModules/FindVLD.cmake b/CMakeModules/FindVLD.cmake new file mode 100644 index 0000000..716625c --- /dev/null +++ b/CMakeModules/FindVLD.cmake @@ -0,0 +1,123 @@ +# Module for locating Visual Leak Detector. +# +# Customizable variables: +# VLD_ROOT_DIR +# This variable points to the Visual Leak Detector root directory. By +# default, the module looks for the installation directory by examining the +# Program Files/Program Files (x86) folders and the VLDROOT environment +# variable. +# +# Read-only variables: +# VLD_FOUND +# Indicates that the library has been found. +# +# VLD_INCLUDE_DIRS +# Points to the Visual Leak Detector include directory. +# +# VLD_LIBRARY_DIRS +# Points to the Visual Leak Detector directory that contains the libraries. +# The content of this variable can be passed to link_directories. +# +# VLD_LIBRARIES +# Points to the Visual Leak Detector libraries that can be passed to +# target_link_libararies. +# +# +# Copyright (c) 2012 Sergiu Dotenco +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +INCLUDE (FindPackageHandleStandardArgs) + +SET (_VLD_POSSIBLE_LIB_SUFFIXES lib) + +# Version 2.0 uses vld_x86 and vld_x64 instead of simply vld as library names +IF (CMAKE_SIZEOF_VOID_P EQUAL 4) + LIST (APPEND _VLD_POSSIBLE_LIB_SUFFIXES lib/Win32) +ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 8) + LIST (APPEND _VLD_POSSIBLE_LIB_SUFFIXES lib/Win64) +ENDIF (CMAKE_SIZEOF_VOID_P EQUAL 4) + +FIND_PATH (VLD_ROOT_DIR + NAMES include/vld.h + PATHS ENV VLDROOT + "$ENV{PROGRAMFILES}/Visual Leak Detector" + "$ENV{PROGRAMFILES(X86)}/Visual Leak Detector" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Visual Leak Detector;InstallLocation]" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Visual Leak Detector;InstallLocation]" + DOC "VLD root directory") + +FIND_PATH (VLD_INCLUDE_DIR + NAMES vld.h + HINTS ${VLD_ROOT_DIR} + PATH_SUFFIXES include + DOC "VLD include directory") + +FIND_LIBRARY (VLD_LIBRARY_DEBUG + NAMES vld + HINTS ${VLD_ROOT_DIR} + PATH_SUFFIXES ${_VLD_POSSIBLE_LIB_SUFFIXES} + DOC "VLD debug library") + +IF (VLD_ROOT_DIR) + SET (_VLD_VERSION_FILE ${VLD_ROOT_DIR}/CHANGES.txt) + + IF (EXISTS ${_VLD_VERSION_FILE}) + SET (_VLD_VERSION_REGEX + "Visual Leak Detector \\(VLD\\) Version (([0-9]+)\\.([0-9]+)([a-z]|(.([0-9]+)))?)") + FILE (STRINGS ${_VLD_VERSION_FILE} _VLD_VERSION_TMP REGEX + ${_VLD_VERSION_REGEX}) + + STRING (REGEX REPLACE ${_VLD_VERSION_REGEX} "\\1" _VLD_VERSION_TMP + "${_VLD_VERSION_TMP}") + + STRING (REGEX REPLACE "([0-9]+).([0-9]+).*" "\\1" VLD_VERSION_MAJOR + "${_VLD_VERSION_TMP}") + STRING (REGEX REPLACE "([0-9]+).([0-9]+).*" "\\2" VLD_VERSION_MINOR + "${_VLD_VERSION_TMP}") + + SET (VLD_VERSION ${VLD_VERSION_MAJOR}.${VLD_VERSION_MINOR}) + + IF ("${_VLD_VERSION_TMP}" MATCHES "^([0-9]+).([0-9]+).([0-9]+)$") + # major.minor.patch version numbering scheme + STRING (REGEX REPLACE "([0-9]+).([0-9]+).([0-9]+)" "\\3" + VLD_VERSION_PATCH "${_VLD_VERSION_TMP}") + SET (VLD_VERSION "${VLD_VERSION}.${VLD_VERSION_PATCH}") + SET (VLD_VERSION_COUNT 3) + ELSE ("${_VLD_VERSION_TMP}" MATCHES "^([0-9]+).([0-9]+).([0-9]+)$") + # major.minor version numbering scheme. The trailing letter is ignored. + SET (VLD_VERSION_COUNT 2) + ENDIF ("${_VLD_VERSION_TMP}" MATCHES "^([0-9]+).([0-9]+).([0-9]+)$") + ENDIF (EXISTS ${_VLD_VERSION_FILE}) +ENDIF (VLD_ROOT_DIR) + +IF (VLD_LIBRARY_DEBUG) + SET (VLD_LIBRARY debug ${VLD_LIBRARY_DEBUG} CACHE DOC "VLD library") + GET_FILENAME_COMPONENT (_VLD_LIBRARY_DIR ${VLD_LIBRARY_DEBUG} PATH) + SET (VLD_LIBRARY_DIR ${_VLD_LIBRARY_DIR} CACHE PATH "VLD library directory") +ENDIF (VLD_LIBRARY_DEBUG) + +SET (VLD_INCLUDE_DIRS ${VLD_INCLUDE_DIR}) +SET (VLD_LIBRARY_DIRS ${VLD_LIBRARY_DIR}) +SET (VLD_LIBRARIES ${VLD_LIBRARY}) + +MARK_AS_ADVANCED (VLD_INCLUDE_DIR VLD_LIBRARY_DIR VLD_LIBRARY_DEBUG VLD_LIBRARY) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS (VLD REQUIRED_VARS VLD_ROOT_DIR + VLD_INCLUDE_DIR VLD_LIBRARY VERSION_VAR VLD_VERSION) diff --git a/README.md b/README.md deleted file mode 100644 index cae31d1..0000000 --- a/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Fast Compiliing C++ Library ------------------------------------------ - -In my prior attempts at developing MACE what I discovered is that compile times -would explode to unreasonable levels that hinder the rate of development more -than what can be saved by reduced typing. So I began a quest to get C++ to compile -as quickly as Java or C# and the result is this library. - -One of the major drawbacks to templates is that they place everything in header and -must be compiled with every run and generate a lot of object code. With Link Time Optimization, -the benefit of inline methods mostly disapears, leaving only static vs dynamic polymorphism. - -For the vast majority of applications, a virtual method call is not the bottleneck and the -increased compile times costs more than is otherwise justified; therefore, the Fast Compiling C++ -library opts for virtual interfaces to handle reflection instead of template interfaces. One could -argue that both types of reflection could be useful. - -Another source of slowness was the standard template library itself. Most standard template library -classes cannot be forward declared and import thousands of lines of code into every compilation unit. - -Another source of slowness is the need to include headers simply because the 'size' of the object must -be known. A new utility class allows you to 'forward declare' the size required for certain types which -allows you to remove their inclusion from the header file. - - diff --git a/include/fc/abstract_types.hpp b/include/fc/abstract_types.hpp deleted file mode 100644 index 0f54e7e..0000000 --- a/include/fc/abstract_types.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef _FC_ABSTRACT_TYPES_HPP_ -#define _FC_ABSTRACT_TYPES_HPP_ -#include -#include - -namespace fc { - - struct abstract_type { - virtual ~abstract_type(){} - virtual size_t size_of()const = 0; - /* - * @brief Inplace destructor (does not free memory) ((T*)dst)->~T(); - */ - virtual void destructor( void* dst )const = 0; - - /** @brief 'delete T' */ - virtual void destroy( void* dst )const = 0; - }; - - template - struct type : virtual abstract_type { - virtual size_t size_of()const { return sizeof(T); } - virtual void destructor( void* dst )const { ((T*)dst)->~T(); } - virtual void destroy( void* dst )const { delete ((T*)dst); } - }; - - struct abstract_moveable_type : virtual abstract_type { - virtual void move_construct( void* dst, void* src )const = 0; - virtual void move( void* dst, void* src )const = 0; - }; - - template - struct moveable_type : virtual type, virtual abstract_moveable_type { - static abstract_moveable_type& instance() { static moveable_type inst; return inst; } - virtual void destruct( void* dst )const { ((T*)dst)->~T(); } - virtual void move_construct( void* dst, void* src )const { slog( "move construct" ); new ((char*)dst) T( fc::move(*((T*)src)) ); } - virtual void move( void* dst, void* src )const { *((T*)dst) = fc::move(*((T*)src)); } - }; - - struct abstract_value_type : virtual abstract_moveable_type { - virtual void construct( void* dst )const = 0; - virtual void copy_construct( void* dst, const void* src )const = 0; - virtual void assign( void* dst, const void* src )const = 0; - }; - - /** - * Default constructable, moveable, copyable, assignable. - */ - template - struct value_type : virtual moveable_type, virtual abstract_value_type { - static abstract_value_type& instance() { static value_type inst; return inst; } - - virtual void construct( void* dst )const { new ((char*)dst) T(); } - virtual void copy_construct( void* dst, const void* src )const { new ((char*)dst) T( *((const T*)src) ); } - virtual void assign( void* dst, const void* src )const { *((T*)dst) = *((const T*)src); } - }; - - struct abstract_less_than_comparable_type { - virtual bool less_than( const void* left, const void* right )const = 0; - }; - - - template - struct less_than_comparable_type : abstract_less_than_comparable_type { - virtual bool less_than( const void* left, const void* right )const { - return *((const T*)left) < *((const T*)right); - } - }; - - struct abstract_equal_comparable_type { - virtual bool equal( const void* left, const void* right )const = 0; - }; - - template - struct equal_comparable_type : abstract_equal_comparable_type { - virtual bool equal( const void* left, const void* right )const { - return *((const T*)left) == *((const T*)right); - } - }; - - struct abstract_callable_type { - virtual void call( const void* self )const = 0; - }; - - template - struct callable_type : virtual abstract_callable_type, virtual value_type { - virtual void call( const void* self )const { (*((const T*)self))(); } - }; - -} // namespace fc - -#endif diff --git a/include/fc/actor.hpp b/include/fc/actor.hpp index 007b937..3460f48 100644 --- a/include/fc/actor.hpp +++ b/include/fc/actor.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace fc { diff --git a/include/fc/aligned.hpp b/include/fc/aligned.hpp index 7bda080..b107ed1 100644 --- a/include/fc/aligned.hpp +++ b/include/fc/aligned.hpp @@ -1,5 +1,4 @@ -#ifndef _FC_ALIGNED_HPP_ -#define _FC_ALIGNED_HPP_ +#pragma once namespace fc { template @@ -13,4 +12,3 @@ namespace fc { }; } -#endif // _FC_ALIGNED_HPP_ diff --git a/include/fc/any.hpp b/include/fc/any.hpp index 632fdb5..022d29e 100644 --- a/include/fc/any.hpp +++ b/include/fc/any.hpp @@ -1,9 +1,7 @@ -#ifndef _FC_ANY_HPP_ -#define _FC_ANY_HPP_ +#pragma once #include namespace fc { + // TODO: define this without using boost typedef boost::any any; } - -#endif // _FC_ANY_HPP_ diff --git a/include/fc/array.hpp b/include/fc/array.hpp index f97ffe5..9f2b4b7 100644 --- a/include/fc/array.hpp +++ b/include/fc/array.hpp @@ -1,5 +1,6 @@ -#ifndef _FC_ARRAY_HPP_ -#define _FC_ARRAY_HPP_ +#pragma once +#include +#include namespace fc { @@ -9,6 +10,27 @@ namespace fc { T data[N]; }; -} + template + bool operator == ( const array& a, const array& b ) + { return 0 == memcmp( a.data, b.data, N ); } + template + bool operator != ( const array& a, const array& b ) + { return 0 != memcmp( a.data, b.data, N ); } -#endif // _FC_ARRAY_HPP_ + template + void to_variant( const array& bi, variant& v ) + { + v = fc::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ); + } + template + void from_variant( const variant& v, array& bi ) + { + fc::vector ve = v.as< vector >(); + if( ve.size() ) + { + memcpy(&bi, ve.data(), fc::min(ve.size(),sizeof(bi)) ); + } + else + memset( &bi, char(0), sizeof(bi) ); + } +} diff --git a/include/fc/asio.hpp b/include/fc/asio.hpp index c63067e..2434d2b 100644 --- a/include/fc/asio.hpp +++ b/include/fc/asio.hpp @@ -5,9 +5,8 @@ #pragma once #include #include -#include -#include -#include +#include +#include namespace fc { /** @@ -53,7 +52,7 @@ namespace asio { * This IO service is automatically running in its own thread to service asynchronous * requests without blocking any other threads. */ - boost::asio::io_service& default_io_service(); + boost::asio::io_service& default_io_service(bool cleanup = false); /** * @brief wraps boost::asio::async_read @@ -62,18 +61,6 @@ namespace asio { */ template size_t read( AsyncReadStream& s, const MutableBufferSequence& buf ) { - detail::non_blocking non_blocking; - - // TODO: determine if non_blocking query results in a system call that - // will slow down every read... - if( non_blocking(s) || non_blocking(s,true) ) { - boost::system::error_code ec; - size_t r = boost::asio::read( s, buf, ec ); - if( !ec ) return r; - if( ec != boost::asio::error::would_block ) - BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); - } - promise::ptr p(new promise("fc::asio::read")); boost::asio::async_read( s, buf, boost::bind( detail::read_write_handler, p, _1, _2 ) ); return p->wait(); @@ -92,39 +79,27 @@ namespace asio { * @return the number of bytes read. */ template - size_t read_some( AsyncReadStream& s, const MutableBufferSequence& buf ) { - detail::non_blocking non_blocking; - - // TODO: determine if non_blocking query results in a system call that - // will slow down every read... - if( non_blocking(s) || non_blocking(s,true) ) { - boost::system::error_code ec; - size_t r = s.read_some( buf, ec ); - if( !ec ) return r; - if( ec != boost::asio::error::would_block ) - BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); - } - - promise::ptr p(new promise("fc::asio::read_some")); + size_t read_some( AsyncReadStream& s, const MutableBufferSequence& buf ) + { + promise::ptr p(new promise("fc::asio::async_read_some")); s.async_read_some( buf, boost::bind( detail::read_write_handler, p, _1, _2 ) ); return p->wait(); } + template + size_t read_some( AsyncReadStream& s, boost::asio::streambuf& buf ) + { + char buffer[1024]; + size_t bytes_read = read_some( s, boost::asio::buffer( buffer, sizeof(buffer) ) ); + buf.sputn( buffer, bytes_read ); + return bytes_read; + } + /** @brief wraps boost::asio::async_write * @return the number of bytes written */ template size_t write( AsyncWriteStream& s, const ConstBufferSequence& buf ) { - detail::non_blocking non_blocking; - - if( non_blocking(s) || non_blocking(s,true) ) { - boost::system::error_code ec; - size_t r = boost::asio::write( s, buf, ec ); - if( !ec ) return r; - if( ec != boost::asio::error::would_block) { - BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); - } - } promise::ptr p(new promise("fc::asio::write")); boost::asio::async_write(s, buf, boost::bind( detail::read_write_handler, p, _1, _2 ) ); return p->wait(); @@ -137,81 +112,11 @@ namespace asio { */ template size_t write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) { - detail::non_blocking non_blocking; - - if( non_blocking(s) || non_blocking(s,true) ) { - boost::system::error_code ec; - size_t r = s.write_some( buf, ec ); - if( !ec ) return r; - if( ec != boost::asio::error::would_block) { - BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); - } - } promise::ptr p(new promise("fc::asio::write_some")); s.async_write_some( buf, boost::bind( detail::read_write_handler, p, _1, _2 ) ); return p->wait(); } - template - class sink : public boost::iostreams::sink { - public: - // struct category : boost::iostreams::sink::category {}; - typedef char type; - - sink( AsyncWriteStream& p ):m_stream(p){} - - std::streamsize write( const char* s, std::streamsize n ) { - return fc::asio::write( m_stream, boost::asio::const_buffers_1(s,n) ); - } - void close() { m_stream.close(); } - - private: - AsyncWriteStream& m_stream; - }; - - template - class source : public boost::iostreams::source { - public: - // struct category : boost::iostreams::sink::category {}; - typedef char type; - - source( AsyncReadStream& p ):m_stream(p){} - - std::streamsize read( char* s, std::streamsize n ) { - return fc::asio::read_some( m_stream, boost::asio::buffer(s,n) ); - } - void close() { m_stream.close(); } - - private: - AsyncReadStream& m_stream; - }; - template - class io_device { - public: - typedef boost::iostreams::bidirectional_device_tag category; - typedef char char_type; - - io_device( AsyncStream& p ):m_stream(p){} - - std::streamsize write( const char* s, std::streamsize n ) { - return fc::asio::write( m_stream, boost::asio::const_buffers_1(s,static_cast(n)) ); - } - std::streamsize read( char* s, std::streamsize n ) { - try { - return fc::asio::read_some( m_stream, boost::asio::buffer(s,n) ); - } catch ( const boost::system::system_error& e ) { - if( e.code() == boost::asio::error::eof ) - return -1; - throw; - } - } - void close() { m_stream.close(); } - - private: - AsyncStream& m_stream; - }; - - namespace tcp { typedef boost::asio::ip::tcp::endpoint endpoint; typedef boost::asio::ip::tcp::resolver::iterator resolver_iterator; @@ -228,7 +133,6 @@ namespace asio { promise::ptr p( new promise("fc::asio::tcp::accept") ); acc.async_accept( sock, boost::bind( fc::asio::detail::error_handler, p, _1 ) ); auto ec = p->wait(); - if( !ec ) sock.non_blocking(true); if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); } @@ -241,23 +145,53 @@ namespace asio { promise::ptr p(new promise("fc::asio::tcp::connect")); sock.async_connect( ep, boost::bind( fc::asio::detail::error_handler, p, _1 ) ); auto ec = p->wait(); - if( !ec ) sock.non_blocking(true); if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); } - - typedef boost::iostreams::stream > ostream; - typedef boost::iostreams::stream > istream; - typedef boost::iostreams::stream > iostream; - } namespace udp { typedef boost::asio::ip::udp::endpoint endpoint; typedef boost::asio::ip::udp::resolver::iterator resolver_iterator; typedef boost::asio::ip::udp::resolver resolver; /// @brief resolve all udp::endpoints for hostname:port - std::vector resolve( resolver& r, const std::string& hostname, const std::string& port ); + std::vector resolve( resolver& r, const std::string& hostname, + const std::string& port ); } + template + class istream : public virtual fc::istream + { + public: + istream( std::shared_ptr str ) + :_stream( fc::move(str) ){} + + virtual size_t readsome( char* buf, size_t len ) + { + auto r = fc::asio::read_some(*_stream, boost::asio::buffer(buf, len) ); + return r; + } + + private: + std::shared_ptr _stream; + }; + + template + class ostream : public virtual fc::ostream + { + public: + ostream( std::shared_ptr str ) + :_stream( fc::move(str) ){} + + virtual size_t writesome( const char* buf, size_t len ) + { + return fc::asio::write_some(*_stream, boost::asio::const_buffers_1(buf, len) ); + } + + virtual void close(){ _stream->close(); } + virtual void flush() {} + private: + std::shared_ptr _stream; + }; + } } // namespace fc::asio diff --git a/include/fc/bigint.hpp b/include/fc/bigint.hpp deleted file mode 100644 index 7c68f1d..0000000 --- a/include/fc/bigint.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _FC_BIGINT_HPP -#define _FC_BIGINT_HPP -#include -#include - -struct bignum_st; -typedef bignum_st BIGNUM; - -namespace fc { - class bigint { - public: - bigint( const char* bige, uint32_t l ); - bigint( unsigned long i = 0 ); - bigint( const bigint& c ); - bigint( bigint&& c ); - ~bigint(); - - bool is_negative()const; - int64_t to_int64()const; - - int64_t log2()const; - bool operator < ( const bigint& c )const; - bool operator > ( const bigint& c )const; - bool operator >= ( const bigint& c )const; - bool operator == ( const bigint& c )const; - - bigint operator + ( const bigint& a )const; - bigint operator * ( const bigint& a )const; - bigint operator / ( const bigint& a )const; - bigint operator - ( const bigint& a )const; - - bigint& operator = ( const bigint& a ); - bigint& operator = ( bigint&& a ); - - operator fc::string()const; - - private: - BIGNUM* n; - }; -} // namespace fc - -#endif diff --git a/include/fc/buffer.hpp b/include/fc/buffer.hpp deleted file mode 100644 index e6fce6d..0000000 --- a/include/fc/buffer.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _FC_BUFFER_HPP_ -#define _FC_BUFFER_HPP_ -namespace fc { - - struct const_buffer { - const_buffer( const char* const c = 0, size_t l = 0 ) - :data(c),size(l){} - const char* const data; - size_t size; - }; - - struct mutable_buffer { - mutable_buffer( char* c = 0, size_t l = 0 ) - :data(c),size(l){} - char* data; - size_t size; - }; - -} - -#endif // _FC_BUFFER_HPP_ diff --git a/include/fc/crypto/base32.hpp b/include/fc/crypto/base32.hpp new file mode 100644 index 0000000..ed81aae --- /dev/null +++ b/include/fc/crypto/base32.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +namespace fc +{ + fc::vector from_base32( const fc::string& b32 ); + fc::string to_base32( const fc::vector& vec ); + fc::string to_base32( const char* data, size_t len ); +} diff --git a/include/fc/crypto/base36.hpp b/include/fc/crypto/base36.hpp new file mode 100644 index 0000000..163dabf --- /dev/null +++ b/include/fc/crypto/base36.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +namespace fc +{ + fc::vector from_base36( const fc::string& b36 ); + fc::string to_base36( const fc::vector& vec ); + fc::string to_base36( const char* data, size_t len ); +} diff --git a/include/fc/base58.hpp b/include/fc/crypto/base58.hpp similarity index 100% rename from include/fc/base58.hpp rename to include/fc/crypto/base58.hpp diff --git a/include/fc/crypto/base64.hpp b/include/fc/crypto/base64.hpp new file mode 100644 index 0000000..ee92618 --- /dev/null +++ b/include/fc/crypto/base64.hpp @@ -0,0 +1,8 @@ +#pragma once +#include + +namespace fc { +std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len); +std::string base64_encode( const std::string& enc ); +std::string base64_decode( const std::string& encoded_string); +} // namespace fc diff --git a/include/fc/crypto/bigint.hpp b/include/fc/crypto/bigint.hpp new file mode 100644 index 0000000..d5e4962 --- /dev/null +++ b/include/fc/crypto/bigint.hpp @@ -0,0 +1,70 @@ +#pragma once +#include +#include +#include + +struct bignum_st; +typedef bignum_st BIGNUM; + +namespace fc { + class bigint { + public: + bigint( const fc::vector& bige ); + bigint( const char* bige, uint32_t l ); + bigint( unsigned long i = 0 ); + bigint( const bigint& c ); + bigint( bigint&& c ); + explicit bigint( BIGNUM* n ); + ~bigint(); + + bigint& operator = ( const bigint& a ); + bigint& operator = ( bigint&& a ); + + operator bool()const; + + bool is_negative()const; + int64_t to_int64()const; + + int64_t log2()const; + bigint exp( const bigint& c )const; + + static bigint random( uint32_t bits, int t, int ); + + bool operator < ( const bigint& c )const; + bool operator > ( const bigint& c )const; + bool operator >= ( const bigint& c )const; + bool operator == ( const bigint& c )const; + bool operator != ( const bigint& c )const; + + bigint operator + ( const bigint& a )const; + bigint operator * ( const bigint& a )const; + bigint operator / ( const bigint& a )const; + bigint operator % ( const bigint& a )const; + bigint operator /= ( const bigint& a ); + bigint operator - ( const bigint& a )const; + + + bigint operator++(int); + bigint& operator++(); + bigint operator--(int); + bigint& operator--(); + + operator fc::string()const; + + // returns bignum as bigendian bytes + operator fc::vector()const; + + BIGNUM* dup()const; + + BIGNUM* get()const { return n; } + private: + BIGNUM* n; + }; + + class variant; + /** encodes the big int as base64 string, or a number */ + void to_variant( const bigint& bi, variant& v ); + /** decodes the big int as base64 string, or a number */ + void from_variant( const variant& v, bigint& bi ); +} // namespace fc + diff --git a/include/fc/blowfish.hpp b/include/fc/crypto/blowfish.hpp similarity index 94% rename from include/fc/blowfish.hpp rename to include/fc/crypto/blowfish.hpp index 3cee331..2ee62b1 100644 --- a/include/fc/blowfish.hpp +++ b/include/fc/crypto/blowfish.hpp @@ -120,8 +120,7 @@ E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA */ -#ifndef __FC_BLOWFISH_HPP__ -#define __FC_BLOWFISH_HPP__ +#pragma once #include namespace fc { @@ -150,12 +149,12 @@ public: void reset_chain() { m_oChain = m_oChain0; } // encrypt/decrypt Buffer in Place - void encrypt(unsigned char* buf, uint64_t n, int iMode=ECB); - void decrypt(unsigned char* buf, uint64_t n, int iMode=ECB); + void encrypt(unsigned char* buf, uint64_t n, int iMode=CBC); + void decrypt(unsigned char* buf, uint64_t n, int iMode=CBC); // encrypt/decrypt from Input Buffer to Output Buffer - void encrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=ECB); - void decrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=ECB); + void encrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CBC); + void decrypt(const unsigned char* in, unsigned char* out, uint64_t n, int iMode=CBC); //Private Functions private: @@ -176,5 +175,4 @@ private: } // namespace fc -#endif // __BLOWFISH_H__ diff --git a/include/fc/dh.hpp b/include/fc/crypto/dh.hpp similarity index 55% rename from include/fc/dh.hpp rename to include/fc/crypto/dh.hpp index ec9112f..92c63b6 100644 --- a/include/fc/dh.hpp +++ b/include/fc/crypto/dh.hpp @@ -1,7 +1,5 @@ -#ifndef _FC_DH_HPP_ -#define _FC_DH_HPP_ -//#include -#include +#pragma once +#include #include namespace fc { @@ -11,13 +9,13 @@ namespace fc { bool generate_params( int s, uint8_t g ); bool generate_pub_key(); bool compute_shared_key( const char* buf, uint32_t s ); - bool compute_shared_key( const std::vector& pubk); + bool compute_shared_key( const vector& pubk); bool validate(); - std::vector p; - std::vector pub_key; - std::vector priv_key; - std::vector shared_key; + vector p; + vector pub_key; + vector priv_key; + vector shared_key; bool valid; uint8_t g; }; @@ -25,4 +23,3 @@ namespace fc { } // namespace fc -#endif diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp new file mode 100644 index 0000000..167d663 --- /dev/null +++ b/include/fc/crypto/elliptic.hpp @@ -0,0 +1,61 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace fc { namespace ecc { + + namespace detail + { + class public_key_impl; + class private_key_impl; + } + + typedef fc::array signature; + typedef fc::array compact_signature; + + class public_key + { + public: + public_key(); + ~public_key(); + bool verify( const fc::sha256& digest, const signature& sig ); + + std::vector serialize(); + public_key( const std::vector& v ); + public_key( const compact_signature& c, const fc::sha256& digest ); + private: + friend class private_key; + fc::fwd my; + }; + + + class private_key + { + public: + private_key(); + private_key( std::vector k ); + ~private_key(); + + static private_key generate(); + static private_key regenerate( const fc::sha256& secret ); + + fc::sha256 get_secret()const; // get the private key secret + + /** + * Given a public key, calculatse a 512 bit shared secret between that + * key and this private key. + */ + fc::sha512 get_shared_secret( const public_key& pub ); + + signature sign( const fc::sha256& digest ); + compact_signature sign_compact( const fc::sha256& digest ); + bool verify( const fc::sha256& digest, const signature& sig ); + + public_key get_public_key()const; + private: + fc::fwd my; + }; +} } // fc::ecc diff --git a/include/fc/hex.hpp b/include/fc/crypto/hex.hpp similarity index 100% rename from include/fc/hex.hpp rename to include/fc/crypto/hex.hpp diff --git a/include/fc/crypto/pke.hpp b/include/fc/crypto/pke.hpp new file mode 100644 index 0000000..3f1c607 --- /dev/null +++ b/include/fc/crypto/pke.hpp @@ -0,0 +1,113 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +namespace fc { + namespace detail { class pke_impl; } + + class private_key; + class public_key; + void generate_key_pair( public_key&, private_key& ); + + typedef std::vector bytes; + typedef bytes signature; + + class public_key + { + public: + public_key(); + explicit public_key( const bytes& d ); + public_key( const public_key& k ); + public_key( public_key&& k ); + ~public_key(); + + operator bool()const; + + public_key& operator=(const public_key& p ); + public_key& operator=(public_key&& p ); + + bool verify( const sha1& digest, const array& sig )const; + bool verify( const sha1& digest, const signature& sig )const; + bool verify( const sha256& digest, const signature& sig )const; + bytes encrypt( const char* data, size_t len )const; + bytes encrypt( const bytes& )const; + bytes decrypt( const bytes& )const; + + bytes serialize()const; + friend void generate_key_pair( public_key&, private_key& ); + private: + std::shared_ptr my; + }; + + class private_key + { + public: + private_key(); + explicit private_key( const bytes& d ); + private_key( const private_key& k ); + private_key( private_key&& k ); + ~private_key(); + + operator bool()const; + + private_key& operator=(const private_key& p ); + private_key& operator=(private_key&& p ); + + void sign( const sha1& digest, array& sig )const; + signature sign( const sha1& digest )const; + signature sign( const sha256& digest )const; + + bytes decrypt( const char* bytes, size_t len )const; + bytes decrypt( const bytes& )const; + bytes encrypt( const bytes& )const; + + bytes serialize()const; + friend void generate_key_pair( public_key&, private_key& ); + + private: + std::shared_ptr my; + }; + bool operator==( const private_key& a, const private_key& b ); + + namespace raw + { + template + void unpack( Stream& s, fc::public_key& pk) + { + bytes ser; + fc::raw::unpack(s,ser); + pk = fc::public_key( ser ); + } + + template + void pack( Stream& s, const fc::public_key& pk) + { + fc::raw::pack( s, pk.serialize() ); + } + + template + void unpack( Stream& s, fc::private_key& pk) + { + bytes ser; + fc::raw::unpack(s,ser); + pk = fc::private_key( ser ); + } + + template + void pack( Stream& s, const fc::private_key& pk) + { + fc::raw::pack( s, pk.serialize() ); + } + } + class variant; + void to_variant( const public_key& bi, variant& v ); + void from_variant( const variant& v, public_key& bi ); + void to_variant( const private_key& bi, variant& v ); + void from_variant( const variant& v, private_key& bi ); + +} // fc + diff --git a/include/fc/crypto/sha1.hpp b/include/fc/crypto/sha1.hpp new file mode 100644 index 0000000..e91503e --- /dev/null +++ b/include/fc/crypto/sha1.hpp @@ -0,0 +1,67 @@ +#pragma once +#include +#include + +namespace fc{ + +class sha1 +{ + public: + sha1(); + explicit sha1( const string& hex_str ); + + string str()const; + operator string()const; + + char* data()const; + + static sha1 hash( const char* d, uint32_t dlen ); + static sha1 hash( const string& ); + + template + static sha1 hash( const T& t ) + { + sha1::encoder e; + e << t; + return e.result(); + } + + class encoder + { + public: + encoder(); + ~encoder(); + + void write( const char* d, uint32_t dlen ); + void put( char c ) { write( &c, 1 ); } + void reset(); + sha1 result(); + + private: + struct impl; + fc::fwd my; + }; + + template + inline friend T& operator<<( T& ds, const sha1& ep ) { + ds.write( ep.data(), sizeof(ep) ); + return ds; + } + + template + inline friend T& operator>>( T& ds, sha1& ep ) { + ds.read( ep.data(), sizeof(ep) ); + return ds; + } + friend sha1 operator << ( const sha1& h1, uint32_t i ); + friend bool operator == ( const sha1& h1, const sha1& h2 ); + friend bool operator != ( const sha1& h1, const sha1& h2 ); + friend sha1 operator ^ ( const sha1& h1, const sha1& h2 ); + friend bool operator >= ( const sha1& h1, const sha1& h2 ); + friend bool operator > ( const sha1& h1, const sha1& h2 ); + friend bool operator < ( const sha1& h1, const sha1& h2 ); + + uint32_t _hash[5]; +}; + +} // namespace fc diff --git a/include/fc/crypto/sha256.hpp b/include/fc/crypto/sha256.hpp new file mode 100644 index 0000000..85a9868 --- /dev/null +++ b/include/fc/crypto/sha256.hpp @@ -0,0 +1,72 @@ +#pragma once +#include +#include + +namespace fc +{ + +class sha256 +{ + public: + sha256(); + explicit sha256( const string& hex_str ); + + string str()const; + operator string()const; + + char* data()const; + + static sha256 hash( const char* d, uint32_t dlen ); + static sha256 hash( const string& ); + + template + static sha256 hash( const T& t ) + { + sha256::encoder e; + e << t; + return e.result(); + } + + class encoder + { + public: + encoder(); + ~encoder(); + + void write( const char* d, uint32_t dlen ); + void put( char c ) { write( &c, 1 ); } + void reset(); + sha256 result(); + + private: + struct impl; + fc::fwd my; + }; + + template + inline friend T& operator<<( T& ds, const sha256& ep ) { + ds.write( ep.data(), sizeof(ep) ); + return ds; + } + + template + inline friend T& operator>>( T& ds, sha256& ep ) { + ds.read( ep.data(), sizeof(ep) ); + return ds; + } + friend sha256 operator << ( const sha256& h1, uint32_t i ); + friend bool operator == ( const sha256& h1, const sha256& h2 ); + friend bool operator != ( const sha256& h1, const sha256& h2 ); + friend sha256 operator ^ ( const sha256& h1, const sha256& h2 ); + friend bool operator >= ( const sha256& h1, const sha256& h2 ); + friend bool operator > ( const sha256& h1, const sha256& h2 ); + friend bool operator < ( const sha256& h1, const sha256& h2 ); + + uint64_t _hash[4]; +}; + + class variant; + void to_variant( const sha256& bi, variant& v ); + void from_variant( const variant& v, sha256& bi ); + +} // fc diff --git a/include/fc/crypto/sha512.hpp b/include/fc/crypto/sha512.hpp new file mode 100644 index 0000000..f926846 --- /dev/null +++ b/include/fc/crypto/sha512.hpp @@ -0,0 +1,72 @@ +#pragma once +#include +#include + +namespace fc +{ + +class sha512 +{ + public: + sha512(); + explicit sha512( const string& hex_str ); + + string str()const; + operator string()const; + + char* data()const; + + static sha512 hash( const char* d, uint32_t dlen ); + static sha512 hash( const string& ); + + template + static sha512 hash( const T& t ) + { + sha512::encoder e; + e << t; + return e.result(); + } + + class encoder + { + public: + encoder(); + ~encoder(); + + void write( const char* d, uint32_t dlen ); + void put( char c ) { write( &c, 1 ); } + void reset(); + sha512 result(); + + private: + struct impl; + fc::fwd my; + }; + + template + inline friend T& operator<<( T& ds, const sha512& ep ) { + ds.write( ep.data(), sizeof(ep) ); + return ds; + } + + template + inline friend T& operator>>( T& ds, sha512& ep ) { + ds.read( ep.data(), sizeof(ep) ); + return ds; + } + friend sha512 operator << ( const sha512& h1, uint32_t i ); + friend bool operator == ( const sha512& h1, const sha512& h2 ); + friend bool operator != ( const sha512& h1, const sha512& h2 ); + friend sha512 operator ^ ( const sha512& h1, const sha512& h2 ); + friend bool operator >= ( const sha512& h1, const sha512& h2 ); + friend bool operator > ( const sha512& h1, const sha512& h2 ); + friend bool operator < ( const sha512& h1, const sha512& h2 ); + + uint64_t _hash[8]; +}; + + class variant; + void to_variant( const sha512& bi, variant& v ); + void from_variant( const variant& v, sha512& bi ); + +} // fc diff --git a/include/fc/super_fast_hash.hpp b/include/fc/crypto/super_fast_hash.hpp similarity index 100% rename from include/fc/super_fast_hash.hpp rename to include/fc/crypto/super_fast_hash.hpp diff --git a/include/fc/error.hpp b/include/fc/error.hpp deleted file mode 100644 index b08087b..0000000 --- a/include/fc/error.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include - -namespace fc { - struct future_wait_timeout: public std::exception{ - future_wait_timeout( const fc::string& msg = "" ):m_msg(msg){} - ~future_wait_timeout()throw() {} - const char* what()const throw() { return m_msg.c_str(); } - private: - fc::string m_msg; - }; - struct task_canceled: public std::exception{}; - struct thread_quit: public std::exception{}; - struct wait_any_error: public std::exception{}; - - struct pke_exception : public std::exception {}; - struct invalid_buffer_length : public pke_exception {}; - struct invalid_key_length : public pke_exception {}; - - struct generic_exception : public std::exception { - generic_exception( const fc::string& msg = "" ):m_msg(msg){} - ~generic_exception()throw() {} - const char* what()const throw() { return m_msg.c_str(); } - private: - fc::string m_msg; - }; - - - struct bad_cast: public std::exception{ - const char* what()const throw(){ return "bad cast"; } - }; - struct range_error: public std::exception{ - const char* what()const throw(){ return "range error"; } - }; -} - diff --git a/include/fc/error_report.hpp b/include/fc/error_report.hpp deleted file mode 100644 index 726f47d..0000000 --- a/include/fc/error_report.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace fc { - - /** - * Represents one stack frame within an error_report. - */ - class error_frame { - public: - error_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value m ); - error_frame( bool detail, const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value m ); - error_frame():file("unknown-file"),line(0){} - error_frame(const error_frame& ); - error_frame(error_frame&& ); - - error_frame& operator=(const error_frame& ); - error_frame& operator=(error_frame&& ); - - fc::string to_string()const; - fc::string to_detail_string()const; - - fc::string desc; - fc::string file; - int64_t line; - fc::string method; - fc::optional meta; - fc::string time; - bool detail; - }; - typedef fc::vector error_context; - - /** - * This class is used for rich error reporting that captures relevant errors the - * whole way up the stack. By using FC_THROW_REPORT(...) and FC_REPORT_PUSH( e, ...) - * you can capture the file, line, and method where the error was caught / rethrown. - */ - class error_report { - public: - error_report(); - error_report( const fc::string& desc, fc::value meta = fc::value() ); - error_report( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() ); - - error_frame& current(); - error_report& pop_frame(); - error_report& push_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() ); - error_report& push_frame( bool detail, const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() ); - error_report& append( const error_report& e ); - - fc::string to_string()const; - fc::string to_detail_string()const; - error_context stack; ///< Human readable stack of what we were atempting to do. - - fc::exception_ptr copy_exception(); - }; - - fc::string substitute( const fc::string& format, const fc::value& keys ); - fc::value recursive_substitute( const value& in, const fc::value& keys ); - -} // namespace fc - -#include -FC_REFLECT( fc::error_frame, (desc)(file)(line)(method)(time)(meta)(detail) ) -FC_REFLECT( fc::error_report, (stack) ) - -#define FC_IDENT(...) __VA_ARGS__ -#define FC_REPORT( X, ... ) fc::error_report X( __FILE__, __LINE__, __func__, __VA_ARGS__ ) -#define FC_THROW_REPORT( ... ) FC_THROW( fc::error_report( __FILE__, __LINE__, __func__, __VA_ARGS__ )) -#define FC_REPORT_CURRENT(ER, ... ) (ER).pop_frame().push_frame( __FILE__, __LINE__, __func__, __VA_ARGS__ ) -#define FC_REPORT_PUSH( ER, ... ) (ER).push_frame( __FILE__, __LINE__, __func__, __VA_ARGS__ ); -#define FC_REPORT_PUSH_DETAIL( ER, ... ) (ER).push_frame( true, __FILE__, __LINE__, __func__, __VA_ARGS__ ) -#define FC_REPORT_POP(ER) (ER).pop_frame() diff --git a/include/fc/example.hpp b/include/fc/example.hpp deleted file mode 100644 index 0feaa7e..0000000 --- a/include/fc/example.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _EXAMPLE_HPP_ -#define _EXAMPLE_HPP_ -#include - - struct example { - int a; - int b; - }; - - FC_REFLECTABLE( example ) - -#endif // _EXAMPLE_HPP_ diff --git a/include/fc/exception.hpp b/include/fc/exception.hpp deleted file mode 100644 index 3b4fc55..0000000 --- a/include/fc/exception.hpp +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef _FC_EXCEPTION_HPP_ -#define _FC_EXCEPTION_HPP_ -#include -#include -#include - -// TODO: Remove boost exception dependency here!! -// TODO: Remove boost format dependency here!! - -// provided for easy integration with boost. -namespace boost { class exception_ptr; } - -namespace fc { - /** - * Simply including boost/exception_ptr.hpp is enough to significantly - * lengthen compile times. This header defines an 'opaque' exception - * type that provides the most 'general' exception handling needs without - * requiring a significant amount of code to be included. - */ - class exception_ptr { - public: - exception_ptr(); - exception_ptr( const boost::exception_ptr& c ); - exception_ptr( boost::exception_ptr&& c ); - exception_ptr( const exception_ptr& c ); - exception_ptr( exception_ptr&& c ); - ~exception_ptr(); - - exception_ptr& operator=(const boost::exception_ptr& c); - exception_ptr& operator=(boost::exception_ptr&& c); - - exception_ptr& operator=(const exception_ptr& c); - exception_ptr& operator=(exception_ptr&& c); - - fc::string diagnostic_information()const; - - operator bool()const; - - operator const boost::exception_ptr& ()const; - operator boost::exception_ptr& (); - private: - char my[sizeof(void*)*2]; - }; - - exception_ptr current_exception(); - template - inline exception_ptr copy_exception( T&& e ) { - try { throw e; } catch (...) { return current_exception(); } - return exception_ptr(); - } - void rethrow_exception( const exception_ptr& e ); - - void throw_exception( const char* func, const char* file, int line, const char* msg ); - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1 ); - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1, const fc::string& a2 ); - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1, const fc::string& a2, const fc::string& a3 ); - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1, const fc::string& a2, const fc::string& a3, const fc::string& a4 ); - - template - fc::string to_string( T&& v ) { return fc::string(fc::forward(v)); } - fc::string to_string( char v ); // { return fc::string(&v,1); } - fc::string to_string( uint64_t v ); - fc::string to_string( int64_t v ); - fc::string to_string( double v ); - fc::string to_string( float v ); - fc::string to_string( int8_t v ); - fc::string to_string( uint8_t v ); - fc::string to_string( int32_t v ); - fc::string to_string( uint32_t v ); - fc::string to_string( int16_t v ); - fc::string to_string( uint16_t v ); -// fc::string to_string( size_t v ); -// fc::string to_string( long int v ); - - template - void throw_exception( const char* func, const char* file, int line, const char* msg, T&& a1 ) { - throw_exception_( func, file, line, msg, to_string(fc::forward(a1) ) ); - } - - template - void throw_exception( const char* func, const char* file, int line, const char* msg, T1&& a1, T2&& a2 ) { - throw_exception_( func, file, line, msg, to_string(fc::forward(a1) ), to_string( fc::forward(a2) ) ); - } - template - void throw_exception( const char* func, const char* file, int line, const char* msg, T1&& a1, T2&& a2, T3&& a3 ) { - throw_exception_( func, file, line, msg, to_string(fc::forward(a1) ), to_string( fc::forward(a2) ), to_string( fc::forward(a3) ) ); - } - template - void throw_exception( const char* func, const char* file, int line, const char* msg, T1&& a1, T2&& a2, T3&& a3, T4&& a4 ) { - throw_exception_( func, file, line, msg, to_string(fc::forward(a1) ), to_string( fc::forward(a2) ), to_string( fc::forward(a3) ), to_string( fc::forward(a4) ) ); - } - - fc::string except_str(); - -} // namespace fc -#define FC_THROW(X) throw X -#define FC_THROW_MSG( ... ) \ - do { \ - fc::throw_exception( BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, __VA_ARGS__ ); \ - } while(0) - - -#endif // _FC_EXCEPTION_HPP_ diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp new file mode 100644 index 0000000..ea181db --- /dev/null +++ b/include/fc/exception/exception.hpp @@ -0,0 +1,238 @@ +#pragma once +/** + * @file exception.hpp + * @brief Defines exception's used by fc + */ +#include +#include +#include + +namespace fc +{ + namespace detail { class exception_impl; } + + /** + * @brief Used to generate a useful error report when an exception is thrown. + * @ingroup serializable + * + * At each level in the stack where the exception is caught and rethrown a + * new log_message is added to the exception. + * + * exception's are designed to be serialized to a variant and + * deserialized from an variant. + * + * @see FC_THROW_EXCEPTION + * @see FC_RETHROW_EXCEPTION + * @see FC_RETHROW_EXCEPTIONS + */ + class exception + { + public: + exception(); + exception( log_message&& ); + exception( const exception& e ); + exception( exception&& e ); + ~exception(); + + virtual const char* what()const throw() { return "exception"; } + + /** + * @return a reference to log messages that have + * been added to this log. + */ + const log_messages& get_log()const; + void append_log( log_message m ); + + /** + * Generates a detailed string including file, line, method, + * and other information that is generally only useful for + * developers. + */ + string to_detail_string( log_level ll = log_level::all )const; + + /** + * Generates a user-friendly error report. + */ + string to_string( log_level ll = log_level::info )const; + + /** + * Throw this exception as its most derived type. + * + * @note does not return. + */ + virtual NO_RETURN void dynamic_rethrow_exception()const; + + /** + * This is equivalent to: + * @code + * try { throwAsDynamic_exception(); } + * catch( ... ) { return std::current_exception(); } + * @endcode + */ + virtual std::shared_ptr dynamic_copy_exception()const; + + protected: + friend void to_variant( const exception& e, variant& v ); + friend void from_variant( const variant& e, exception& ll ); + virtual void from_variant( const variant& ){} + virtual void to_variant( variant& ){} + + std::unique_ptr my; + }; + void to_variant( const exception& e, variant& v ); + void from_variant( const variant& e, exception& ll ); + typedef std::shared_ptr exception_ptr; + + typedef optional oexception; + + + + /** + * @brief re-thrown whenever an unhandled exception is caught. + * @ingroup serializable + * Any exceptions thrown by 3rd party libraries that are not + * caught get wrapped in an unhandled_exception exception. + * + * The original exception is captured as a std::exception_ptr + * which may be rethrown. The std::exception_ptr does not + * propgate across process boundaries. + */ + class unhandled_exception : public exception + { + public: + unhandled_exception( log_message&& m, std::exception_ptr e = std::current_exception() ); + unhandled_exception( log_messages ); + unhandled_exception( const exception& ); + virtual const char* what()const throw() { return "Unhandled _exception"; } + std::exception_ptr get_inner_exception()const; + + virtual NO_RETURN void dynamic_rethrow_exception()const; + virtual std::shared_ptr dynamic_copy_exception()const; + private: + std::exception_ptr _inner; + }; + + template + fc::exception_ptr copy_exception( T&& e ) + { +#if defined(_MSC_VER) && (_MSC_VER < 1700) + return std::make_shared( log_message(), std::copy_exception(fc::forward(e)) ); +#else + return std::make_shared( log_message(), std::make_exception_ptr(fc::forward(e)) ); +#endif + } + + /** + * @brief wraps unhanlded std::exception's + * @ingroup serializable + * + * This exception allows the 'what' field of unhandled std::exceptions + * to be propagated across process boundaries. + */ + class std_exception : public unhandled_exception + { + public: + std_exception( log_message&& m, std::exception_ptr e, const char* w ); + std_exception( log_messages ); + std_exception( const exception& c); + virtual const char* what()const throw() { return _what.c_str(); } + + protected: + void from_variant( const variant& v ); + void to_variant( variant& v ); + private: + string _what; + }; + + +#define FC_DECLARE_EXCEPTION( TYPE, WHAT ) \ + class TYPE : public exception \ + { \ + public: \ + TYPE( log_message&& m ); \ + TYPE( log_messages ); \ + TYPE( const TYPE& c ); \ + TYPE(); \ + virtual const char* what()const throw() { return WHAT; } \ + }; + + FC_DECLARE_EXCEPTION( timeout_exception, "Timeout" ); + FC_DECLARE_EXCEPTION( file_not_found_exception, "File Not Found" ); + /** + * @brief report's parse errors + */ + FC_DECLARE_EXCEPTION( parse_error_exception, "Parse Error" ); + FC_DECLARE_EXCEPTION( invalid_arg_exception, "Invalid Argument" ); + /** + * @brief reports when a key, guid, or other item is not found. + */ + FC_DECLARE_EXCEPTION( key_not_found_exception, "Key Not Found" ); + FC_DECLARE_EXCEPTION( bad_cast_exception, "Bad Cast" ); + FC_DECLARE_EXCEPTION( out_of_range_exception, "Out of Range" ); + + /** @brief if an operation is unsupported or not valid this may be thrown */ + FC_DECLARE_EXCEPTION( invalidOperation_exception, "Invalid Operation" ); + + /** + * @brief used to report a canceled Operation + */ + FC_DECLARE_EXCEPTION( canceled_exception, "Canceled" ); + /** + * @brief used inplace of assert() to report violations of pre conditions. + */ + FC_DECLARE_EXCEPTION( assert_exception, "Assert Exception" ); + FC_DECLARE_EXCEPTION( eof_exception, "End Of File" ); + + fc::string except_str(); + + +} // namespace fc +/** + * @brief Checks a condition and throws an assert_exception if the test is FALSE + */ +#define FC_ASSERT( TEST, ... ) \ +if( !(TEST) ) { FC_THROW_EXCEPTION( assert_exception, #TEST __VA_ARGS__ ); } + +#define FC_THROW( FORMAT, ... ) \ + throw fc::exception( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ) + +#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \ + fc::EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ) +/** + * @def FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) + * @param EXCEPTION a class in the Phoenix::Athena::API namespace that inherits + * @param format - a const char* string with "${keys}" + */ +#define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \ + throw fc::EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ) + + +/** + * @def FC_RETHROW_EXCEPTION(ER,LOG_LEVEL,FORMAT,...) + * @brief Appends a log_message to the exception ER and rethrows it. + */ +#define FC_RETHROW_EXCEPTION( ER, LOG_LEVEL, FORMAT, ... ) \ + do { \ + er.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \ + throw;\ + } while(false) + +/** + * @def FC_RETHROW_EXCEPTIONS(LOG_LEVEL,FORMAT,...) + * @brief Catchs all exception's, std::exceptions, and ... and rethrows them after + * appending the provided log message. + */ +#define FC_RETHROW_EXCEPTIONS( LOG_LEVEL, FORMAT, ... ) \ + catch( fc::exception& er ) { \ + FC_RETHROW_EXCEPTION( er, LOG_LEVEL, FORMAT, __VA_ARGS__ ); \ + } catch( const std::exception& e ) { \ + throw fc::std_exception( \ + FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \ + std::current_exception(), \ + e.what() ) ; \ + } catch( ... ) { \ + throw fc::unhandled_exception( \ + FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \ + std::current_exception() ); \ + } + diff --git a/include/fc/filesystem.hpp b/include/fc/filesystem.hpp index 5cea39e..988d11c 100644 --- a/include/fc/filesystem.hpp +++ b/include/fc/filesystem.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include -#include +#include +#include #include namespace boost { @@ -60,6 +62,9 @@ namespace fc { bool is_relative()const; bool is_absolute()const; + + static char separator_char; + private: fwd _p; }; @@ -104,20 +109,64 @@ namespace fc { void create_directories( const path& p ); void remove_all( const path& p ); path absolute( const path& p ); + path make_relative(const path& from, const path& to); path canonical( const path& p ); uint64_t file_size( const path& p ); bool remove( const path& p ); void copy( const path& from, const path& to ); void rename( const path& from, const path& to ); + void create_hard_link( const path& from, const path& to ); path unique_path(); path temp_directory_path(); - class value; - void pack( fc::value& , const fc::path& ); - void unpack( const fc::value& , fc::path& ); + class variant; + void to_variant( const fc::path&, fc::variant& ); + void from_variant( const fc::variant& , fc::path& ); template<> struct get_typename { static const char* name() { return "path"; } }; + + /** + * Class which creates a temporary directory inside an existing temporary directory. + */ + class temp_file_base + { + public: + inline ~temp_file_base() { remove(); } + inline operator bool() const { return _path; } + inline bool operator!() const { return !_path; } + const fc::path& path() const; + void remove(); + void release(); + protected: + typedef fc::optional path_t; + inline temp_file_base(const path_t& path) : _path(path) {} + inline temp_file_base(path_t&& path) : _path(std::move(path)) {} + path_t _path; + }; + + /** + * Class which creates a temporary directory inside an existing temporary directory. + */ + class temp_file : public temp_file_base + { + public: + temp_file(temp_file&& other); + temp_file& operator=(temp_file&& other); + temp_file(const fc::path& tempFolder = fc::temp_directory_path(), bool create = false); + }; + + /** + * Class which creates a temporary directory inside an existing temporary directory. + */ + class temp_directory : public temp_file_base + { + public: + temp_directory(temp_directory&& other); + temp_directory& operator=(temp_directory&& other); + temp_directory(const fc::path& tempFolder = fc::temp_directory_path()); + }; + } diff --git a/include/fc/function.hpp b/include/fc/function.hpp deleted file mode 100644 index 6aec96e..0000000 --- a/include/fc/function.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#if 0 -#pragma once -#include -#include -namespace fc { -template -class function { - public: - function(){} - - template - function( Functor&& f ) - :func( new impl( fc::forward(f) ) ){}; - - function( const function& c ):func(c.func){} - function( function&& c ) { fc::swap( func, c.func); } - ~function(){} - - template - function& operator=( Functor&& f ) { - func.reset( new impl( fc::forward(f) ) ); - return *this; - } - - function& operator=( const function& c ) { func = c.func; return *this; } - function& operator=( function&& c ) { fc::swap(func,c.func); return *this; } - - R operator()( Args... args)const { return func->call(args...); } - - bool operator!()const { return !func; } - - protected: - - struct impl_base : public fc::retainable { - virtual ~impl_base(){} - virtual R call(Args...)const = 0; - }; - - template - struct impl : impl_base { - template - impl( U&& u ):func( fc::forward(u) ){} - - virtual R call(Args... args)const { return func(args...); } - - Functor func; - }; - function( const fc::shared_ptr& f ):func(f){} - function( fc::shared_ptr&& f ):func(fc::move(f)){} - - fc::shared_ptr func; -}; - -/** - * Provides functionality similar to boost::function. - * - * Functions have 'reference semantics', meaning that copies will all - * refer to the same underlying function. - * - * TODO: Small functions are allocated on the stack, large functors are - * allocated on the heap. - * - * Simply including boost/function adds an additional 0.6 seconds to every - * object file compared to using fc/function. - * - * Including on the other hand adds a mere 0.05 - * seconds to every object file compared to fc/function. - */ -template -class function : public function { - public: - function(){} - template - function( U&& u ) { *this = fc::forward(u); } - using function::operator=; -}; - -template -class function : public function { - public: - function(){} - function( const function& u ):function(u){} - function( function&& u ):function(u){} - function( const function& u ):function(u.func){} - function( function&& u ):function(fc::move(u.func)){} - - using function::operator=; -}; - -template -class function : public function { - public: - function(){} - template - function( U&& u ):function( fc::forward(u) ){} - function( const function& c ):function(c.func){} - using function::operator=; -}; - -template -class function : public function { - public: - function(){} - template - function( U&& u ):function( fc::forward(u) ){} - function( const function& c ):function(c.func){} - using function::operator=; -}; - -} -#endif - diff --git a/include/fc/fwd_impl.hpp b/include/fc/fwd_impl.hpp index c5862ce..639085a 100644 --- a/include/fc/fwd_impl.hpp +++ b/include/fc/fwd_impl.hpp @@ -1,5 +1,4 @@ -#ifndef _FC_FWD_IMPL_HPP_ -#define _FC_FWD_IMPL_HPP_ +#pragma once #include #include @@ -134,4 +133,3 @@ namespace fc { } // namespace fc -#endif //_FC_FWD_IMPL_HPP_ diff --git a/include/fc/fwd_reflect.hpp b/include/fc/fwd_reflect.hpp deleted file mode 100644 index 62b5bfe..0000000 --- a/include/fc/fwd_reflect.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _FC_FWD_REFLECT_HPP_ -#define _FC_FWD_REFLECT_HPP_ -#include -#include - -namespace fc { - template - class reflector> : public detail::reflector_impl, reflector> >{ - public: - virtual const char* name()const { return instance().name(); } - virtual void visit( void* s, const abstract_visitor& v )const { - instance().visit(s,v); - } - virtual void visit( const void* s, const abstract_const_visitor& v )const { - instance().visit(s,v); - } - - static reflector& instance() { return reflector::instance(); } - }; -} // namespace fc -#endif //_FC_FWD_REFLECT_HPP_ diff --git a/include/fc/http/connection.hpp b/include/fc/http/connection.hpp deleted file mode 100644 index 0f71530..0000000 --- a/include/fc/http/connection.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - namespace ip { class endpoint; } - class tcp_socket; - - namespace http { - - struct header { - header( fc::string k, fc::string v ) - :key(fc::move(k)),val(fc::move(v)){} - header(){} - fc::string key; - fc::string val; - }; - - struct reply { - enum status_code { - OK = 200, - RecordCreated = 201, - NotFound = 404, - Found = 302, - InternalServerError = 500 - }; - reply( status_code c = OK):status(c){} - int status; - fc::vector
headers; - fc::vector body; - }; - - struct request { - fc::string get_header( const fc::string& key )const; - fc::string method; - fc::string domain; - fc::string path; - fc::vector
headers; - fc::vector body; - }; - - fc::vector
parse_urlencoded_params( const fc::string& f ); - - /** - * Connections have reference semantics, all copies refer to the same - * underlying socket. - */ - class connection { - public: - // used for clients - void connect_to( const fc::ip::endpoint& ep ); - http::reply request( const fc::string& method, const fc::string& url, const fc::string& body ); - - // used for servers - fc::tcp_socket& get_socket()const; - - http::request read_request()const; - - FC_REFERENCE_TYPE(connection) - }; - -} } // fc::http - diff --git a/include/fc/interprocess/file_mapping.hpp b/include/fc/interprocess/file_mapping.hpp index 18f9e01..00863e8 100644 --- a/include/fc/interprocess/file_mapping.hpp +++ b/include/fc/interprocess/file_mapping.hpp @@ -25,7 +25,7 @@ namespace fc { }; class mapped_region { public: - mapped_region( const file_mapping& fm, mode_t m, size_t start, size_t size ); + mapped_region( const file_mapping& fm, mode_t m, uint64_t start, size_t size ); mapped_region( const file_mapping& fm, mode_t m ); ~mapped_region(); void flush(); diff --git a/include/fc/interprocess/iprocess.hpp b/include/fc/interprocess/iprocess.hpp new file mode 100644 index 0000000..77d9ce6 --- /dev/null +++ b/include/fc/interprocess/iprocess.hpp @@ -0,0 +1,66 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace fc +{ + /** + * @brief abstract interface for interacting with external processes + * + * At the very least we have ssh::process and direct child processes, and + * there may be other processes that need to implement this protocol. + */ + class iprocess + { + public: + enum exec_opts { + open_none = 0, + open_stdin = 0x01, + open_stdout = 0x02, + open_stderr = 0x04, + open_all = open_stdin|open_stdout|open_stderr, + }; + + virtual ~iprocess(){} + + /** + * + * @return *this + */ + virtual iprocess& exec( const fc::path& exe, vector args, + const fc::path& work_dir = fc::path(), exec_opts opts = open_all ) = 0; + + /** + * @return blocks until the process exits + */ + virtual int result() = 0; + + + /** + * Forcefully kills the process. + */ + virtual void kill() = 0; + + /** + * @brief returns a stream that writes to the process' stdin + */ + virtual fc::buffered_ostream_ptr in_stream() = 0; + + /** + * @brief returns a stream that reads from the process' stdout + */ + virtual fc::buffered_istream_ptr out_stream() = 0; + /** + * @brief returns a stream that reads from the process' stderr + */ + virtual fc::buffered_istream_ptr err_stream() = 0; + + }; + + typedef std::shared_ptr iprocess_ptr; + + +} // namespace fc diff --git a/include/fc/interprocess/process.hpp b/include/fc/interprocess/process.hpp new file mode 100644 index 0000000..54813b8 --- /dev/null +++ b/include/fc/interprocess/process.hpp @@ -0,0 +1,36 @@ +#pragma once +#include + +namespace fc { + + fc::path find_executable_in_path( const fc::string name ); + + /** + * @brief start and manage an local process + * @note this class implements reference semantics. + */ + class process : public iprocess + { + public: + process(); + ~process(); + + virtual iprocess& exec( const fc::path& exe, + vector args, + const fc::path& work_dir = fc::path(), + exec_opts opts = open_all ); + + virtual int result(); + virtual void kill(); + virtual fc::buffered_ostream_ptr in_stream(); + virtual fc::buffered_istream_ptr out_stream(); + virtual fc::buffered_istream_ptr err_stream(); + + class impl; + private: + std::unique_ptr my; + }; + + typedef std::shared_ptr process_ptr; + +} // namespace fc diff --git a/include/fc/invokeable.hpp b/include/fc/invokeable.hpp deleted file mode 100644 index ee7d9e4..0000000 --- a/include/fc/invokeable.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _FC_INVOKEABLE_HPP_ -#define _FC_INVOKEABLE_HPP_ - -namespace fc { - - class invokeable { - public: - virtual ~invokeable(){}; - - virtual void invoke( const promise::ptr& prom, const string& name, size_t num_params, reflect::cref* params ); - - void invoke( const std::string& name ) { invoke( promise::ptr(), name, 0, 0 ); } - }; - -} - -#endif // _FC_INVOKEABLE_HPP_ diff --git a/include/fc/io/base16.hpp b/include/fc/io/base16.hpp new file mode 100644 index 0000000..f3ca29e --- /dev/null +++ b/include/fc/io/base16.hpp @@ -0,0 +1,13 @@ +#pragma once +#include +#include + +namespace fc { + uint8_t from_hex( char c ); + fc::string to_hex( const char* d, uint32_t s ); + + /** + * @return the number of bytes decoded + */ + size_t from_hex( const fc::string& hex_str, char* out_data, size_t out_data_len ); +} diff --git a/include/fc/io/base58.hpp b/include/fc/io/base58.hpp new file mode 100644 index 0000000..71beb15 --- /dev/null +++ b/include/fc/io/base58.hpp @@ -0,0 +1,8 @@ +#pragma once +#include + +namespace fc { + fc::string to_base58( const char* d, size_t s ); + fc::vector from_base58( const fc::string& base58_str ); + size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len ); +} diff --git a/include/fc/base64.hpp b/include/fc/io/base64.hpp similarity index 100% rename from include/fc/base64.hpp rename to include/fc/io/base64.hpp diff --git a/include/fc/io/buffered_iostream.hpp b/include/fc/io/buffered_iostream.hpp new file mode 100644 index 0000000..5ebb566 --- /dev/null +++ b/include/fc/io/buffered_iostream.hpp @@ -0,0 +1,71 @@ +#pragma once +#include + +namespace fc +{ + namespace detail + { + class buffered_istream_impl; + class buffered_ostream_impl; + } + + /** + * @brief Reads data from an unbuffered stream + * and enables peek functionality. + */ + class buffered_istream : public virtual istream + { + public: + buffered_istream( istream_ptr is ); + buffered_istream( buffered_istream&& o ); + + buffered_istream& operator=( buffered_istream&& i ); + + virtual ~buffered_istream(); + + /** read at least 1 byte or throw, if no data is available + * this method should block cooperatively until data is + * available or fc::eof_exception is thrown. + * + * @pre len > 0 + * @pre buf != nullptr + * @throws fc::eof if at least 1 byte cannot be read + **/ + virtual std::size_t readsome( char* buf, std::size_t len ); + + /** + * This method may block until at least 1 character is + * available. + */ + char peek()const; + + private: + std::unique_ptr my; + }; + typedef std::shared_ptr buffered_istream_ptr; + + + /** + * + */ + class buffered_ostream : public virtual ostream + { + public: + buffered_ostream( ostream_ptr o, size_t bufsize = 4096 ); + buffered_ostream( buffered_ostream&& m ); + ~buffered_ostream(); + + buffered_ostream& operator=( buffered_ostream&& m ); + /** + * This method will return immediately unless the buffer + * is full, in which case it will flush which may block. + */ + virtual size_t writesome( const char* buf, size_t len ); + + virtual void close(); + virtual void flush(); + private: + std::unique_ptr my; + }; + typedef std::shared_ptr buffered_ostream_ptr; +} diff --git a/include/fc/io/datastream.hpp b/include/fc/io/datastream.hpp new file mode 100644 index 0000000..5e54998 --- /dev/null +++ b/include/fc/io/datastream.hpp @@ -0,0 +1,182 @@ +#pragma once +#include +#include +#include + +namespace fc { + +namespace detail +{ + NO_RETURN void throw_datastream_range_error( const char* file, size_t len, size_t over ); +} + +/** + * The purpose of this datastream is to provide a fast, effecient, means + * of calculating the amount of data "about to be written" and then + * writing it. This means having two modes of operation, "test run" where + * you call the entire pack sequence calculating the size, and then + * actually packing it after doing a single allocation. + */ +template +class datastream { + public: + datastream( T start, size_t s ) + :_start(start),_pos(start),_end(start+s){}; + + + inline void skip( size_t s ){ _pos += s; } + inline bool read( char* d, size_t s ) { + if( size_t(_end - _pos) >= (size_t)s ) { + memcpy( d, _pos, s ); + _pos += s; + return true; + } + detail::throw_datastream_range_error( "read", _end-_start, int64_t(-((_end-_pos) - 1))); + } + + inline bool write( const char* d, size_t s ) { + if( _end - _pos >= (int32_t)s ) { + memcpy( _pos, d, s ); + _pos += s; + return true; + } + detail::throw_datastream_range_error( "write", _end-_start, int64_t(-((_end-_pos) - 1))); + } + + inline bool put(char c) { + if( _pos < _end ) { + *_pos = c; + ++_pos; + return true; + } + detail::throw_datastream_range_error( "put", _end-_start, int64_t(-((_end-_pos) - 1))); + } + + inline bool get( unsigned char& c ) { return get( *(char*)&c ); } + inline bool get( char& c ) + { + if( _pos < _end ) { + c = *_pos; + ++_pos; + return true; + } + detail::throw_datastream_range_error( "get", _end-_start, int64_t(-((_end-_pos) - 1))); + } + + T pos()const { return _pos; } + inline bool valid()const { return _pos <= _end && _pos >= _start; } + inline bool seekp(size_t p) { _pos = _start + p; return _pos <= _end; } + inline size_t tellp()const { return _pos - _start; } + inline size_t remaining()const { return _end - _pos; } + private: + T _start; + T _pos; + T _end; +}; + +template<> +class datastream { + public: + datastream( size_t init_size = 0):_size(init_size){}; + inline bool skip( size_t s ) { _size += s; return true; } + inline bool write( const char* ,size_t s ) { _size += s; return true; } + inline bool put(char ) { ++_size; return true; } + inline bool valid()const { return true; } + inline bool seekp(size_t p) { _size = p; return true; } + inline size_t tellp()const { return _size; } + inline size_t remaining()const { return 0; } + private: + size_t _size; +}; + +template +inline datastream& operator<<(datastream& ds, const int32_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator>>(datastream& ds, int32_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator<<(datastream& ds, const uint32_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} + +template +inline datastream& operator>>(datastream& ds, uint32_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator<<(datastream& ds, const int64_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} + +template +inline datastream& operator>>(datastream& ds, int64_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator<<(datastream& ds, const uint64_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} + +template +inline datastream& operator>>(datastream& ds, uint64_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator<<(datastream& ds, const int16_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} + +template +inline datastream& operator>>(datastream& ds, int16_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator<<(datastream& ds, const uint16_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} + +template +inline datastream& operator>>(datastream& ds, uint16_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator<<(datastream& ds, const int8_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} + +template +inline datastream& operator>>(datastream& ds, int8_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} +template +inline datastream& operator<<(datastream& ds, const uint8_t& d) { + ds.write( (const char*)&d, sizeof(d) ); + return ds; +} + +template +inline datastream& operator>>(datastream& ds, uint8_t& d) { + ds.read((char*)&d, sizeof(d) ); + return ds; +} + + +} // namespace fc + diff --git a/include/fc/datastream.hpp b/include/fc/io/datastream_back.hpp similarity index 53% rename from include/fc/datastream.hpp rename to include/fc/io/datastream_back.hpp index d4f965c..8c4e092 100644 --- a/include/fc/datastream.hpp +++ b/include/fc/io/datastream_back.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include @@ -14,96 +13,78 @@ namespace fc { * actually packing it after doing a single allocation. */ template -struct datastream { +class datastream { + public: datastream( T start, size_t s ) - :m_start(start),m_pos(start),m_end(start+s){}; + :_start(start),_pos(start),_end(start+s){}; - inline void skip( size_t s ){ m_pos += s; } + inline void skip( size_t s ){ _pos += s; } inline bool read( char* d, size_t s ) { - if( size_t(m_end - m_pos) >= (size_t)s ) { - memcpy( d, m_pos, s ); - m_pos += s; + if( size_t(_end - _pos) >= (size_t)s ) { + memcpy( d, _pos, s ); + _pos += s; return true; } - FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", - fc::value("bytes_past",int64_t(-((m_end-m_pos) - s))) - ("buffer_size", int64_t(m_end-m_start)) ); + detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1))) return false; } inline bool write( const char* d, size_t s ) { - if( m_end - m_pos >= (int32_t)s ) { - memcpy( m_pos, d, s ); - m_pos += s; + if( _end - _pos >= (int32_t)s ) { + memcpy( _pos, d, s ); + _pos += s; return true; } - FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", - fc::value("bytes_past",int64_t(-((m_end-m_pos) - s))) - ("buffer_size", int64_t(m_end-m_start)) ); + detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1))) return false; } inline bool put(char c) { - if( m_pos < m_end ) { - *m_pos = c; - ++m_pos; + if( _pos < _end ) { + *_pos = c; + ++_pos; return true; } - FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", - fc::value("bytes_past",int64_t(-((m_end-m_pos) - 1))) - ("buffer_size", int64_t(m_end-m_start)) ); + detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1))) } inline bool get( unsigned char& c ) { return get( *(char*)&c ); } inline bool get( char& c ) { - if( m_pos < m_end ) { - c = *m_pos; - ++m_pos; + if( _pos < _end ) { + c = *_pos; + ++_pos; return true; } - FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer of size ${buffer_size} ", - fc::value("bytes_past",int64_t(-((m_end-m_pos) - 1))) - ("buffer_size", int64_t(m_end-m_start)) ); + detail::throw_datastream_range_error( _end-start, int64_t(-((_end-_pos) - 1))) } - T pos()const { return m_pos; } - inline bool valid()const { return m_pos <= m_end && m_pos >= m_start; } - inline bool seekp(size_t p) { m_pos = m_start + p; return m_pos <= m_end; } - inline size_t tellp()const { return m_pos - m_start; } - inline size_t remaining()const { return m_end - m_pos; } + T pos()const { return _pos; } + inline bool valid()const { return _pos <= _end && _pos >= _start; } + inline bool seekp(size_t p) { _pos = _start + p; return _pos <= _end; } + inline size_t tellp()const { return _pos - _start; } + inline size_t remaining()const { return _end - _pos; } private: - T m_start; - T m_pos; - T m_end; + T _start; + T _pos; + T _end; }; template<> -struct datastream { - datastream( size_t init_size = 0):m_size(init_size){}; - inline bool skip( size_t s ) { m_size += s; return true; } - inline bool write( const char* d,size_t s ) { m_size += s; return true; } - inline bool put(char c) { ++m_size; return true; } - inline bool valid()const { return true; } - inline bool seekp(size_t p) { m_size = p; return true; } - inline size_t tellp()const { return m_size; } - inline size_t remaining()const { return 0; } -private: - size_t m_size; +class datastream { + public: + datastream( size_t init_size = 0):_size(init_size){}; + inline bool skip( size_t s ) { _size += s; return true; } + inline bool write( const char* d,size_t s ) { _size += s; return true; } + inline bool put(char c) { ++_size; return true; } + inline bool valid()const { return true; } + inline bool seekp(size_t p) { _size = p; return true; } + inline size_t tellp()const { return _size; } + inline size_t remaining()const { return 0; } + private: + size_t _size; }; -/* -template -inline datastream& operator<<(datastream& ds, const size_t& d) { - ds.write( (const char*)&d, sizeof(d) ); - return *this; -} -template -inline datastream& operator>>(datastream& ds, size_t& d) { - ds.read((char*)&d, sizeof(d) ); - return *this; -} -*/ template inline datastream& operator<<(datastream& ds, const int32_t& d) { ds.write( (const char*)&d, sizeof(d) ); diff --git a/include/fc/fstream.hpp b/include/fc/io/fstream.hpp similarity index 92% rename from include/fc/fstream.hpp rename to include/fc/io/fstream.hpp index fd31862..fe05a9a 100644 --- a/include/fc/fstream.hpp +++ b/include/fc/io/fstream.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include namespace fc { class path; @@ -13,7 +13,7 @@ namespace fc { ~ofstream(); void open( const fc::path& file, int m = binary ); - ofstream& write( const char* buf, size_t len ); + size_t writesome( const char* buf, size_t len ); void put( char c ); void close(); void flush(); diff --git a/include/fc/io/iobuffer.hpp b/include/fc/io/iobuffer.hpp new file mode 100644 index 0000000..02f919b --- /dev/null +++ b/include/fc/io/iobuffer.hpp @@ -0,0 +1,81 @@ +#pragma once +#include +#include + +namespace fc +{ + /** + * Records the size, but discards the data. + */ + class size_stream : public virtual fc::ostream + { + public: + size_stream( size_t s = 0):_size(s){} + + size_t size()const { return _size; } + size_t seek( size_t pos ) { return _size = pos; } + + virtual size_t writesome( const char* /*ignored buf*/, size_t len ) + { + _size += len; + return len; + } + + virtual void close(){} + virtual void flush(){} + + private: + size_t _size; + }; + + + class iobuffer : public virtual fc::iostream + { + public: + iobuffer( size_t s ) + :_data(s){} + + size_t size()const { return _data.size(); } + size_t pos()const { return _pos; } + size_t seek( size_t pos ) + { + return _pos = std::min(_data.size(),pos); + } + + virtual size_t readsome( char* buf, size_t len ) + { + auto avail = std::min( _data.size()-_pos, len ); + if( avail == 0 ) throw fc::eof_exception(); + memcpy( buf, _data.data()+_pos, avail ); + _pos += avail; + return avail; + } + /** + * This method may block until at least 1 character is + * available. + */ + char peek()const + { + if( _pos == _data.size() ) throw fc::eof_exception(); + return _data[_pos]; + } + + virtual size_t writesome( const char* buf, size_t len ) + { + auto avail = std::max( _data.size(), _pos + len ); + _data.resize(avail); + memcpy( _data.data()+_pos, buf, len ); + _pos += avail; + return avail; + } + char* data() { return _data.data(); } + + virtual void close(){} + virtual void flush(){} + + private: + std::vector _data; + size_t _pos; + }; + +} diff --git a/include/fc/io/iostream.hpp b/include/fc/io/iostream.hpp new file mode 100644 index 0000000..27945ee --- /dev/null +++ b/include/fc/io/iostream.hpp @@ -0,0 +1,98 @@ +#pragma once +#include +#include +#include + +namespace fc { + + /** + * Provides a fc::thread friendly cooperatively multi-tasked stream that + * will block 'cooperatively' instead of hard blocking. + */ + class istream + { + public: + virtual ~istream(){}; + + /** read at least 1 byte or throw, if no data is available + * this method should block cooperatively until data is + * available or fc::eof is thrown. + * + * @throws fc::eof if at least 1 byte cannot be read + **/ + virtual size_t readsome( char* buf, size_t len ) = 0; + + /** read len bytes or throw, this method is implemented + * in terms of readsome. + * + * @throws fc::eof_exception if len bytes cannot be read + **/ + istream& read( char* buf, size_t len ); + char get(); + }; + typedef std::shared_ptr istream_ptr; + + /** + * Provides a fc::thread friendly cooperatively multi-tasked stream that + * will block 'cooperatively' instead of hard blocking. + */ + class ostream + { + public: + virtual ~ostream(){}; + virtual size_t writesome( const char* buf, size_t len ) = 0; + virtual void close() = 0; + virtual void flush() = 0; + + void put( char c ) { write(&c,1); } + + /** implemented in terms of writesome, guarantees len bytes are sent + * but not flushed. + **/ + ostream& write( const char* buf, size_t len ); + }; + + typedef std::shared_ptr ostream_ptr; + + class iostream : public virtual ostream, public virtual istream {}; + + fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' ); + + template + ostream& operator<<( ostream& o, char (&array)[N] ) + { + return o.write( array, N ); + } + + ostream& operator<<( ostream& o, char ); + ostream& operator<<( ostream& o, const char* v ); + ostream& operator<<( ostream& o, const std::string& v ); + ostream& operator<<( ostream& o, const fc::string& v ); + ostream& operator<<( ostream& o, const double& v ); + ostream& operator<<( ostream& o, const float& v ); + ostream& operator<<( ostream& o, const int64_t& v ); + ostream& operator<<( ostream& o, const uint64_t& v ); + ostream& operator<<( ostream& o, const int32_t& v ); + ostream& operator<<( ostream& o, const uint32_t& v ); + ostream& operator<<( ostream& o, const int16_t& v ); + ostream& operator<<( ostream& o, const uint16_t& v ); + ostream& operator<<( ostream& o, const int8_t& v ); + ostream& operator<<( ostream& o, const uint8_t& v ); +#ifndef _MSC_VER + ostream& operator<<( ostream& o, const size_t& v ); +#endif + + istream& operator>>( istream& o, std::string& v ); + istream& operator>>( istream& o, fc::string& v ); + istream& operator>>( istream& o, char& v ); + istream& operator>>( istream& o, double& v ); + istream& operator>>( istream& o, float& v ); + istream& operator>>( istream& o, int64_t& v ); + istream& operator>>( istream& o, uint64_t& v ); + istream& operator>>( istream& o, int32_t& v ); + istream& operator>>( istream& o, uint32_t& v ); + istream& operator>>( istream& o, int16_t& v ); + istream& operator>>( istream& o, uint16_t& v ); + istream& operator>>( istream& o, int8_t& v ); + istream& operator>>( istream& o, uint8_t& v ); +} diff --git a/include/fc/io/json.hpp b/include/fc/io/json.hpp new file mode 100644 index 0000000..4950a87 --- /dev/null +++ b/include/fc/io/json.hpp @@ -0,0 +1,56 @@ +#pragma once +#include + +namespace fc +{ + class path; + class ostream; + class buffered_istream; + + /** + * Provides interface for json serialization. + * + * json strings are always UTF8 + */ + class json + { + public: + static ostream& to_stream( ostream& out, const fc::string& ); + static ostream& to_stream( ostream& out, const variant& v ); + static ostream& to_stream( ostream& out, const variants& v ); + static ostream& to_stream( ostream& out, const variant_object& v ); + + static variant from_stream( buffered_istream& in ); + + static variant from_string( const string& utf8_str ); + static string to_string( const variant& v ); + static string to_pretty_string( const variant& v ); + static void save_to_file( const variant& v, const string& fi, bool pretty = true ); + static variant from_file( const fc::path& p ); + + template + static T from_file( const fc::path& p ) + { + return json::from_file(p).as(); + } + + template + static string to_string( const T& v ) + { + return to_string( variant(v) ); + } + + template + static string to_pretty_string( const T& v ) + { + return to_pretty_string( variant(v) ); + } + + template + static void save_to_file( const T& v, const string& p, bool pretty = true ) + { + save_to_file( variant(v), p, pretty ); + } + }; + +} // fc diff --git a/include/fc/raw.hpp b/include/fc/io/raw.hpp similarity index 62% rename from include/fc/raw.hpp rename to include/fc/io/raw.hpp index 0733408..52321bc 100644 --- a/include/fc/raw.hpp +++ b/include/fc/io/raw.hpp @@ -1,52 +1,55 @@ #pragma once -#include -#include -#include +#include +#include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include namespace fc { - class value; namespace raw { + template + inline void pack( Stream& s, const variant_object& v ); + template + inline void unpack( Stream& s, variant_object& v ); - template - void unpack( Stream& s, fc::optional& v ); - template - void pack( Stream& s, const fc::optional& v ); + template + inline void pack( Stream& s, const variant& v ); + template + inline void unpack( Stream& s, variant& v ); template - void unpack( Stream& s, fc::value& ); - template - void pack( Stream& s, const fc::value& ); + inline void pack( Stream& s, const fc::time_point& tp ) + { + uint64_t usec = tp.time_since_epoch().count(); + s.write( (const char*)&usec, sizeof(usec) ); + } template - void unpack( Stream& s, fc::string& ); - - template - void pack( Stream& s, const fc::string& ); - - template - inline void pack( Stream& s, const T& v ); - - template - inline void unpack( Stream& s, T& v ); - - template - inline void pack( Stream& s, const fc::vector& v ); - template - inline void unpack( Stream& s, fc::vector& v ); - + inline void unpack( Stream& s, fc::time_point& tp ) + { + uint64_t usec; + s.read( (char*)&usec, sizeof(usec) ); + tp = fc::time_point() + fc::microseconds(usec); + } template inline void pack( Stream& s, const fc::array& v) { s.write((const char*)&v.data[0],N*sizeof(T)); } + template inline void unpack( Stream& s, fc::array& v) { s.read((char*)&v.data[0],N*sizeof(T)); } + template inline void pack( Stream& s, const signed_int& v ) { uint32_t val = (v.value<<1) ^ (v.value>>31); do { @@ -239,12 +242,152 @@ namespace fc { fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack(s,v); } + template + class variant_packer : public variant::visitor + { + public: + variant_packer( Stream& _s ):s(_s){} + virtual void handle()const { } + virtual void handle( const int64_t& v )const + { + fc::raw::pack( s, v ); + } + virtual void handle( const uint64_t& v )const + { + fc::raw::pack( s, v ); + } + virtual void handle( const double& v )const + { + fc::raw::pack( s, v ); + } + virtual void handle( const bool& v )const + { + fc::raw::pack( s, v ); + } + virtual void handle( const string& v )const + { + fc::raw::pack( s, v ); + } + virtual void handle( const variant_object& v)const + { + fc::raw::pack( s, v ); + } + virtual void handle( const variants& v)const + { + fc::raw::pack( s, v ); + } + + Stream& s; + + }; + + + template + inline void pack( Stream& s, const variant& v ) + { + pack( s, uint8_t(v.get_type()) ); + v.visit( variant_packer(s) ); + } + template + inline void unpack( Stream& s, variant& v ) + { + uint8_t t; + unpack( s, t ); + switch( t ) + { + case variant::null_type: + return; + case variant::int64_type: + { + int64_t val; + raw::unpack(s,val); + v = val; + return; + } + case variant::uint64_type: + { + uint64_t val; + raw::unpack(s,val); + v = val; + return; + } + case variant::double_type: + { + double val; + raw::unpack(s,val); + v = val; + return; + } + case variant::bool_type: + { + bool val; + raw::unpack(s,val); + v = val; + return; + } + case variant::string_type: + { + fc::string val; + raw::unpack(s,val); + v = fc::move(val); + return; + } + case variant::array_type: + { + variants val; + raw::unpack(s,val); + v = fc::move(val); + return; + } + case variant::object_type: + { + variant_object val; + raw::unpack(s,val); + v = fc::move(val); + return; + } + default: + FC_THROW_EXCEPTION( parse_error_exception, "Unknown Variant Type ${t}", ("t", t) ); + } + } + + template + inline void pack( Stream& s, const variant_object& v ) + { + unsigned_int vs = v.size(); + pack( s, vs ); + for( auto itr = v.begin(); itr != v.end(); ++itr ) + { + pack( s, itr->key() ); + pack( s, itr->value() ); + } + wlog( "------------ done pack -------------" ); + } + template + inline void unpack( Stream& s, variant_object& v ) + { + unsigned_int vs; + unpack( s, vs ); + + mutable_variant_object mvo; + mvo.reserve(vs.value); + for( auto i = 0; i < vs.value; ++i ) + { + fc::string key; + fc::variant value; + fc::raw::unpack(s,key); + fc::raw::unpack(s,value); + mvo.set( fc::move(key), fc::move(value) ); + } + v = fc::move(mvo); + } template inline fc::vector pack( const T& v ) { datastream ps; raw::pack(ps,v ); fc::vector vec(ps.tellp()); + if( vec.size() ) { datastream ds( vec.data(), size_t(vec.size()) ); raw::pack(ds,v); @@ -275,6 +418,12 @@ namespace fc { raw::unpack(ds,v); return v; } + template + inline void unpack( const char* d, uint32_t s, T& v ) { + datastream ds( d, s ); + raw::unpack(ds,v); + return v; + } } } // namespace fc::raw diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp new file mode 100644 index 0000000..24e1c1a --- /dev/null +++ b/include/fc/io/raw_fwd.hpp @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +namespace fc { namespace raw { + template void unpack( Stream& s, fc::optional& v ); + template void pack( Stream& s, const fc::optional& v ); + + template void unpack( Stream& s, fc::string& ); + template void pack( Stream& s, const fc::string& ); + + template inline void pack( Stream& s, const T& v ); + template inline void unpack( Stream& s, T& v ); + + template inline void pack( Stream& s, const fc::vector& v ); + template inline void unpack( Stream& s, fc::vector& v ); + + template inline void pack( Stream& s, const signed_int& v ); + template inline void unpack( Stream& s, signed_int& vi ); + + template inline void pack( Stream& s, const unsigned_int& v ); + template inline void unpack( Stream& s, unsigned_int& vi ); + + template inline void pack( Stream& s, const char* v ); + template inline void pack( Stream& s, const fc::vector& value ); + template inline void unpack( Stream& s, fc::vector& value ); + + template inline void pack( Stream& s, const fc::array& v); + template inline void unpack( Stream& s, fc::array& v); + + template inline void pack( Stream& s, const bool& v ); + template inline void unpack( Stream& s, bool& v ); + + template inline fc::vector pack( const T& v ); + template inline T unpack( const fc::vector& s ); + template inline T unpack( const char* d, uint32_t s ); + template inline void unpack( const char* d, uint32_t s, T& v ); +} } diff --git a/include/fc/io/raw_unpack_file.hpp b/include/fc/io/raw_unpack_file.hpp new file mode 100644 index 0000000..580a64c --- /dev/null +++ b/include/fc/io/raw_unpack_file.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include +#include + +namespace fc +{ + namespace raw + { + template + void unpack_file( const fc::path& filename, T& obj ) + { + try { + fc::file_mapping fmap( filename.generic_string().c_str(), fc::read_only); + fc::mapped_region mapr( fmap, fc::read_only, 0, fc::file_size(filename) ); + auto cs = (const char*)mapr.get_address(); + + fc::datastream ds( cs, mapr.get_size() ); + fc::raw::unpack(ds,obj); + } FC_RETHROW_EXCEPTIONS( info, "unpacking file ${file}", ("file",filename) ); + } + } +} diff --git a/include/fc/io/sstream.hpp b/include/fc/io/sstream.hpp new file mode 100644 index 0000000..0aacb7a --- /dev/null +++ b/include/fc/io/sstream.hpp @@ -0,0 +1,31 @@ +#pragma once +#include +#include + +namespace fc { + + class stringstream : virtual public iostream { + public: + stringstream(); + stringstream( fc::string& s); + stringstream( const fc::string& s); + ~stringstream(); + + fc::string str(); + void str(const fc::string& s); + + void clear(); + + virtual bool eof()const; + virtual size_t writesome( const char* buf, size_t len ); + virtual size_t readsome( char* buf, size_t len ); + virtual void close(); + virtual void flush(); + char peek(); + + private: + class impl; + fwd my; + }; + +} diff --git a/include/fc/io/stdio.hpp b/include/fc/io/stdio.hpp new file mode 100644 index 0000000..63d6e17 --- /dev/null +++ b/include/fc/io/stdio.hpp @@ -0,0 +1,36 @@ +#pragma once +#include + +namespace fc +{ + + class cout_t : virtual public ostream { + public: + virtual size_t writesome( const char* buf, size_t len ); + virtual void close(); + virtual void flush(); + }; + + class cerr_t : virtual public ostream { + public: + virtual size_t writesome( const char* buf, size_t len ); + virtual void close(); + virtual void flush(); + }; + + class cin_t : virtual public istream { + public: + ~cin_t(); + virtual size_t readsome( char* buf, size_t len ); + virtual istream& read( char* buf, size_t len ); + virtual bool eof()const; + }; + + extern cout_t& cout; + extern cerr_t& cerr; + extern cin_t& cin; + + extern std::shared_ptr cin_ptr; + extern std::shared_ptr cout_ptr; + extern std::shared_ptr cerr_ptr; +} diff --git a/include/fc/varint.hpp b/include/fc/io/varint.hpp similarity index 66% rename from include/fc/varint.hpp rename to include/fc/io/varint.hpp index 2e98be5..9f5cebd 100644 --- a/include/fc/varint.hpp +++ b/include/fc/io/varint.hpp @@ -1,5 +1,4 @@ -#ifndef _FC_VARINT_HPP_ -#define _FC_VARINT_HPP_ +#pragma once #include namespace fc { @@ -24,7 +23,13 @@ struct signed_int { int32_t value; }; +class variant; + +void to_variant( const signed_int& var, variant& vo ); +void from_variant( const variant& var, signed_int& vo ); +void to_variant( const unsigned_int& var, variant& vo ); +void from_variant( const variant& var, unsigned_int& vo ); + } // namespace fc -#endif diff --git a/include/fc/iostream.hpp b/include/fc/iostream.hpp deleted file mode 100644 index 4f04fce..0000000 --- a/include/fc/iostream.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - - class istream { - public: - virtual ~istream(){}; - - virtual size_t readsome( char* buf, size_t len ) = 0; - virtual istream& read( char* buf, size_t len ) = 0; - - virtual bool eof()const = 0; - }; - - class ostream { - public: - virtual ~ostream(){}; - - virtual ostream& write( const char* buf, size_t len ) = 0; - virtual void close(){} - virtual void flush(){} - }; - - class iostream : public virtual ostream, public virtual istream {}; - - - struct cout_t : virtual public ostream { - virtual ostream& write( const char* buf, size_t len ); - virtual void close(); - virtual void flush(); - - virtual ostream& write( const fc::string& ); - }; - - struct cerr_t : virtual public ostream { - virtual ostream& write( const char* buf, size_t len ); - virtual void close(); - virtual void flush(); - - virtual ostream& write( const fc::string& ); - }; - - struct cin_t : virtual public istream { - ~cin_t(); - virtual size_t readsome( char* buf, size_t len ); - virtual istream& read( char* buf, size_t len ); - virtual bool eof()const; - }; - fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' ); - - - extern cout_t cout; - extern cerr_t cerr; - extern cin_t cin; - - - template - ostream& operator<<( ostream& o, const T& v ) { - auto str = fc::lexical_cast(v); - o.write( str.c_str(), static_cast(str.size()) ); - return o; - } - ostream& operator<<( ostream& o, const char* v ); - - template - ostream& operator<<( ostream& o, const fc::string& str ) { - o.write( str.c_str(), static_cast(str.size()) ); - return o; - } - template - istream& operator>>( istream& o, T& v ) { - fc::string str; - getline( o, str, ' ' ); - v = fc::lexical_cast(str); - return o; - } -} diff --git a/include/fc/iostream_wrapper.hpp b/include/fc/iostream_wrapper.hpp deleted file mode 100644 index 1798137..0000000 --- a/include/fc/iostream_wrapper.hpp +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - /** - * Used to wrap references to other streams - */ - class ostream_wrapper : public ostream { - public: - template - ostream_wrapper( Stream& s ) - :my( new impl(s) ){} - - virtual ~ostream_wrapper(){}; - - virtual ostream& write( const char* buf, size_t len ) { - my->write(buf,len); - return *this; - } - virtual void close() { - // TODO: move to cpp - my->close(); - } - virtual void flush() { - my->flush(); - } - - protected: - virtual ostream& write( const fc::string& s ) { - return write( s.c_str(), s.size() ); - } - - struct impl_base : public fc::retainable { - virtual ~impl_base(){} - virtual void write( const char* buf, size_t len ) = 0; - virtual void close() = 0; - virtual void flush() = 0; - }; - - template - struct impl : public impl_base { - impl(T& i):st(i){} - - virtual void write( const char* buf, size_t len ) { - st.write(buf,len); - } - virtual void close() { st.close(); } - virtual void flush() { st.flush(); } - T& st; - }; - - fc::shared_ptr my; - }; - /** - * Used to wrap references to other streams - */ - class istream_wrapper : public istream { - public: - template - istream_wrapper( Stream& s ) - :my( new impl(s) ){} - - virtual ~istream_wrapper(){}; - - virtual size_t readsome( char* buf, size_t len ) { - return my->readsome(buf,len); - } - virtual istream& read( char* buf, size_t len ) { - // slog( "%p %lld", my.get(), len ); - my->read(buf,len); - return *this; - } - virtual void close() { } - virtual bool eof()const{ return my->eof(); } - - /* - virtual istream& read( int64_t& ) { return *this; } - virtual istream& read( uint64_t& ) { return *this; } - virtual istream& read( int32_t& ) { return *this; } - virtual istream& read( uint32_t& ) { return *this; } - virtual istream& read( int16_t& ) { return *this; } - virtual istream& read( uint16_t& ) { return *this; } - virtual istream& read( int8_t& ) { return *this; } - virtual istream& read( uint8_t& ) { return *this; } - virtual istream& read( float& ) { return *this; } - virtual istream& read( double& ) { return *this; } - virtual istream& read( bool& ) { return *this; } - virtual istream& read( char& ) { return *this; } - virtual istream& read( fc::string& ) { return *this; } - */ - - protected: - struct impl_base : public fc::retainable { - virtual ~impl_base(){} - virtual void read( char* buf, size_t len )=0; - virtual size_t readsome( char* buf, size_t len )=0; - virtual bool eof()const=0; - }; - - template - struct impl : public impl_base { - impl(T& i):st(i){} - - virtual size_t readsome( char* buf, size_t len ) { return size_t(st.readsome(buf,len)); } - virtual void read( char* buf, size_t len ) { - st.read(buf,len); - } - virtual bool eof()const { return st.eof() || !st.good(); } - T& st; - }; - - fc::shared_ptr my; - }; - -} // namespace fc - diff --git a/include/fc/json.hpp b/include/fc/json.hpp deleted file mode 100644 index ccfc129..0000000 --- a/include/fc/json.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace fc { - class istream; - class ostream; - class path; - - namespace json { - string to_string( const value& o ); - string to_pretty_string( const value& v ); - - - value from_string( const string& s ); - value from_string( const char* s, const char* e ); - value from_string( const fc::vector& v ); - - - string escape_string( const string& ); - string unescape_string( const string& ); - - void write( ostream& out, const value& val ); - - template - void write( ostream& out, const T& val ) { - write( out, value(val) ); - } - - template - string to_string( const T& o ) { - return json::to_string(value(o)); - } - template - string to_pretty_string( const T& o ) { - return json::to_pretty_string(value(o)); - } - - template - T from_string( const string& s ) { - return value_cast( from_string(s) ); - } - - value from_file( const fc::path& s ); - template - T from_file( const fc::path& s ) { - return value_cast( fc::json::from_file(s) ); - } - - } // namespace json -} // fc - diff --git a/include/fc/json_rpc_client.hpp b/include/fc/json_rpc_client.hpp deleted file mode 100644 index 88bc081..0000000 --- a/include/fc/json_rpc_client.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - - -namespace fc { namespace json { - - namespace detail { - struct rpc_member { - #ifdef BOOST_NO_VARIADIC_TEMPLATES - #define RPC_MEMBER_FUNCTOR(z,n,IS_CONST) \ - template \ - static std::function( BOOST_PP_ENUM_PARAMS(n,A) ) > \ - functor( P, R (C::*mem_func)(BOOST_PP_ENUM_PARAMS(n,A)) IS_CONST, \ - const rpc_connection::ptr& c = rpc_connection::ptr(), const char* name = nullptr ) { \ - return [=](BOOST_PP_ENUM_BINARY_PARAMS(n,A,a))->fc::future{ \ - return c->invoke( name, make_tuple(BOOST_PP_ENUM_PARAMS(n,a)) ); }; \ - } - BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, const ) - BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, BOOST_PP_EMPTY() ) - #undef RPC_MEMBER_FUNCTOR - - #else - template - static std::function(Args...)> functor( P&& p, R (C::*mem_func)(Args...), - const rpc_connection::ptr& c = rpc_connection::ptr(), const char* name = nullptr ) { - return [=](Args... args)->fc::future{ - return c->invoke( name, make_tuple(args...) ); }; - } - template - static std::function(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const, - const rpc_connection::ptr& c = rpc_connection::ptr(), const char* name = nullptr ) { - return [=](Args... args)->fc::future{ - return c->invoke( name, make_tuple(args...) ); }; - } - #endif - }; - - struct vtable_visitor { - vtable_visitor( rpc_connection::ptr& c ):_con(c){} - - template - void operator()( const char* name, Function& memb, MemberPtr m )const { - memb = rpc_member::functor( nullptr, m, _con, name ); - } - rpc_connection::ptr& _con; - }; - }; - - - template - class rpc_client : public actor { //ptr { - public: - rpc_client(){} - rpc_client( const rpc_connection::ptr& c ){ set_connection(c); } - //rpc_client( const rpc_client& c ):_con(c._con){} - - void set_connection( const rpc_connection::ptr& c ) { - _con = c; - this->_vtable.reset(new fc::detail::vtable() ); - this->_vtable->template visit_other( fc::json::detail::vtable_visitor(_con) ); - } - const rpc_connection::ptr& connection()const { return _con; } - - private: - rpc_connection::ptr _con; - }; - -} } // fc::json diff --git a/include/fc/json_rpc_connection.hpp b/include/fc/json_rpc_connection.hpp deleted file mode 100644 index 7b5a9cb..0000000 --- a/include/fc/json_rpc_connection.hpp +++ /dev/null @@ -1,196 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace fc { namespace json { - class rpc_connection; - class error_object; - - struct rpc_server_method : public fc::retainable { - typedef fc::shared_ptr ptr; - virtual value call( const value& v ) = 0; - }; - - namespace detail { - struct pending_result : virtual public promise_base { - typedef shared_ptr ptr; - virtual void handle_result( const fc::value& ) = 0; - void handle_error( const fc::string& ); - int64_t id; - pending_result::ptr next; - protected: - ~pending_result(){} - }; - template - struct pending_result_impl : virtual public promise, virtual public pending_result { - virtual void handle_result( const fc::value& s ) { - this->set_value( value_cast(s) ); - } - protected: - ~pending_result_impl(){} - }; - template<> - struct pending_result_impl : virtual public promise, virtual public pending_result { - virtual void handle_result( const fc::value& ) { - set_value(); - } - protected: - ~pending_result_impl(){} - }; - - template - struct named_param { - typedef fc::false_type type; - static T cast( const value& v ) { return fc::value_cast(v); } - - template - static value to_value( X&& x ) { return value(fc::forward(x)); } - }; - - #define FC_JSON_NAMED_PARAMS( T ) \ - namespace fc { namespace json {namespace detail { \ - template<> \ - struct named_param< fc::tuple > { \ - typedef fc::true_type type; \ - static tuple cast( const value& v ) { return make_tuple(fc::value_cast(v)); } \ - template \ - static value to_value( X&& x ) { return value( x.a0 ); }\ - }; \ - } } } - - template - struct rpc_server_method_impl : public rpc_server_method { - rpc_server_method_impl( const std::function& f ):func(f){} - virtual value call( const value& v ) { - return value( fc::call_fused(func, named_param::type>::cast(v) ) ); - } - std::function func; - }; - template - struct rpc_server_method_impl : public rpc_server_method { - rpc_server_method_impl( const std::function& f ):func(f){} - virtual value call( const value& v ) { - fc::call_fused(func, named_param::type>::cast(v) ); - return value(); - } - std::function func; - }; - - template - struct add_method_visitor { - public: - add_method_visitor( const fc::ptr& p, fc::json::rpc_connection& c ):_ptr(p),_con(c){} - - template - void operator()( const char* name, std::function& meth); - template - void operator()( const char* name, std::function& meth); - template - void operator()( const char* name, std::function& meth); - template - void operator()( const char* name, std::function& meth); - - const fc::ptr& _ptr; - fc::json::rpc_connection& _con; - }; - } - - /** - * This is the base JSON RPC connection that handles the protocol - * level issues. It does not implement a transport which should - * be provided separately and use the handle_message and set_send_delegate - * methods to manage the protocol. - */ - class rpc_connection : public fc::retainable { - public: - rpc_connection(); - rpc_connection(const rpc_connection&); - rpc_connection(rpc_connection&&); - ~rpc_connection(); - rpc_connection& operator=(const rpc_connection&); - rpc_connection& operator=(rpc_connection&&); - - typedef fc::shared_ptr ptr; - - void cancel_pending_requests(); - - template - future invoke( const fc::string& method, Args&& a = nullptr ){ - auto r = new detail::pending_result_impl(); - typename promise::ptr rtn( r, true ); - invoke( detail::pending_result::ptr(r), method, - value(detail::named_param::type>::to_value(a)) ); - return rtn; - } - - template - void notice( const fc::string& method, Args&& a = nullptr ){ - send_notice( method, - value(detail::named_param::type>::to_value(a)) ); - } - - template - void add_interface( const fc::ptr& it ) { - it->TEMPLATE visit( detail::add_method_visitor( it, *this ) ); - } - - void add_method( const fc::string& name, const fc::json::rpc_server_method::ptr& func ); - - virtual void close(){}; - - protected: - void handle_message( const value& m ); - virtual void send_notice( const fc::string& m, value&& param ) = 0; - virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ) = 0; - virtual void send_error( uint64_t id, const error_object& e ) = 0; - virtual void send_result( uint64_t id, value&& r ) = 0; - - - private: - void invoke( detail::pending_result::ptr&& p, const fc::string& m, value&& param ); - void add_method( const fc::string& name, rpc_server_method::ptr&& m ); - template - friend struct detail::add_method_visitor; - - class impl; - fc::shared_ptr my; - }; - - namespace detail { - - template - template - void add_method_visitor::operator()( const char* name, - std::function& meth) { - _con.add_method( name, rpc_server_method::ptr( - new rpc_server_method_impl,R(A1) >(meth) ) ); - } - template - template - void add_method_visitor::operator()( const char* name, - std::function& meth) { - _con.add_method( name, rpc_server_method::ptr( - new rpc_server_method_impl,R(A1,A2) >(meth) ) ); - } - template - template - void add_method_visitor::operator()( const char* name, - std::function& meth) { - _con.add_method( name, rpc_server_method::ptr( - new rpc_server_method_impl,R(A1,A2,A3) >(meth) ) ); - } - template - template - void add_method_visitor::operator()( const char* name, - std::function& meth) { - _con.add_method( name, rpc_server_method::ptr( - new rpc_server_method_impl,R() >(meth) ) ); - } - - } // namespace detail - -} } // fc::json - diff --git a/include/fc/json_rpc_error_object.hpp b/include/fc/json_rpc_error_object.hpp deleted file mode 100644 index d898356..0000000 --- a/include/fc/json_rpc_error_object.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include -#include -#include -#include - - -namespace fc { - class value; - - namespace json { - - class error_object { - public: - error_object( const fc::string& msg, const fc::value& v , int64_t c = -32000); - error_object( const fc::string& msg=fc::string(), int64_t c = -32000 ); - error_object( const error_object& e ); - ~error_object(); - - int64_t code; - fc::string message; - fc::optional data; - }; - -} } - -FC_REFLECT( fc::json::error_object, (code)(message)(data) ) diff --git a/include/fc/json_rpc_process_client.hpp b/include/fc/json_rpc_process_client.hpp deleted file mode 100644 index d1022e5..0000000 --- a/include/fc/json_rpc_process_client.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace fc { namespace json { - - template - class rpc_process_client : public ptr { - public: - - fc::future exec( const fc::path& exe, int opt = fc::process::open_all ) { - return exec( exe, fc::path("."), opt ); - } - fc::future exec( const fc::path& exe, const fc::path& wd, - int opt = fc::process::open_all ) { - return exec( exe, fc::vector(), wd, opt ); - } - fc::future exec( const fc::path& exe, fc::vector&& args , - int opt = fc::process::open_all ) { - return exec( exe, fc::move(args), fc::path("."), opt ); - } - fc::future exec( const fc::path& exe, fc::vector&& args, - const fc::path& wd, int opt = fc::process::open_all ) { - auto r = _proc.exec( canonical(exe), fc::move(args), wd, opt ); - _con.reset( new fc::json::rpc_stream_connection( _proc.out_stream(), _proc.in_stream() ) ); - this->_vtable.reset(new fc::detail::vtable() ); - rpc_connection::ptr p(_con); - this->_vtable->template visit_other( fc::json::detail::vtable_visitor(p) ); - return r; - } - - void kill() { _con->close(); _proc.kill(); } - - /** - * @brief returns a stream that reads from the process' stderr - */ - fc::istream& err_stream() { return _proc.err_stream(); } - - template - void on_close( T&& f) { _con->on_close( fc::forward(f) ); } - - const fc::json::rpc_stream_connection::ptr& connection()const { return _con; } - - ~rpc_process_client() { - if(_con) - _con->close(); - } - private: - fc::process _proc; - fc::json::rpc_stream_connection::ptr _con; - }; -} } diff --git a/include/fc/json_rpc_ssh_process_client.hpp b/include/fc/json_rpc_ssh_process_client.hpp deleted file mode 100644 index cadae75..0000000 --- a/include/fc/json_rpc_ssh_process_client.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { namespace json { - - template - class rpc_ssh_process_client : public rpc_client { - public: - rpc_ssh_process_client(){} - bool valid()const { return proc.valid(); } - - rpc_ssh_process_client( const fc::ssh::process& proc ) - :rpc_client(rpc_connection::ptr(new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ) ){} - - rpc_ssh_process_client& operator = ( const fc::ssh::process& proc ) { - this->set_connection( rpc_connection::ptr(new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ) ); - return *this; - } - - /** - * @brief returns a stream that reads from the process' stderr - */ - fc::istream& err_stream() { return proc.err_stream(); } - - fc::ssh::process& get_ssh_process() { return proc; } - private: - fc::ssh::process proc; - fc::json::rpc_stream_connection::ptr _con; - - }; -} } diff --git a/include/fc/json_rpc_stream_connection.hpp b/include/fc/json_rpc_stream_connection.hpp deleted file mode 100644 index acf689b..0000000 --- a/include/fc/json_rpc_stream_connection.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include - -namespace fc { - class istream; - class ostream; - - namespace json { - class rpc_stream_connection : public rpc_connection { - public: - typedef fc::shared_ptr ptr; - rpc_stream_connection( fc::istream&, fc::ostream& ); - rpc_stream_connection(const rpc_stream_connection& ); - rpc_stream_connection(); - - // the life of the streams must exceed the life of all copies - // of this rpc_stream_connection - void open( fc::istream&, fc::ostream& ); - - // cancels all pending requests, closes the ostream - // results on_close() being called if the stream is not already closed. - virtual void close(); - - /** - * When the connection is closed, call the given method - */ - void on_close( const std::function& ); - - protected: - ~rpc_stream_connection(); - virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ); - virtual void send_notice( const fc::string& m, value&& param ); - virtual void send_error( uint64_t id, const error_object& eo ); - virtual void send_result( uint64_t id, value&& r ); - - private: - class impl; - fc::shared_ptr my; - }; -} } // fc::json diff --git a/include/fc/json_rpc_tcp_connection.hpp b/include/fc/json_rpc_tcp_connection.hpp deleted file mode 100644 index 7f57256..0000000 --- a/include/fc/json_rpc_tcp_connection.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include - -namespace fc { - class tcp_socket; - namespace ip { class endpoint; } - - namespace json { - class rpc_tcp_connection : public rpc_stream_connection { - public: - typedef fc::shared_ptr ptr; - - rpc_tcp_connection(); - rpc_tcp_connection( const rpc_tcp_connection& c ); - ~rpc_tcp_connection(); - - void connect_to( const fc::ip::endpoint& e ); - void start(); - tcp_socket& get_socket()const; - - virtual void close(); - - private: - class impl; - fc::shared_ptr my; - }; - } // json -} // fc diff --git a/include/fc/json_rpc_tcp_server.hpp b/include/fc/json_rpc_tcp_server.hpp deleted file mode 100644 index 7c334b8..0000000 --- a/include/fc/json_rpc_tcp_server.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include - -namespace fc { - - namespace json { - class rpc_tcp_server { - private: - template - struct add_method_visitor { - add_method_visitor( fc::ptr& p, rpc_connection& s ):_ptr(p),_rpcc(s) { } - - template - void operator()( const char* name, Functor& fun ) { - _rpcc.add_method( name, fun ); - } - - fc::ptr& _ptr; - rpc_connection& _rpcc; - }; - - public: - rpc_tcp_server(); - ~rpc_tcp_server(); - - template - void add_interface( const fc::ptr& ptr ) { - on_new_connection( [=]( rpc_connection& c ) { - ptr->visit( detail::add_method_visitor( ptr, c ) ); - }); - } - - void on_new_connection( const std::function& c ); - - void listen( uint16_t port ); - - private: - class impl; - impl* my; - }; - } -} diff --git a/include/fc/lexical_cast.hpp b/include/fc/lexical_cast.hpp deleted file mode 100644 index 3c0aa3a..0000000 --- a/include/fc/lexical_cast.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include - -namespace fc { - - namespace detail { - template - struct lexical_cast { }; - - double to_double( const fc::string& s ); - inline double to_double( double d ) { return d; } - - int64_t to_int64( const fc::string& s ); - inline int64_t to_int64( double d ) { return static_cast(d); } - inline int64_t to_int64( int64_t d ) { return d; } - - uint64_t to_uint64( const fc::string& s ); - inline uint64_t to_uint64( double d ) { return static_cast(d); } - inline uint64_t to_uint64( uint64_t d ) { return d; } - - fc::string to_string( double d ); - fc::string to_string( size_t d ); - fc::string to_string( uint64_t d ); - fc::string to_string( uint32_t d ); - fc::string to_string( uint16_t d ); - fc::string to_string( uint8_t d ); - fc::string to_string( int64_t d ); - fc::string to_string( int32_t d ); - fc::string to_string( int16_t d ); - fc::string to_string( int8_t d ); - fc::string to_string( char d ); - inline fc::string to_string( const char* d ) { return d; } - inline fc::string to_string( fc::string s ) { return s; } - - template - struct lexical_cast { - static double cast( const R& v ) { return to_double( v ); } - }; - - template - struct lexical_cast { - static fc::string cast( const R& v ) { return to_string( v ); } - }; - template - struct lexical_cast { - static std::string cast( const R& v ) { return to_string( v ); } - }; - - template - struct lexical_cast { - static uint64_t cast( const R& v ) { return to_uint64( v ); } - }; - - template - struct lexical_cast { static int64_t cast( const R& v ) { return static_cast(to_int64( v )); } }; - - template - struct lexical_cast { static int32_t cast( const R& v ) { return static_cast(to_int64( v )); } }; - - template - struct lexical_cast { static int16_t cast( const R& v ) { return static_cast(to_int64( v )); } }; - - template - struct lexical_cast { static int8_t cast( const R& v ) { return static_cast(to_int64( v )); } }; - - - template - struct lexical_cast { static uint32_t cast( const R& v ) { return static_cast(to_uint64( v )); } }; - - template - struct lexical_cast { static uint16_t cast( const R& v ) { return static_cast(to_uint64( v )); } }; - - template - struct lexical_cast { static uint8_t cast( const R& v ) { return static_cast(to_uint64( v )); } }; - - template - struct lexical_cast { static bool cast( const R& v ) { return v != 0; } }; - - template<> - struct lexical_cast { static char cast( const fc::string& v ) - { return v[0]; } };// TODO: check string len - - template<> - struct lexical_cast { static bool cast( const fc::string& v ) { return v == "true"; } }; - - template<> - struct lexical_cast { static fc::string cast( const bool& v ) { return v ? "true" : "false";} }; - - template - struct lexical_cast { static float cast( const R& v ) { return static_cast(to_double( v )); } }; - } - - - template - T lexical_cast( const R& v ) { - return detail::lexical_cast::cast(v); - } -} diff --git a/include/fc/log.hpp b/include/fc/log.hpp deleted file mode 100644 index 4ad5dd9..0000000 --- a/include/fc/log.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include - -namespace boost { class mutex; } - -namespace fc { - /** wrapper on printf */ - void log( const char* color, const char* file_name, size_t line_num, const char* method_name, const char* format, ... ); - - /** used to add extra fields to be printed (thread,fiber,time,etc) */ - void add_log_field( void (*f)() ); - void remove_log_field( void (*f)() ); - - boost::mutex& log_mutex(); -} - -#ifndef __func__ -#define __func__ __FUNCTION__ -#endif - -#ifndef WIN32 -#define COLOR_CONSOLE 1 -#endif -#include - -#define dlog(...) do { fc::log( CONSOLE_DEFAULT, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false) -#define slog(...) do { fc::log( CONSOLE_DEFAULT, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false) -#define wlog(...) do { fc::log( CONSOLE_BROWN, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false) -#define elog(...) do { fc::log( CONSOLE_RED, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false) - - diff --git a/include/fc/appender.hpp b/include/fc/log/appender.hpp similarity index 83% rename from include/fc/appender.hpp rename to include/fc/log/appender.hpp index f8fa1d4..093cce8 100644 --- a/include/fc/appender.hpp +++ b/include/fc/log/appender.hpp @@ -4,22 +4,22 @@ namespace fc { class appender; class log_message; - class value; class string; + class variant; class appender_factory : public fc::retainable { public: typedef fc::shared_ptr ptr; virtual ~appender_factory(){}; - virtual fc::shared_ptr create( const value& args ) = 0; + virtual fc::shared_ptr create( const variant& args ) = 0; }; namespace detail { template class appender_factory_impl : public appender_factory { public: - virtual fc::shared_ptr create( const value& args ) { + virtual fc::shared_ptr create( const variant& args ) { return fc::shared_ptr(new T(args)); } }; @@ -34,7 +34,7 @@ namespace fc { return register_appender( type, new detail::appender_factory_impl() ); } - static appender::ptr create( const fc::string& name, const fc::string& type, const value& args ); + static appender::ptr create( const fc::string& name, const fc::string& type, const variant& args ); static appender::ptr get( const fc::string& name ); static bool register_appender( const fc::string& type, const appender_factory::ptr& f ); diff --git a/include/fc/console_appender.hpp b/include/fc/log/console_appender.hpp similarity index 69% rename from include/fc/console_appender.hpp rename to include/fc/log/console_appender.hpp index 371d2b9..9fe9f30 100644 --- a/include/fc/console_appender.hpp +++ b/include/fc/log/console_appender.hpp @@ -1,11 +1,14 @@ #pragma once -#include -#include +#include +#include -namespace fc { - class console_appender : public appender { +namespace fc +{ + class console_appender : public appender + { public: - struct color { + struct color + { enum type { red, green, @@ -17,20 +20,23 @@ namespace fc { console_default, }; }; + struct stream { enum type { std_out, std_error }; }; - struct level_color { - level_color( log_level::type l=log_level::all, + struct level_color + { + level_color( log_level l=log_level::all, color::type c=color::console_default ) :level(l),color(c){} - log_level::type level; + log_level level; console_appender::color::type color; }; - struct config { + struct config + { config() - :format( "${when} ${thread} ${context} ${file}:${line} ${method} ${level}] ${message}" ), + :format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ), stream(console_appender::stream::std_error),flush(true){} fc::string format; @@ -40,16 +46,17 @@ namespace fc { }; - console_appender( const value& args ); - const char* get_color( log_level::type l )const; + console_appender( const variant& args ); + const char* get_color( log_level l )const; virtual void log( const log_message& m ); + private: config cfg; color::type lc[log_level::off+1]; }; } // namespace fc -#include +#include FC_REFLECT_ENUM( fc::console_appender::stream::type, (std_out)(std_error) ) FC_REFLECT_ENUM( fc::console_appender::color::type, (red)(green)(brown)(blue)(magenta)(cyan)(white)(console_default) ) FC_REFLECT( fc::console_appender::level_color, (level)(color) ) diff --git a/include/fc/file_appender.hpp b/include/fc/log/file_appender.hpp similarity index 81% rename from include/fc/file_appender.hpp rename to include/fc/log/file_appender.hpp index 0ffae0d..8adaf6a 100644 --- a/include/fc/file_appender.hpp +++ b/include/fc/log/file_appender.hpp @@ -1,10 +1,12 @@ #pragma once -#include -#include +#include +#include #include namespace fc { +class varaint; + class file_appender : public appender { public: struct config { @@ -15,7 +17,7 @@ class file_appender : public appender { bool flush; bool truncate; }; - file_appender( const value& args ); + file_appender( const variant& args ); ~file_appender(); virtual void log( const log_message& m ); @@ -25,5 +27,5 @@ class file_appender : public appender { }; } // namespace fc -#include +#include FC_REFLECT( fc::file_appender::config, (format)(filename)(flush)(truncate) ) diff --git a/include/fc/log/log_message.hpp b/include/fc/log/log_message.hpp new file mode 100644 index 0000000..c632cc6 --- /dev/null +++ b/include/fc/log/log_message.hpp @@ -0,0 +1,159 @@ +#pragma once +/** + * @file log_message.hpp + * @brief Defines types and helper macros necessary for generating log messages. + */ +#include +#include +#include +#include + +namespace fc +{ + namespace detail + { + class log_context_impl; + class log_message_impl; + } + + /** + * Named scope for log_level enumeration. + */ + class log_level + { + public: + /** + * @brief Define's the various log levels for reporting. + * + * Each log level includes all higher levels such that + * Debug includes Error, but Error does not include Debug. + */ + enum values + { + all, + debug, + info, + warn, + error, + off + }; + log_level( values v = off ):value(v){} + explicit log_level( int v ):value( static_cast(v)){} + operator int()const { return value; } + values value; + }; + + void to_variant( log_level e, variant& v ); + void from_variant( const variant& e, log_level& ll ); + + /** + * @brief provides information about where and when a log message was generated. + * @ingroup AthenaSerializable + * + * @see FC_LOG_CONTEXT + */ + class log_context + { + public: + log_context(); + log_context( log_level ll, + const char* file, + uint64_t line, + const char* method ); + ~log_context(); + explicit log_context( const variant& v ); + variant to_variant()const; + + string get_file()const; + uint64_t get_line_number()const; + string get_method()const; + string get_thread_name()const; + string get_host_name()const; + time_point get_timestamp()const; + log_level get_log_level()const; + string get_context()const; + + void append_context( const fc::string& c ); + + string to_string()const; + private: + std::shared_ptr my; + }; + + void to_variant( const log_context& l, variant& v ); + void from_variant( const variant& l, log_context& c ); + + /** + * @brief aggregates a message along with the context and associated meta-information. + * @ingroup AthenaSerializable + * + * @note log_message has reference semantics, all copies refer to the same log message + * and the message is read-only after construction. + * + * When converted to JSON, log_message has the following form: + * @code + * { + * "context" : { ... }, + * "format" : "string with ${keys}", + * "data" : { "keys" : "values" } + * } + * @endcode + * + * @see FC_LOG_MESSAGE + */ + class log_message + { + public: + log_message(); + /** + * @param ctx - generally provided using the FC_LOG_CONTEXT(LEVEL) macro + */ + log_message( log_context ctx, const char* format, variant_object args = variant_object() ); + ~log_message(); + + log_message( const variant& v ); + variant to_variant()const; + + string get_message()const; + + log_context get_context()const; + string get_format()const; + variant_object get_data()const; + + private: + std::shared_ptr my; + }; + + void to_variant( const log_message& l, variant& v ); + void from_variant( const variant& l, log_message& c ); + + typedef fc::vector log_messages; + + +} // namespace fc + +#ifndef __func__ +#define __func__ __FUNCTION__ +#endif + +/** + * @def FC_LOG_CONTEXT(LOG_LEVEL) + * @brief Automatically captures the File, Line, and Method names and passes them to + * the constructor of fc::log_context along with LOG_LEVEL + * @param LOG_LEVEL - a valid log_level::Enum name. + */ +#define FC_LOG_CONTEXT(LOG_LEVEL) \ + fc::log_context( fc::log_level::LOG_LEVEL, __FILE__, __LINE__, __func__ ) + +/** + * @def FC_LOG_MESSAGE(LOG_LEVEL,FORMAT,...) + * + * @brief A helper method for generating log messages. + * + * @param LOG_LEVEL a valid log_level::Enum name to be passed to the log_context + * @param FORMAT A const char* string containing zero or more references to keys as "${key}" + * @param ... A set of key/value pairs denoted as ("key",val)("key2",val2)... + */ +#define FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, ... ) \ + fc::log_message( FC_LOG_CONTEXT(LOG_LEVEL), FORMAT, fc::mutable_variant_object()__VA_ARGS__ ) + diff --git a/include/fc/log/logger.hpp b/include/fc/log/logger.hpp new file mode 100644 index 0000000..6ea1d43 --- /dev/null +++ b/include/fc/log/logger.hpp @@ -0,0 +1,137 @@ +#pragma once +#include +#include +#include +#include + +namespace fc +{ + + class appender; + + /** + * + * + @code + void my_class::func() + { + fc_dlog( my_class_logger, "Format four: ${arg} five: ${five}", ("arg",4)("five",5) ); + } + @endcode + */ + class logger + { + public: + static logger get( const fc::string& name = "default"); + + logger(); + logger( const string& name, const logger& parent = nullptr ); + logger( std::nullptr_t ); + logger( const logger& c ); + logger( logger&& c ); + ~logger(); + logger& operator=(const logger&); + logger& operator=(logger&&); + friend bool operator==( const logger&, nullptr_t ); + friend bool operator!=( const logger&, nullptr_t ); + + logger& set_log_level( log_level e ); + log_level get_log_level()const; + logger& set_parent( const logger& l ); + logger get_parent()const; + + void set_name( const fc::string& n ); + const fc::string& name()const; + + void add_appender( const fc::shared_ptr& a ); + + bool is_enabled( log_level e )const; + void log( log_message m ); + + private: + class impl; + fc::shared_ptr my; + }; + +} // namespace fc + + +#define fc_dlog( LOGGER, FORMAT, ... ) \ + do { \ + if( (LOGGER).is_enabled( fc::log_level::debug ) ) { \ + (LOGGER).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#define fc_ilog( LOGGER, FORMAT, ... ) \ + do { \ + if( (LOGGER).is_enabled( fc::log_level::info ) ) { \ + (LOGGER).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#define fc_wlog( LOGGER, FORMAT, ... ) \ + do { \ + if( (LOGGER).is_enabled( fc::log_level::warn ) ) { \ + (LOGGER).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#define fc_elog( LOGGER, FORMAT, ... ) \ + do { \ + if( (LOGGER).is_enabled( fc::log_level::error ) ) { \ + (LOGGER).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#define dlog( FORMAT, ... ) \ + do { \ + if( (fc::logger::get()).is_enabled( fc::log_level::debug ) ) { \ + (fc::logger::get()).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#define ilog( FORMAT, ... ) \ + do { \ + if( (fc::logger::get()).is_enabled( fc::log_level::info ) ) { \ + (fc::logger::get()).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#define wlog( FORMAT, ... ) \ + do { \ + if( (fc::logger::get()).is_enabled( fc::log_level::warn ) ) { \ + (fc::logger::get()).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#define elog( FORMAT, ... ) \ + do { \ + if( (fc::logger::get()).is_enabled( fc::log_level::error ) ) { \ + (fc::logger::get()).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \ + } \ + } while (0) + +#include +#include +#include +#include +#include +#include + + +#define FC_FORMAT_ARG(r, unused, base) \ + BOOST_PP_STRINGIZE(base) ": ${" BOOST_PP_STRINGIZE( base ) "} " + +#define FC_FORMAT_ARGS(r, unused, base) \ + BOOST_PP_LPAREN() BOOST_PP_STRINGIZE(base),fc::variant(base) BOOST_PP_RPAREN() + +#define FC_FORMAT( SEQ )\ + BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARG, v, SEQ ) + +#define FC_FORMAT_ARG_PARAMS( SEQ )\ + BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARGS, v, SEQ ) + +#define idump( SEQ ) \ + ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ) + diff --git a/include/fc/logger_config.hpp b/include/fc/log/logger_config.hpp similarity index 81% rename from include/fc/logger_config.hpp rename to include/fc/log/logger_config.hpp index a089052..c46accc 100644 --- a/include/fc/logger_config.hpp +++ b/include/fc/log/logger_config.hpp @@ -1,15 +1,15 @@ #pragma once -#include +#include namespace fc { class path; struct appender_config { - appender_config(const fc::string& n="",const fc::string& t="", const value& a=value()) - :name(n),type(t),args(a),enabled(true){} - string name; - string type; - value args; - bool enabled; + appender_config(const fc::string& n="",const fc::string& t="", variant a=variant()) + :name(n),type(t),args(fc::move(a)),enabled(true){} + string name; + string type; + variant args; + bool enabled; }; struct logger_config { @@ -17,7 +17,7 @@ namespace fc { string name; ostring parent; /// if not set, then parents level is used. - fc::optional level; + fc::optional level; bool enabled; /// if any appenders are sepecified, then parent's appenders are not set. bool additivity; @@ -37,7 +37,7 @@ namespace fc { bool configure_logging( const logging_config& l ); } -#include +#include FC_REFLECT( fc::appender_config, (name)(type)(args)(enabled) ) FC_REFLECT( fc::logger_config, (name)(parent)(level)(enabled)(additivity)(appenders) ) FC_REFLECT( fc::logging_config, (includes)(appenders)(loggers) ) diff --git a/include/fc/logger.hpp b/include/fc/logger.hpp deleted file mode 100644 index 4b2fafc..0000000 --- a/include/fc/logger.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once -#include -#include -#include -#include - - -namespace fc { - - struct log_level { - enum type { - all, trace, debug, info, warn, error, fatal, off - }; - }; - - struct log_message { - log_message(log_level::type, const string& file, int line, const string& func, const string& format ); - log_message(); - - otime_point when; - log_level::type level; - ostring context; - ostring thread; - ostring fiber; - ostring host; - string file; - int line; - string method; - string format; - value args; - ovalue meta; - - // key based args - template - log_message& operator()( const string& arg, const T& v ) { - return (*this)(arg,value(v)); - } - - log_message& operator()( const string& arg, value&& v ); - log_message& operator()( const string& arg, const value& v ); - // position based args... - log_message& operator()( value&& v ); - log_message& operator()( const value& v ); - }; - - class appender; - - /** - * - * - @code - void my_class::func() - { - fc_dlog( my_class_logger, "Format four: ${arg} five: ${five}", ("arg",4)("five",5) ); - } - @endcode - */ - class logger { - public: - static logger get( const fc::string& name = "default"); - - logger(); - logger( const string& name, const logger& parent = nullptr ); - logger( std::nullptr_t ); - logger( const logger& c ); - logger( logger&& c ); - ~logger(); - logger& operator=(const logger&); - logger& operator=(logger&&); - friend bool operator==( const logger&, std::nullptr_t ); - friend bool operator!=( const logger&, std::nullptr_t ); - - logger& set_log_level( log_level::type e ); - log_level::type get_log_level()const; - logger& set_parent( const logger& l ); - logger get_parent()const; - - void set_name( const fc::string& n ); - const fc::string& name()const; - - void add_appender( const fc::shared_ptr& a ); - - - bool is_enabled( log_level::type e )const; - void log( log_message m ); - - private: - class impl; - fc::shared_ptr my; - }; - - /** - * This helper class is used to automatically print a log message - * once upon construction, and again upon destruction and is therefore - * helpful in catching scope changes. - struct tracer { - tracer( const logger::ptr& lgr ); - ~tracer(); - - void set_message( log_message&& ms g); - - private: - logger::ptr logger; - log_message msg; - }; - */ - -} // namespace fc - -#include -FC_REFLECT( fc::log_message, (when)(level)(context)(thread)(fiber)(host)(method)(file)(line)(format)(args)(meta) ) -FC_REFLECT_ENUM( fc::log_level::type, (all)(trace)(debug)(info)(warn)(error)(fatal)(off) ) - -#define fc_scope_log( LOGGER, FORMAT, ... ) \ - fc::tracer __tracer; \ - if( (LOGGER).is_enabled( fc::log_level::trace ) ) { \ - __tracer.set_message( fc::log_message( fc::log_level::trace, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\ - } - -#define fc_dlog( LOGGER, FORMAT, ... ) \ - if( (LOGGER).is_enabled( fc::log_level::debug ) ) { \ - (LOGGER).log( fc::log_message( fc::log_level::debug, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\ - } - -#define fc_ilog( LOGGER, FORMAT, ... ) \ - if( (LOGGER).is_enabled( fc::log_level::info ) ) { \ - (LOGGER).log( fc::log_message( fc::log_level::info, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\ - } - -#define fc_wlog( LOGGER, FORMAT, ... ) \ - if( (LOGGER).is_enabled( fc::log_level::warn ) ) { \ - (LOGGER).log( fc::log_message( fc::log_level::warn, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\ - } - -#define fc_elog( LOGGER, FORMAT, ... ) \ - if( (LOGGER).is_enabled( fc::log_level::error ) ) { \ - (LOGGER).log( fc::log_message( fc::log_level::error, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\ - } - -#define fc_flog( LOGGER, FORMAT, ... ) \ - if( (LOGGER).is_enabled( fc::log_level::fatal ) ) { \ - (LOGGER).log( fc::log_message( fc::log_level::fatal, __FILE__, __LINE__, __func__, FORMAT ) __VA_ARGS__ );\ - } - diff --git a/include/fc/make_fused.hpp b/include/fc/make_fused.hpp index cc82ff8..acbf901 100644 --- a/include/fc/make_fused.hpp +++ b/include/fc/make_fused.hpp @@ -4,23 +4,23 @@ namespace fc { template - fc::function > make_fused( const fc::function& f ) { + std::function > make_fused( const std::function& f ) { return [=]( fc::tuple<> ){ return f(); }; } template - fc::function) > make_fused( const fc::function& f ) { + std::function) > make_fused( const std::function& f ) { return [f]( fc::tuple t){ return f(t.a); }; } template - fc::function) > make_fused( const fc::function& f ) { + std::function) > make_fused( const std::function& f ) { return [f]( fc::tuple t){ return f(t.a,t.b); }; } template - fc::function) > make_fused( const fc::function& f ) { + std::function) > make_fused( const std::function& f ) { return [f]( fc::tuple t){ return f(t.a,t.b,t.c); }; } template - fc::function) > make_fused( const fc::function& f ) { + std::function) > make_fused( const std::function& f ) { return [f]( fc::tuple t){ return f(t.a,t.b,t.c,t.d); }; } } diff --git a/include/fc/map.hpp b/include/fc/map.hpp deleted file mode 100644 index 1cdb745..0000000 --- a/include/fc/map.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _FC_MAP_HPP_ -namespace fc { - - namespace detail { - class map_impl { - public: - - - }; - } - template - class map : public map_impl { - - - }; - - -} diff --git a/include/fc/endpoint.hpp b/include/fc/network/endpoint.hpp similarity index 100% rename from include/fc/endpoint.hpp rename to include/fc/network/endpoint.hpp diff --git a/include/fc/network/http/connection.hpp b/include/fc/network/http/connection.hpp new file mode 100644 index 0000000..90d9090 --- /dev/null +++ b/include/fc/network/http/connection.hpp @@ -0,0 +1,76 @@ +#pragma once +#include +#include +#include + +namespace fc { + namespace ip { class endpoint; } + class tcp_socket; + + namespace http { + + struct header + { + header( fc::string k, fc::string v ) + :key(fc::move(k)),val(fc::move(v)){} + header(){} + fc::string key; + fc::string val; + }; + + typedef fc::vector
headers; + + struct reply + { + enum status_code { + OK = 200, + RecordCreated = 201, + NotFound = 404, + Found = 302, + InternalServerError = 500 + }; + reply( status_code c = OK):status(c){} + int status; + fc::vector
headers; + fc::vector body; + }; + + struct request + { + fc::string get_header( const fc::string& key )const; + fc::string method; + fc::string domain; + fc::string path; + fc::vector
headers; + fc::vector body; + }; + + fc::vector
parse_urlencoded_params( const fc::string& f ); + + /** + * Connections have reference semantics, all copies refer to the same + * underlying socket. + */ + class connection + { + public: + connection(); + ~connection(); + // used for clients + void connect_to( const fc::ip::endpoint& ep ); + http::reply request( const fc::string& method, const fc::string& url, const fc::string& body, const headers& = headers()); + + // used for servers + fc::tcp_socket& get_socket()const; + + http::request read_request()const; + + class impl; + private: + std::unique_ptr my; + }; + + typedef std::shared_ptr connection_ptr; + +} } // fc::http + diff --git a/include/fc/http/server.hpp b/include/fc/network/http/server.hpp similarity index 87% rename from include/fc/http/server.hpp rename to include/fc/network/http/server.hpp index e8764f1..711ea50 100644 --- a/include/fc/http/server.hpp +++ b/include/fc/network/http/server.hpp @@ -1,7 +1,8 @@ #pragma once -#include +#include #include #include +#include namespace fc { namespace http { @@ -11,18 +12,18 @@ namespace fc { namespace http { * function for every http request. * */ - class server { + class server + { public: server(); server( uint16_t port ); - server( const server& s ); server( server&& s ); ~server(); - server& operator=(const server& s); server& operator=(server&& s); - class response { + class response + { public: class impl; @@ -53,8 +54,8 @@ namespace fc { namespace http { private: class impl; - fc::shared_ptr my; - + std::unique_ptr my; }; + typedef std::shared_ptr server_ptr; } } diff --git a/include/fc/ip.hpp b/include/fc/network/ip.hpp similarity index 83% rename from include/fc/ip.hpp rename to include/fc/network/ip.hpp index ea64ed1..f21eb27 100644 --- a/include/fc/ip.hpp +++ b/include/fc/network/ip.hpp @@ -46,7 +46,10 @@ namespace fc { address _ip; }; } - class value; - void pack( fc::value& , const fc::ip::endpoint& ); - void unpack( const fc::value& , fc::ip::endpoint& ); + class variant; + void to_variant( const ip::endpoint& var, variant& vo ); + void from_variant( const variant& var, ip::endpoint& vo ); + + void to_variant( const ip::address& var, variant& vo ); + void from_variant( const variant& var, ip::address& vo ); } diff --git a/include/fc/tcp_socket.hpp b/include/fc/network/tcp_socket.hpp similarity index 80% rename from include/fc/tcp_socket.hpp rename to include/fc/network/tcp_socket.hpp index e2eb354..69d4ea4 100644 --- a/include/fc/tcp_socket.hpp +++ b/include/fc/network/tcp_socket.hpp @@ -1,11 +1,12 @@ #pragma once #include #include -#include +#include namespace fc { namespace ip { class endpoint; } - class tcp_socket : public iostream { + class tcp_socket : public virtual iostream + { public: tcp_socket(); ~tcp_socket(); @@ -15,13 +16,12 @@ namespace fc { /// istream interface /// @{ virtual size_t readsome( char* buffer, size_t max ); - virtual istream& read( char* buffer, size_t s ); virtual bool eof()const; /// @} /// ostream interface /// @{ - virtual ostream& write( const char* buffer, size_t len ); + virtual size_t writesome( const char* buffer, size_t len ); virtual void flush(); virtual void close(); /// @} @@ -33,8 +33,11 @@ namespace fc { class impl; fc::fwd my; }; + typedef std::shared_ptr tcp_socket_ptr; - class tcp_server { + + class tcp_server + { public: tcp_server(); ~tcp_server(); diff --git a/include/fc/udp_socket.hpp b/include/fc/network/udp_socket.hpp similarity index 100% rename from include/fc/udp_socket.hpp rename to include/fc/network/udp_socket.hpp diff --git a/include/fc/network/url.hpp b/include/fc/network/url.hpp new file mode 100644 index 0000000..6f8c745 --- /dev/null +++ b/include/fc/network/url.hpp @@ -0,0 +1,106 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +namespace fc { + + typedef fc::optional ostring; + typedef fc::optional opath; + typedef fc::optional ovariant_object; + + namespace detail { class url_impl; } + + class mutable_url; + + /** + * Used to pass an immutable URL and + * query its parts. + */ + class url + { + public: + url(); + explicit url( const string& u ); + url( const url& c ); + url( url&& c ); + url( mutable_url&& c ); + url( const mutable_url& c ); + ~url(); + + url& operator=( const url& c ); + url& operator=( url&& c ); + + url& operator=( const mutable_url& c ); + url& operator=( mutable_url&& c ); + + bool operator==( const url& cmp )const; + + operator string()const; + + //// file, ssh, tcp, http, ssl, etc... + string proto()const; + ostring host()const; + ostring user()const; + ostring pass()const; + opath path()const; + ovariant_object args()const; + fc::optional port()const; + + private: + friend class mutable_url; + std::shared_ptr my; + }; + + void to_variant( const url& u, fc::variant& v ); + void from_variant( const fc::variant& v, url& u ); + + /** + * Used to create / manipulate a URL + */ + class mutable_url + { + public: + mutable_url(); + explicit mutable_url( const string& mutable_url ); + mutable_url( const mutable_url& c ); + mutable_url( const url& c ); + mutable_url( mutable_url&& c ); + ~mutable_url(); + + mutable_url& operator=( const url& c ); + mutable_url& operator=( const mutable_url& c ); + mutable_url& operator=( mutable_url&& c ); + + bool operator==( const mutable_url& cmp )const; + bool operator==( const url& cmp )const; + + operator string()const; + + //// file, ssh, tcp, http, ssl, etc... + string proto()const; + ostring host()const; + ostring user()const; + ostring pass()const; + opath path()const; + ovariant_object args()const; + fc::optional port()const; + + void set_proto( string ); + void set_host( string ); + void set_user( string ); + void set_pass( string ); + void set_path( fc::path p ); + void set_args( variant_object ); + void set_port( uint16_t ); + + private: + friend class url; + std::unique_ptr my; + }; + +} // namespace fc + diff --git a/include/fc/numeric_cast.hpp b/include/fc/numeric_cast.hpp deleted file mode 100644 index 3fdb766..0000000 --- a/include/fc/numeric_cast.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace fc { - template - T numeric_cast( const R& v ) { - // TODO: do something smarter here, check ranges, etc - return static_cast(v); - } -} diff --git a/include/fc/optional.hpp b/include/fc/optional.hpp index e32ff74..48ef53f 100644 --- a/include/fc/optional.hpp +++ b/include/fc/optional.hpp @@ -8,6 +8,12 @@ namespace fc { * Simply including boost::optional adds 35,000 lines to each object file, using * fc::optional adds less than 400. */ + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4521) /* multiple copy ctors */ +#endif + template class optional { public: @@ -20,6 +26,12 @@ namespace fc { _valid = o._valid; } + optional( optional& o ) + :_valid(false) { + if( o._valid ) new (&**this) T( *o ); + _valid = o._valid; + } + optional( optional&& o ) :_valid(false) { if( o._valid ) new (&**this) T( fc::move(*o) ); @@ -39,23 +51,36 @@ namespace fc { new (&**this) T( fc::forward(u) ); _valid = true; } else { - **this = fc::forward(u); + **this = static_cast(fc::forward(u)); } return *this; } optional& operator=( const optional& o ) { - if( _valid && o._valid ) { **this = *o; } - else if( !_valid && o._valid ) { - *this = *o; - } // else !_valid && !o._valid == same! + if (this != &o) { + if( _valid && o._valid ) { + **this = *o; + } else if( !_valid && o._valid ) { + *this = *o; + } else if (_valid) { + (**this).~T(); + _valid = false; + } + } return *this; } + optional& operator=( optional&& o ) { - if( _valid && o._valid ) { **this = fc::move(*o); } - else if( !_valid && o._valid ) { - *this = fc::move(*o); - } + if (this != &o) { + if( _valid && o._valid ) { + **this = fc::move(*o); + } else if ( !_valid && o._valid ) { + *this = fc::move(*o); + } else if (_valid) { + (**this).~T(); + _valid = false; + } + } return *this; } @@ -91,5 +116,9 @@ namespace fc { return !left || *left != u; } +#ifdef _MSC_VER +# pragma warning(pop) +#endif + } // namespace fc diff --git a/include/fc/pke.hpp b/include/fc/pke.hpp deleted file mode 100644 index b0edba9..0000000 --- a/include/fc/pke.hpp +++ /dev/null @@ -1,155 +0,0 @@ -#pragma once -#include -#include -#include - -/** - * Define common crypto methods and data types to abstract underlying implementation. - */ -namespace fc { - - template - struct signature { - char data[KeySize/8]; - template - friend T& operator<<( T& ds, const fc::signature& sig ) - { - ds.write(sig.data, KS/8 ); - return ds; - } - template - friend T& operator>>( T& ds, fc::signature& sig ) - { - ds.read(sig.data, KS/8 ); - return ds; - } - bool operator != ( const signature& s )const { - return memcmp( s.data, data, sizeof(data) ) != 0; - } - bool operator == ( const signature& s )const { - return memcmp( s.data, data, sizeof(data) ) == 0; - } - }; - - bool verify_data( const char* key, uint32_t key_size, uint32_t pe, const sha1& hc, const char* sig ); - bool sign_data( const fc::vector& key, uint32_t key_size, uint32_t pe, const sha1& hc, char* sig ); - bool public_encrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ); - bool public_decrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ); - bool private_encrypt( const fc::vector& key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ); - bool private_decrypt( const fc::vector& key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ); - bool generate_keys( char* pubkey, fc::vector& privkey, uint32_t key_size, uint32_t pe ); - - template - struct private_key; - - template - struct public_key { - public_key() { memset( key, 0, sizeof(key) ); } - public_key( const public_key& pk ) { memcpy( key, pk.key, sizeof(key) ); } - - bool verify( const sha1& digest, const signature& sig )const { - return verify_data( key, sizeof(key), PublicExponent, digest, sig.data ); - } - bool encrypt( const fc::vector& in, fc::vector& out )const { - return public_encrypt( key, KeySize, PublicExponent, in, out ); - } - bool decrypt( const fc::vector& in, fc::vector& out )const { - return public_decrypt( key, KeySize, PublicExponent, in, out ); - } - - public_key& operator = ( const public_key& pk ) { - memcpy( key, pk.key, sizeof(key) ); - return *this; - } - bool operator == ( const public_key& pk )const { - return 0 == memcmp( key, pk.key, sizeof(key) ); - } - bool operator != ( const public_key& pk )const { - return 0 != memcmp( key, pk.key, sizeof(key) ); - } - bool operator > ( const public_key& pk )const { - return memcmp( key, pk.key, sizeof(key) ) > 0; - } - bool operator < ( const public_key& pk )const { - return memcmp( key, pk.key, sizeof(key) ) < 0; - } - - template - inline friend T& operator<<( T& ds, const fc::public_key& pk ) { - ds.write(pk.key, KS/8 ); - return ds; - } - template - inline friend T& operator>>( T& ds, fc::public_key& pk ) { - ds.read( pk.key, KS/8 ); - return ds; - } - - private: - template - friend void generate_keys( public_key& pub, private_key& priv ); - - char key[KeySize/8]; - }; - - - template - struct private_key { - bool encrypt( const fc::vector& in, fc::vector& out )const { - return private_encrypt( key, KeySize, PublicExponent, in, out ); - } - bool decrypt( const fc::vector& in, fc::vector& out )const { - return private_decrypt( key, KeySize, PublicExponent, in, out ); - } - bool sign( const sha1& digest, signature& sig )const { - return sign_data( key, KeySize, PublicExponent, digest, sig.data ); - } - - template - friend T& operator<<( T& ds, const fc::private_key& pk ) { - uint16_t s = pk.key.size(); - ds.write( (const char*)&s, sizeof(s) ); - ds.write( pk.key.data(), pk.key.size() ); - return ds; - } - template - friend T& operator>>( T& ds, fc::private_key& pk ) { - uint16_t s; - ds.read((char*)&s,sizeof(s) ); - pk.key.resize(s); - ds.read( pk.key.data(), pk.key.size() ); - return ds; - } - private: - template - friend void generate_keys( public_key& pub, private_key& priv ); - fc::vector key; - }; - - template - void generate_keys( public_key& pub, private_key& priv ) { - generate_keys( pub.key, priv.key, KeySize, PublicExponent ); - } - /* - template - inline std::ostream& operator<< ( std::ostream& os, const signature& s ) { - for( uint32_t i = 0; i < KeySize; ++i ) - os << std::hex << int(s.data[i]) << ' '; - return os; - } - */ - - typedef public_key<> public_key_t; - typedef private_key<> private_key_t; - typedef signature<> signature_t; - - class value; - void pack( fc::value& , const fc::signature_t& ); - void unpack( const fc::value& , fc::signature_t& ); - void pack( fc::value& , const fc::public_key_t& ); - void unpack( const fc::value& , fc::private_key_t& ); - void pack( fc::value& , const fc::private_key_t& ); - void unpack( const fc::value& , fc::public_key_t& ); -} // namespace fc - - diff --git a/include/fc/process.hpp b/include/fc/process.hpp deleted file mode 100644 index 4a596a7..0000000 --- a/include/fc/process.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - class istream; - class ostream; - class path; - template class vector; - - fc::path find_executable_in_path( const fc::string name ); - - /** - * @brief start and manage an external process - * - * @note this class implements reference semantics. - */ - class process { - public: - enum exec_opts { - open_none = 0, - open_stdin = 0x01, - open_stdout = 0x02, - open_stderr = 0x04, - open_all = open_stdin|open_stdout|open_stderr, - }; - - /** - * Return a new process executing the specified exe with the specified args. - */ - fc::future exec( const fc::path& exe, int opt = open_all ); - fc::future exec( const fc::path& exe, const fc::path& wd, int opt = open_all ); - fc::future exec( const fc::path& exe, fc::vector&& args , int opt = open_all ); - fc::future exec( const fc::path& exe, fc::vector&& args, const fc::path& wd, int opt = open_all ); - - /** - * Forcefully kills the process. - */ - void kill(); - - /** - * @brief returns a stream that writes to the process' stdin - */ - fc::ostream& in_stream(); - - /** - * @brief returns a stream that reads from the process' stdout - */ - fc::istream& out_stream(); - /** - * @brief returns a stream that reads from the process' stderr - */ - fc::istream& err_stream(); - - FC_REFERENCE_TYPE(process) - }; - -} // namespace fc diff --git a/include/fc/program_options.hpp b/include/fc/program_options.hpp deleted file mode 100644 index f839d72..0000000 --- a/include/fc/program_options.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _FC_PROGRAM_OPTIONS_HPP_ -#define _FC_PROGRAM_OPTIONS_HPP_ -#include -#include -#include -#include -#include - -namespace boost { - namespace program_options { - class variables_map; - } -} - -namespace fc { - class ostream; - - namespace program_options { - template - class value { - public: - value( T* v ):_v(v){} - value& default_value( const T& d ) { _default = d; } - - T* get()const { return _v; } - private: - fc::optional _default; - T* _v; - }; - - class options_description { - public: - options_description( const char* c ); - ~options_description(); - - options_description& add_options(); - options_description& operator()( const char* o, const char* desc ); - options_description& operator()( const char* o, const value&, const char* desc ); - options_description& operator()( const char* o, const value&, const char* desc ); - options_description& operator()( const char* o, const value >&, const char* desc ); - - private: - class impl; - fwd my; - - friend class variables_map; - friend fc::ostream& operator<<( fc::ostream& o, const options_description& ); - }; - - class variables_map { - public: - variables_map(); - ~variables_map(); - - void parse_command_line( int argc, char** argv, const options_description& d ); - int count( const char* opt ); - private: - class impl; - fwd my; - }; - - } -} -#endif // _FC_PROGRAM_OPTIONS_HPP_ diff --git a/include/fc/reflect.hpp b/include/fc/reflect/reflect.hpp similarity index 96% rename from include/fc/reflect.hpp rename to include/fc/reflect/reflect.hpp index 44d86c2..57bf64a 100644 --- a/include/fc/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -1,12 +1,10 @@ - +#pragma once /** * @file fc/reflect.hpp * * @brief Defines types and macros used to provide reflection. * */ -#ifndef _FC_REFLECT_HPP_ -#define _FC_REFLECT_HPP_ #include #include @@ -16,8 +14,7 @@ #include #include -#include -#include +#include namespace fc { @@ -41,7 +38,7 @@ struct reflector{ * * @code * struct functor { - * template + * template * void operator()( const char* name )const; * }; * @endcode @@ -90,7 +87,7 @@ void throw_bad_enum_cast( const char* k, const char* e ); #define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \ - OP fc::reflector::member_count + OP fc::reflector::total_member_count #define FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ template\ @@ -207,4 +204,3 @@ template<> struct reflector {\ -#endif diff --git a/include/fc/typename.hpp b/include/fc/reflect/typename.hpp similarity index 100% rename from include/fc/typename.hpp rename to include/fc/reflect/typename.hpp diff --git a/include/fc/reflect/variant.hpp b/include/fc/reflect/variant.hpp new file mode 100644 index 0000000..0c41de1 --- /dev/null +++ b/include/fc/reflect/variant.hpp @@ -0,0 +1,99 @@ +#pragma once +#include +#include + +namespace fc +{ + template + void to_variant( const T& o, variant& v ); + template + void from_variant( const variant& v, T& o ); + + + template + class to_variant_visitor + { + public: + to_variant_visitor( mutable_variant_object& mvo, const T& v ) + :vo(mvo),val(v){} + + template + void operator()( const char* name )const + { + vo(name,(val.*member)); + } + + mutable_variant_object& vo; + const T& val; + }; + + template + class from_variant_visitor + { + public: + from_variant_visitor( const variant_object& _vo, T& v ) + :vo(_vo),val(v){} + + template + void operator()( const char* name )const + { + auto itr = vo.find(name); + if( itr != vo.end() ) + from_variant( itr->value(), val.*member ); + } + + const variant_object& vo; + T& val; + }; + + template + struct if_enum + { + template + static inline void to_variant( const T& v, fc::variant& vo ) + { + mutable_variant_object mvo; + fc::reflector::visit( to_variant_visitor( mvo, v ) ); + vo = fc::move(mvo); + } + template + static inline void from_variant( const fc::variant& v, T& o ) + { + const variant_object& vo = v.get_object(); + fc::reflector::visit( from_variant_visitor( vo, o ) ); + } + }; + + template<> + struct if_enum + { + template + static inline void to_variant( const T& o, fc::variant& v ) + { + v = fc::reflector::to_string(o); + } + template + static inline void from_variant( const fc::variant& v, T& o ) + { + if( v.is_string() ) + o = fc::reflector::from_string( v.get_string().c_str() ); + else + // throw if invalid int, by attempting to convert to string + fc::reflector::to_string( o = static_cast(v.as_int64()) ); + } + }; + + + template + void to_variant( const T& o, variant& v ) + { + if_enum::is_enum>::to_variant( o, v ); + } + + template + void from_variant( const variant& v, T& o ) + { + if_enum::is_enum>::from_variant( v, o ); + } + +} diff --git a/include/fc/rpc/json_connection.hpp b/include/fc/rpc/json_connection.hpp new file mode 100644 index 0000000..e275362 --- /dev/null +++ b/include/fc/rpc/json_connection.hpp @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace fc { namespace rpc { + + namespace detail { class json_connection_impl; } + + /** + * @brief Implements JSON-RPC 2.0 over a set of io streams + * + * Each JSON RPC message is expected to be on its own line, violators + * will be prosecuted to the fullest extent of the law. + */ + class json_connection + { + public: + typedef std::function method; + typedef std::function named_param_method; + + json_connection( fc::buffered_istream_ptr in, fc::buffered_ostream_ptr out ); + ~json_connection(); + + /** + * Starts processing messages from input + */ + future exec(); + + logger get_logger()const; + void set_logger( const logger& l ); + + /** + * @name server interface + * + * Adding methods to the interface allows the remote side + * to call them. + */ + ///@{ + void add_method( const fc::string& name, method ); + void add_method( const fc::string& name, named_param_method ); + void remove_method( const fc::string& name ); + //@} + + /** + * @name client interface + */ + ///@{ + void notice( const fc::string& method ); + void notice( const fc::string& method, const variants& args ); + void notice( const fc::string& method, const variant_object& named_args ); + + /// args will be handled as named params + future async_call( const fc::string& method, + const variant_object& args ); + + future async_call( const fc::string& method, mutable_variant_object args ); + + /// Sending in an array of variants will be handled as positional arguments + future async_call( const fc::string& method, + const variants& args ); + + future async_call( const fc::string& method ); + + future async_call( const fc::string& method, + const variant& a1 ); + + future async_call( const fc::string& method, + const variant& a1, + const variant& a2 ); + + future async_call( const fc::string& method, + const variant& a1, + const variant& a2, + const variant& a3 ); + + template + Result call( const fc::string& method, + const variant& a1, + const variant& a2, + const variant& a3, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, a1, a2, a3 ).wait(timeout).as(); + } + + template + Result call( const fc::string& method, + const variant& a1, + const variant& a2, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, a1, a2 ).wait(timeout).as(); + } + + template + Result call( const fc::string& method, + const variant& a1, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, a1 ).wait(timeout).as(); + } + + template + Result call( const fc::string& method, + variant_object a1, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, fc::move(a1) ).wait(timeout).as(); + } + template + Result call( const fc::string& method, + mutable_variant_object a1, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, variant_object( fc::move(a1) ) ).wait(timeout).as(); + } + + + template + Result call( const fc::string& method, microseconds timeout = microseconds::maximum() ) + { + return async_call( method ).wait(timeout).as(); + } + + /// Sending in a variant_object will be issued as named parameters + variant call( const fc::string& method, const variant_object& named_args ); + ///@} + + private: + std::unique_ptr my; + }; + typedef std::shared_ptr json_connection_ptr; + +}} // fc::rpc + + + diff --git a/include/fc/rpc/variant_connection.hpp b/include/fc/rpc/variant_connection.hpp new file mode 100644 index 0000000..cb6973e --- /dev/null +++ b/include/fc/rpc/variant_connection.hpp @@ -0,0 +1,140 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace fc { namespace rpc { + + namespace detail { class variant_connection_impl; } + + /** + * @brief Implements JSON-RPC 2.0 over a set of io streams + * + * Each JSON RPC message is expected to be on its own line, violators + * will be prosecuted to the fullest extent of the law. + */ + class variant_connection + { + public: + typedef std::function method; + typedef std::function named_param_method; + + variant_connection( fc::variant_stream::ptr in, fc::variant_stream::ptr out ); + ~variant_connection(); + + /** + * Starts processing messages from input + */ + future exec(); + + logger get_logger()const; + void set_logger( const logger& l ); + + /** + * @name server interface + * + * Adding methods to the interface allows the remote side + * to call them. + */ + ///@{ + void add_method( const fc::string& name, method ); + void add_method( const fc::string& name, named_param_method ); + void remove_method( const fc::string& name ); + //@} + + /** + * @name client interface + */ + ///@{ + void notice( const fc::string& method ); + void notice( const fc::string& method, const variants& args ); + void notice( const fc::string& method, const variant_object& named_args ); + + /// args will be handled as named params + future async_call( const fc::string& method, + const variant_object& args ); + + future async_call( const fc::string& method, mutable_variant_object args ); + + /// Sending in an array of variants will be handled as positional arguments + future async_call( const fc::string& method, + const variants& args ); + + future async_call( const fc::string& method ); + + future async_call( const fc::string& method, + const variant& a1 ); + + future async_call( const fc::string& method, + const variant& a1, + const variant& a2 ); + + future async_call( const fc::string& method, + const variant& a1, + const variant& a2, + const variant& a3 ); + + template + Result call( const fc::string& method, + const variant& a1, + const variant& a2, + const variant& a3, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, a1, a2, a3 ).wait(timeout).as(); + } + + template + Result call( const fc::string& method, + const variant& a1, + const variant& a2, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, a1, a2 ).wait(timeout).as(); + } + + template + Result call( const fc::string& method, + const variant& a1, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, a1 ).wait(timeout).as(); + } + + template + Result call( const fc::string& method, + variant_object a1, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, fc::move(a1) ).wait(timeout).as(); + } + template + Result call( const fc::string& method, + mutable_variant_object a1, + microseconds timeout = microseconds::maximum()) + { + return async_call( method, variant_object( fc::move(a1) ) ).wait(timeout).as(); + } + + + template + Result call( const fc::string& method, microseconds timeout = microseconds::maximum() ) + { + return async_call( method ).wait(timeout).as(); + } + + /// Sending in a variant_object will be issued as named parameters + variant call( const fc::string& method, const variant_object& named_args ); + ///@} + + private: + std::unique_ptr my; + }; + typedef std::shared_ptr variant_connection_ptr; + +}} // fc::rpc + + + diff --git a/include/fc/rpc/variant_stream.hpp b/include/fc/rpc/variant_stream.hpp new file mode 100644 index 0000000..585b776 --- /dev/null +++ b/include/fc/rpc/variant_stream.hpp @@ -0,0 +1,36 @@ +#pragma once + +namespace fc +{ + + /** + * Thread-safe, circular buffer for passing variants + * between threads. + */ + class variant_stream + { + public: + variant_stream( size_t s ); + ~variant_stream(); + + /** producer api */ + int64_t free(); // number of spaces available + int64_t claim( int64_t num ); + int64_t publish( int64_t pos ); + int64_t wait_free(); // wait for free space + + // producer/consumer api + variant& get( int64_t pos ); + + /** consumer api */ + int64_t begin(); // returns the first index ready to be read + int64_t end(); // returns the first index that cannot be read + int64_t wait(); // wait for variants to be posted + + private: + std::vector _variants; + uint64_t _read_pos; + uint64_t _write_pos; + }; + +} diff --git a/include/fc/server.hpp b/include/fc/server.hpp deleted file mode 100644 index a2976c1..0000000 --- a/include/fc/server.hpp +++ /dev/null @@ -1,27 +0,0 @@ - - -class istream { - public: - template - istream( T& s ) { - - } - - istream& read( char* buf, uint64_t s ); - int64_t readsome( char* buf, uint64_t s ); - bool eof()const; - - private: - struct vtable { - void* (*read)(void*, char* buf, uint64_t s ); - int64_t (*readsome)(void*, char* buf, uint64_t s ); - bool (*eof)(void* ) - }; - - vtable& _vtable; - void* _stream; -}; - - - - diff --git a/include/fc/sha1.hpp b/include/fc/sha1.hpp deleted file mode 100644 index 60a3449..0000000 --- a/include/fc/sha1.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - class path; - - class sha1 { - public: - sha1(); - explicit sha1( const fc::string& hex_str ); - - fc::string str()const; - - operator fc::string()const; - - char* data()const; - - static sha1 hash( const char* d, uint32_t dlen ); - static sha1 hash( const fc::string& ); - static sha1 hash( const fc::path& ); - - template - static sha1 hash( const T& t ) { sha1::encoder e; e << t; return e.result(); } - - class encoder { - public: - encoder(); - ~encoder(); - - void write( const char* d, uint32_t dlen ); - void put( char c ) { write( &c, 1 ); } - void reset(); - sha1 result(); - - private: - struct impl; - fwd my; - }; - - template - inline friend T& operator<<( T& ds, const sha1& ep ) { - ds.write( ep.data(), sizeof(ep) ); - return ds; - } - - template - inline friend T& operator>>( T& ds, sha1& ep ) { - ds.read( ep.data(), sizeof(ep) ); - return ds; - } - friend sha1 operator << ( const sha1& h1, uint32_t i ); - friend bool operator == ( const sha1& h1, const sha1& h2 ); - friend bool operator != ( const sha1& h1, const sha1& h2 ); - friend sha1 operator ^ ( const sha1& h1, const sha1& h2 ); - friend bool operator >= ( const sha1& h1, const sha1& h2 ); - friend bool operator > ( const sha1& h1, const sha1& h2 ); - friend bool operator < ( const sha1& h1, const sha1& h2 ); - - uint32_t _hash[5]; - }; - - class value; - void pack( fc::value& , const fc::sha1& ); - void unpack( const fc::value& , fc::sha1& ); -} - - diff --git a/include/fc/sha256.hpp b/include/fc/sha256.hpp deleted file mode 100644 index 1b04db5..0000000 --- a/include/fc/sha256.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - class path; - - class sha256 { - public: - sha256(); - explicit sha256( const fc::string& hex_str ); - - fc::string str()const; - - operator fc::string()const; - - char* data()const; - - static sha256 hash( const char* d, uint32_t dlen ); - static sha256 hash( const fc::string& ); - static sha256 hash( const fc::path& ); - - template - static sha256 hash( const T& t ) { sha256::encoder e; e << t; return e.result(); } - - class encoder { - public: - encoder(); - ~encoder(); - - void write( const char* d, uint32_t dlen ); - void put( char c ) { write( &c, 1 ); } - void reset(); - sha256 result(); - - private: - struct impl; - fwd my; - }; - - template - inline friend T& operator<<( T& ds, const sha256& ep ) { - ds.write( ep.data(), sizeof(ep) ); - return ds; - } - - template - inline friend T& operator>>( T& ds, sha256& ep ) { - ds.read( ep.data(), sizeof(ep) ); - return ds; - } - friend sha256 operator << ( const sha256& h1, uint32_t i ); - friend bool operator == ( const sha256& h1, const sha256& h2 ); - friend bool operator != ( const sha256& h1, const sha256& h2 ); - friend sha256 operator ^ ( const sha256& h1, const sha256& h2 ); - friend bool operator >= ( const sha256& h1, const sha256& h2 ); - friend bool operator > ( const sha256& h1, const sha256& h2 ); - friend bool operator < ( const sha256& h1, const sha256& h2 ); - - uint64_t _hash[4]; - }; - - class value; - void pack( fc::value& , const fc::sha256& ); - void unpack( const fc::value& , fc::sha256& ); -} - - diff --git a/include/fc/shared_impl.cpp b/include/fc/shared_impl.cpp deleted file mode 100644 index 6781f17..0000000 --- a/include/fc/shared_impl.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include - -namespace fc { -template -typename shared_impl::impl& shared_impl::operator* ()const { return *_impl; } - -template -typename shared_impl::impl* shared_impl::operator-> ()const { return _impl.get(); } - -template -template -shared_impl::shared_impl( U&& u ):_impl(fc::forward(u)){} - -template -shared_impl::shared_impl( const shared_impl& u ):_impl(u._impl){} -//template -//shared_impl::shared_impl( shared_impl& u ):_impl(u._impl){} - -template -shared_impl::shared_impl( shared_impl&& u ):_impl(fc::move(u._impl)){} - -template -shared_impl& shared_impl::operator=( shared_impl&& u ) { - fc_swap(_impl,u._impl); - return *this; -} -template -shared_impl& shared_impl::operator=( const shared_impl& u ) { - _impl = u._impl; - return *this; -} - -template -bool shared_impl::operator !()const { return !_impl; } - -template -shared_impl::~shared_impl(){} - -} - -#define FC_REFERENCE_TYPE_IMPL( TYPE ) \ -template \ -TYPE::TYPE( A1&& a1 ) \ -:my( new typename fc::shared_impl::impl( fc::forward(a1) ) ){}\ -template \ -TYPE::TYPE( A1&& a1, A2&& a2 ) \ -:my( new typename fc::shared_impl::impl( fc::forward(a1), fc::forward(a2) ) ){}\ -template \ -TYPE::TYPE( A1&& a1, A2&& a2, A3&& a3 ) \ -:my( new fc::shared_impl::impl( fc::forward(a1), fc::forward(a2), fc::forward(a3) ) ){}\ -TYPE::TYPE( shared_impl::impl* m ) \ -:my(m){}\ -TYPE::TYPE( TYPE* c )\ -:my(fc::move(c->my)){ delete c; }\ -TYPE::TYPE( TYPE&& c )\ -:my(fc::move(c.my)){}\ -TYPE::TYPE( const TYPE& c )\ -:my(c.my){}\ -TYPE::TYPE() \ -:my( new fc::shared_impl::impl( ) ){}\ -TYPE::~TYPE(){}\ -bool TYPE::operator !()const { return !my; }\ -TYPE& TYPE::operator = ( const TYPE& c ) {\ - my = c.my;\ - return *this;\ -}\ -TYPE& TYPE::operator = ( TYPE&& c ) {\ - fc_swap( my._impl, c.my._impl );\ - return *this;\ -}\ -TYPE& TYPE::operator = ( TYPE* c ) {\ - fc_swap( my._impl, c->my._impl );\ - delete c;\ - return *this;\ -} \ -bool operator==( const TYPE& a, const TYPE& b ) {\ - return a.my._impl.get() == b.my._impl.get(); \ -} \ -bool operator!=( const TYPE& a, const TYPE& b ) {\ - return a.my._impl.get() != b.my._impl.get(); \ -} - - diff --git a/include/fc/shared_impl.hpp b/include/fc/shared_impl.hpp deleted file mode 100644 index 6b43ace..0000000 --- a/include/fc/shared_impl.hpp +++ /dev/null @@ -1,163 +0,0 @@ -#pragma once -#include - -namespace fc { - /** - * @class shared_impl - * @brief used to create types with reference semantics - * - * A type with reference semantics is effectively a shared pointer except that - * it is used like a Java or C# type using '.' notation instead of -> notation. - * - * It is ideal for use with classes that almost always get managed by a shared - * pointer (sockets and long-lived resources). These types are rarely, if ever - * copied by value and often by-value copy or 'deep-copy' has no real meaning. - * - * An additional feature of shared_impl is that your classes implementation - * should be private and defined entirely in your source file. There should be - * no member variables defined in your types header. - * - * To make this design pattern work requires a lot of 'boiler-plate' code for - * handling assignments, moves, copies, etc that cannot be provided via tradtional - * means such as templates or base classes. - * - * To create a new type with reference semantics you place FC_REFERENCE_TYPE(type) - * inside the private section of 'type'. Then in your source file you will - * need to define your 'private' data. - * - * @code - * #include - * - * FC_START_SHARED_IMPL( your_namespace::your_type ) - * impl( int x, int y ); // custom constructor - * - * ... - * int member_variable; - * your private member variables / methods go here. - * ... - * FC_END_SHARED_IMPL - * #include - * @endcode - * - * - * Lastly, you will need to provide the implementation your class below. This - * implementation will need to provide the matching implementations for the - * methods declared by FC_REFERENCE_TYPE(type) in your header. To do this - * use the FC_REFERENCE_TYPE_IMPL(type) - * - * @code - * namespace your_namespace { - * FC_REFERENCE_TYPE(your_type) - * ... your methods here... - * } - * @endcode - * - * Within the body of your methods you can access your private data and members - * via using 'my->member_variable' - * - * If you want to define custom constructors for your reference type, you will - * need to implement them inside the FC_START_SHARED_IMPL block using the pattern: - * - * @code - * FC_START_SHARED_IMPL( your_namespace::your_type ) - * impl( int x, int y ){} // custom constructor - * FC_END_SHARED_IMPL - * @code - * - * A limited number (3) of arguments are supported for custom constructors. - * - * Once you have defined your reference type you can use it like so: - * - * @code - * your_type val = nullptr; // create a null type - * your_type val2 = new your_type(...); // construct a new instance, unnecessary temporary heap alloc - * your_type val3(...); // constructs a new instance, more effecient - * - * val2.your_method(); - * val2 = nullptr; // reset val2 to a null object - * - * val2 = val3; // val2 and val3 now reference the same data - * if( !!val2 ){} // val2 is not null - * else{} // val2 is null - * @endcode - * - * As you can see, when creating types with this method your code will - * look and act like a Java or C# garbage collected type. - * - * Often times your private methods will need to call your public methods, to achieve - * this you can use the following techinque: - * - * @code - * FC_START_SHARED_IMPL( your_namespace::your_type ) - * void private_method( int x, int y ){ - * auto s = self(); - * s.public_method(); - * } - * FC_END_SHARED_IMPL - * @code - * - * For performance reasons, it is best to only call 'self()' once and save the - * result to avoid unnecessary copies of shared pointers which require atomic - * operations. - * - */ - template - struct shared_impl { - class impl; - impl& operator* ()const; - impl* operator-> ()const; - - bool operator !()const; - - template - explicit shared_impl( U&& u ); - - shared_impl( const shared_impl& u ); - // shared_impl( shared_impl& u ); - shared_impl( shared_impl&& u ); - shared_impl& operator=( shared_impl&& u ); - shared_impl& operator=( const shared_impl& u ); - - ~shared_impl(); - - fc::shared_ptr::impl> _impl; - }; - -} - -#define FC_REFERENCE_TYPE( TYPE ) \ - public:\ - TYPE(); \ - TYPE( std::nullptr_t ); \ - TYPE( TYPE* ); \ - TYPE( TYPE&& ); \ - TYPE( const TYPE& ); \ - template \ - TYPE( A1&& ); \ - template \ - TYPE( A1&&, A2&& ); \ - template \ - TYPE( A1&&, A2&&, A3&& ); \ - ~TYPE(); \ - bool operator !()const; \ - friend bool operator==( const TYPE& a, const TYPE& b ); \ - friend bool operator!=( const TYPE& a, const TYPE& b ); \ - TYPE& operator = ( const TYPE& ); \ - TYPE& operator = ( TYPE&& );\ - TYPE& operator = ( TYPE* );\ - TYPE& operator = ( std::nullptr_t );\ - private: \ - friend class shared_impl::impl; \ - TYPE( shared_impl::impl* m ); \ - shared_impl my; - -#define FC_START_SHARED_IMPL( SCOPED_TYPE ) \ -namespace fc { \ -template<> \ -class fc::shared_impl::impl : public fc::retainable { \ - public:\ - SCOPED_TYPE self() { return SCOPED_TYPE(this); } \ - - -#define FC_END_SHARED_IMPL }; } - diff --git a/include/fc/shared_ptr.hpp b/include/fc/shared_ptr.hpp index e7f0ab8..60a2cd3 100644 --- a/include/fc/shared_ptr.hpp +++ b/include/fc/shared_ptr.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include namespace fc { diff --git a/include/fc/signal.hpp b/include/fc/signal.hpp index b2ed9ee..9e9b5a8 100644 --- a/include/fc/signal.hpp +++ b/include/fc/signal.hpp @@ -1,7 +1,10 @@ #pragma once #include #include - +#include +#ifdef emit +#undef emit +#endif namespace fc { @@ -41,6 +44,18 @@ namespace fc { (*_handlers[i])( fc::forward(arg), fc::forward(arg2) ); } } + template + void emit( Arg&& arg, Arg2&& arg2, Arg3&& arg3 ) { + for( size_t i = 0; i < _handlers.size(); ++i ) { + (*_handlers[i])( fc::forward(arg), fc::forward(arg2), fc::forward(arg3) ); + } + } + template + void operator()( Arg&& arg, Arg2&& arg2, Arg3&& arg3 ) { + for( size_t i = 0; i < _handlers.size(); ++i ) { + (*_handlers[i])( fc::forward(arg), fc::forward(arg2), fc::forward(arg3) ); + } + } #else template void emit( Args&&... args ) { @@ -66,6 +81,18 @@ namespace fc { ++itr; } } + signal() + { + _handlers.reserve(4); + } + ~signal() + { + for( auto itr = _handlers.begin(); itr != _handlers.end(); ++itr ) + { + delete *itr; + } + _handlers.clear(); + } private: fc::vector< std::function* > _handlers; diff --git a/include/fc/signals.hpp b/include/fc/signals.hpp index 97e3518..53a7692 100644 --- a/include/fc/signals.hpp +++ b/include/fc/signals.hpp @@ -1,8 +1,7 @@ #include -#include -#include +#include +#include -#include namespace fc { #if !defined(BOOST_NO_TEMPLATE_ALIASES) @@ -12,13 +11,13 @@ namespace fc { #endif template - inline T wait( boost::signal& sig, const microseconds& timeout_us=microseconds::max() ) { + inline T wait( boost::signal& sig, const microseconds& timeout_us=microseconds::maximum() ) { typename promise::ptr p(new promise()); boost::signals::scoped_connection c = sig.connect( [=]( T t ) { p->set_value(t); } ); return p->wait( timeout_us ); } - inline void wait( boost::signal& sig, const microseconds& timeout_us=microseconds::max() ) { + inline void wait( boost::signal& sig, const microseconds& timeout_us=microseconds::maximum() ) { promise::ptr p(new promise()); boost::signals::scoped_connection c = sig.connect( [=]() { p->set_value(); } ); p->wait( timeout_us ); diff --git a/include/fc/ssh/client.hpp b/include/fc/ssh/client.hpp index b88451d..eb24a8e 100644 --- a/include/fc/ssh/client.hpp +++ b/include/fc/ssh/client.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include @@ -59,7 +59,8 @@ namespace fc { * via client::create(); * */ - class client { + class client + { public: enum trace_level { TRACE_NONE = 0, @@ -88,14 +89,26 @@ namespace fc { void set_logger( const logger& lgr ); const logger& get_logger()const; + /** + * Connect, with no password specified. Authentication will try public key, + * (via agent or explicitly-set key), empty password, then keyboard-interactive + */ void connect( const fc::string& user, const fc::string& host, uint16_t port = 22); /** - * Connect via password or keyboard-interactive + * Connect, specifying a password to be used for password authentication */ void connect( const fc::string& user, const fc::string& pass, const fc::string& host, uint16_t port = 22); /** + * @note THIS METHOD IS DEPRECATED and should be replace with: + * + * ssh::client_ptr sshc = std::make_shared(); + * sshc->connect( ... ) + * ssh::process_ptr proc = std::make_shared( sshc ); + * proc->exec( ... ) + * + * * @brief execute command on remote machine * @param pty_type - whether or not to request a PTY when executing this process, this is necessary * for interactive (non-buffered) IO with the remote process, if left empty no pty will be @@ -104,8 +117,8 @@ namespace fc { * @note Processes launched in this manner will fully buffer stdin and stdout regardless of whether * the process calls flush(). If you need unbuffered (streaming, realtime) access to standard * out then you must launch the process via a shell. - */ ssh::process exec( const fc::string& cmd, const fc::string& pty_type = "" ); + */ /** @@ -115,7 +128,7 @@ namespace fc { * transfer, the callback should return true. To cancel the callback should return false. */ void scp_send( const fc::path& local_path, const fc::path& remote_path, - std::function progress = [](size_t,size_t){return true;} ); + std::function progress = [](uint64_t,uint64_t){return true;} ); /** * @brief recursively sends the contents of local_dir to the remote_path @@ -126,13 +139,22 @@ namespace fc { * Progress will be reported as total bytes transferred for all files. */ void scp_send_dir( const fc::path& local_dir, const fc::path& remote_path, - std::function progress = [](size_t,size_t){return true;} ); + std::function progress = [](uint64_t,uint64_t){return true;} ); /** * @pre remote_path is not a directory * @post remote file is removed from the remote filesystem */ void rm( const fc::path& remote_path ); + + /** + * @pre remote_path is a directory + * @post remote directory is removed from the remote filesystem + */ + void rmdir( const fc::path& remote_path ); + + void rmdir_recursive( const fc::path& remote_path ); + file_attrib stat( const fc::path& remote_path ); /** @@ -149,6 +171,13 @@ namespace fc { */ void create_directories( const fc::path& remote_dir, int mode = owner_read|owner_write|owner_exec ); + /** + * Sets whether the remote system is believed to be a Windows box (by default, it's + * assumed to be running UNIX. This alters how command-line arguments are quoted + * and possibly how filenames are altered when copying files + */ + void set_remote_system_is_windows(bool is_windows = true); + void close(); client(); @@ -157,7 +186,8 @@ namespace fc { private: friend class process; friend class detail::process_impl; - fc::shared_ptr my; + std::unique_ptr my; }; + typedef std::shared_ptr client_ptr; } } // namespace fc::ssh diff --git a/include/fc/ssh/process.hpp b/include/fc/ssh/process.hpp index 8d4c4b8..3f26ead 100644 --- a/include/fc/ssh/process.hpp +++ b/include/fc/ssh/process.hpp @@ -1,13 +1,8 @@ #pragma once -#include -#include +#include -namespace fc { - - class istream; - class ostream; - - namespace ssh { +namespace fc { namespace ssh +{ class client; @@ -21,39 +16,43 @@ namespace fc { * * Process can only be created by mace::ssh::client. */ - class process { //: public fc::retainable { + class process : public iprocess + { public: - //typedef fc::shared_ptr ptr; - - process( const process& p ); - process( process&& p ); - process(); - ~process(); - - bool valid()const; + virtual iprocess& exec( const fc::path& exe, vector args, + const fc::path& work_dir = fc::path(), exec_opts opts = open_all ); /** * Blocks until the result code of the process has been returned. */ - int result(); + virtual int result(); + + /** - * @brief returns a stream that writes to the procss' stdin + * Not supported. libssh2 does not support sending signals to remote processes. + * closing in_stream() is the best you can do */ - fc::ostream& in_stream()const; + virtual void kill(); + + + /** + * @brief returns a stream that writes to the process' stdin + */ + virtual fc::buffered_ostream_ptr in_stream(); + /** * @brief returns a stream that reads from the process' stdout */ - fc::istream& out_stream()const; + virtual fc::buffered_istream_ptr out_stream(); /** * @brief returns a stream that reads from the process' stderr */ - fc::istream& err_stream()const; + virtual fc::buffered_istream_ptr err_stream(); - process& operator=( const process& p ); + process( fc::ssh::client_ptr c ); + ~process(); private: - friend class client; - process( client& c, const fc::string& cmd, const fc::string& pty_type = fc::string() ); - - fc::shared_ptr my; + std::unique_ptr my; }; + } } // fc::ssh diff --git a/include/fc/sstream.hpp b/include/fc/sstream.hpp deleted file mode 100644 index 79baac3..0000000 --- a/include/fc/sstream.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include - -namespace fc { - - class stringstream : virtual public iostream { - public: - stringstream(); - stringstream( fc::string& s); - stringstream( const fc::string& s); - ~stringstream(); - - fc::string str(); - - virtual bool eof()const; - virtual ostream& write( const char* buf, size_t len ); - virtual size_t readsome( char* buf, size_t len ); - virtual istream& read( char* buf, size_t len ); - virtual void close(); - virtual void flush(); - - protected: - virtual istream& read( int64_t& ); - virtual istream& read( uint64_t& ); - virtual istream& read( int32_t& ); - virtual istream& read( uint32_t& ); - virtual istream& read( int16_t& ); - virtual istream& read( uint16_t& ); - virtual istream& read( int8_t& ); - virtual istream& read( uint8_t& ); - virtual istream& read( float& ); - virtual istream& read( double& ); - virtual istream& read( bool& ); - virtual istream& read( char& ); - virtual istream& read( fc::string& ); - - virtual ostream& write( const fc::string& ); - - private: - class impl; - fwd my; - }; - -} diff --git a/include/fc/stream.hpp b/include/fc/stream.hpp deleted file mode 100644 index f5f97fc..0000000 --- a/include/fc/stream.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once -#include -#include - -namespace fc { - class string; - - class istream { - public: - virtual ~istream(){}; - - virtual size_t readsome( char* buf, size_t len ) = 0; - - template - friend istream& operator>>( istream& i, T& v ){ return i.read(v); } - - virtual bool eof()const = 0; - - protected: - virtual istream& read( int64_t& ) = 0; - virtual istream& read( uint64_t& ) = 0; - virtual istream& read( int32_t& ) = 0; - virtual istream& read( uint32_t& ) = 0; - virtual istream& read( int16_t& ) = 0; - virtual istream& read( uint16_t& ) = 0; - virtual istream& read( int8_t& ) = 0; - virtual istream& read( uint8_t& ) = 0; - virtual istream& read( float& ) = 0; - virtual istream& read( double& ) = 0; - virtual istream& read( bool& ) = 0; - virtual istream& read( char& ) = 0; - virtual istream& read( fc::string& ) = 0; - }; - - class ostream { - public: - virtual ~ostream(){}; - - virtual size_t write( const char* buf, size_t len ) = 0; - virtual void close() = 0; - virtual void flush() = 0; - - template - friend ostream& operator<<( ostream& o, const T& v ){ return o.write(fc::lexical_cast(v)); } - - protected: - virtual ostream& write( const fc::string& ) = 0; - }; - class iostream : public virtual ostream, public virtual istream {}; - - bool getline( fc::istream&, fc::string&, char delim = '\n' ); - - struct cout_t : virtual public ostream { - virtual size_t write( const char* buf, size_t len ); - virtual void close(); - virtual void flush(); - - virtual ostream& write( const fc::string& ); - }; - - struct cerr_t : virtual public ostream { - virtual size_t write( const char* buf, size_t len ); - virtual void close(); - virtual void flush(); - - virtual ostream& write( const fc::string& ); - }; - - struct cin_t : virtual public istream { - virtual size_t readsome( char* buf, size_t len ); - virtual bool eof()const; - - virtual istream& read( int64_t& ); - virtual istream& read( uint64_t& ); - virtual istream& read( int32_t& ); - virtual istream& read( uint32_t& ); - virtual istream& read( int16_t& ); - virtual istream& read( uint16_t& ); - virtual istream& read( int8_t& ); - virtual istream& read( uint8_t& ); - virtual istream& read( float& ); - virtual istream& read( double& ); - virtual istream& read( bool& ); - virtual istream& read( char& ); - virtual istream& read( fc::string& ); - }; - - - extern cout_t cout; - extern cerr_t cerr; - extern cin_t cin; -} - diff --git a/include/fc/string.hpp b/include/fc/string.hpp index 50215b0..c3798e5 100644 --- a/include/fc/string.hpp +++ b/include/fc/string.hpp @@ -22,10 +22,8 @@ namespace std { typedef basic_string, allocator > string; } -#include namespace fc { - // typedef std::string string; /** * @brief wrapper on std::string * @@ -44,7 +42,8 @@ namespace fc { public: typedef char* iterator; typedef const char* const_iterator; - static const size_t npos = -1; + enum { npos = size_t(-1) }; + // static const size_t npos;// = -1; string(); string( const std::string& s ); @@ -74,14 +73,21 @@ namespace fc { void reserve( size_t ); size_t size()const; size_t find( char c, size_t pos = 0 )const; + size_t find(const fc::string& str, size_t pos = 0) const; + size_t find(const char* s, size_t pos = 0) const; size_t rfind( char c, size_t pos = npos )const; size_t rfind( const char* c, size_t pos = npos )const; size_t rfind( const fc::string& c, size_t pos = npos )const; + size_t find_first_of (const fc::string& str, size_t pos = 0) const; + size_t find_first_of (const char* s, size_t pos = 0) const; + string& replace(size_t pos, size_t len, const fc::string& str); + string& replace(size_t pos, size_t len, const char* s); void resize( size_t s ); void clear(); const char* c_str()const; + char* data(); bool operator == ( const char* s )const; bool operator == ( const string& s )const; @@ -101,7 +107,16 @@ namespace fc { fc::fwd my; }; + int64_t to_int64( const fc::string& ); + uint64_t to_uint64( const fc::string& ); + double to_double( const fc::string& ); + fc::string to_string( double ); + fc::string to_string( uint64_t ); + fc::string to_string( int64_t ); + typedef fc::optional ostring; + class variant_object; + fc::string format_string( const fc::string&, const variant_object& ); } // namespace fc diff --git a/include/fc/future.hpp b/include/fc/thread/future.hpp similarity index 86% rename from include/fc/future.hpp rename to include/fc/thread/future.hpp index 438c5b2..06c4793 100644 --- a/include/fc/future.hpp +++ b/include/fc/thread/future.hpp @@ -1,17 +1,15 @@ -#ifndef _FC_FUTURE_HPP_ -#define _FC_FUTURE_HPP_ +#pragma once #include #include #include -#include -#include +#include +#include #include namespace fc { class abstract_thread; - struct void_t; + struct void_t{}; class priority; - class exception_ptr; class thread; namespace detail { @@ -46,9 +44,9 @@ namespace fc { }; } - class promise_base : virtual public retainable { + class promise_base : public virtual retainable{ public: - typedef shared_ptr ptr; + typedef fc::shared_ptr ptr; promise_base(const char* desc="?"); const char* get_desc()const; @@ -63,6 +61,7 @@ namespace fc { void _wait( const microseconds& timeout_us ); void _wait_until( const time_point& timeout_us ); void _enqueue_thread(); + void _dequeue_thread(); void _notify(); void _set_timeout(); void _set_value(const void* v); @@ -78,6 +77,9 @@ namespace fc { bool _ready; mutable spin_yield_lock _spin_yield; thread* _blocked_thread; +#ifndef NDEBUG + unsigned _blocked_fiber_count; +#endif time_point _timeout; fc::exception_ptr _exceptp; bool _canceled; @@ -88,12 +90,12 @@ namespace fc { template class promise : virtual public promise_base { public: - typedef shared_ptr< promise > ptr; + typedef fc::shared_ptr< promise > ptr; promise( const char* desc = "?" ):promise_base(desc){} promise( const T& val ){ set_value(val); } promise( T&& val ){ set_value(fc::move(val) ); } - const T& wait(const microseconds& timeout = microseconds::max() ){ + const T& wait(const microseconds& timeout = microseconds::maximum() ){ this->_wait( timeout ); return *result; } @@ -124,11 +126,11 @@ namespace fc { template<> class promise : virtual public promise_base { public: - typedef shared_ptr< promise > ptr; + typedef fc::shared_ptr< promise > ptr; promise( const char* desc = "?" ):promise_base(desc){} - promise( const void_t& v ){ set_value(); } + promise( const void_t& ){ set_value(); } - void wait(const microseconds& timeout = microseconds::max() ){ + void wait(const microseconds& timeout = microseconds::maximum() ){ this->_wait( timeout ); } void wait_until(const time_point& tp ) { @@ -136,7 +138,7 @@ namespace fc { } void set_value(){ this->_set_value(nullptr); } - void set_value( const void_t& v ) { this->_set_value(nullptr); } + void set_value( const void_t& ) { this->_set_value(nullptr); } template void on_complete( CompletionHandler&& c ) { @@ -164,8 +166,8 @@ namespace fc { template class future { public: - future( const shared_ptr>& p ):m_prom(p){} - future( shared_ptr>&& p ):m_prom(fc::move(p)){} + future( const fc::shared_ptr>& p ):m_prom(p){} + future( fc::shared_ptr>&& p ):m_prom(fc::move(p)){} future(){} operator const T&()const { return wait(); } @@ -173,7 +175,7 @@ namespace fc { /// @pre valid() /// @post ready() /// @throws timeout - const T& wait( const microseconds& timeout = microseconds::max() )const { + const T& wait( const microseconds& timeout = microseconds::maximum() )const { return m_prom->wait(timeout); } @@ -207,20 +209,20 @@ namespace fc { } private: friend class thread; - shared_ptr> m_prom; + fc::shared_ptr> m_prom; }; template<> class future { public: - future( const shared_ptr>& p ):m_prom(p){} - future( shared_ptr>&& p ):m_prom(fc::move(p)){} + future( const fc::shared_ptr>& p ):m_prom(p){} + future( fc::shared_ptr>&& p ):m_prom(fc::move(p)){} future(){} /// @pre valid() /// @post ready() /// @throws timeout - void wait( const microseconds& timeout = microseconds::max() ){ + void wait( const microseconds& timeout = microseconds::maximum() ){ m_prom->wait(timeout); } @@ -248,8 +250,7 @@ namespace fc { private: friend class thread; - shared_ptr> m_prom; + fc::shared_ptr> m_prom; }; } -#endif // _FC_FUTURE_HPP_ diff --git a/include/fc/mutex.hpp b/include/fc/thread/mutex.hpp similarity index 98% rename from include/fc/mutex.hpp rename to include/fc/thread/mutex.hpp index c8a1a79..f94b577 100644 --- a/include/fc/mutex.hpp +++ b/include/fc/thread/mutex.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace fc { class microseconds; diff --git a/include/fc/priority.hpp b/include/fc/thread/priority.hpp similarity index 100% rename from include/fc/priority.hpp rename to include/fc/thread/priority.hpp diff --git a/include/fc/scoped_lock.hpp b/include/fc/thread/scoped_lock.hpp similarity index 100% rename from include/fc/scoped_lock.hpp rename to include/fc/thread/scoped_lock.hpp diff --git a/include/fc/spin_lock.hpp b/include/fc/thread/spin_lock.hpp similarity index 98% rename from include/fc/spin_lock.hpp rename to include/fc/thread/spin_lock.hpp index 6dfbd1a..c69bbc6 100644 --- a/include/fc/spin_lock.hpp +++ b/include/fc/thread/spin_lock.hpp @@ -1,3 +1,4 @@ +#pragma once namespace boost { template class atomic; } diff --git a/include/fc/spin_yield_lock.hpp b/include/fc/thread/spin_yield_lock.hpp similarity index 100% rename from include/fc/spin_yield_lock.hpp rename to include/fc/thread/spin_yield_lock.hpp diff --git a/include/fc/task.hpp b/include/fc/thread/task.hpp similarity index 95% rename from include/fc/task.hpp rename to include/fc/thread/task.hpp index 9c36e6d..f86ce37 100644 --- a/include/fc/task.hpp +++ b/include/fc/thread/task.hpp @@ -1,7 +1,6 @@ -#ifndef _FC_TASK_HPP_ -#define _FC_TASK_HPP_ -#include -#include +#pragma once +#include +#include #include #include @@ -93,4 +92,3 @@ namespace fc { } -#endif // _FC_TASK_HPP_ diff --git a/include/fc/thread.hpp b/include/fc/thread/thread.hpp similarity index 91% rename from include/fc/thread.hpp rename to include/fc/thread/thread.hpp index 3fb1634..ee60c70 100644 --- a/include/fc/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include @@ -15,6 +15,9 @@ namespace fc { /** * Returns the current thread. + Note: Creates fc::thread object (but not a boost thread) if no current thread assigned yet + (this can happend if current() is called from the main thread of application or from + an existing "unknown" boost thread). In such cases, thread_d doesn't have access boost::thread object. */ static thread& current(); @@ -105,7 +108,7 @@ namespace fc { ~thread(); template - int wait_any( const fc::future& f1, const fc::future& f2, const microseconds& timeout_us = microseconds::max()) { + int wait_any( const fc::future& f1, const fc::future& f2, const microseconds& timeout_us = microseconds::maximum()) { fc::vector proms(2); proms[0] = fc::static_pointer_cast(f1.m_prom); proms[1] = fc::static_pointer_cast(f2.m_prom); @@ -162,10 +165,10 @@ namespace fc { * @return 0 if f1 is ready, 1 if f2 is ready or throw on error. */ template - int wait_any( const fc::future& f1, const fc::future& f2, const microseconds timeout_us = microseconds::max()) { + int wait_any( const fc::future& f1, const fc::future& f2, const microseconds timeout_us = microseconds::maximum()) { return fc::thread::current().wait_any(f1,f2,timeout_us); } - int wait_any( fc::vector&& v, const microseconds& timeout_us = microseconds::max() ); + int wait_any( fc::vector&& v, const microseconds& timeout_us = microseconds::maximum() ); int wait_any_until( fc::vector&& v, const time_point& tp ); template diff --git a/include/fc/unique_lock.hpp b/include/fc/thread/unique_lock.hpp similarity index 63% rename from include/fc/unique_lock.hpp rename to include/fc/thread/unique_lock.hpp index c1531fe..0facf4d 100644 --- a/include/fc/unique_lock.hpp +++ b/include/fc/thread/unique_lock.hpp @@ -1,5 +1,5 @@ -#ifndef _FC_UNIQUE_LOCK_HPP_ -#define _FC_UNIQUE_LOCK_HPP_ +#pragma once +#include namespace fc { struct try_to_lock_t{}; @@ -14,9 +14,11 @@ namespace fc { public: unique_lock( T& l, const fc::time_point& abs ):_lock(l) { _locked = _lock.try_lock_until(abs); } unique_lock( T& l, try_to_lock_t ):_lock(l) { _locked = _lock.try_lock(); } - unique_lock( T& l ):_lock(l) { _lock.lock(); _locked = true; } - ~unique_lock() { _lock.unlock(); _locked = false; } - operator bool()const { return _locked; } + unique_lock( T& l ): _locked(false), _lock(l) { lock(); } + ~unique_lock() { if (_locked) unlock(); } + operator bool() const { return _locked; } + void unlock() { assert(_locked); if (_locked) { _lock.unlock(); _locked = false;} } + void lock() { assert(!_locked); if (!_locked) { _lock.lock(); _locked = true; } } private: unique_lock( const unique_lock& ); unique_lock& operator=( const unique_lock& ); @@ -38,4 +40,3 @@ namespace fc { */ #define synchronized(X) fc::unique_lock __lock(((X))); -#endif diff --git a/include/fc/thread/wait_condition.hpp b/include/fc/thread/wait_condition.hpp new file mode 100644 index 0000000..75670d2 --- /dev/null +++ b/include/fc/thread/wait_condition.hpp @@ -0,0 +1,68 @@ +#pragma once +#include +#include +#include +#include + +namespace fc +{ + /** + * A thread-safe, fiber-aware condition variable that + * can be used to signal/wait on a certain condition between + * threads. + */ + template + class wait_condition + { + public: + void wait( const microseconds& timeout = microseconds::maximum() ) + { + typename fc::promise::ptr p = new fc::promise(); + { synchronized( _prom_lock ) + _promises.push_back( p ); + } + p->wait(timeout); + } + + template + T wait( LockType& l, const microseconds& timeout = microseconds::maximum() ) + { + typename fc::promise::ptr p( new fc::promise()); + { synchronized( _prom_lock ) + _promises.push_back( p ); + } + l.unlock(); + return p->wait(timeout); + } + + void notify_one( const T& t=T()) + { + typename fc::promise::ptr prom; + { synchronized( _prom_lock ) + if( _promises.size() ) + { + prom = _promises.front(); + _promises.pop_front(); + } + } + + if( prom && prom->retain_count() > 1 ) + prom->set_value(t); + } + void notify_all(const T& t=T()) + { + std::deque::ptr> all; + { synchronized( _prom_lock ) + all = fc::move(_promises); + } + for( auto itr = all.begin(); itr != all.end(); ++itr ) + { + if( (*itr)->retain_count() > 1 ) + (*itr)->set_value(t); + } + } + private: + fc::spin_yield_lock _prom_lock; + std::deque::ptr> _promises; + }; +} diff --git a/include/fc/thread_d.hpp b/include/fc/thread_d.hpp deleted file mode 100644 index 8a0c245..0000000 --- a/include/fc/thread_d.hpp +++ /dev/null @@ -1,393 +0,0 @@ -#include -#include - -#include -#include "context.hpp" -#include -#include -#include -#include - -namespace fc { - class thread_d { - public: - thread_d(fc::thread& s) - :self(s), boost_thread(0), - task_in_queue(0), - done(false), - current(0), - pt_head(0), - ready_head(0), - ready_tail(0), - blocked(0) - { - static char cnt = 0; - name = fc::string("th_") + char('a'+cnt); - cnt++; - } - fc::thread& self; - boost::thread* boost_thread; - bc::stack_allocator stack_alloc; - boost::mutex task_ready_mutex; - boost::condition_variable task_ready; - - boost::atomic task_in_queue; - std::vector task_pqueue; - std::vector task_sch_queue; - std::vector sleep_pqueue; - std::vector free_list; - - bool done; - std::string name; - cmt::context* current; - - cmt::context* pt_head; - - cmt::context* ready_head; - cmt::context* ready_tail; - - cmt::context* blocked; - - time_point check_for_timeouts(); - - - void debug( const std::string& s ) { - boost::unique_lock lock(detail::log_mutex()); - - std::cerr<<"--------------------- "<cur_task ) std::cerr<<'('<cur_task->get_desc()<<')'; - std::cerr<<" ---------------------------\n"; - std::cerr<<" Ready\n"; - cmt::context* c = ready_head; - while( c ) { - std::cerr<<" "<cur_task ) std::cerr<<'('<cur_task->get_desc()<<')'; - cmt::context* p = c->caller_context; - while( p ) { - std::cerr<<" -> "<caller_context; - } - std::cerr<<"\n"; - c = c->next; - } - std::cerr<<" Blocked\n"; - c = blocked; - while( c ) { - std::cerr<<" ctx: "<< c; - if( c->cur_task ) std::cerr<<'('<cur_task->get_desc()<<')'; - std::cerr << " blocked on prom: "; - for( uint32_t i = 0; i < c->blocking_prom.size(); ++i ) { - std::cerr<blocking_prom[i].prom<<'('<blocking_prom[i].prom->get_desc()<<')'; - if( i + 1 < c->blocking_prom.size() ) { - std::cerr<<","; - } - } - - cmt::context* p = c->caller_context; - while( p ) { - std::cerr<<" -> "<caller_context; - } - std::cerr<<"\n"; - c = c->next_blocked; - } - std::cerr<<"-------------------------------------------------\n"; - } - - // insert at from of blocked linked list - inline void add_to_blocked( cmt::context* c ) { - c->next_blocked = blocked; - blocked = c; - } - - void pt_push_back(cmt::context* c) { - c->next = pt_head; - pt_head = c; - /* - cmt::context* n = pt_head; - int i = 0; - while( n ) { - ++i; - n = n->next; - } - wlog( "idle context...%2% %1%", c, i ); - */ - } - cmt::context::ptr ready_pop_front() { - cmt::context::ptr tmp = 0; - if( ready_head ) { - tmp = ready_head; - ready_head = tmp->next; - if( !ready_head ) - ready_tail = 0; - tmp->next = 0; - } - return tmp; - } - void ready_push_front( const cmt::context::ptr& c ) { - c->next = ready_head; - ready_head = c; - if( !ready_tail ) - ready_tail = c; - } - void ready_push_back( const cmt::context::ptr& c ) { - c->next = 0; - if( ready_tail ) { - ready_tail->next = c; - } else { - ready_head = c; - } - ready_tail = c; - } - struct task_priority_less { - bool operator()( const task::ptr& a, const task::ptr& b ) { - return a->prio.value < b->prio.value ? true : (a->prio.value > b->prio.value ? false : a->posted_num > b->posted_num ); - } - }; - struct task_when_less { - bool operator()( const task::ptr& a, const task::ptr& b ) { - return a->when < b->when; - } - }; - - void enqueue( const task::ptr& t ) { - time_point now = system_clock::now(); - task::ptr cur = t; - while( cur ) { - if( cur->when > now ) { - task_sch_queue.push_back(cur); - std::push_heap( task_sch_queue.begin(), - task_sch_queue.end(), task_when_less() ); - } else { - task_pqueue.push_back(cur); - BOOST_ASSERT( this == thread::current().my ); - std::push_heap( task_pqueue.begin(), - task_pqueue.end(), task_priority_less() ); - } - cur = cur->next; - } - } - task* dequeue() { - // get a new task - BOOST_ASSERT( this == thread::current().my ); - - task* pending = 0; - - pending = task_in_queue.exchange(0,boost::memory_order_consume); - if( pending ) { enqueue( pending ); } - - task::ptr p(0); - if( task_sch_queue.size() ) { - if( task_sch_queue.front()->when <= system_clock::now() ) { - p = task_sch_queue.front(); - std::pop_heap(task_sch_queue.begin(), task_sch_queue.end(), task_when_less() ); - task_sch_queue.pop_back(); - return p; - } - } - if( task_pqueue.size() ) { - p = task_pqueue.front(); - std::pop_heap(task_pqueue.begin(), task_pqueue.end(), task_priority_less() ); - task_pqueue.pop_back(); - } - return p; - } - - /** - * This should be before or after a context switch to - * detect quit/cancel operations and throw an exception. - */ - void check_fiber_exceptions() { - if( current && current->canceled ) { - BOOST_THROW_EXCEPTION( error::task_canceled() ); - } else if( done ) { - BOOST_THROW_EXCEPTION( error::thread_quit() ); - } - } - - /** - * Find the next available context and switch to it. - * If none are available then create a new context and - * have it wait for something to do. - */ - bool start_next_fiber( bool reschedule = false ) { - check_for_timeouts(); - if( !current ) current = new cmt::context( &fc::thread::current() ); - - // check to see if any other contexts are ready - if( ready_head ) { - cmt::context* next = ready_pop_front(); - // jump to next context, saving current context - cmt::context* prev = current; - current = next; - if( reschedule ) ready_push_back(current); - - slog( "jump from %p to %p", prev, next ); - bc::jump_fcontext( &prev->my_context, &next->my_context, 0 ); - current = prev; - BOOST_ASSERT( current ); - } else { // all contexts are blocked, create a new context - // that will process posted tasks... - if( reschedule ) ready_push_back(current); - - cmt::context* next; - if( pt_head ) { - next = pt_head; - pt_head = pt_head->next; - next->next = 0; - } else { - next = new cmt::context( &thread_d::start_process_tasks, stack_alloc, - &fc::thread::current() ); - } - cmt::context* prev = current; - current = next; - slog( "jump from %p to %p", prev, next ); - bc::jump_fcontext( &prev->my_context, &next->my_context, (intptr_t)this ); - current = prev; - BOOST_ASSERT( current ); - } - - if( current->canceled ) - BOOST_THROW_EXCEPTION( cmt::error::task_canceled() ); - - return true; - } - - static void start_process_tasks( intptr_t my ) { - thread_d* self = (thread_d*)my; - try { - self->process_tasks(); - } catch ( ... ) { - std::cerr<<"fiber exited with uncaught exception:\n "<< - boost::current_exception_diagnostic_information() <free_list.push_back(self->current); - self->start_next_fiber( false ); - } - - bool run_next_task() { - time_point timeout_time = check_for_timeouts(); - task* next = dequeue(); - if( next ) { - next->set_active_context( current ); - current->cur_task = next; - next->run(); - current->cur_task = 0; - next->set_active_context(0); - next->release(); - //delete next; - return true; - } - return false; - } - bool has_next_task() { - if( task_pqueue.size() || - (task_sch_queue.size() && task_sch_queue.front()->when <= system_clock::now()) || - task_in_queue.load( boost::memory_order_relaxed ) ) - return true; - return false; - } - void clear_free_list() { - for( uint32_t i = 0; i < free_list.size(); ++i ) { - delete free_list[i]; - } - free_list.clear(); - } - void process_tasks() { - while( !done || blocked ) { - if( run_next_task() ) continue; - - // if I have something else to do other than - // process tasks... do it. - if( ready_head ) { - pt_push_back( current ); - start_next_fiber(false); - continue; - } - - clear_free_list(); - - { // lock scope - boost::unique_lock lock(task_ready_mutex); - if( has_next_task() ) continue; - time_point timeout_time = check_for_timeouts(); - - if( timeout_time == time_point::max() ) { - task_ready.wait( lock ); - } else if( timeout_time != time_point::min() ) { - task_ready.wait_until( lock, timeout_time ); - } - } - } - } - - void yield_until( const time_point& tp, bool reschedule ) { - check_fiber_exceptions(); - - if( tp <= system_clock::now() ) - return; - - if( !current ) { - current = new cmt::context(&cmt::thread::current()); - } - - current->resume_time = tp; - current->clear_blocking_promises(); - - sleep_pqueue.push_back(current); - std::push_heap( sleep_pqueue.begin(), - sleep_pqueue.end(), sleep_priority_less() ); - - start_next_fiber(reschedule); - - // clear current context from sleep queue... - for( uint32_t i = 0; i < sleep_pqueue.size(); ++i ) { - if( sleep_pqueue[i] == current ) { - sleep_pqueue[i] = sleep_pqueue.back(); - sleep_pqueue.pop_back(); - std::make_heap( sleep_pqueue.begin(), - sleep_pqueue.end(), sleep_priority_less() ); - break; - } - } - - current->resume_time = time_point::max(); - check_fiber_exceptions(); - } - - void wait( const promise_base::ptr& p, const time_point& timeout ) { - if( p->ready() ) return; - if( timeout < system_clock::now() ) - BOOST_THROW_EXCEPTION( cmt::error::future_wait_timeout() ); - - if( !current ) { - current = new cmt::context(&cmt::thread::current()); - } - - //slog( " %1% blocking on %2%", current, p.get() ); - current->add_blocking_promise(p.get(),true); - - // if not max timeout, added to sleep pqueue - if( timeout != time_point::max() ) { - current->resume_time = timeout; - sleep_pqueue.push_back(current); - std::push_heap( sleep_pqueue.begin(), - sleep_pqueue.end(), - sleep_priority_less() ); - } - - // elog( "blocking %1%", current ); - add_to_blocked( current ); - // debug("swtiching fibers..." ); - - - start_next_fiber(); - // slog( "resuming %1%", current ); - - //slog( " %1% unblocking blocking on %2%", current, p.get() ); - current->remove_blocking_promise(p.get()); - - check_fiber_exceptions(); - } - }; -} // namespace fc diff --git a/include/fc/time.hpp b/include/fc/time.hpp index d2bda19..aec234e 100644 --- a/include/fc/time.hpp +++ b/include/fc/time.hpp @@ -1,20 +1,20 @@ #pragma once #include #include -#include #include namespace fc { class microseconds { public: explicit microseconds( int64_t c = 0) :_count(c){} - static microseconds max() { return microseconds(0x7fffffffffffffffll); } + static microseconds maximum() { return microseconds(0x7fffffffffffffffll); } friend microseconds operator + (const microseconds& l, const microseconds& r ) { return microseconds(l._count+r._count); } - friend microseconds operator - (const microseconds& l, const microseconds& r ) { return microseconds(l._count-r._count); } bool operator==(const microseconds& c)const { return _count == c._count; } friend bool operator>(const microseconds& a, const microseconds& b){ return a._count > b._count; } + friend bool operator>=(const microseconds& a, const microseconds& b){ return a._count >= b._count; } friend bool operator<(const microseconds& a, const microseconds& b){ return a._count < b._count; } + friend bool operator<=(const microseconds& a, const microseconds& b){ return a._count <= b._count; } microseconds& operator+=(const microseconds& c) { _count += c._count; return *this; } int64_t count()const { return _count; } private: @@ -28,37 +28,25 @@ namespace fc { public: explicit time_point( microseconds e = microseconds() ) :elapsed(e){} static time_point now(); - static time_point max() { return time_point( microseconds::max() ); } - static time_point min() { return time_point(); } + static time_point maximum() { return time_point( microseconds::maximum() ); } + static time_point (min)() { return time_point(); } operator fc::string()const; static time_point from_iso_string( const fc::string& s ); const microseconds& time_since_epoch()const { return elapsed; } bool operator > ( const time_point& t )const { return elapsed._count > t.elapsed._count; } + bool operator >=( const time_point& t )const { return elapsed._count >=t.elapsed._count; } bool operator < ( const time_point& t )const { return elapsed._count < t.elapsed._count; } bool operator <=( const time_point& t )const { return elapsed._count <=t.elapsed._count; } bool operator ==( const time_point& t )const { return elapsed._count ==t.elapsed._count; } bool operator !=( const time_point& t )const { return elapsed._count !=t.elapsed._count; } time_point& operator += ( const microseconds& m ) { elapsed+=m; return *this; } friend time_point operator + ( const time_point& t, const microseconds& m ) { return time_point(t.elapsed+m); } - friend time_point operator - ( const time_point& t, const microseconds& m ) { return time_point(t.elapsed-m); } friend microseconds operator - ( const time_point& t, const time_point& m ) { return microseconds(t.elapsed.count() - m.elapsed.count()); } private: microseconds elapsed; }; - // forward declare io - class value; - void pack( fc::value& , const fc::time_point& ); - void unpack( const fc::value& , fc::time_point& ); - - namespace raw { - template - void unpack( Stream& s, fc::time_point& v ); - template - void pack( Stream& s, const fc::time_point& v ); - } - typedef fc::optional otime_point; } diff --git a/include/fc/time_io.hpp b/include/fc/time_io.hpp deleted file mode 100644 index 4fb284b..0000000 --- a/include/fc/time_io.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include - -namespace fc { - namespace raw { - template - void unpack( Stream& s, fc::time_point& v ) { - int64_t micro; - fc::raw::unpack(s, micro ); - v = fc::time_point( fc::microseconds(micro); - } - template - void pack( Stream& s, const fc::time_point& v ) { - fc::raw::pack( s, v.time_since_epoch().count() ); - } - } -} diff --git a/include/fc/unique_ptr.hpp b/include/fc/unique_ptr.hpp new file mode 100644 index 0000000..609eff8 --- /dev/null +++ b/include/fc/unique_ptr.hpp @@ -0,0 +1,60 @@ +#pragma once +#include +#include + +namespace fc +{ + template + class unique_ptr + { + public: + typedef T* pointer; + + explicit unique_ptr( pointer t = nullptr ):_p(t){} + + unique_ptr( unique_ptr&& m ) + :_p(m._p){ m._p = nullptr; } + + ~unique_ptr() { delete _p; } + + operator bool()const { return _p != nullptr; } + friend bool operator==(const unique_ptr& p, nullptr_t) + { + return p._p == nullptr; + } + + friend bool operator!=(const unique_ptr& p, nullptr_t) + { + return p._p != nullptr; + } + + unique_ptr& operator=( nullptr_t ) + { + delete _p; _p = nullptr; + } + + unique_ptr& operator=( unique_ptr&& o ) + { + fc_swap( _p, o._p ); + return *this; + } + + pointer operator->()const { return _p; } + T& operator*()const { return *_p; } + + void reset( pointer v ) + { + delete _p; _p = v; + } + pointer release() + { + auto tmp = _p; + _p = nullptr; + return tmp; + } + + private: + pointer _p; + }; + +} diff --git a/include/fc/url.hpp b/include/fc/url.hpp deleted file mode 100644 index a1bfc91..0000000 --- a/include/fc/url.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - - typedef fc::optional ostring; - - struct url { - url(){} - url( const string& url ); - /* - url( const url& u ); - - url( url&& u ); - url& operator=(url&& c); - url& operator=(const url& c); - */ - - operator string()const { return to_string(); } - string to_string()const; - url& from_string( const string& s ); - - bool operator==( const url& cmp )const; - - string proto; // file, ssh, tcp, http, ssl, etc... - ostring host; - ostring user; - ostring pass; - ostring path; - ostring args; - fc::optional port; - }; - -} // namespace fc - -#include -FC_REFLECT( fc::url, (proto)(host)(user)(pass)(path)(args)(port) ) - diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp index 96742ae..0c6c77e 100644 --- a/include/fc/utility.hpp +++ b/include/fc/utility.hpp @@ -2,14 +2,23 @@ #include #include -//#define nullptr 0 +#ifdef _MSC_VER +#pragma warning(disable: 4482) // nonstandard extension used enum Name::Val, standard in C++11 +#define NO_RETURN __declspec(noreturn) +#else +#define NO_RETURN __attribute__((noreturn)) +#endif + -typedef decltype(sizeof(int)) size_t; namespace std { typedef decltype(sizeof(int)) size_t; + typedef decltype(nullptr) nullptr_t; } namespace fc { + using std::size_t; + typedef decltype(nullptr) nullptr_t; + template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; @@ -36,14 +45,16 @@ namespace fc { template struct is_class { typedef decltype(detail::is_class_helper(0)) type; enum value_enum { value = type::value }; }; - +#ifdef min +#undef min +#endif template const T& min( const T& a, const T& b ) { return a < b ? a: b; } } // outside of namespace fc becuase of VC++ conflict with std::swap template - void fc_swap( T& a, T& b ) { + void fc_swap( T& a, T& b ) { T tmp = fc::move(a); a = fc::move(b); b = fc::move(tmp); diff --git a/include/fc/value.hpp b/include/fc/value.hpp deleted file mode 100644 index 0f095e8..0000000 --- a/include/fc/value.hpp +++ /dev/null @@ -1,240 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER - // Disable warning C4482: nonstandard extention used: enum 'enum_type::enum_value' used in qualified name - #pragma warning( disable: 4482 ) -#endif - -namespace fc { - template struct tuple; - - /** - * @brief a dynamic container that can hold - * integers, reals, strings, booleans, arrays, and - * or null. - * - * This type serves as an intermediate representation between - * C++ type and serialized type (JSON,XML,etc). - * - * As much as possible value attempts to preserve 'type' information, but - * type information is not always provided equally by all serialization formats. - * - * value is move aware, so move it when you can to avoid expensive copies - */ - class value { - public: - enum value_type { - null_type, string_type, bool_type, - int8_type, int16_type, int32_type, int64_type, - uint8_type, uint16_type, uint32_type, uint64_type, - double_type, float_type, - array_type, object_type - }; - - class key_val; - class object { - public: - typedef fc::vector::const_iterator const_iterator; - fc::vector fields; - }; - typedef fc::vector array; - - struct const_visitor { - virtual ~const_visitor(){} - virtual void operator()(const int8_t& v )=0; - virtual void operator()(const int16_t& v )=0; - virtual void operator()(const int32_t& v )=0; - virtual void operator()(const int64_t& v )=0; - virtual void operator()(const uint8_t& v )=0; - virtual void operator()(const uint16_t& v )=0; - virtual void operator()(const uint32_t& v )=0; - virtual void operator()(const uint64_t& v )=0; - virtual void operator()(const float& v )=0; - virtual void operator()(const double& v )=0; - virtual void operator()(const bool& v )=0; - virtual void operator()(const fc::string& v )=0; - virtual void operator()(const object& )=0; - virtual void operator()(const fc::vector& )=0; - virtual void operator()()=0; - }; - - value(); - value(value&& m ); - value(const value& m ); - - value(const char* c ); - value(char* c ); - value(int8_t ); - value(int16_t ); - value(int32_t ); - value(int64_t ); - value(uint8_t ); - value(uint16_t ); - value(uint32_t ); - value(uint64_t ); - value(double ); - value(float ); - value(bool ); - value(fc::string&& ); - value(fc::string& ); - value(const fc::string& ); - - value(object&& o ); - value(const object& o ); - value(object& o ); - - /// initialize an object with a single key/value pair - value(const fc::string&, const value& v ); - template - value(const fc::string& s, const T& v ) { - set( s, v ); - } - - value(fc::vector&& a ); - value(fc::vector& a ); - value(const fc::vector& a ); - - ~value(); - - value& operator=(value&& v ); - value& operator=(const value& v ); - - - /** - * Include fc/value_cast.hpp for implementation - */ - template - explicit value(const T& v ); - - template - value& operator=( const T& v ); - - template - T cast()const; - - /** used to iterate over object fields, use array index + size to iterate over array */ - object::const_iterator find(const char* key )const; - object::const_iterator begin()const; - object::const_iterator end()const; - - /** avoid creating temporary string just for comparisons! **/ - value& operator[](const char* key ); - const value& operator[](const char* key )const; - value& operator[](const fc::string& key ); - const value& operator[](const fc::string& key )const; - - /** array & object interface **/ - void clear(); - size_t size()const; - - /** array interface **/ - void resize(size_t s ); - void reserve(size_t s ); - value& push_back(value&& v ); - value& push_back(const value& v ); - const fc::vector& as_array()const; - fc::vector& as_array(); - const fc::string& as_string()const; - fc::string& as_string(); - const value::object& as_object()const; - value::object& as_object(); - - /** same as push_back(), used for short-hand construction of value()(1)(2)(3)(4) */ - value& operator()(fc::value v ); - value& operator[](int32_t idx ); - const value& operator[](int32_t idx )const; - - /** gets the stored type **/ - value_type type()const; - bool is_null()const; - bool is_string()const; - bool is_object()const; - bool is_array()const; - - void visit(const_visitor&& v )const; - - /** same as set(key, v ), used for short-hand construction of value()("key",1)("key2",2) */ - value& operator()(const char* key, fc::value v ); - value& set(const char* key, fc::value v ); - value& set(const fc::string& key, fc::value v ); - value& clear(const fc::string& key ); - - template - value& set(S&& key, T&& v ) { return set(fc::forward(key), fc::value(fc::forward(v) ) ); } - - private: - /** throws exceptions on errors - * - * Defined in fc/value_cast.hpp because it depends upon - * reflection - */ - template - friend T value_cast(const value& v ); - - aligned<40> holder; - }; - typedef fc::optional ovalue; - bool operator == (const value& v, std::nullptr_t ); - bool operator != (const value& v, std::nullptr_t ); - - class value::key_val { - public: - key_val(){}; - - key_val(fc::string k ) - :key(fc::move(k)){} - - key_val(const fc::string& k, const value& v ) - :key(k),val(v){} - - key_val(key_val&& m ) - :key(fc::move(m.key)),val(fc::move(m.val)){ } - - key_val(const key_val& m ) - :key(m.key),val(m.val){} - - ~key_val(){ } - - key_val& operator=(key_val&& k ) { - fc_swap(key, k.key ); - fc_swap(val, k.val ); - return *this; - } - - key_val& operator=(const key_val& k ) { - key = k.key; - val = k.val; - return *this; - } - - fc::string key; - value val; - }; - -} // namespace fc - -#include -FC_REFLECT_ENUM(fc::value::value_type, - (null_type) - (string_type) - (bool_type) - (int8_type) - (int16_type) - (int32_type) - (int64_type) - (uint8_type) - (uint16_type) - (uint32_type) - (uint64_type) - (double_type) - (float_type) - (array_type) - (object_type) -) diff --git a/include/fc/value_cast.hpp b/include/fc/value_cast.hpp deleted file mode 100644 index d29ca2c..0000000 --- a/include/fc/value_cast.hpp +++ /dev/null @@ -1,180 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#include - -namespace fc { - - namespace detail { - - void cast_value( const value& v, int8_t& ); - void cast_value( const value& v, int16_t& ); - void cast_value( const value& v, int32_t& ); - void cast_value( const value& v, int64_t& ); - void cast_value( const value& v, uint8_t& ); - void cast_value( const value& v, uint16_t& ); - void cast_value( const value& v, uint32_t& ); - void cast_value( const value& v, uint64_t& ); - void cast_value( const value& v, double& ); - void cast_value( const value& v, float& ); - void cast_value( const value& v, bool& ); - void cast_value( const value& v, fc::string& ); - void cast_value( const value& v, value& ); - - template - void cast_value( const value& v, T& t) { - unpack(v,t); - } - template - void cast_value( const value& v, std::vector& out ) { - if( v.type() != value::array_type ) { - FC_THROW_REPORT( "Error casting ${type} to array", fc::value("type", fc::reflector::to_string(v.type()) ) ); - } - out.resize(v.size()); - slog( "out .size %d", out.size() ); - const fc::vector& val = v.as_array(); - auto oitr = out.begin(); - int idx = 0; - for( auto itr = val.begin(); itr != val.end(); ++itr, ++oitr, ++idx ) { - try { - *oitr = itr->cast(); //value_cast(*itr); - // value_cast( *itr, *oitr ); - } catch ( fc::error_report& er ) { - throw FC_REPORT_PUSH( er, "Error casting value[${index}] to ${type}", - fc::value("index",idx) - ("type", fc::get_typename::name()) - ); - } - } - } - - template - void cast_value( const value& v, fc::vector& out ) { - if( v.type() != value::array_type ) { - FC_THROW_REPORT( "Error casting ${type} to array", fc::value("type", fc::reflector::to_string(v.type()) ) ); - } - out.resize(v.size()); - slog( "out .size %d", out.size() ); - const fc::vector& val = v.as_array(); - auto oitr = out.begin(); - int idx = 0; - for( auto itr = val.begin(); itr != val.end(); ++itr, ++oitr, ++idx ) { - try { - *oitr = itr->cast(); //value_cast(*itr); - // value_cast( *itr, *oitr ); - } catch ( fc::error_report& er ) { - throw FC_REPORT_PUSH( er, "Error casting value[${index}] to ${type}", - fc::value("index",idx) - ("type", fc::get_typename::name()) - ); - } - } - } - - template - struct cast_if_tuple { - template - static T cast( const value& v ) { - typename fc::deduce::type out; - cast_value(v,out); - // v.visit(cast_visitor(out)); - return out; - } - }; - template<> - struct cast_if_tuple { - struct member_visitor { - member_visitor( const value& v ) - :_val(v),idx(0){} - template - void operator()( Member& m ) { - try { - m = value_cast(_val[idx]); - } catch ( fc::error_report& er ) { - throw FC_REPORT_PUSH( er, "Error parsing tuple element ${index}", fc::value().set("index",idx) ); - } - ++idx; - } - const value& _val; - int idx; - }; - - template - static Tuple cast( const value& v ) { - typename fc::deduce::type out; - out.visit( member_visitor(v) ); - return out; - } - }; - - template - struct cast_if_reflected { - template - static T cast( const value& v ) { - return cast_if_tuple::type>::template cast(v); - } - }; - - template<> - struct cast_if_reflected { - template - static T cast( const value& v ) { - T tmp; - unpack(v,tmp); - return tmp; - } - }; - - void new_value_holder_void( value* v ); - } // namespace detail - - - /** - * Convert from value v to T - * - * Performs the following conversions - * true -> 1.0, 1, "true" - * - * Not all casts are 'clean', the following conversions - * could cause errors: - * - * signed int -> unsigned - * large int -> smaller int - * real -> int - * non-numeric string -> number - * object -> string or number - * array -> string or number - * number,string,array -> object - */ - template - T value_cast( const value& v ) { - return detail::cast_if_reflected::type>::is_defined>::template cast< typename fc::deduce::type >(v); - } - - template - value::value( const T& v ) { - detail::new_value_holder_void(this); - fc::pack( *this, v); - } - template - value& value::operator=( const T& v ) { - this->~value(); - value tmp(v); - *this = fc::move(tmp); - return *this; - } - template - T value::cast()const { - return value_cast(*this); - } -} diff --git a/include/fc/value_io.hpp b/include/fc/value_io.hpp deleted file mode 100644 index e69f002..0000000 --- a/include/fc/value_io.hpp +++ /dev/null @@ -1,332 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace fc { - template - T value_cast( const value& v ); - - struct void_t{}; - - template - void pack(fc::value& jsv, const T& v ); - - template - void unpack( const fc::value& jsv, T& v ); - - template - void pack( fc::value& v, const tuple& t ); - template - void unpack( const fc::value& val, tuple& t ); - - template - void pack( fc::value& jsv, const fc::optional& v ); - - template - void unpack( const fc::value& jsv, fc::optional& v ); - - inline void pack( fc::value& jsv, const char& v ) { jsv = fc::string(&v,1); } - inline void pack( fc::value& jsv, const fc::value& v ) { jsv = v; } - inline void pack( fc::value& jsv, fc::value& v ) { jsv = v; } - inline void pack( fc::value& jsv, fc::value&& v ) { jsv = fc::move(v); } - inline void pack( fc::value& jsv, const void_t& v ) { jsv = fc::value(); } - inline void pack( fc::value& jsv, const bool& v ) { jsv = v; } - inline void pack( fc::value& jsv, const float& v ) { jsv = v; } - inline void pack( fc::value& jsv, const double& v ) { jsv = v; } - inline void pack( fc::value& jsv, const uint8_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const uint16_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const uint32_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const uint64_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const int8_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const int16_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const int32_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const int64_t& v ) { jsv = v; } - inline void pack( fc::value& jsv, const fc::string& v ) { jsv = value(v); } - inline void pack( fc::value& jsv, fc::string& v ) { jsv = v; } - inline void pack( fc::value& jsv, fc::string&& v ) { jsv = fc::move(v); } - inline void pack( fc::value& jsv, const char* v ) { jsv = fc::string(v); } - - void pack( fc::value& jsv, const fc::vector& value ); - template - void pack( fc::value& jsv, const fc::vector& value ); - template - void pack( fc::value& jsv, const std::vector& value ); - - - inline void unpack( const fc::value& jsv, fc::value& v ) { v = jsv; } - template - void unpack( const fc::value& jsv, const T& v ); - template - void unpack( const fc::value& jsv, T& v ); - void unpack( const fc::value& jsv, bool& v ); - - inline void unpack( const fc::value& jsv, void_t& v ){ }; - - void unpack( const fc::value& jsv, float& v ); - void unpack( const fc::value& jsv, double& v ); - void unpack( const fc::value& jsv, uint8_t& v ); - void unpack( const fc::value& jsv, uint16_t& v ); - void unpack( const fc::value& jsv, uint32_t& v ); - void unpack( const fc::value& jsv, uint64_t& v ); - void unpack( const fc::value& jsv, int8_t& v ); - void unpack( const fc::value& jsv, int16_t& v ); - void unpack( const fc::value& jsv, int32_t& v ); - void unpack( const fc::value& jsv, int64_t& v ); - void unpack( const fc::value& jsv, fc::string& v ); - - void unpack( const fc::value& jsv, fc::vector& value ); - - void unpack( const fc::value& jsv, fc::vector& value ); - template - void unpack( const fc::value& jsv, fc::vector& value ); - template - void unpack( const fc::value& jsv, std::vector& value ); - - namespace detail { - template - struct pack_object_visitor { - pack_object_visitor(const Class& _c, fc::value& _val) - :c(_c),obj(_val){} - - /** - VC++ does not understand the difference of return types, so an extra layer is needed. - */ - template - inline void pack_helper( const T& v, const char* name )const { - value* o = &obj[name]; - fc::pack( *o, v ); - } - template - inline void pack_helper( const fc::optional& v, const char* name )const { - if( !!v ) { - fc::pack( obj[name], *v ); - } - } - template - inline void operator()( const char* name )const { - pack_helper( c.*p, name ); - } - - private: - const Class& c; - fc::value& obj; - }; - - template - struct is_optional { - typedef fc::false_type type; - }; - template - struct is_optional > { - typedef fc::true_type type; - }; - - template - struct unpack_object_visitor { - unpack_object_visitor(Class& _c, const fc::value& _val) - :c(_c),obj(_val){} - - template - void operator()( const char* name )const { - if( obj.find(name) != obj.end()) { - try { - fc::unpack( obj[name], c.*p ); - } catch ( fc::error_report& er ) { - throw FC_REPORT_PUSH( er, "Error parsing field '${field_name}'", fc::value("field_name",name) ); - } - } - else { - if( !is_optional< typename fc::remove_reference::type >::type::value ) { - wlog( "unable to find name: '%s'",name); - } - } - } - Class& c; - const fc::value& obj; - }; - - template - struct if_enum { - template - static inline void pack( fc::value& jsv, const T& v ) { - jsv = fc::value::object(); - detail::pack_object_visitor pov(v,jsv); - fc::reflector::visit(pov); - } - template - static inline void unpack( const fc::value& jsv, T& v ) { - detail::unpack_object_visitor pov(v,jsv ); - fc::reflector::visit(pov); - } - }; - - template<> struct if_enum { - template - static inline void pack( fc::value& jsv, const T& v ) { - fc::pack( jsv, fc::reflector::to_string(v) ); - } - template - static inline void unpack( const fc::value& jsv, T& v ) { - if( jsv.is_string() ) { - v = fc::reflector::from_string( fc::value_cast(jsv).c_str() ); - } else { - // throw if invalid int, by attempting to convert to string - fc::reflector::to_string( v = static_cast(value_cast(jsv)) ); - } - } - }; - - - template - struct if_reflected { - template - static inline void pack(fc::value& s, const T& v ) { - v.did_not_implement_reflect_macro(); - } - template - static inline void unpack( const fc::value& s, T& v ) { - v.did_not_implement_reflect_macro(); - } - }; - - template<> - struct if_reflected { - template - static inline void pack( fc::value& jsv, const T& v ) { - if_enum::is_enum>::pack( jsv,v ); - } - template - static inline void unpack( const fc::value& jsv, T& v ) { - if_enum::is_enum>::unpack( jsv,v ); - } - }; - - } // namesapce detail - - inline void unpack( const fc::value& jsv, char& v ) { - auto s = value_cast(jsv); - if( s.size() ) v = s[0]; - } - inline void unpack( const fc::value& jsv, bool& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, float& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, double& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, uint8_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, uint16_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, uint32_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, uint64_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, int8_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, int16_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, int32_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, int64_t& v ) { v = value_cast(jsv); } - inline void unpack( const fc::value& jsv, fc::string& v ) { v = value_cast(jsv); } - - template - void pack( fc::value& jsv, const fc::optional& v ) { - if( v ) pack( jsv, *v ); - else jsv = fc::value(); - } - template - void unpack( const fc::value& jsv, fc::optional& v ) { - if( !jsv.is_null() ) { - T tmp; - unpack( jsv, tmp ); - v = fc::move(tmp); - } - } - - - template - inline void pack( fc::value& jsv, const fc::vector& value ) { - jsv = fc::value::array(); - jsv.resize(value.size()); - typename fc::vector::const_iterator itr = value.begin(); - typename fc::vector::const_iterator end = value.end(); - uint32_t i = 0; - while( itr != end ) { - fc::pack( jsv[i], *itr ); - ++itr; - ++i; - } - } - template - inline void pack( fc::value& jsv, const std::vector& value ) { - jsv = fc::value::array(); - jsv.resize(value.size()); - auto itr = value.begin(); - auto end = value.end(); - uint32_t i = 0; - while( itr != end ) { - fc::pack( jsv[i], *itr ); - ++itr; - ++i; - } - } - struct tuple_to_value_visitor { - tuple_to_value_visitor( value& v ):_val(v),_count(0) { } - template - void operator()( T&& t ) { - _val[_count] = value(fc::forward(t) ); - ++_count; - } - value& _val; - int _count; - }; - struct tuple_from_value_visitor { - tuple_from_value_visitor( const value& v ):_val(v),_count(0) { } - template - void operator()( T&& t ) { - if( _count < _val.size() ) unpack( _val[_count], t ); - ++_count; - } - const value& _val; - int _count; - }; - - template - inline void pack( fc::value& val, const tuple& t ) { - val = fc::value::array( tuple::size ); - t.visit( tuple_to_value_visitor(val) ); - } - template - inline void unpack( const fc::value& val, tuple& t ) { - if( val.size() < tuple::size ) - FC_THROW_REPORT( "Attempt to unpack tuple of size ${size} from array of size ${array_size}", - fc::value( "size", tuple::size)("array_size",val.size() ) ); - t.visit( tuple_from_value_visitor(val) ); - } - - template - inline void unpack( const fc::value& jsv, fc::vector& val ) { - val.resize( jsv.size() ); - uint32_t s = jsv.size(); - for( uint32_t i = 0; i < s; ++i ) { - unpack( jsv[i], val[i] ); - } - } - template - inline void unpack( const fc::value& jsv, std::vector& val ) { - val.resize( jsv.size() ); - uint32_t s = jsv.size(); - for( uint32_t i = 0; i < s; ++i ) { - unpack( jsv[i], val[i] ); - } - } - - // default case - template - inline void pack( fc::value& jsv, const T& v ) { - detail::if_reflected< typename fc::reflector::is_defined >::pack(jsv,v); - } - - template - inline void unpack( const fc::value& jsv, T& v ) { - detail::if_reflected< typename fc::reflector::is_defined >::unpack(jsv,v); - } - -} // namespace fc - diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp new file mode 100644 index 0000000..896a79d --- /dev/null +++ b/include/fc/variant.hpp @@ -0,0 +1,296 @@ +#pragma once +#include +#include +#include +#include + +namespace fc +{ + /** + * @defgroup serializable Serializable _types + * @brief Clas_ses that may be converted to/from an variant + * + * To make a class 'serializable' the following methods must be available + * for your Serializable_type + * + * @code + * void to_variant( const Serializable_type& e, variant& v ); + * void from_variant( const variant& e, Serializable_type& ll ); + * @endcode + */ + + class variant; + class variant_object; + class mutable_variant_object; + class time_point; + + void to_variant( const uint16_t& var, variant& vo ); + void from_variant( const variant& var, uint16_t& vo ); + void to_variant( const uint32_t& var, variant& vo ); + void from_variant( const variant& var, uint32_t& vo ); + void to_variant( const uint8_t& var, variant& vo ); + void from_variant( const variant& var, uint8_t& vo ); + + void to_variant( const variant_object& var, variant& vo ); + void from_variant( const variant& var, variant_object& vo ); + void to_variant( const mutable_variant_object& var, variant& vo ); + void from_variant( const variant& var, mutable_variant_object& vo ); + void to_variant( const vector& var, variant& vo ); + void from_variant( const variant& var, vector& vo ); + void to_variant( const time_point& var, variant& vo ); + void from_variant( const variant& var, time_point& vo ); + #ifdef __APPLE__ + void to_variant( size_t s, variant& v ); + #endif + void to_variant( const std::string& s, variant& v ); + + template + void to_variant( const std::shared_ptr& var, variant& vo ); + + template + void from_variant( const variant& var, std::shared_ptr& vo ); + + typedef vector variants; + + /** + * @brief stores null, int64, uint64, double, bool, string, vector, + * and variant_object's. + * + * variant's allocate everything but strings, arrays, and objects on the + * stack and are 'move aware' for values allcoated on the heap. + * + * Memory usage on 64 bit systems is 16 bytes and 12 bytes on 32 bit systems. + */ + class variant + { + public: + enum type_id + { + null_type = 0, + int64_type = 1, + uint64_type = 2, + double_type = 3, + bool_type = 4, + string_type = 5, + array_type = 6, + object_type = 7 + }; + + /// Constructs a null_type variant + variant(); + /// Constructs a null_type variant + variant( nullptr_t ); + + /// @param str - UTF8 string + variant( const char* str ); + variant( char* str ); + variant( wchar_t* str ); + variant( const wchar_t* str ); + variant( int val ); + variant( float val ); + variant( int64_t val ); + variant( uint64_t val ); + variant( double val ); + variant( bool val ); + variant( fc::string val ); + variant( variant_object ); + variant( mutable_variant_object ); + variant( variants ); + variant( const variant& ); + variant( variant&& ); + ~variant(); + + /** + * Read-only access to the content of the variant. + */ + class visitor + { + public: + virtual ~visitor(){} + /// handles null_type variants + virtual void handle()const = 0; + virtual void handle( const int64_t& v )const = 0; + virtual void handle( const uint64_t& v )const = 0; + virtual void handle( const double& v )const = 0; + virtual void handle( const bool& v )const = 0; + virtual void handle( const string& v )const = 0; + virtual void handle( const variant_object& v)const = 0; + virtual void handle( const variants& v)const = 0; + }; + + void visit( const visitor& v )const; + + type_id get_type()const; + + bool is_null()const; + bool is_string()const; + bool is_bool()const; + bool is_int64()const; + bool is_uint64()const; + bool is_double()const; + bool is_object()const; + bool is_array()const; + /** + * int64, uint64, double,bool + */ + bool is_numeric()const; + + int64_t as_int64()const; + uint64_t as_uint64()const; + bool as_bool()const; + double as_double()const; + + /** Convert's double, ints, bools, etc to a string + * @throw if get_type() == array_type | get_type() == object_type + */ + string as_string()const; + + /// @pre get_type() == string_type + const string& get_string()const; + + /// @throw if get_type() != array_type | null_type + variants& get_array(); + + /// @throw if get_type() != array_type + const variants& get_array()const; + + /// @throw if get_type() != object_type | null_type + variant_object& get_object(); + + /// @throw if get_type() != object_type + const variant_object& get_object()const; + + /// @pre is_object() + const variant& operator[]( const char* )const; + /// @pre is_array() + const variant& operator[]( size_t pos )const; + /// @pre is_array() + size_t size()const; + + /** + * _types that use non-intrusive variant conversion can implement the + * following method to implement conversion from variant to T. + * + * + * void from_variant( const Variant& var, T& val ) + * + * + * The above form is not always convienant, so the this templated + * method is used to enable conversion from Variants to other + * types. + */ + template + T as()const + { + T tmp; + from_variant( *this, tmp ); + return tmp; + } + + variant& operator=( variant&& v ); + variant& operator=( const variant& v ); + + template + variant& operator=( T&& v ) + { + *this = variant( fc::forward(v) ); + return *this; + } + + template + variant( const optional& v ) + { + if( v ) *this = variant(*v); + } + + template + explicit variant( const T& val ); + + + private: + double _data; ///< Alligned according to double requirements + char _type[sizeof(void*)]; ///< pad to void* size + }; + typedef optional ovariant; + + /** @ingroup Serializable */ + void from_variant( const variant& var, string& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, variants& vo ); + void from_variant( const variant& var, variant& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, int64_t& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, uint64_t& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, bool& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, double& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, float& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, int32_t& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, uint32_t& vo ); + /** @ingroup Serializable */ + template + void from_variant( const variant& var, optional& vo ) + { + if( var.is_null() ) vo = optional(); + else + { + vo = T(); + from_variant( var, *vo ); + } + } + + /** @ingroup Serializable */ + template + void from_variant( const variant& var, vector& tmp ) + { + const variants& vars = var.get_array(); + tmp.clear(); + tmp.reserve( vars.size() ); + for( auto itr = vars.begin(); itr != vars.end(); ++itr ) + tmp.push_back( itr->as() ); + } + + /** @ingroup Serializable */ + template + void to_variant( const vector& t, variant& v ) + { + vector vars(t.size()); + for( size_t i = 0; i < t.size(); ++i ) + vars[i] = variant(t[i]); + v = vars; + } + + + template + variant::variant( const T& val ) + { + memset( this, 0, sizeof(*this) ); + to_variant( val, *this ); + } + #ifdef __APPLE__ + inline void to_variant( size_t s, variant& v ) { v = variant(uint64_t(s)); } + #endif + template + void to_variant( const std::shared_ptr& var, variant& vo ) + { + if( var ) to_variant( *var, vo ); + else vo = nullptr; + } + + template + void from_variant( const variant& var, std::shared_ptr& vo ) + { + if( var.is_null() ) vo = nullptr; + else if( vo ) from_variant( var, *vo ); + else { + vo = std::make_shared(); + from_variant( var, *vo ); + } + } + +} // namespace fc diff --git a/include/fc/variant_object.hpp b/include/fc/variant_object.hpp new file mode 100644 index 0000000..a5942ce --- /dev/null +++ b/include/fc/variant_object.hpp @@ -0,0 +1,216 @@ +#pragma once +#include +#include +#include + +namespace fc +{ + class mutable_variant_object; + + /** + * @ingroup Serializable + * + * @brief An order-perserving dictionary of variant's. + * + * Keys are kept in the order they are inserted. + * This dictionary implements copy-on-write + * + * @note This class is not optimized for random-access on large + * sets of key-value pairs. + */ + class variant_object + { + public: + /** @brief a key/value pair */ + class entry + { + public: + entry(); + entry( string k, variant v ); + entry( entry&& e ); + entry( const entry& e); + entry& operator=(const entry&); + entry& operator=(entry&&); + + const string& key()const; + const variant& value()const; + void set( variant v ); + + variant& value(); + + private: + string _key; + variant _value; + }; + + typedef vector< entry >::const_iterator iterator; + + /** + * @name Immutable Interface + * + * Calling these methods will not result in copies of the + * underlying type. + */ + ///@{ + iterator begin()const; + iterator end()const; + iterator find( const string& key )const; + iterator find( const char* key )const; + const variant& operator[]( const string& key )const; + const variant& operator[]( const char* key )const; + size_t size()const; + bool contains( const char* key ) { return find(key) != end(); } + ///@} + + variant_object(); + + /** initializes the first key/value pair in the object */ + variant_object( string key, variant val ); + + template + variant_object( string key, T&& val ) + :_key_value( std::make_shared >() ) + { + *this = variant_object( move(key), variant(forward(val)) ); + } + variant_object( const variant_object& ); + variant_object( variant_object&& ); + + variant_object( const mutable_variant_object& ); + variant_object( mutable_variant_object&& ); + + variant_object& operator=( variant_object&& ); + variant_object& operator=( const variant_object& ); + + variant_object& operator=( mutable_variant_object&& ); + variant_object& operator=( const mutable_variant_object& ); + + private: + std::shared_ptr< vector< entry > > _key_value; + friend class mutable_variant_object; + }; + /** @ingroup Serializable */ + void to_variant( const variant_object& var, variant& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, variant_object& vo ); + + + /** + * @ingroup Serializable + * + * @brief An order-perserving dictionary of variant's. + * + * Keys are kept in the order they are inserted. + * This dictionary implements copy-on-write + * + * @note This class is not optimized for random-access on large + * sets of key-value pairs. + */ + class mutable_variant_object + { + public: + /** @brief a key/value pair */ + typedef variant_object::entry entry; + + typedef vector< entry >::iterator iterator; + typedef vector< entry >::const_iterator const_iterator; + + /** + * @name Immutable Interface + * + * Calling these methods will not result in copies of the + * underlying type. + */ + ///@{ + iterator begin()const; + iterator end()const; + iterator find( const string& key )const; + iterator find( const char* key )const; + const variant& operator[]( const string& key )const; + const variant& operator[]( const char* key )const; + size_t size()const; + ///@} + variant& operator[]( const string& key ); + variant& operator[]( const char* key ); + + /** + * @name mutable Interface + * + * Calling these methods will result in a copy of the underlying type + * being created if there is more than one reference to this object. + */ + ///@{ + void reserve( size_t s); + iterator begin(); + iterator end(); + void erase( const string& key ); + /** + * + * @return end() if key is not found + */ + iterator find( const string& key ); + iterator find( const char* key ); + + + /** replaces the value at \a key with \a var or insert's \a key if not found */ + mutable_variant_object& set( string key, variant var ); + /** Appends \a key and \a var without checking for duplicates, designed to + * simplify construction of dictionaries using (key,val)(key2,val2) syntax + */ + /** + * Convenience method to simplify the manual construction of + * variant_object's + * + * Instead of: + * mutable_variant_object("c",c).set("a",a).set("b",b); + * + * You can use: + * mutable_variant_object( "c", c )( "b", b)( "c",c ) + * + * @return *this; + */ + mutable_variant_object& operator()( string key, variant var ); + template + mutable_variant_object& operator()( string key, T&& var ) + { + set(move(key), variant( forward(var) ) ); + return *this; + } + ///@} + + + template + explicit mutable_variant_object( T&& v ) + :_key_value( new vector() ) + { + *this = variant(fc::forward(v)).get_object(); + } + + mutable_variant_object(); + + /** initializes the first key/value pair in the object */ + mutable_variant_object( string key, variant val ); + template + mutable_variant_object( string key, T&& val ) + :_key_value( new vector() ) + { + set( move(key), variant(forward(val)) ); + } + + mutable_variant_object( mutable_variant_object&& ); + mutable_variant_object( const mutable_variant_object& ); + mutable_variant_object( const variant_object& ); + + mutable_variant_object& operator=( mutable_variant_object&& ); + mutable_variant_object& operator=( const mutable_variant_object& ); + mutable_variant_object& operator=( const variant_object& ); + private: + std::unique_ptr< vector< entry > > _key_value; + friend class variant_object; + }; + /** @ingroup Serializable */ + void to_variant( const mutable_variant_object& var, variant& vo ); + /** @ingroup Serializable */ + void from_variant( const variant& var, mutable_variant_object& vo ); + +} // namespace fc diff --git a/include/fc/vector.hpp b/include/fc/vector.hpp index 4396c4e..9220777 100644 --- a/include/fc/vector.hpp +++ b/include/fc/vector.hpp @@ -3,8 +3,6 @@ #include #include #include -#include -#include namespace fc { @@ -51,13 +49,11 @@ namespace fc { vector_impl():_data(nullptr){} vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; } vector_impl( const vector_impl& c):_data(nullptr) { - //slog( "copy: c.size %d", c.size() ); if( c.size() ) { _data = detail::data::allocate( c.size() ); _data->size = c.size(); memcpy(begin(),c.begin(), static_cast(c.size()) ); } - //slog( "copy: this.size %d", size() ); } vector_impl(const_iterator b, const_iterator e ):_data(nullptr) { resize(e-b); @@ -102,7 +98,16 @@ namespace fc { } void reserve( size_t i ) { - _data = detail::data::reallocate( _data, i ); + if( nullptr == _data ) + { + _data = detail::data::allocate( i ); + _data->size = 0; + _data->capacity = i; + } + else + { + _data = detail::data::reallocate( _data, i ); + } } void resize( size_t i ) { @@ -120,6 +125,11 @@ namespace fc { resize( size()+1 ); back() = fc::forward(v); } + template + void emplace_back( U&& v ) { + resize( size()+1 ); + back() = fc::forward(v); + } template iterator insert( const_iterator loc, U&& t ) { @@ -223,6 +233,7 @@ namespace fc { iterator begin() { return _data ? &front() : 0;} const_iterator begin()const { return _data ? &front() : 0;} const_iterator end()const { return _data ? (&back())+1: 0;} + iterator end(){ return _data ? (&back())+1: 0;} T& operator[]( size_t i ) { return (&_data->first)[i]; } const T& operator[]( size_t i )const { return (&_data->first)[i]; } @@ -283,6 +294,14 @@ namespace fc { new (&back()+1) T(fc::forward(v)); ++this->_data->size; } + template + void emplace_back( U&& v ) { + this->reserve( this->size()+1 ); + new (&back()+1) T(fc::forward(v)); + ++this->_data->size; + } + + template iterator insert( const_iterator loc, U&& t ) { diff --git a/include/fc/vector_g.hpp b/include/fc/vector_g.hpp deleted file mode 100644 index 0876022..0000000 --- a/include/fc/vector_g.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef _FC_VECTOR_HPP_ -#define _FC_VECTOR_HPP_ -#include - -namespace fc { - class vector_impl { - public: - size_t size()const; - size_t capacity()const; - void pop_back(); - void clear(); - void resize( size_t ); - void reserve( size_t ); - - protected: - vector_impl( abstract_value_type& v, size_t size ); - vector_impl( const vector_impl& ); - vector_impl( vector_impl&& ); - ~vector_impl(); - - vector_impl& operator=( const vector_impl& v ); - vector_impl& operator=( vector_impl&& v ); - - void _push_back( const void* v ); - void _push_back_m( void* v ); - - void* _back(); - const void* _back()const; - - void* _at(size_t); - const void* _at(size_t)const; - - void* _insert( void* pos, const void* t ); - void* _insert( void* pos, void* t ); - void* _erase( void* pos ); - void* _erase( void* first, void* last ); - - struct vector_impl_d* my; - }; - - class vector_pod_impl { - public: - size_t size()const; - size_t capacity()const; - void pop_back(); - void clear(); - void resize( size_t ); - void reserve( size_t ); - - protected: - vector_pod_impl( unsigned int size_of, size_t size ); - vector_pod_impl( const vector_pod_impl& ); - vector_pod_impl( vector_pod_impl&& ); - ~vector_pod_impl(); - - vector_pod_impl& operator=( const vector_pod_impl& v ); - vector_pod_impl& operator=( vector_pod_impl&& v ); - - void _push_back( const void* v ); - void _push_back_m( void* v ); - - void* _back(); - const void* _back()const; - - void* _at(size_t); - const void* _at(size_t)const; - - void* _insert( void* pos, const void* t ); - void* _erase( void* pos ); - void* _erase( void* first, void* last ); - - struct vector_pod_impl_d* my; - }; - - template - class vector_base : public vector_impl { - public: - vector_base( size_t s ):vector_impl( value_type::instance(), s ){}; - vector_base( const vector_base& c ):vector_impl( c ){}; - vector_base( vector_base&& c ):vector_impl( fc::move(c) ){}; - - vector_base& operator=( const vector_base& v ){ vector_impl::operator=(v); return *this; } - vector_base& operator=( vector_base&& v ) { vector_impl::operator=(fc::move(v)); return *this; } - }; - - template - class vector_base : public vector_pod_impl { - public: - vector_base( size_t s ):vector_pod_impl( sizeof(T), s ){}; - vector_base( const vector_base& c ):vector_pod_impl( c ){}; - vector_base( vector_base&& c ):vector_pod_impl( fc::move(c) ){}; - - vector_base& operator=( const vector_base& v ){ vector_pod_impl::operator=(v); return *this; } - vector_base& operator=( vector_base&& v ) { vector_pod_impl::operator=(fc::move(v)); return *this; } - }; - - template - class vector : public vector_base::value > { - public: - vector( size_t size = 0 ):vector_base::value>( size ){} - vector( const vector& v ):vector_base::value>(v){} - vector( vector&& v ):vector_base::value>(fc::move(v)){} - - vector& operator=( const vector& v ){ vector_base::value>::operator=(v); return *this; } - vector& operator=( vector&& v ) { vector_base::value>::operator=(fc::move(v)); return *this; } - - typedef T* iterator; - typedef const T* const_iterator; - - T* begin() { return &front(); } - const T* begin()const { return &front(); } - const T* end()const { return &back() + 1; } - - void push_back( const T& t ) { _push_back(&t); } - void push_back( T&& t ) { _push_back_m(&t); } - - T& back() { return *((T*)this->_back()); } - const T& back()const { return *((const T*)this->_back()); } - - T& front() { return *((T*)this->_at(0)); } - const T& front()const { return *((const T*)this->_at(0)); } - - T& operator[]( size_t p ) { return *((T*)this->_at(p)); } - const T& operator[]( size_t p )const { return *((const T*)this->_at(p)); } - - T& at( size_t p ) { return *((T*)this->_at(p)); } - const T& at( size_t p )const { return *((const T*)this->_at(p)); } - - iterator insert( iterator pos, const T& t ) { return (iterator*)this->_insert( pos, &t ); } - iterator insert( iterator pos, T&& t ) { return (iterator*)this->_insert_m(pos, &t); } - iterator erase( iterator pos ) { return (iterator*)this->_erase(pos); } - iterator erase( iterator first, iterator last ) { return (iterator*)this->_erase(first,last); } - }; - namespace reflect { - template class reflector; - template class reflector>; - } -} // namespace fc - -#endif // _FC_VECTOR_HPP_ diff --git a/include/fc/wait_any.hpp b/include/fc/wait_any.hpp index f31428b..c3d6207 100644 --- a/include/fc/wait_any.hpp +++ b/include/fc/wait_any.hpp @@ -1,7 +1,6 @@ -#ifndef _FC_WAIT_ANY_HPP_ -#define _FC_WAIT_ANY_HPP_ +#pragma once #include -#include +#include namespace fc { template @@ -12,4 +11,3 @@ namespace fc { return wait( fc::move(p), timeout_us ); } } -#endif // _FC_WAIT_ANY_HPP_ diff --git a/src/asio.cpp b/src/asio.cpp index 90cbc14..3e4dbdb 100644 --- a/src/asio.cpp +++ b/src/asio.cpp @@ -1,14 +1,28 @@ #include -#include -#include +#include #include +#include namespace fc { namespace asio { namespace detail { void read_write_handler( const promise::ptr& p, const boost::system::error_code& ec, size_t bytes_transferred ) { if( !ec ) p->set_value(bytes_transferred); - else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + else { + // elog( "%s", boost::system::system_error(ec).what() ); + // p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + if( ec == boost::asio::error::eof ) + { + p->set_exception( fc::exception_ptr( new fc::eof_exception( + FC_LOG_MESSAGE( error, "${message} ", ("message", boost::system::system_error(ec).what())) ) ) ); + } + else + { + // elog( "${message} ", ("message", boost::system::system_error(ec).what())); + p->set_exception( fc::exception_ptr( new fc::exception( + FC_LOG_MESSAGE( error, "${message} ", ("message", boost::system::system_error(ec).what())) ) ) ); + } + } } void read_write_handler_ec( promise* p, boost::system::error_code* oec, const boost::system::error_code& ec, size_t bytes_transferred ) { p->set_value(bytes_transferred); @@ -37,17 +51,41 @@ namespace fc { } p->set_value( eps ); } else { - p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + //elog( "%s", boost::system::system_error(ec).what() ); + //p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + p->set_exception( + fc::exception_ptr( new fc::exception( + FC_LOG_MESSAGE( error, "process exited with: ${message} ", + ("message", boost::system::system_error(ec).what())) ) ) ); } } } - boost::asio::io_service& default_io_service() { - static boost::asio::io_service* io = new boost::asio::io_service(); - static boost::asio::io_service::work the_work(*io); - static boost::thread io_t([=] { fc::thread::current().set_name("asio1"); io->run(); }); - static boost::thread io_t2([=]{ fc::thread::current().set_name("asio2"); io->run(); }); - static boost::thread io_t3([=]{ fc::thread::current().set_name("asio3"); io->run(); }); - return *io; + boost::asio::io_service& default_io_service(bool cleanup) { + static boost::asio::io_service io; + static boost::asio::io_service::work the_work(io); + static fc::thread fc1("asio1"); + static fc::thread fc2("asio2"); + static fc::thread fc3("asio3"); + static fc::future future1( fc1.async([=]() { io.run(); }) ); + static fc::future future2( fc2.async([=]() { io.run(); }) ); + static fc::future future3( fc3.async([=]() { io.run(); }) ); + /* + static boost::thread io_t([=] { fc1 = &fc::thread::current(); fc1->set_name("asio1"); io.run(); }); + static boost::thread io_t2([=]{ fc2 = &fc::thread::current(); fc2->set_name("asio2"); io.run(); }); + static boost::thread io_t3([=]{ fc3 = &fc::thread::current(); fc3->set_name("asio3"); io.run(); }); + */ + if (cleanup) + { + io.stop(); + fc1.quit(); + fc2.quit(); + fc3.quit(); + future1.wait(); + future2.wait(); + future3.wait(); + } + + return io; } namespace tcp { diff --git a/src/bigint.cpp b/src/bigint.cpp deleted file mode 100644 index ad8d5ce..0000000 --- a/src/bigint.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include - -namespace fc { - bigint::bigint( const char* bige, uint32_t l ) { - n = BN_bin2bn( (const unsigned char*)bige, l, NULL ); - } - - bigint::bigint( unsigned long i ) - :n(BN_new()) { - BN_set_word( n, i ); - } - - bigint::bigint( const bigint& c ) { - n = BN_dup( c.n ); - } - - bigint::bigint( bigint&& b ) { - n = b.n; - b.n = 0; - } - - bigint::~bigint() { - if(n!=0) BN_free(n); - } - - bool bigint::is_negative()const { return BN_is_negative(n); } - int64_t bigint::to_int64()const { return BN_get_word(n); } - - int64_t bigint::log2()const { return BN_num_bits(n); } - bool bigint::operator < ( const bigint& c )const { - return BN_cmp( n, c.n ) < 0; - } - bool bigint::operator > ( const bigint& c )const { - return BN_cmp( n, c.n ) > 0; - } - bool bigint::operator >= ( const bigint& c )const { - return BN_cmp( n, c.n ) >= 0; - } - bool bigint::operator == ( const bigint& c )const { - return BN_cmp( n, c.n ) == 0; - } - - bigint bigint::operator + ( const bigint& a )const { - bigint tmp(*this); - BN_add( tmp.n, n, a.n ); - return tmp; - } - bigint bigint::operator * ( const bigint& a )const { - BN_CTX* ctx = BN_CTX_new(); - bigint tmp(*this); - BN_mul( tmp.n, n, a.n, ctx ); - BN_CTX_free(ctx); - return tmp; - } - bigint bigint::operator / ( const bigint& a ) const { - BN_CTX* ctx = BN_CTX_new(); - bigint tmp(*this); - BN_div( tmp.n, NULL, n, a.n, ctx ); - BN_CTX_free(ctx); - return tmp; - } - bigint bigint::operator - ( const bigint& a )const { - bigint tmp(*this); - BN_sub( tmp.n, n, a.n ); - return tmp; - } - - - bigint& bigint::operator = ( bigint&& a ) { - fc_swap( a.n, n ); - return *this; - } - bigint& bigint::operator = ( const bigint& a ) { - if( &a == this ) - return *this; - BN_copy( n, a.n ); - return *this; - } - bigint::operator fc::string()const { - return BN_bn2dec(n); - } -} // namespace fc diff --git a/src/console_appender.cpp b/src/console_appender.cpp deleted file mode 100644 index 84f5f1a..0000000 --- a/src/console_appender.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif - -namespace fc { - console_appender::console_appender( const value& args ) { - cfg = fc::value_cast(args); - for( int i = 0; i < log_level::off+1; ++i ) - lc[i] = color::console_default; - for( auto itr = cfg.level_colors.begin(); itr != cfg.level_colors.end(); ++itr ) - lc[itr->level] = itr->color; - } - const char* get_console_color(console_appender::color::type t ) { - switch( t ) { - case console_appender::color::red: return CONSOLE_RED; - case console_appender::color::green: return CONSOLE_GREEN; - case console_appender::color::brown: return CONSOLE_BROWN; - case console_appender::color::blue: return CONSOLE_BLUE; - case console_appender::color::magenta: return CONSOLE_MAGENTA; - case console_appender::color::cyan: return CONSOLE_CYAN; - case console_appender::color::white: return CONSOLE_WHITE; - case console_appender::color::console_default: - default: - return CONSOLE_DEFAULT; - } - } - const char* console_appender::get_color( log_level::type l )const { - return get_console_color( lc[l] ); - } - void console_appender::log( const log_message& m ) { - fc::string message = fc::substitute( m.format, m.args ); - fc::value lmsg(m); - - FILE* out = stream::std_error ? stderr : stdout; - fc::string fmt_str = fc::substitute( cfg.format, value(m).set( "message", message) ); - - fc::unique_lock lock(log_mutex()); - #ifndef WIN32 - if(isatty(fileno(out))) fprintf( out, "\r%s", get_color( m.level ) ); - #endif - - fprintf( out, "%s", fmt_str.c_str() ); - - #ifndef WIN32 - if(isatty(fileno(out))) fprintf( out, "\r%s", CONSOLE_DEFAULT ); - #endif - fprintf( out, "\n" ); - if( cfg.flush ) fflush( out ); - } - -} diff --git a/src/crypto/base32.cpp b/src/crypto/base32.cpp new file mode 100644 index 0000000..a41e300 --- /dev/null +++ b/src/crypto/base32.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +namespace fc +{ + fc::vector from_base32( const fc::string& b32 ) + { + auto len = cyoBase32DecodeGetLength( b32.size() ); + fc::vector v(len); + cyoBase32Decode( v.data(), b32.c_str(), b32.size() ); + return v; + } + + fc::string to_base32( const char* data, size_t len ) + { + auto s = cyoBase16EncodeGetLength(len); + fc::string b32; + b32.resize(s); + cyoBase16Encode( b32.data(), data, len ); + b32.resize( b32.size()-1); // strip the nullterm + return b32; + } + + fc::string to_base32( const fc::vector& vec ) + { + return to_base32( vec.data(), vec.size() ); + } +} diff --git a/src/crypto/base36.cpp b/src/crypto/base36.cpp new file mode 100644 index 0000000..cbd1cc1 --- /dev/null +++ b/src/crypto/base36.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +namespace fc +{ + fc::string to_base36( const char* data, size_t len ) + { + if( len == 0 ) return fc::string(); + fc::bigint value( data, len ); + auto base36 = "0123456789abcdefghijklmnopqrstuvwxyz"; + fc::vector out( static_cast(len * 1.6) + 1 ); + int pos = out.size() - 1; + out[pos] = '\0'; + fc::bigint _36(36); + do { + if( value ) { + --pos; + out[pos] = base36[(value % _36).to_int64()]; + } + } while (value /= _36); + + return &out[pos]; //fc::string( &out[pos], out.size() - pos); + } + + fc::string to_base36( const fc::vector& vec ) + { + return to_base36( (const char*)vec.data(), vec.size() ); + } + + fc::vector from_base36( const fc::string& b36 ) + { + fc::bigint value; + + fc::bigint pos = 0; + fc::bigint _36(36); + for( auto itr = b36.begin(); itr != b36.end(); ++itr ) + { + if( *itr - '0' < 10 ) value = value + _36.exp(pos) * fc::bigint(*itr - '0'); + else if( *itr - 'a' < 26 ) value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'a')); + else if( *itr - 'A' < 26 ) value = value + (_36.exp(pos) * fc::bigint(10+*itr - 'A')); + else + { + wlog("unknown '${char}'", ("char",fc::string(&*itr,1)) ); + } + ++pos; + } + return value; + } +} diff --git a/src/base58.cpp b/src/crypto/base58.cpp similarity index 98% rename from src/base58.cpp rename to src/crypto/base58.cpp index 2b1905f..aeffe3f 100644 --- a/src/base58.cpp +++ b/src/crypto/base58.cpp @@ -21,10 +21,9 @@ #include #include -#include +#include #include -#include -#include +#include #include #include @@ -567,7 +566,7 @@ inline bool DecodeBase58(const char* psz, std::vector& vchRet) while (isspace(*p)) p++; if (*p != '\0') { - slog( "%s '%c'", pszBase58,*p ); + //slog( "%s '%c'", pszBase58,*p ); return false; } break; @@ -613,7 +612,7 @@ fc::string to_base58( const char* d, size_t s ) { fc::vector from_base58( const fc::string& base58_str ) { std::vector out; if( !DecodeBase58( base58_str.c_str(), out ) ) { - FC_THROW_REPORT( "Unable to decode base58 string ${base58_str}", fc::value().set("base58_str",base58_str) ); + FC_THROW_EXCEPTION( exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) ); } return fc::vector((const char*)out.data(), ((const char*)out.data())+out.size() ); } @@ -624,7 +623,7 @@ size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_dat //slog( "%s", base58_str.c_str() ); std::vector out; if( !DecodeBase58( base58_str.c_str(), out ) ) { - FC_THROW_REPORT( "Unable to decode base58 string ${base58_str}", fc::value().set("base58_str",base58_str) ); + FC_THROW_EXCEPTION( exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) ); } memcpy( out_data, out.data(), out.size() ); diff --git a/src/base64.cpp b/src/crypto/base64.cpp similarity index 99% rename from src/base64.cpp rename to src/crypto/base64.cpp index 05e25e1..2752c57 100644 --- a/src/base64.cpp +++ b/src/crypto/base64.cpp @@ -1,4 +1,4 @@ -#include +#include #include /* base64.cpp and base64.h diff --git a/src/crypto/bigint.cpp b/src/crypto/bigint.cpp new file mode 100644 index 0000000..431b36c --- /dev/null +++ b/src/crypto/bigint.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include + +namespace fc { + bigint::bigint( const char* bige, uint32_t l ) { + n = BN_bin2bn( (const unsigned char*)bige, l, NULL ); + } + bigint::bigint( const fc::vector& bige ) { + n = BN_bin2bn( (const unsigned char*)bige.data(), bige.size(), NULL ); + } + bigint::bigint( BIGNUM* in ) + { + n = BN_dup(in); + } + + BIGNUM* bigint::dup()const + { + return BN_dup( n ); + } + + bigint::bigint( unsigned long i ) + :n(BN_new()) { + BN_set_word( n, i ); + } + + bigint::bigint( const bigint& c ) { + n = BN_dup( c.n ); + } + + bigint::bigint( bigint&& b ) { + n = b.n; + b.n = 0; + } + + bigint::~bigint() { + if(n!=0) BN_free(n); + } + + bool bigint::is_negative()const { return BN_is_negative(n); } + int64_t bigint::to_int64()const { return BN_get_word(n); } + + int64_t bigint::log2()const { return BN_num_bits(n); } + bool bigint::operator < ( const bigint& c )const { + return BN_cmp( n, c.n ) < 0; + } + bool bigint::operator > ( const bigint& c )const { + return BN_cmp( n, c.n ) > 0; + } + bool bigint::operator >= ( const bigint& c )const { + return BN_cmp( n, c.n ) >= 0; + } + bool bigint::operator == ( const bigint& c )const { + return BN_cmp( n, c.n ) == 0; + } + bool bigint::operator != ( const bigint& c )const { + return BN_cmp( n, c.n ) == 0; + } + bigint::operator bool()const + { + return !BN_is_zero( n ); + } + bigint bigint::operator++(int) + { + bigint tmp = *this; + *this = *this + bigint(1); + return tmp; + } + bigint& bigint::operator++() + { + return *this = *this + bigint(1); + } + bigint bigint::operator--(int) + { + bigint tmp = *this; + *this = *this - bigint(1); + return tmp; + } + bigint& bigint::operator--() + { + return *this = *this - bigint(1); + } + + bigint bigint::operator + ( const bigint& a )const { + bigint tmp(*this); + BN_add( tmp.n, n, a.n ); + return tmp; + } + bigint bigint::operator * ( const bigint& a )const { + BN_CTX* ctx = BN_CTX_new(); + bigint tmp(*this); + BN_mul( tmp.n, n, a.n, ctx ); + BN_CTX_free(ctx); + return tmp; + } + bigint bigint::operator / ( const bigint& a ) const { + BN_CTX* ctx = BN_CTX_new(); + bigint tmp;//(*this); + BN_div( tmp.n, NULL, n, a.n, ctx ); + BN_CTX_free(ctx); + return tmp; + } + bigint bigint::operator % ( const bigint& a ) const { + BN_CTX* ctx = BN_CTX_new(); + bigint tmp;//(*this); + BN_mod( tmp.n, n, a.n, ctx ); + BN_CTX_free(ctx); + return tmp; + } + + bigint bigint::operator /= ( const bigint& a ) { + BN_CTX* ctx = BN_CTX_new(); + bigint tmp;//*this); + BN_div( tmp.n, NULL, n, a.n, ctx ); + fc_swap( tmp.n, n ); + BN_CTX_free(ctx); + return tmp; + } + + + bigint bigint::operator - ( const bigint& a )const { + bigint tmp; + BN_sub( tmp.n, n, a.n ); + return tmp; + } + bigint bigint::exp( const bigint& a )const + { + BN_CTX* ctx = BN_CTX_new(); + bigint tmp; + BN_exp( tmp.n, n, a.n, ctx ); + BN_CTX_free(ctx); + return tmp; + } + + + bigint& bigint::operator = ( bigint&& a ) { + fc_swap( a.n, n ); + return *this; + } + bigint& bigint::operator = ( const bigint& a ) { + if( &a == this ) + return *this; + BN_copy( n, a.n ); + return *this; + } + bigint::operator fc::string()const { + return BN_bn2dec(n); + } + + bigint::operator fc::vector()const { + fc::vector to(BN_num_bytes(n)); + BN_bn2bin(n,(unsigned char*)to.data()); + return to; + } + + /** encodes the big int as base64 string, or a number */ + void to_variant( const bigint& bi, variant& v ) + { + fc::vector ve = bi; + v = fc::variant(base64_encode((unsigned char*)ve.data(),ve.size())); + } + + /** decodes the big int as base64 string, or a number */ + void from_variant( const variant& v, bigint& bi ) + { + if( v.is_numeric() ) bi = bigint( static_cast(v.as_uint64()) ); + else + { + std::string b64 = v.as_string(); + std::string bin = base64_decode(b64); + bi = bigint(bin.c_str(), bin.size() ); + } + } + +} // namespace fc diff --git a/src/blowfish.cpp b/src/crypto/blowfish.cpp similarity index 94% rename from src/blowfish.cpp rename to src/crypto/blowfish.cpp index 74f58dc..5d3cbb4 100644 --- a/src/blowfish.cpp +++ b/src/crypto/blowfish.cpp @@ -6,9 +6,8 @@ // Cryptography", Second Edition. #include -#include -#include -#include +#include +#include namespace fc { //Extract low order byte @@ -310,13 +309,13 @@ void blowfish::start(unsigned char* ucKey, uint64_t keysize, const sblock& roCha m_oChain = roChain; if(keysize<1) - FC_THROW(invalid_key_length()); + FC_THROW_EXCEPTION( exception, "invalid key length" ); //Check the Key - the key length should be between 1 and 56 bytes if(keysize>56) keysize = 56; unsigned char aucLocalKey[56]; unsigned int i, j; - memcpy(aucLocalKey, ucKey, keysize); + memcpy(aucLocalKey, ucKey, static_cast(keysize)); //Reflexive Initialization of the Blowfish. //Generating the Subkeys from the Key flood P and S boxes with PI memcpy(m_auiP, scm_auiInitP, sizeof m_auiP); @@ -452,7 +451,7 @@ void blowfish::encrypt(unsigned char* buf, uint64_t n, int iMode) { //Check the buffer's length - should be > 0 and multiple of 8 if((n==0)||(n%8!=0)) - FC_THROW(invalid_buffer_length()); + FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) ); sblock work; if(iMode == CBC) //CBC mode, using the Chain { @@ -495,7 +494,7 @@ void blowfish::decrypt(unsigned char* buf, uint64_t n, int iMode) { //Check the buffer's length - should be > 0 and multiple of 8 if((n==0)||(n%8!=0)) - FC_THROW(invalid_buffer_length()); + FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) ); sblock work; if(iMode == CBC) //CBC mode, using the Chain { @@ -540,7 +539,7 @@ void blowfish::encrypt(const unsigned char* in, unsigned char* out, uint64_t n, { //Check the buffer's length - should be > 0 and multiple of 8 if((n==0)||(n%8!=0)) - FC_THROW(invalid_buffer_length()); + FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) ); sblock work; if(iMode == CBC) //CBC mode, using the Chain { @@ -583,7 +582,7 @@ void blowfish::decrypt(const unsigned char* in, unsigned char* out, uint64_t n, { //Check the buffer's length - should be > 0 and multiple of 8 if((n==0)||(n%8!=0)) - FC_THROW(invalid_buffer_length()); + FC_THROW_EXCEPTION( exception, "invalid buffer length ${n}, not multiple of 8", ("n", n) ); sblock work; if(iMode == CBC) //CBC mode, using the Chain { diff --git a/src/dh.cpp b/src/crypto/dh.cpp similarity index 96% rename from src/dh.cpp rename to src/crypto/dh.cpp index 642deb2..492cbcd 100644 --- a/src/dh.cpp +++ b/src/crypto/dh.cpp @@ -1,4 +1,4 @@ -#include +#include #include namespace fc { @@ -84,7 +84,7 @@ namespace fc { DH_free(dh); return valid = true; } - bool diffie_hellman::compute_shared_key( const std::vector& pubk ) { + bool diffie_hellman::compute_shared_key( const vector& pubk ) { return compute_shared_key( &pubk.front(), pubk.size() ); } diff --git a/src/crypto/elliptic.cpp b/src/crypto/elliptic.cpp new file mode 100644 index 0000000..2c15abb --- /dev/null +++ b/src/crypto/elliptic.cpp @@ -0,0 +1,429 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc { namespace ecc { + namespace detail + { + class public_key_impl + { + public: + public_key_impl() + :_key(nullptr) + { + } + ~public_key_impl() + { + if( _key != nullptr ) + { + EC_KEY_free(_key); + } + } + public_key_impl( const public_key_impl& cpy ) + { + _key = cpy._key ? EC_KEY_dup( cpy._key ) : nullptr; + } + EC_KEY* _key; + }; + class private_key_impl + { + public: + private_key_impl() + :_key(nullptr) + { + } + ~private_key_impl() + { + if( _key != nullptr ) + { + EC_KEY_free(_key); + } + } + private_key_impl( const private_key_impl& cpy ) + { + _key = cpy._key ? EC_KEY_dup( cpy._key ) : nullptr; + } + EC_KEY* _key; + }; + } + void * ecies_key_derivation(const void *input, size_t ilen, void *output, size_t *olen) + { + if (*olen < SHA512_DIGEST_LENGTH) { + return NULL; + } + *olen = SHA512_DIGEST_LENGTH; + return (void*)SHA512((const unsigned char*)input, ilen, (unsigned char*)output); + } + + // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields + // recid selects which key is recovered + // if check is non-zero, additional checks are performed + int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) + { + if (!eckey) FC_THROW_EXCEPTION( exception, "null key" ); + + int ret = 0; + BN_CTX *ctx = NULL; + + BIGNUM *x = NULL; + BIGNUM *e = NULL; + BIGNUM *order = NULL; + BIGNUM *sor = NULL; + BIGNUM *eor = NULL; + BIGNUM *field = NULL; + EC_POINT *R = NULL; + EC_POINT *O = NULL; + EC_POINT *Q = NULL; + BIGNUM *rr = NULL; + BIGNUM *zero = NULL; + int n = 0; + int i = recid / 2; + + const EC_GROUP *group = EC_KEY_get0_group(eckey); + if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; } + BN_CTX_start(ctx); + order = BN_CTX_get(ctx); + if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; } + x = BN_CTX_get(ctx); + if (!BN_copy(x, order)) { ret=-1; goto err; } + if (!BN_mul_word(x, i)) { ret=-1; goto err; } + if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; } + field = BN_CTX_get(ctx); + if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; } + if (BN_cmp(x, field) >= 0) { ret=0; goto err; } + if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; } + if (check) + { + if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; } + if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; } + } + if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + n = EC_GROUP_get_degree(group); + e = BN_CTX_get(ctx); + if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; } + if (8*msglen > n) BN_rshift(e, e, 8-(n & 7)); + zero = BN_CTX_get(ctx); + if (!BN_zero(zero)) { ret=-1; goto err; } + if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; } + rr = BN_CTX_get(ctx); + if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; } + sor = BN_CTX_get(ctx); + if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; } + eor = BN_CTX_get(ctx); + if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; } + if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; } + if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; } + + ret = 1; + + err: + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (R != NULL) EC_POINT_free(R); + if (O != NULL) EC_POINT_free(O); + if (Q != NULL) EC_POINT_free(Q); + return ret; + } + + + int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key) + { + int ok = 0; + BN_CTX *ctx = NULL; + EC_POINT *pub_key = NULL; + + if (!eckey) return 0; + + const EC_GROUP *group = EC_KEY_get0_group(eckey); + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + pub_key = EC_POINT_new(group); + + if (pub_key == NULL) + goto err; + + if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) + goto err; + + EC_KEY_set_private_key(eckey,priv_key); + EC_KEY_set_public_key(eckey,pub_key); + + ok = 1; + + err: + + if (pub_key) EC_POINT_free(pub_key); + if (ctx != NULL) BN_CTX_free(ctx); + + return(ok); + } + +/* + public_key::public_key() + :my( new detail::public_key_impl() ) + { + } + + public_key::public_key( fc::bigint pub_x, fc::bigint pub_y ) + :my( new detail::public_key_impl() ) + { + } + + public_key::~public_key() + { + } + */ + + private_key::private_key() + {} + + private_key private_key::regenerate( const fc::sha256& secret ) + { + private_key self; + self.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 ); + if( !self.my->_key ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" ); + + BIGNUM* bn = BN_bin2bn( (const unsigned char*)&secret, 32, BN_new() ); + if( bn == NULL ) + { + FC_THROW_EXCEPTION( exception, "unable to create bignum from secret" ); + } + + if( !EC_KEY_regenerate_key(self.my->_key,bn) ) + { + BN_clear_free(bn); + FC_THROW_EXCEPTION( exception, "unable to regenerate key" ); + } + + BN_clear_free(bn); + return self; + } + + fc::sha256 private_key::get_secret()const + { + fc::sha256 sec; + const BIGNUM* bn = EC_KEY_get0_private_key(my->_key); + if( bn == NULL ) + { + FC_THROW_EXCEPTION( exception, "get private key failed" ); + } + int nbytes = BN_num_bytes(bn); + BN_bn2bin(bn, &((unsigned char*)&sec)[32-nbytes] ); + return sec; + } + + private_key private_key::generate() + { + private_key self; + EC_KEY* k = EC_KEY_new_by_curve_name( NID_secp256k1 ); + if( !k ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" ); + self.my->_key = k; + if( !EC_KEY_generate_key( self.my->_key ) ) + { + elog( "key generation error" ); + } + +#if 0 + = bigint( EC_KEY_get0_private_key( k ); + EC_POINT* pub = EC_KEY_get0_public_key( k ); + EC_GROUP* group = EC_KEY_get0_group( k ); + + EC_POINT_get_affine_coordinates_GFp( group, pub, self.my->_pub_x.get(), self.my->_pub_y.get(), nullptr/*ctx*/ ); + + EC_KEY_free(k); +#endif + + return self; + } + + signature private_key::sign( const fc::sha256& digest ) + { + unsigned int buf_len = ECDSA_size(my->_key); +// fprintf( stderr, "%d %d\n", buf_len, sizeof(sha256) ); + signature sig; + assert( buf_len == sizeof(sig) ); + + if( !ECDSA_sign( 0, + (const unsigned char*)&digest, sizeof(digest), + (unsigned char*)&sig, &buf_len, my->_key ) ) + { + fprintf( stderr, "sign error\n"); + } + + + return sig; + } + bool public_key::verify( const fc::sha256& digest, const fc::ecc::signature& sig ) + { + return 1 == ECDSA_verify( 0, (unsigned char*)&digest, sizeof(digest), (unsigned char*)&sig, sizeof(sig), my->_key ); + } + + std::vector public_key::serialize() + { + EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED ); + size_t nbytes = i2o_ECPublicKey( my->_key, nullptr ); + std::vector dat(nbytes); + char* front = &dat[0]; + i2o_ECPublicKey( my->_key, (unsigned char**)&front ); + fprintf( stderr, "public key size: %lu\n", nbytes ); + return dat; + /* + EC_POINT* pub = EC_KEY_get0_public_key( my->_key ); + EC_GROUP* group = EC_KEY_get0_group( my->_key ); + EC_POINT_get_affine_coordinates_GFp( group, pub, self.my->_pub_x.get(), self.my->_pub_y.get(), nullptr ); + */ + } + public_key::public_key() + { + } + public_key::~public_key() + { + } + public_key::public_key( const std::vector& v ) + { + const char* front = &v[0]; + my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 ); + my->_key = o2i_ECPublicKey( &my->_key, (const unsigned char**)&front, v.size() ); + if( !my->_key ) + { + fprintf( stderr, "decode error occurred??" ); + } + } + + bool private_key::verify( const fc::sha256& digest, const fc::ecc::signature& sig ) + { + return 1 == ECDSA_verify( 0, (unsigned char*)&digest, sizeof(digest), (unsigned char*)&sig, sizeof(sig), my->_key ); + } + + public_key private_key::get_public_key()const + { + + public_key pub; + pub.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 ); + EC_KEY_set_public_key( pub.my->_key, EC_KEY_get0_public_key( my->_key ) ); + return pub; + } + + private_key::private_key( std::vector k ) + { +#if 0 + fc::bigint priv(k); + my->_key = EC_KEY_new_by_curve_name( NID_sect283r1 ); + auto k = my->_key; + + if( !k ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" ); + + EC_KEY_set_private_key( my->_key, priv.get() ); + + EC_GROUP* group = EC_KEY_get0_group( k ); + EC_POINT* pub = EC_POINT_new(group); + + fc::bigint x, y; + EC_POINT_set_affine_coordinates_GFp( group, pub, x.get(), y.get(), nullptr/*ctx*/ ); + + bool fail = false; + fail = EC_KEY_set_private_key( k, pub ) == 0; + fail = fail | EC_KEY_check_key( k ) == 0; + + EC_POINT_free( pub ); + + if( fail ) FC_THROW_EXCEPTION( exception, "Unable to load private key" ); +#endif + } + + fc::sha512 private_key::get_shared_secret( const public_key& other ) + { + fc::sha512 buf; + ECDH_compute_key( (unsigned char*)&buf, sizeof(buf), EC_KEY_get0_public_key(other.my->_key), my->_key, ecies_key_derivation ); + return buf; + } + + private_key::~private_key() + { + } + + public_key::public_key( const compact_signature& c, const fc::sha256& digest ) + { + int nV = c.data[0]; + if (nV<27 || nV>=35) + FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" ); + + ECDSA_SIG *sig = ECDSA_SIG_new(); + BN_bin2bn(&c.data[1],32,sig->r); + BN_bin2bn(&c.data[33],32,sig->s); + + my->_key = EC_KEY_new_by_curve_name(NID_secp256k1); + + if (nV >= 31) + { + EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED ); + nV -= 4; + fprintf( stderr, "compressed\n" ); + } + + if (ECDSA_SIG_recover_key_GFp(my->_key, sig, (unsigned char*)&digest, sizeof(digest), nV - 27, 0) == 1) + { + ECDSA_SIG_free(sig); + return; + } + ECDSA_SIG_free(sig); + FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" ); + } + + compact_signature private_key::sign_compact( const fc::sha256& digest ) + { + ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key); + + if (sig==NULL) + FC_THROW_EXCEPTION( exception, "Unable to sign" ); + + compact_signature csig; + + int nBitsR = BN_num_bits(sig->r); + int nBitsS = BN_num_bits(sig->s); + if (nBitsR <= 256 && nBitsS <= 256) + { + int nRecId = -1; + auto my_pub_key = get_public_key().serialize(); + for (int i=0; i<4; i++) + { + public_key keyRec; + keyRec.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 ); + // keyRec.fSet = true; + // if (fCompressedPubKey) keyRec.SetCompressedPubKey(); + if (ECDSA_SIG_recover_key_GFp(keyRec.my->_key, sig, (unsigned char*)&digest, sizeof(digest), i, 1) == 1) + { + if (keyRec.serialize() == my_pub_key ) + { + nRecId = i; + break; + } + } + } + + if (nRecId == -1) + FC_THROW_EXCEPTION( exception, "unable to construct recoverable key"); + + csig.data[0] = nRecId+27+4;//(fCompressedPubKey ? 4 : 0); + BN_bn2bin(sig->r,&csig.data[33-(nBitsR+7)/8]); + BN_bn2bin(sig->s,&csig.data[65-(nBitsS+7)/8]); + } + ECDSA_SIG_free(sig); + return csig; + } + +} } diff --git a/src/hex.cpp b/src/crypto/hex.cpp similarity index 87% rename from src/hex.cpp rename to src/crypto/hex.cpp index ac51309..375726a 100644 --- a/src/hex.cpp +++ b/src/crypto/hex.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include namespace fc { @@ -10,7 +10,7 @@ namespace fc { return c - 'a' + 10; if( c >= 'A' && c <= 'F' ) return c - 'A' + 10; - FC_THROW_MSG( "Invalid hex character '%s'", c ); + FC_THROW_EXCEPTION( exception, "Invalid hex character '${c}'", ("c", fc::string(&c,1) ) ); return 0; } diff --git a/src/crypto/pke.cpp b/src/crypto/pke.cpp new file mode 100644 index 0000000..a425621 --- /dev/null +++ b/src/crypto/pke.cpp @@ -0,0 +1,365 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc { + + namespace detail { + class pke_impl + { + public: + pke_impl():rsa(nullptr){} + ~pke_impl() + { + if( rsa != nullptr ) + RSA_free(rsa); + } + RSA* rsa; + }; + } // detail + + public_key::operator bool()const { return !!my; } + private_key::operator bool()const { return !!my; } + + public_key::public_key() + {} + + public_key::public_key( const bytes& d ) + :my( std::make_shared() ) + { + string pem = "-----BEGIN RSA PUBLIC KEY-----\n"; + auto b64 = fc::base64_encode( (const unsigned char*)d.data(), d.size() ); + for( size_t i = 0; i < b64.size(); i += 64 ) + pem += b64.substr( i, 64 ) + "\n"; + pem += "-----END RSA PUBLIC KEY-----\n"; + // fc::cerr<rsa = PEM_read_bio_RSAPublicKey(mem, NULL, NULL, NULL ); + BIO_free(mem); + } + public_key::public_key( const public_key& k ) + :my(k.my) + { + } + + public_key::public_key( public_key&& k ) + :my(std::move(k.my)) + { + } + + public_key::~public_key() { } + + public_key& public_key::operator=(const public_key& p ) + { + my = p.my; return *this; + } + public_key& public_key::operator=( public_key&& p ) + { + my = std::move(p.my); return *this; + } + bool public_key::verify( const sha1& digest, const array& sig )const + { + return 0 != RSA_verify( NID_sha1, (const uint8_t*)&digest, 20, + (uint8_t*)&sig, 2048/8, my->rsa ); + } + + bool public_key::verify( const sha1& digest, const signature& sig )const + { + assert( sig.size() == 2048/8 ); + return 0 != RSA_verify( NID_sha1, (const uint8_t*)&digest, 20, + (uint8_t*)sig.data(), 2048/8, my->rsa ); + } + bool public_key::verify( const sha256& digest, const signature& sig )const + { + assert( sig.size() == 2048/8 ); + return 0 != RSA_verify( NID_sha256, (const uint8_t*)&digest, 32, + (uint8_t*)sig.data(), 2048/8, my->rsa ); + } + bytes public_key::encrypt( const char* b, size_t l )const + { + FC_ASSERT( my && my->rsa ); + bytes out( RSA_size(my->rsa) ); //, char(0) ); + int rtn = RSA_public_encrypt( l, + (unsigned char*)b, + (unsigned char*)out.data(), + my->rsa, RSA_PKCS1_OAEP_PADDING ); + if( rtn >= 0 ) { + out.resize(rtn); + return out; + } + FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + + bytes public_key::encrypt( const bytes& in )const + { + FC_ASSERT( my && my->rsa ); + bytes out( RSA_size(my->rsa) ); //, char(0) ); + int rtn = RSA_public_encrypt( in.size(), + (unsigned char*)in.data(), + (unsigned char*)out.data(), + my->rsa, RSA_PKCS1_OAEP_PADDING ); + fc::cerr<<"rtn: "<= 0 ) { + out.resize(rtn); + return out; + } + FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + bytes public_key::decrypt( const bytes& in )const + { + FC_ASSERT( my && my->rsa ); + bytes out( RSA_size(my->rsa) );//, char(0) ); + int rtn = RSA_public_decrypt( in.size(), + (unsigned char*)in.data(), + (unsigned char*)out.data(), + my->rsa, RSA_PKCS1_OAEP_PADDING ); + if( rtn >= 0 ) { + out.resize(rtn); + return out; + } + FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + + bytes public_key::serialize()const + { + bytes ba; + if( !my ) { return ba; } + + BIO *mem = BIO_new(BIO_s_mem()); + int e = PEM_write_bio_RSAPublicKey( mem, my->rsa ); + if( e != 1 ) + { + BIO_free(mem); + FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + char* dat; + uint32_t l = BIO_get_mem_data( mem, &dat ); + + fc::stringstream ss( string( dat, l ) ); + fc::stringstream key; + fc::string tmp; + fc::getline( ss, tmp ); + fc::getline( ss, tmp ); + while( tmp.size() && tmp[0] != '-' ) + { + key << tmp; + fc::getline( ss, tmp ); + } + auto str = key.str(); + str = fc::base64_decode( str ); + ba = bytes( str.begin(), str.end() ); + + BIO_free(mem); + return ba; + } + + private_key::private_key() + { + } + private_key::private_key( const bytes& d ) + :my( std::make_shared() ) + { + + string pem = "-----BEGIN RSA PRIVATE KEY-----\n"; + auto b64 = fc::base64_encode( (const unsigned char*)d.data(), d.size() ); + for( size_t i = 0; i < b64.size(); i += 64 ) + pem += b64.substr( i, 64 ) + "\n"; + pem += "-----END RSA PRIVATE KEY-----\n"; + // fc::cerr<rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL ); + BIO_free(mem); + + FC_ASSERT( my->rsa, "read private key" ); + } + + private_key::private_key( const private_key& k ) + :my(k.my) + { + } + private_key::private_key( private_key&& k ) + :my(std::move(k.my) ) + { + } + private_key::~private_key() { } + + private_key& private_key::operator=(const private_key& p ) + { + my = p.my; return *this; + } + private_key& private_key::operator=(private_key&& p ) + { + my = std::move(p.my); return *this; + } + + void private_key::sign( const sha1& digest, array& sig )const + { + FC_ASSERT( (size_t(RSA_size(my->rsa)) <= sizeof(sig)), "Invalid RSA size" ); + uint32_t slen = 0; + if( 1 != RSA_sign( NID_sha1, (uint8_t*)&digest, + 20, (unsigned char*)&sig, &slen, my->rsa ) ) + { + FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + } + + signature private_key::sign( const sha1& digest )const + { + if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" ); + signature sig; + sig.resize( RSA_size(my->rsa) ); + + uint32_t slen = 0; + if( 1 != RSA_sign( NID_sha1, (uint8_t*)digest.data(), + 20, (unsigned char*)sig.data(), &slen, my->rsa ) ) + { + FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + return sig; + } + signature private_key::sign( const sha256& digest )const + { + if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" ); + signature sig; + sig.resize( RSA_size(my->rsa) ); + + uint32_t slen = 0; + if( 1 != RSA_sign( NID_sha256, (uint8_t*)digest.data(), + 32, (unsigned char*)sig.data(), &slen, my->rsa ) ) + { + FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + return sig; + } + + + bytes private_key::encrypt( const bytes& in )const + { + if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" ); + bytes out; + out.resize( RSA_size(my->rsa) ); + int rtn = RSA_private_encrypt( in.size(), + (unsigned char*)in.data(), + (unsigned char*)out.data(), + my->rsa, RSA_PKCS1_OAEP_PADDING ); + if( rtn >= 0 ) { + out.resize(rtn); + return out; + } + + FC_THROW_EXCEPTION( exception, "encrypt failed" ); + } + + bytes private_key::decrypt( const char* in, size_t l )const + { + if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" ); + bytes out; + out.resize( RSA_size(my->rsa) ); + int rtn = RSA_private_decrypt( l, + (unsigned char*)in, + (unsigned char*)out.data(), + my->rsa, RSA_PKCS1_OAEP_PADDING ); + if( rtn >= 0 ) { + out.resize(rtn); + return out; + } + FC_THROW_EXCEPTION( exception, "decrypt failed" ); + } + bytes private_key::decrypt( const bytes& in )const + { + if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" ); + bytes out; + out.resize( RSA_size(my->rsa) ); + int rtn = RSA_private_decrypt( in.size(), + (unsigned char*)in.data(), + (unsigned char*)out.data(), + my->rsa, RSA_PKCS1_OAEP_PADDING ); + if( rtn >= 0 ) { + out.resize(rtn); + return out; + } + FC_THROW_EXCEPTION( exception, "decrypt failed" ); + } + + bytes private_key::serialize()const + { + bytes ba; + if( !my ) { return ba; } + + BIO *mem = BIO_new(BIO_s_mem()); + int e = PEM_write_bio_RSAPrivateKey( mem, my->rsa, NULL, NULL, 0, NULL, NULL ); + if( e != 1 ) + { + BIO_free(mem); + FC_THROW_EXCEPTION( exception, "Error writing private key, ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); + } + char* dat; + uint32_t l = BIO_get_mem_data( mem, &dat ); + // return bytes( dat, dat + l ); + + stringstream ss( string( dat, l ) ); + stringstream key; + string tmp; + fc::getline( ss, tmp ); + fc::getline( ss, tmp ); + + while( tmp.size() && tmp[0] != '-' ) + { + key << tmp; + fc::getline( ss, tmp ); + } + auto str = key.str(); + str = fc::base64_decode( str ); + ba = bytes( str.begin(), str.end() ); + // ba = bytes( dat, dat + l ); + BIO_free(mem); + return ba; + } + + void generate_key_pair( public_key& pub, private_key& priv ) + { + static bool init = true; + if( init ) { ERR_load_crypto_strings(); init = false; } + + pub.my = std::make_shared(); + priv.my = pub.my; + pub.my->rsa = RSA_generate_key( 2048, 65537, NULL, NULL ); + } + + /** encodes the big int as base64 string, or a number */ + void to_variant( const public_key& bi, variant& v ) + { + v = bi.serialize(); + } + + /** decodes the big int as base64 string, or a number */ + void from_variant( const variant& v, public_key& bi ) + { + bi = public_key( v.as >() ); + } + + + /** encodes the big int as base64 string, or a number */ + void to_variant( const private_key& bi, variant& v ) + { + v = bi.serialize(); + } + + /** decodes the big int as base64 string, or a number */ + void from_variant( const variant& v, private_key& bi ) + { + bi = private_key( v.as >() ); + } + +} // fc diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp new file mode 100644 index 0000000..2617d97 --- /dev/null +++ b/src/crypto/sha1.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include + +namespace fc +{ + +sha1::sha1() { memset( _hash, 0, sizeof(_hash) ); } +sha1::sha1( const string& hex_str ) { + fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) ); +} + +string sha1::str()const { + return fc::to_hex( (char*)_hash, sizeof(_hash) ); +} +sha1::operator string()const { return str(); } + +char* sha1::data()const { return (char*)&_hash[0]; } + + +struct sha1::encoder::impl { + SHA_CTX ctx; +}; + +sha1::encoder::~encoder() {} +sha1::encoder::encoder() { + reset(); +} + +sha1 sha1::hash( const char* d, uint32_t dlen ) { + encoder e; + e.write(d,dlen); + return e.result(); +} +sha1 sha1::hash( const string& s ) { + return hash( s.c_str(), s.size() ); +} + +void sha1::encoder::write( const char* d, uint32_t dlen ) { + SHA1_Update( &my->ctx, d, dlen); +} +sha1 sha1::encoder::result() { + sha1 h; + SHA1_Final((uint8_t*)h.data(), &my->ctx ); + return h; +} +void sha1::encoder::reset() { + SHA1_Init( &my->ctx); +} + +sha1 operator << ( const sha1& h1, uint32_t i ) { + sha1 result; + uint8_t* r = (uint8_t*)result._hash; + uint8_t* s = (uint8_t*)h1._hash; + for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p ) + r[p] = s[p] << i | (s[p+1]>>(8-i)); + r[19] = s[19] << i; + return result; +} +sha1 operator ^ ( const sha1& h1, const sha1& h2 ) { + sha1 result; + result._hash[0] = h1._hash[0] ^ h2._hash[0]; + result._hash[1] = h1._hash[1] ^ h2._hash[1]; + result._hash[2] = h1._hash[2] ^ h2._hash[2]; + result._hash[3] = h1._hash[3] ^ h2._hash[3]; + result._hash[4] = h1._hash[4] ^ h2._hash[4]; + return result; +} +bool operator >= ( const sha1& h1, const sha1& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) >= 0; +} +bool operator > ( const sha1& h1, const sha1& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0; +} +bool operator < ( const sha1& h1, const sha1& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0; +} +bool operator != ( const sha1& h1, const sha1& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0; +} +bool operator == ( const sha1& h1, const sha1& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0; +} + +} // fc diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp new file mode 100644 index 0000000..0e4526e --- /dev/null +++ b/src/crypto/sha256.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include + +namespace fc { + + sha256::sha256() { memset( _hash, 0, sizeof(_hash) ); } + sha256::sha256( const string& hex_str ) { + fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) ); + } + + string sha256::str()const { + return fc::to_hex( (char*)_hash, sizeof(_hash) ); + } + sha256::operator string()const { return str(); } + + char* sha256::data()const { return (char*)&_hash[0]; } + + + struct sha256::encoder::impl { + SHA256_CTX ctx; + }; + + sha256::encoder::~encoder() {} + sha256::encoder::encoder() { + reset(); + } + + sha256 sha256::hash( const char* d, uint32_t dlen ) { + encoder e; + e.write(d,dlen); + return e.result(); + } + sha256 sha256::hash( const string& s ) { + return hash( s.c_str(), s.size() ); + } + + void sha256::encoder::write( const char* d, uint32_t dlen ) { + SHA256_Update( &my->ctx, d, dlen); + } + sha256 sha256::encoder::result() { + sha256 h; + SHA256_Final((uint8_t*)h.data(), &my->ctx ); + return h; + } + void sha256::encoder::reset() { + SHA256_Init( &my->ctx); + } + + sha256 operator << ( const sha256& h1, uint32_t i ) { + sha256 result; + uint8_t* r = (uint8_t*)result._hash; + uint8_t* s = (uint8_t*)h1._hash; + for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p ) + r[p] = s[p] << i | (s[p+1]>>(8-i)); + r[31] = s[31] << i; + return result; + } + sha256 operator ^ ( const sha256& h1, const sha256& h2 ) { + sha256 result; + result._hash[0] = h1._hash[0] ^ h2._hash[0]; + result._hash[1] = h1._hash[1] ^ h2._hash[1]; + result._hash[2] = h1._hash[2] ^ h2._hash[2]; + result._hash[3] = h1._hash[3] ^ h2._hash[3]; + return result; + } + bool operator >= ( const sha256& h1, const sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) >= 0; + } + bool operator > ( const sha256& h1, const sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0; + } + bool operator < ( const sha256& h1, const sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0; + } + bool operator != ( const sha256& h1, const sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0; + } + bool operator == ( const sha256& h1, const sha256& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0; + } + + void to_variant( const sha256& bi, variant& v ) + { + v = fc::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ); + } + void from_variant( const variant& v, sha256& bi ) + { + fc::vector ve = v.as< vector >(); + if( ve.size() ) + { + memcpy(&bi, ve.data(), fc::min(ve.size(),sizeof(bi)) ); + } + else + memset( &bi, char(0), sizeof(bi) ); + } +} diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp new file mode 100644 index 0000000..0c598c5 --- /dev/null +++ b/src/crypto/sha512.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include + +namespace fc { + + sha512::sha512() { memset( _hash, 0, sizeof(_hash) ); } + sha512::sha512( const string& hex_str ) { + fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) ); + } + + string sha512::str()const { + return fc::to_hex( (char*)_hash, sizeof(_hash) ); + } + sha512::operator string()const { return str(); } + + char* sha512::data()const { return (char*)&_hash[0]; } + + + struct sha512::encoder::impl { + SHA512_CTX ctx; + }; + + sha512::encoder::~encoder() {} + sha512::encoder::encoder() { + reset(); + } + + sha512 sha512::hash( const char* d, uint32_t dlen ) { + encoder e; + e.write(d,dlen); + return e.result(); + } + sha512 sha512::hash( const string& s ) { + return hash( s.c_str(), s.size() ); + } + + void sha512::encoder::write( const char* d, uint32_t dlen ) { + SHA512_Update( &my->ctx, d, dlen); + } + sha512 sha512::encoder::result() { + sha512 h; + SHA512_Final((uint8_t*)h.data(), &my->ctx ); + return h; + } + void sha512::encoder::reset() { + SHA512_Init( &my->ctx); + } + + sha512 operator << ( const sha512& h1, uint32_t i ) { + sha512 result; + uint8_t* r = (uint8_t*)result._hash; + uint8_t* s = (uint8_t*)h1._hash; + for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p ) + r[p] = s[p] << i | (s[p+1]>>(8-i)); + r[63] = s[63] << i; + return result; + } + sha512 operator ^ ( const sha512& h1, const sha512& h2 ) { + sha512 result; + result._hash[0] = h1._hash[0] ^ h2._hash[0]; + result._hash[1] = h1._hash[1] ^ h2._hash[1]; + result._hash[2] = h1._hash[2] ^ h2._hash[2]; + result._hash[3] = h1._hash[3] ^ h2._hash[3]; + result._hash[4] = h1._hash[4] ^ h2._hash[4]; + result._hash[5] = h1._hash[5] ^ h2._hash[5]; + result._hash[6] = h1._hash[6] ^ h2._hash[6]; + result._hash[7] = h1._hash[7] ^ h2._hash[7]; + return result; + } + bool operator >= ( const sha512& h1, const sha512& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) >= 0; + } + bool operator > ( const sha512& h1, const sha512& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0; + } + bool operator < ( const sha512& h1, const sha512& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0; + } + bool operator != ( const sha512& h1, const sha512& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0; + } + bool operator == ( const sha512& h1, const sha512& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0; + } + + void to_variant( const sha512& bi, variant& v ) + { + v = fc::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ); + } + void from_variant( const variant& v, sha512& bi ) + { + fc::vector ve = v.as< vector >(); + if( ve.size() ) + { + memcpy(&bi, ve.data(), fc::min(ve.size(),sizeof(bi)) ); + } + else + memset( &bi, char(0), sizeof(bi) ); + } +} diff --git a/src/error_report.cpp b/src/error_report.cpp deleted file mode 100644 index a6ac843..0000000 --- a/src/error_report.cpp +++ /dev/null @@ -1,189 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -namespace fc { - -error_frame::error_frame( const fc::string& f, uint64_t l, const fc::string& m, const fc::string& d, fc::value met ) -:desc(d),file(fc::path(f).filename().generic_string()),line(l),method(m),meta(fc::move(met)),time(fc::time_point::now()),detail(false){} - -error_frame::error_frame( bool is_detail, const fc::string& f, uint64_t l, const fc::string& m, const fc::string& d, fc::value met ) -:desc(d),file(fc::path(f).filename().generic_string()),line(l),method(m),meta(fc::move(met)),time(fc::time_point::now()),detail(is_detail){} -error_report::error_report() -{ -} -error_frame::error_frame(const fc::error_frame& e) -:desc(e.desc),file(e.file),line(e.line),method(e.method),meta(e.meta),time(e.time),detail(e.detail){} - -error_frame::error_frame(fc::error_frame&& e) -:desc(fc::move(e.desc)), - file(fc::move(e.file)), - line(e.line), - method(fc::move(e.method)), - meta(fc::move(e.meta)), - time(e.time), - detail(e.detail) - {} - -fc::error_frame& fc::error_frame::operator=(const fc::error_frame& f ) { - auto tmp = f; - fc_swap( tmp, *this ); - return *this; -} -fc::error_frame& fc::error_frame::operator=(fc::error_frame&& e ) -{ - desc=fc::move(e.desc); - file=fc::move(e.file); - line=fc::move(e.line); - method=fc::move(e.method); - time=e.time; - meta=fc::move(e.meta); - detail = e.detail; - return *this; -} - -error_report::error_report( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta ) -{ - push_frame( file, line, method, desc, meta ); -} - - -fc::error_frame& error_report::current() -{ - if( !stack.size() ) stack.resize(1); - return stack.back(); -} - -fc::error_report& error_report::pop_frame() -{ - stack.pop_back(); - return *this; -} - -fc::error_report& error_report::push_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta ) -{ - stack.push_back( fc::error_frame( file, line, method, desc, meta ) ); - return *this; -} -fc::error_report& error_report::push_frame( bool detail, const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta ) -{ - stack.push_back( fc::error_frame( detail, file, line, method, desc, meta ) ); - return *this; -} - -fc::error_report& error_report::append( const error_report& e ) -{ - // TODO: what to do about the 'failure...?' - stack.reserve( stack.size()+e.stack.size()); - for( uint32_t i = 0; i < e.stack.size(); ++i ) { - stack.push_back( e.stack[i] ); - } - return *this; -} - -fc::string error_frame::to_detail_string()const { - fc::stringstream ss; - ss << to_string() << "\n\t"; - ss << file << ":" << line << "\t"<val.is_string() ) { - ss<val.cast(); - } else { - ss << fc::json::to_string( itr->val ); - } - } else { - ss << "${"<(), keys ); - } - else if( in.is_object() ) { - for( auto itr = in.begin(); itr != in.end(); ++itr ) { - out[fc::substitute(itr->key, keys)] = recursive_substitute( itr->val, keys ); - } - return out; - } - else if( in.is_array() ) { - for( size_t i = 0; i < in.size(); ++i ) { - out.push_back( recursive_substitute( in[i], keys ) ); - } - } - return in; -} - -fc::string error_report::to_string()const { - fc::stringstream ss; - for( uint32_t i = 0; i < stack.size(); ++i ) { - ss << stack[i].to_string() << "\n"; - } - return ss.str(); -} -fc::string error_report::to_detail_string()const { - fc::stringstream ss; - for( uint32_t i = 0; i < stack.size(); ++i ) { - ss << stack[i].to_detail_string() << "\n"; - } - return ss.str(); -} -fc::exception_ptr error_report::copy_exception() { - return boost::copy_exception(*this); -} - -} // namespace fc diff --git a/src/exception.cpp b/src/exception.cpp index 9b1f64d..b0bcde7 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -1,109 +1,344 @@ -#include -#include +#include #include -#include -#include +#include +#include +#include -namespace fc { - #define bexcept void* e = &my[0]; (*((boost::exception_ptr*)e)) - #define cbexcept const void* e = &my[0]; (*((const boost::exception_ptr*)e)) +namespace fc +{ + namespace detail + { + enum exception_code + { + unspecified_exception_code = 0, ///< for exceptions we threw that don't have an assigned code + unhandled_exception_code = 1, ///< for unhandled 3rd party exceptions + timeout_exception_code = 2, ///< timeout exceptions + file_not_found_exception_code = 3, + parse_error_exception_code = 4, + invalid_arg_exception_code = 5, + key_not_found_exception_code = 6, + bad_cast_exception_code = 7, + out_of_range_exception_code = 8, + canceled_exception_code = 9, + assert_exception_code = 10, + eof_exception_code = 11, + std_exception_code = 12, + }; - exception_ptr::exception_ptr() { - new (&my[0]) boost::exception_ptr(); - } - exception_ptr::exception_ptr( const boost::exception_ptr& c ){ - static_assert( sizeof(my) >= sizeof(c), "boost::exception_ptr is larger than space reserved for it" ); - new (&my[0]) boost::exception_ptr(c); - } - exception_ptr::exception_ptr( boost::exception_ptr&& c ){ - new (&my[0]) boost::exception_ptr(fc::move(c)); - } - exception_ptr::exception_ptr( const exception_ptr& c ){ - new (&my[0]) boost::exception_ptr(c); - } - exception_ptr::exception_ptr( exception_ptr&& c ){ - new (&my[0]) boost::exception_ptr(fc::move(c)); - } - exception_ptr::~exception_ptr(){ - bexcept.~exception_ptr(); - } - exception_ptr& exception_ptr::operator=(const boost::exception_ptr& c){ - bexcept = c; - return *this; - } - exception_ptr& exception_ptr::operator=(boost::exception_ptr&& c){ - bexcept = fc::move(c); - return *this; - } + void to_variant( detail::exception_code e, variant& v ) + { + switch( e ) + { + case unhandled_exception_code: + v = "unhandled"; + break; + case timeout_exception_code: + v = "timeout"; + break; + case key_not_found_exception_code: + v = "invalid_key"; + break; + case bad_cast_exception_code: + v = "bad_cast"; + break; + case file_not_found_exception_code: + v = "file_not_found"; + break; + case parse_error_exception_code: + v = "parse_error"; + break; + case invalid_arg_exception_code: + v = "invalid_arg"; + break; + case out_of_range_exception_code: + v = "out_of_range"; + break; + case canceled_exception_code: + v = "canceled"; + break; + case assert_exception_code: + v = "assert"; + break; + case std_exception_code: + v = "std"; + break; + case eof_exception_code: + v = "eof"; + break; + case unspecified_exception_code: + default: + v = "unspecified"; + break; + + } + } + void from_variant( const variant& e, detail::exception_code& ll ) + { + string v = e.as_string(); + if( v == "unspecified" ) ll = unspecified_exception_code; + else if( v == "unhandled" ) ll = unhandled_exception_code; + else if( v == "timeout" ) ll = timeout_exception_code; + else if( v == "key_not_found" ) ll = key_not_found_exception_code; + else if( v == "bad_cast" ) ll = bad_cast_exception_code; + else if( v == "file_not_found" ) ll = file_not_found_exception_code; + else if( v == "parse_error" ) ll = parse_error_exception_code; + else if( v == "invalid_arg" ) ll = invalid_arg_exception_code; + else if( v == "out_of_range" ) ll = out_of_range_exception_code; + else if( v == "canceled" ) ll = canceled_exception_code; + else if( v == "assert" ) ll = assert_exception_code; + else if( v == "std" ) ll = std_exception_code; + else if( v == "eof" ) ll = eof_exception_code; + else FC_THROW_EXCEPTION( bad_cast_exception, + "Invalid Error Report _code '${code}'", + ("code", v) ); + } - exception_ptr& exception_ptr::operator=(const exception_ptr& c){ - bexcept = c; - return *this; - } - exception_ptr& exception_ptr::operator=(exception_ptr&& c){ - bexcept = fc::move(c); - return *this; - } + class exception_impl + { + public: + exception_code _ecode; + log_messages _elog; + variant _props; + }; + } - fc::string exception_ptr::diagnostic_information()const{ - const void* e = &my[0]; - return boost::diagnostic_information( *((const boost::exception_ptr*)e) ).c_str(); - } + std_exception::std_exception( log_message&& m, std::exception_ptr e, const char* w ) + :unhandled_exception( fc::move(m), e ) + { + my->_ecode = detail::std_exception_code; + _what = w; + } + std_exception::std_exception( const exception& e ) + :unhandled_exception(e) + { + from_variant( my->_props ); + } - exception_ptr::operator const boost::exception_ptr& ()const{ - const void* e = &my[0]; - return (*((const boost::exception_ptr*)e)); - } - exception_ptr::operator boost::exception_ptr& (){ - void* e = &my[0]; - return (*((boost::exception_ptr*)e)); - } + std_exception::std_exception( log_messages m ) + :unhandled_exception(fc::move(m) ) + { + my->_ecode = detail::std_exception_code; + } - exception_ptr current_exception() { - return boost::current_exception(); - } - void rethrow_exception( const exception_ptr& e ) { - boost::rethrow_exception( static_cast(e) ); - } - exception_ptr::operator bool()const { - const void* e = &my[0]; - return (*((boost::exception_ptr*)e)); - } + void std_exception::from_variant( const variant& v ) + { + _what = v.get_object()["what"].as_string(); + } + void std_exception::to_variant( variant& v ) + { + v = variant_object( "what", _what ); + } - fc::string to_string( char v ) { return fc::string(&v,1); } - fc::string to_string( uint64_t v ) { return fc::lexical_cast(v).c_str(); } - fc::string to_string( int64_t v ){ return fc::lexical_cast(v).c_str(); } - fc::string to_string( double v ){ return fc::lexical_cast(v).c_str(); } - fc::string to_string( float v ){ return fc::lexical_cast(v).c_str(); } - fc::string to_string( int32_t v ){ return fc::lexical_cast(v).c_str(); } - fc::string to_string( uint32_t v ){ return fc::lexical_cast(v).c_str(); } - fc::string to_string( int16_t v ){ return fc::lexical_cast(v).c_str(); } - fc::string to_string( uint16_t v ){ return fc::lexical_cast(v).c_str(); } -// fc::string to_string( size_t v ){ return fc::lexical_cast(v).c_str(); } - //fc::string to_string( long int v ){ return fc::lexical_cast(v).c_str(); } + unhandled_exception::unhandled_exception( log_message&& m, std::exception_ptr e ) + :exception( fc::move(m) ) + { + my->_ecode = detail::unhandled_exception_code; + _inner = e; + } + unhandled_exception::unhandled_exception( const exception& r ) + :exception(r) + { + } + unhandled_exception::unhandled_exception( log_messages m ) + :exception() + { my->_elog = fc::move(m); + my->_ecode = detail::unhandled_exception_code; + } + std::exception_ptr unhandled_exception::get_inner_exception()const { return _inner; } + NO_RETURN void unhandled_exception::dynamic_rethrow_exception()const + { + if( !(_inner == std::exception_ptr()) ) std::rethrow_exception( _inner ); + else { fc::exception::dynamic_rethrow_exception(); } + } + std::shared_ptr unhandled_exception::dynamic_copy_exception()const + { + auto e = std::make_shared( *this ); + e->_inner = _inner; + return e; + } - void throw_exception( const char* func, const char* file, int line, const char* msg ) { - ::boost::exception_detail::throw_exception_(fc::generic_exception(msg),func, file, line ); - } - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1 ) { - ::boost::exception_detail::throw_exception_(fc::generic_exception( (boost::format(msg) % a1.c_str() ).str().c_str()) ,func, file, line ); - } - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1, const fc::string& a2 ) { - ::boost::exception_detail::throw_exception_(fc::generic_exception( (boost::format(msg) % a1.c_str() %a2.c_str()).str().c_str()),func, file, line ); - } - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1, const fc::string& a2, const fc::string& a3 ) { - ::boost::exception_detail::throw_exception_(fc::generic_exception(msg),func, file, line ); - } - void throw_exception_( const char* func, const char* file, int line, const char* msg, - const fc::string& a1, const fc::string& a2, const fc::string& a3, const fc::string& a4 ) { - ::boost::exception_detail::throw_exception_(fc::generic_exception(msg),func, file, line ); - } - fc::string except_str() { return boost::current_exception_diagnostic_information(); }//boost::current_exception_diagonstic_information(); } - //fc::current_exception().diagnostic_information(); } +#define FC_EXCEPTION_IMPL( TYPE ) \ + TYPE::TYPE( log_message&& m ) \ + :exception( fc::move(m) ) { my->_ecode = detail::TYPE ##_code; } \ + TYPE::TYPE(){ my->_ecode = detail::TYPE ##_code; } \ + TYPE::TYPE(const TYPE& t):exception(t){} \ + TYPE::TYPE( log_messages m ) \ + :exception() { my->_elog = fc::move(m); my->_ecode = detail::TYPE ##_code; } -} + FC_EXCEPTION_IMPL(timeout_exception) + FC_EXCEPTION_IMPL(file_not_found_exception) + FC_EXCEPTION_IMPL(parse_error_exception) + FC_EXCEPTION_IMPL(invalid_arg_exception) + FC_EXCEPTION_IMPL(key_not_found_exception) + FC_EXCEPTION_IMPL(bad_cast_exception) + FC_EXCEPTION_IMPL(out_of_range_exception) + FC_EXCEPTION_IMPL(canceled_exception) + FC_EXCEPTION_IMPL(assert_exception) + FC_EXCEPTION_IMPL(eof_exception) + + + + exception::exception() + :my( new detail::exception_impl() ) + { + my->_ecode = detail::unspecified_exception_code; + } + + exception::exception( log_message&& msg) + :my( new detail::exception_impl() ) + { + my->_ecode = detail::unspecified_exception_code; + my->_elog.push_back( fc::move( msg ) ); + } + exception::exception( const exception& c ) + :my( new detail::exception_impl(*c.my) ) + { + } + exception::exception( exception&& c ) + :my( fc::move(c.my) ){} + + exception::~exception(){} + + + void to_variant( const exception& e, variant& v ) + { + v = mutable_variant_object( "stack", e.my->_elog ) + ( "type", e.my->_ecode) + ( "props", e.my->_props ); + } + void from_variant( const variant& v, exception& ll ) + { + auto obj = v.get_object(); + ll.my->_elog = obj["stack"].as(); + ll.my->_ecode = obj["type"].as(); + ll.my->_props = obj["props"]; + } + + const log_messages& exception::get_log()const { return my->_elog; } + void exception::append_log( log_message m ) + { + my->_elog.push_back( fc::move(m) ); + } + + /** + * Generates a detailed string including file, line, method, + * and other information that is generally only useful for + * developers. + */ + string exception::to_detail_string( log_level ll )const + { + fc::stringstream ss; + ss << variant(my->_ecode).as_string() <<"\n"; + for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) + { + ss << itr->get_message() <<"\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; + ss << " " << json::to_string( itr->get_data() )<<"\n"; + ss << " " << itr->get_context().to_string(); + ++itr; + if( itr != my->_elog.end() ) ss<<"\n"; + } + return ss.str(); + } + + /** + * Generates a user-friendly error report. + */ + string exception::to_string( log_level ll )const + { + fc::stringstream ss; + ss << what() << "(" << variant(my->_ecode).as_string() <<")\n"; + for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) + { + ss << fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; + // ss << " " << itr->get_context().to_string() <<"\n"; + } + return ss.str(); + } + + /** + * Rethrows the exception restoring the proper type based upon + * the error code. This is used to propagate exception types + * across conversions to/from JSON + */ + NO_RETURN void exception::dynamic_rethrow_exception()const + { + switch( my->_ecode ) + { + case detail::unhandled_exception_code: + throw unhandled_exception( my->_elog ); + case detail::timeout_exception_code: + throw timeout_exception( my->_elog ); + case detail::key_not_found_exception_code: + throw key_not_found_exception( my->_elog ); + case detail::bad_cast_exception_code: + throw bad_cast_exception( my->_elog ); + case detail::parse_error_exception_code: + throw parse_error_exception( my->_elog ); + case detail::canceled_exception_code: + throw canceled_exception( my->_elog); + case detail::assert_exception_code: + throw assert_exception( my->_elog ); + case detail::file_not_found_exception_code: + throw file_not_found_exception( my->_elog ); + case detail::invalid_arg_exception_code: + throw invalid_arg_exception( my->_elog ); + case detail::out_of_range_exception_code: + throw out_of_range_exception( my->_elog ); + case detail::eof_exception_code: + throw eof_exception( my->_elog ); + case detail::std_exception_code: + throw std_exception( *this ); + case detail::unspecified_exception_code: + default: + throw fc::exception(*this); + } + } + exception_ptr exception::dynamic_copy_exception()const + { + switch( my->_ecode ) + { + case detail::unhandled_exception_code: + return std::make_shared( my->_elog ); + case detail::timeout_exception_code: + return std::make_shared( my->_elog ); + case detail::key_not_found_exception_code: + return std::make_shared( my->_elog ); + case detail::bad_cast_exception_code: + return std::make_shared( my->_elog ); + case detail::parse_error_exception_code: + return std::make_shared( my->_elog ); + case detail::canceled_exception_code: + return std::make_shared( my->_elog); + case detail::assert_exception_code: + return std::make_shared( my->_elog ); + case detail::file_not_found_exception_code: + return std::make_shared( my->_elog ); + case detail::invalid_arg_exception_code: + return std::make_shared( my->_elog ); + case detail::out_of_range_exception_code: + return std::make_shared( my->_elog ); + case detail::eof_exception_code: + return std::make_shared( my->_elog ); + case detail::std_exception_code: + return std::make_shared( *this ); + case detail::unspecified_exception_code: + default: + return std::make_shared(*this); + } + } + fc::string except_str() + { + return boost::current_exception_diagnostic_information(); + } + void throw_bad_enum_cast( int64_t i, const char* e ) + { + FC_THROW_EXCEPTION( bad_cast_exception, "invalid index '${key}' in enum '${enum}'", ("key",i)("enum",e) ); + } + void throw_bad_enum_cast( const char* k, const char* e ) + { + FC_THROW_EXCEPTION( bad_cast_exception, "invalid name '${key}' in enum '${enum}'", ("key",k)("enum",e) ); + } + +} // fc diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 6980572..972b66a 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -1,20 +1,24 @@ //#define BOOST_NO_SCOPED_ENUMS #include +#include #include #include +#include #include #include -#include -#include +#include namespace fc { - void pack( fc::value& v, const fc::path& s ) { - v = s.generic_string(); + void to_variant( const fc::path& t, variant& v ) { + v = t.generic_string(); } - void unpack( const fc::value& v, fc::path& s ) { - s = path(fc::value_cast(v)); + void from_variant( const fc::variant& v, fc::path& t ) { + t = fc::path(v.as_string()); } + // Note: we can do this cast because the separator should be an ASCII character + char path::separator_char = static_cast(boost::filesystem::path("/").make_preferred().native()[0]); + path::path(){} path::~path(){}; path::path( const boost::filesystem::path& p ) @@ -69,7 +73,7 @@ namespace fc { */ fc::string path::windows_string()const { auto gs = _p->generic_string(); - for( int i =0 ; i < gs.size(); ++i ) { + for( size_t i =0 ; i < gs.size(); ++i ) { if( gs[i] == '/' ) gs[i] = '\\'; } return gs; @@ -140,59 +144,161 @@ namespace fc { try { boost::filesystem::create_directories(p); } catch ( ... ) { - FC_THROW_REPORT( "Unable to create directories ${path}", fc::value().set("path", p ).set("inner", fc::except_str() ) ); + FC_THROW( "Unable to create directories ${path}", ("path", p )("inner", fc::except_str() ) ); } } bool is_directory( const path& p ) { return boost::filesystem::is_directory(p); } bool is_regular_file( const path& p ) { return boost::filesystem::is_regular_file(p); } uint64_t file_size( const path& p ) { return boost::filesystem::file_size(p); } void remove_all( const path& p ) { boost::filesystem::remove_all(p); } - void rename( const path& f, const path& t ) { - try { - boost::filesystem::rename( boost::filesystem::path(f), boost::filesystem::path(t) ); - } catch ( boost::system::system_error& e ) { - FC_THROW_REPORT( "Rename from ${srcfile} to ${dstfile} failed because ${reason}", - fc::value().set("srcfile",f).set("dstfile",t).set("reason",e.what() ) ); - } catch ( ... ) { - FC_THROW_REPORT( "Rename from ${srcfile} to ${dstfile} failed", - fc::value().set("srcfile",f).set("dstfile",t).set("inner", fc::except_str() ) ); - } - } void copy( const path& f, const path& t ) { try { boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) ); } catch ( boost::system::system_error& e ) { - FC_THROW_REPORT( "Copy from ${srcfile} to ${dstfile} failed because ${reason}", - fc::value().set("srcfile",f).set("dstfile",t).set("reason",e.what() ) ); + FC_THROW( "Copy from ${srcfile} to ${dstfile} failed because ${reason}", + ("srcfile",f)("dstfile",t)("reason",e.what() ) ); } catch ( ... ) { - FC_THROW_REPORT( "Copy from ${srcfile} to ${dstfile} failed", - fc::value().set("srcfile",f).set("dstfile",t).set("inner", fc::except_str() ) ); + FC_THROW( "Copy from ${srcfile} to ${dstfile} failed", + ("srcfile",f)("dstfile",t)("inner", fc::except_str() ) ); + } + } + void rename( const path& f, const path& t ) { + try { + boost::filesystem::rename( boost::filesystem::path(f), boost::filesystem::path(t) ); + } catch ( boost::system::system_error& e ) { + FC_THROW( "Rename from ${srcfile} to ${dstfile} failed because ${reason}", + ("srcfile",f)("dstfile",t)("reason",e.what() ) ); + } catch ( ... ) { + FC_THROW( "Rename from ${srcfile} to ${dstfile} failed", + ("srcfile",f)("dstfile",t)("inner", fc::except_str() ) ); } } void create_hard_link( const path& f, const path& t ) { try { boost::filesystem::create_hard_link( f, t ); } catch ( ... ) { - FC_THROW_REPORT( "Unable to create hard link from '${from}' to '${to}'", - fc::value().set( "from", f ) - .set("to",t).set("exception", fc::except_str() ) ); + FC_THROW( "Unable to create hard link from '${from}' to '${to}'", + ( "from", f )("to",t)("exception", fc::except_str() ) ); } } bool remove( const path& f ) { try { return boost::filesystem::remove( f ); } catch ( ... ) { - FC_THROW_REPORT( "Unable to remove '${path}'", fc::value().set( "path", f ).set("exception", fc::except_str() ) ); + FC_THROW( "Unable to remove '${path}'", ( "path", f )("exception", fc::except_str() ) ); } } fc::path canonical( const fc::path& p ) { try { return boost::filesystem::canonical(p); } catch ( ... ) { - FC_THROW_REPORT( "Unable to resolve path '${path}'", fc::value().set( "path", p ).set("exception", fc::except_str() ) ); + FC_THROW( "Unable to resolve path '${path}'", ( "path", p )("exception", fc::except_str() ) ); } } fc::path absolute( const fc::path& p ) { return boost::filesystem::absolute(p); } path unique_path() { return boost::filesystem::unique_path(); } path temp_directory_path() { return boost::filesystem::temp_directory_path(); } + + // Return path when appended to a_From will resolve to same as a_To + fc::path make_relative(const fc::path& from, const fc::path& to) { + boost::filesystem::path a_From = boost::filesystem::absolute(from); + boost::filesystem::path a_To = boost::filesystem::absolute(to); + boost::filesystem::path ret; + boost::filesystem::path::const_iterator itrFrom(a_From.begin()), itrTo(a_To.begin()); + // Find common base + for( boost::filesystem::path::const_iterator toEnd( a_To.end() ), fromEnd( a_From.end() ) ; itrFrom != fromEnd && itrTo != toEnd && *itrFrom == *itrTo; ++itrFrom, ++itrTo ); + // Navigate backwards in directory to reach previously found base + for( boost::filesystem::path::const_iterator fromEnd( a_From.end() ); itrFrom != fromEnd; ++itrFrom ) { + if( (*itrFrom) != "." ) + ret /= ".."; + } + // Now navigate down the directory branch + for (; itrTo != a_To.end(); ++itrTo) + ret /= *itrTo; + return ret; + } + + temp_file::temp_file(const fc::path& p, bool create) + : temp_file_base(p / fc::unique_path()) + { + if (fc::exists(*_path)) + { + FC_THROW( "Name collision: ${path}", ("path", _path->string()) ); + } + if (create) + { + fc::ofstream ofs(*_path, fc::ofstream::out | fc::ofstream::binary); + ofs.close(); + } + } + + temp_file::temp_file(temp_file&& other) + : temp_file_base(std::move(other._path)) + { + } + + temp_file& temp_file::operator=(temp_file&& other) + { + if (this != &other) + { + remove(); + _path = std::move(other._path); + } + return *this; + } + + temp_directory::temp_directory(const fc::path& p) + : temp_file_base(p / fc::unique_path()) + { + if (fc::exists(*_path)) + { + FC_THROW( "Name collision: ${path}", ("path", _path->string()) ); + } + fc::create_directories(*_path); + } + + temp_directory::temp_directory(temp_directory&& other) + : temp_file_base(std::move(other._path)) + { + } + + temp_directory& temp_directory::operator=(temp_directory&& other) + { + if (this != &other) + { + remove(); + _path = std::move(other._path); + } + return *this; + } + + const fc::path& temp_file_base::path() const + { + if (!_path) + { + FC_THROW( "Temporary directory has been released." ); + } + return *_path; + } + + void temp_file_base::remove() + { + if (_path) + { + try + { + fc::remove_all(*_path); + } + catch (...) + { + // eat errors on cleanup + } + release(); + } + } + + void temp_file_base::release() + { + _path = fc::optional(); + } } diff --git a/src/file_mapping.cpp b/src/interprocess/file_mapping.cpp similarity index 96% rename from src/file_mapping.cpp rename to src/interprocess/file_mapping.cpp index 0d68fb8..7ff557a 100644 --- a/src/file_mapping.cpp +++ b/src/interprocess/file_mapping.cpp @@ -10,7 +10,7 @@ namespace fc { - mapped_region::mapped_region( const file_mapping& fm, mode_t m, size_t start, size_t size ) + mapped_region::mapped_region( const file_mapping& fm, mode_t m, uint64_t start, size_t size ) :my( *fm.my, m == read_only ? boost::interprocess::read_only : boost::interprocess::read_write ,start, size) { } mapped_region::mapped_region( const file_mapping& fm, mode_t m ) :my( *fm.my, m == read_only ? boost::interprocess::read_only : boost::interprocess::read_write) { } diff --git a/src/interprocess/process.cpp b/src/interprocess/process.cpp new file mode 100644 index 0000000..55a5e6c --- /dev/null +++ b/src/interprocess/process.cpp @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc { + namespace bp = boost::process; + namespace io = boost::iostreams; + +fc::path find_executable_in_path( const fc::string name ) { + try { + return fc::string(bp::find_executable_in_path( std::string(name), "" )); + } catch (...) { + const char* p = std::getenv("PATH"); + FC_THROW( "Unable to find executable ${exe} in path.", + ("exe", name) + ("inner", fc::except_str() ) + ("PATH", fc::string(p!=nullptr?p:"") ) ); + } + return fc::path(); +} + + +class process::impl +{ + public: + impl() + :stat( fc::asio::default_io_service() ){} + + ~impl() + { + try + { + if( _in ) + { + _in->close(); + } + if( _exited.valid() && !_exited.ready()) + { + //child->terminate(); + _exited.wait(); + } + } + catch(...) + { + wlog( "caught exception cleaning up process: ${except_str}", ("except_str",fc::except_str()) ); + } + } + + std::shared_ptr child; + + std::shared_ptr _inp; + std::shared_ptr _outp; + std::shared_ptr _errp; + + buffered_istream_ptr _out; + buffered_istream_ptr _err; + buffered_ostream_ptr _in; + + bp::status stat; + bp::context pctx; + + fc::future _exited; +}; + +process::process() +:my( new process::impl() ){} +process::~process(){} + +iprocess& process::exec( const fc::path& exe, + fc::vector args, + const fc::path& work_dir, exec_opts opt ) +{ + + my->pctx.work_dir = work_dir.string(); + + if( opt&open_stdout) + my->pctx.streams[boost::process::stdout_id] = bp::behavior::async_pipe(); + else + my->pctx.streams[boost::process::stdout_id] = bp::behavior::null(); + + + if( opt& open_stderr ) + my->pctx.streams[boost::process::stderr_id] = bp::behavior::async_pipe(); + else + my->pctx.streams[boost::process::stderr_id] = bp::behavior::null(); + + if( opt& open_stdin ) + my->pctx.streams[boost::process::stdin_id] = bp::behavior::async_pipe(); + else + my->pctx.streams[boost::process::stdin_id] = bp::behavior::close(); + + std::vector a; + a.reserve(size_t(args.size())); + for( uint32_t i = 0; i < args.size(); ++i ) { + a.push_back( fc::move(args[i]) ); + } + my->child.reset( new bp::child( bp::create_child( exe.string(), fc::move(a), my->pctx ) ) ); + + if( opt & open_stdout ) { + bp::handle outh = my->child->get_handle( bp::stdout_id ); + my->_outp.reset( new bp::pipe( fc::asio::default_io_service(), outh.release() ) ); + } + if( opt & open_stderr ) { + bp::handle errh = my->child->get_handle( bp::stderr_id ); + my->_errp.reset( new bp::pipe( fc::asio::default_io_service(), errh.release() ) ); + } + if( opt & open_stdin ) { + bp::handle inh = my->child->get_handle( bp::stdin_id ); + my->_inp.reset( new bp::pipe( fc::asio::default_io_service(), inh.release() ) ); + } + + + promise::ptr p(new promise("process")); + my->stat.async_wait( my->child->get_id(), [=]( const boost::system::error_code& ec, int exit_code ) + { + //slog( "process::result %d", exit_code ); + if( !ec ) { + #ifdef BOOST_POSIX_API + if( WIFEXITED(exit_code) ) p->set_value( WEXITSTATUS(exit_code) ); + else + { + p->set_exception( + fc::exception_ptr( new fc::exception( + FC_LOG_MESSAGE( error, "process exited with: ${message} ", + ("message", strsignal(WTERMSIG(exit_code))) ) ) ) ); + } + #else + p->set_value(exit_code); + #endif + } + else + { + p->set_exception( + fc::exception_ptr( new fc::exception( + FC_LOG_MESSAGE( error, "process exited with: ${message} ", + ("message", boost::system::system_error(ec).what())) ) ) ); + } + }); + my->_in = std::make_shared(std::make_shared>(my->_inp)); + my->_out = std::make_shared(std::make_shared>(my->_outp)); + my->_err = std::make_shared(std::make_shared>(my->_errp)); + my->_exited = p; + return *this; +} + +/** + * Forcefully kills the process. + */ +void process::kill() { + my->child->terminate(); +} + +/** + * @brief returns a stream that writes to the process' stdin + */ +fc::buffered_ostream_ptr process::in_stream() { + return my->_in; +} + +/** + * @brief returns a stream that reads from the process' stdout + */ +fc::buffered_istream_ptr process::out_stream() { + return my->_out; +} +/** + * @brief returns a stream that reads from the process' stderr + */ +fc::buffered_istream_ptr process::err_stream() { + return my->_err; +} + +int process::result() +{ + return my->_exited.wait(); +} + +} diff --git a/src/io/buffered_iostream.cpp b/src/io/buffered_iostream.cpp new file mode 100644 index 0000000..d6cf1f9 --- /dev/null +++ b/src/io/buffered_iostream.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include + +#include + +namespace fc +{ + namespace detail + { + class buffered_istream_impl + { + public: + buffered_istream_impl( istream_ptr is ) + :_istr(fc::move(is)){} + + istream_ptr _istr; + boost::asio::streambuf _rdbuf; + }; + static const size_t minimum_read_size = 1024; + } + + buffered_istream::buffered_istream( istream_ptr is ) + :my( new detail::buffered_istream_impl( fc::move(is) ) ) + { + FC_ASSERT( my->_istr != nullptr, " this shouldn't be null" ); + } + + buffered_istream::buffered_istream( buffered_istream&& o ) + :my( fc::move(o.my) ){} + + buffered_istream& buffered_istream::operator=( buffered_istream&& i ) + { + my = fc::move(i.my); + return *this; + } + + buffered_istream::~buffered_istream(){} + + size_t buffered_istream::readsome( char* buf, size_t len ) + { + size_t bytes_from_rdbuf = static_cast(my->_rdbuf.sgetn(buf, len)); + if (bytes_from_rdbuf) + return bytes_from_rdbuf; + + + if( len > detail::minimum_read_size ) + return my->_istr->readsome(buf,len); + + char tmp[detail::minimum_read_size]; + size_t bytes_read = my->_istr->readsome( tmp, detail::minimum_read_size ); + + size_t bytes_to_deliver_immediately = std::min(bytes_read,len); + + memcpy( buf, tmp, bytes_to_deliver_immediately ); + + + if( bytes_read > len ) + { + my->_rdbuf.sputn( tmp + len, bytes_read - len ); + } + + return bytes_to_deliver_immediately; + } + + char buffered_istream::peek()const + { + if( my->_rdbuf.size() ) + { + return my->_rdbuf.sgetc(); + } + + char tmp[detail::minimum_read_size]; + size_t bytes_read = my->_istr->readsome( tmp, detail::minimum_read_size ); + my->_rdbuf.sputn( tmp, bytes_read ); + + if( my->_rdbuf.size() ) + { + return my->_rdbuf.sgetc(); + } + FC_THROW_EXCEPTION( assert_exception, + "at least one byte should be available, or eof should have been thrown" ); + } + + + namespace detail + { + class buffered_ostream_impl + { + public: + buffered_ostream_impl( ostream_ptr os ) + :_ostr(fc::move(os)){} + + ostream_ptr _ostr; + boost::asio::streambuf _rdbuf; + }; + } + + buffered_ostream::buffered_ostream( ostream_ptr os, size_t bufsize ) + :my( new detail::buffered_ostream_impl( fc::move(os) ) ) + { + } + + buffered_ostream::buffered_ostream( buffered_ostream&& o ) + :my( fc::move(o.my) ){} + + buffered_ostream& buffered_ostream::operator=( buffered_ostream&& i ) + { + my = fc::move(i.my); + return *this; + } + + buffered_ostream::~buffered_ostream(){} + + size_t buffered_ostream::writesome( const char* buf, size_t len ) + { + size_t written = static_cast(my->_rdbuf.sputn( buf, len )); + if( written < len ) { flush(); } + return written + static_cast(my->_rdbuf.sputn( buf+written, len-written )); + } + + void buffered_ostream::flush() + { + char buffer[2048]; + while( size_t bytes_from_rdbuf = static_cast(my->_rdbuf.sgetn(buffer,sizeof(buffer))) ) + my->_ostr->write( buffer, bytes_from_rdbuf ); + my->_ostr->flush(); + } + + void buffered_ostream::close() + { + flush(); + my->_ostr->close(); + } + + +} diff --git a/src/io/datastream.cpp b/src/io/datastream.cpp new file mode 100644 index 0000000..da38e14 --- /dev/null +++ b/src/io/datastream.cpp @@ -0,0 +1,7 @@ +#include +#include + +NO_RETURN void fc::detail::throw_datastream_range_error(char const* method, size_t len, size_t over) +{ + FC_THROW_EXCEPTION( out_of_range_exception, "${method} datastream of length ${len} over by ${over}", ("method",fc::string(method))("len",len)("over",over) ); +} diff --git a/src/fstream.cpp b/src/io/fstream.cpp similarity index 73% rename from src/fstream.cpp rename to src/io/fstream.cpp index e927eed..0619fab 100644 --- a/src/fstream.cpp +++ b/src/io/fstream.cpp @@ -1,6 +1,9 @@ -#include +#include #include #include +#include +#include + namespace fc { class ofstream::impl : public fc::retainable { @@ -22,9 +25,9 @@ namespace fc { void ofstream::open( const fc::path& file, int m ) { my->ofs.open( file.string().c_str(), std::ios::binary ); } - ofstream& ofstream::write( const char* buf, size_t len ) { + size_t ofstream::writesome( const char* buf, size_t len ) { my->ofs.write(buf,len); - return *this; + return len; } void ofstream::put( char c ) { my->ofs.put(c); @@ -49,11 +52,19 @@ namespace fc { my->ifs.open( file.string().c_str(), std::ios::binary ); } size_t ifstream::readsome( char* buf, size_t len ) { - return size_t(my->ifs.readsome( buf, len )); + auto s = size_t(my->ifs.readsome( buf, len )); + if( s <= 0 ) { + read( buf, 1 ); + s = 1; + } + return s; } ifstream& ifstream::read( char* buf, size_t len ) { - my->ifs.read(buf,len); - return *this; + if( eof() ) FC_THROW_EXCEPTION( eof_exception , ""); + my->ifs.read(buf,len); + if (my->ifs.gcount() < int64_t(len)) + FC_THROW_EXCEPTION( eof_exception , ""); + return *this; } ifstream& ifstream::seekg( size_t p, seekdir d ) { switch( d ) { @@ -65,7 +76,7 @@ namespace fc { } void ifstream::close() { return my->ifs.close(); } - bool ifstream::eof()const { return my->ifs.eof(); } + bool ifstream::eof()const { return !my->ifs.good(); } } // namespace fc diff --git a/src/io/iostream.cpp b/src/io/iostream.cpp new file mode 100644 index 0000000..a0936d0 --- /dev/null +++ b/src/io/iostream.cpp @@ -0,0 +1,354 @@ +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc { + + struct cin_buffer { + cin_buffer():eof(false),write_pos(0),read_pos(0),cinthread("cin"){ + + cinthread.async( [=](){read();} ); + } + + void read() { + char c; + std::cin.read(&c,1); + while( !std::cin.eof() ) { + while( write_pos - read_pos > 0xfffff ) { + fc::promise::ptr wr( new fc::promise() ); + write_ready = wr; + if( write_pos - read_pos <= 0xfffff ) { + wr->wait(); + } + write_ready.reset(); + } + buf[write_pos&0xfffff] = c; + ++write_pos; + + fc::promise::ptr tmp; + { // copy read_ready because it is accessed from multiple threads + fc::scoped_lock lock( read_ready_mutex ); + tmp = read_ready; + } + + if( tmp && !tmp->ready() ) { + tmp->set_value(); + } + std::cin.read(&c,1); + } + eof = true; + fc::promise::ptr tmp; + { // copy read_ready because it is accessed from multiple threads + fc::scoped_lock lock( read_ready_mutex ); + tmp = read_ready; + } + if( tmp && !tmp->ready() ) { + tmp->set_exception( exception_ptr( new eof_exception() )); + } + } + boost::mutex read_ready_mutex; + fc::promise::ptr read_ready; + fc::promise::ptr write_ready; + + volatile bool eof; + + volatile uint64_t write_pos; + char buf[0xfffff+1]; // 1 mb buffer + volatile uint64_t read_pos; + fc::thread cinthread; + }; + + cin_buffer& get_cin_buffer() { + static cin_buffer* b = new cin_buffer(); + return *b; + } + + + fc::thread& cin_thread() { static fc::thread i("cin"); return i; } + + fc::istream& getline( fc::istream& i, fc::string& s, char delim ) { + fc::stringstream ss; + try + { + char c; + i.read( &c, 1 ); + while( true ) { + if( c == delim ) { s = ss.str(); return i; } + if( c != '\r' ) ss.write(&c,1); + i.read( &c, 1 ); + } + } catch ( fc::eof_exception& ) + { + } + s = ss.str(); + return i; + } + + + size_t cout_t::writesome( const char* buf, size_t len ) { std::cout.write(buf,len); return len; } + void cout_t::close() {} + void cout_t::flush() { std::cout.flush(); } + + size_t cerr_t::writesome( const char* buf, size_t len ) { std::cerr.write(buf,len); return len; } + void cerr_t::close() {}; + void cerr_t::flush() { std::cerr.flush(); } + + + size_t cin_t::readsome( char* buf, size_t len ) { + cin_buffer& b = get_cin_buffer(); + int64_t avail = b.write_pos - b.read_pos; + avail = (fc::min)(int64_t(len),avail); + int64_t u = 0; + + if( !((avail>0) && (len>0)) ) { + read( buf, 1 ); + ++buf; + ++u; + --len; + } + + while( (avail>0) && (len>0) ) { + *buf = b.buf[b.read_pos&0xfffff]; + ++b.read_pos; + ++buf; + --avail; + --len; + ++u; + } + return size_t(u); + } + + cin_t::~cin_t() { + /* + cin_buffer& b = get_cin_buffer(); + if( b.read_ready ) { + b.read_ready->wait(); + } + */ + } + istream& cin_t::read( char* buf, size_t len ) { + cin_buffer& b = get_cin_buffer(); + do { + while( !b.eof && (b.write_pos - b.read_pos)==0 ){ + // wait for more... + fc::promise::ptr rr( new fc::promise() ); + { // copy read_ready because it is accessed from multiple threads + fc::scoped_lock lock( b.read_ready_mutex ); + b.read_ready = rr; + } + if( b.write_pos - b.read_pos == 0 ) { + rr->wait(); + } + // b.read_ready.reset(); + { // copy read_ready because it is accessed from multiple threads + fc::scoped_lock lock( b.read_ready_mutex ); + b.read_ready.reset(); + } + } + if( b.eof ) FC_THROW_EXCEPTION( eof_exception, "cin" ); + size_t r = readsome( buf, len ); + buf += r; + len -= r; + + auto tmp = b.write_ready; // copy write_writey because it is accessed from multiple thwrites + if( tmp && !tmp->ready() ) { + tmp->set_value(); + } + } while( len > 0 && !b.eof ); + if( b.eof ) FC_THROW_EXCEPTION( eof_exception, "cin" ); + return *this; + } + + bool cin_t::eof()const { return get_cin_buffer().eof; } + + + std::shared_ptr cin_ptr = std::make_shared(); + std::shared_ptr cout_ptr = std::make_shared(); + std::shared_ptr cerr_ptr = std::make_shared(); + cout_t& cout = *cout_ptr; + cerr_t& cerr = *cerr_ptr; + cin_t& cin = *cin_ptr; + + + ostream& operator<<( ostream& o, const char v ) + { + o.write( &v, 1 ); + return o; + } + ostream& operator<<( ostream& o, const char* v ) + { + o.write( v, strlen(v) ); + return o; + } + + ostream& operator<<( ostream& o, const std::string& v ) + { + o.write( v.c_str(), v.size() ); + return o; + } + + ostream& operator<<( ostream& o, const fc::string& v ) + { + o.write( v.c_str(), v.size() ); + return o; + } + + ostream& operator<<( ostream& o, const double& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const float& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const int64_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const uint64_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const int32_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const uint32_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const int16_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const uint16_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const int8_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + + ostream& operator<<( ostream& o, const uint8_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + +#ifdef __APPLE__ + ostream& operator<<( ostream& o, const size_t& v ) + { + return o << boost::lexical_cast(v).c_str(); + } + +#endif + + istream& operator>>( istream& o, std::string& v ) + { + return o; + } + + istream& operator>>( istream& o, fc::string& v ) + { + return o; + } + + istream& operator>>( istream& o, char& v ) + { + o.read(&v,1); + return o; + } + + istream& operator>>( istream& o, double& v ) + { + return o; + } + + istream& operator>>( istream& o, float& v ) + { + return o; + } + + istream& operator>>( istream& o, int64_t& v ) + { + return o; + } + + istream& operator>>( istream& o, uint64_t& v ) + { + return o; + } + + istream& operator>>( istream& o, int32_t& v ) + { + return o; + } + + istream& operator>>( istream& o, uint32_t& v ) + { + return o; + } + + istream& operator>>( istream& o, int16_t& v ) + { + return o; + } + + istream& operator>>( istream& o, uint16_t& v ) + { + return o; + } + + istream& operator>>( istream& o, int8_t& v ) + { + return o; + } + + istream& operator>>( istream& o, uint8_t& v ) + { + return o; + } + + + char istream::get() + { + char tmp; + read(&tmp,1); + return tmp; + } + + istream& istream::read( char* buf, size_t len ) + { + auto pos = buf; + while( size_t(pos-buf) < len ) + pos += readsome( pos, len - (pos - buf) ); + return *this; + } + + ostream& ostream::write( const char* buf, size_t len ) + { + auto pos = buf; + while( size_t(pos-buf) < len ) + pos += writesome( pos, len - (pos - buf) ); + return *this; + } + +} diff --git a/src/io/json.cpp b/src/io/json.cpp new file mode 100644 index 0000000..c2fa1a8 --- /dev/null +++ b/src/io/json.cpp @@ -0,0 +1,483 @@ +#include +#include +#include +#include +#include +#include +#include +//#include + +namespace fc +{ + template + variant variant_from_stream( T& in ); + template + char parseEscape( T& in ) + { + if( in.peek() == '\\' ) + { + try { + in.get(); + switch( in.peek() ) + { + case 't': + in.get(); + return '\t'; + case 'n': + in.get(); + return '\n'; + case 'r': + in.get(); + return '\r'; + case '\\': + in.get(); + return '\\'; + default: + return in.get(); + } + } FC_RETHROW_EXCEPTIONS( info, "Stream ended with '\\'" ); + } + FC_THROW_EXCEPTION( parse_error_exception, "Expected '\\'" ); + } + + + template + void skip_white_space( T& in ) + { + while( true ) + { + switch( in.peek() ) + { + case ' ': + case '\t': + case '\n': + case '\r': + in.get(); + break; + default: + return; + } + } + } + + template + fc::string stringFromStream( T& in ) + { + fc::stringstream token; + try + { + char c = in.peek(); + + if( c != '"' ) + FC_THROW_EXCEPTION( parse_error_exception, + "Expected '\"' but read '${char}'", + ("char", string(&c, (&c) + 1) ) ); + in.get(); + while( true ) + { + + switch( c = in.peek() ) + { + case '\\': + token << parseEscape( in ); + break; + case '"': + in.get(); + return token.str(); + default: + token << c; + in.get(); + } + } + FC_THROW_EXCEPTION( parse_error_exception, "EOF before closing '\"' in string '${token}'", + ("token", token.str() ) ); + } FC_RETHROW_EXCEPTIONS( warn, "while parsing token '${token}'", + ("token", token.str() ) ); + } + + template + variant_object objectFromStream( T& in ) + { + mutable_variant_object obj; + try + { + char c = in.peek(); + if( c != '{' ) + FC_THROW_EXCEPTION( parse_error_exception, + "Expected '{', but read '${char}'", + ("char",string(&c, &c + 1)) ); + in.get(); + skip_white_space(in); + while( in.peek() != '}' ) + { + if( in.peek() == ',' ) + { + in.get(); + } + skip_white_space(in); + string key = stringFromStream( in ); + skip_white_space(in); + if( in.peek() != ':' ) + { + FC_THROW_EXCEPTION( parse_error_exception, "Expected ':' after key \"${key}\"", + ("key", key) ); + } + in.get(); + auto val = variant_from_stream( in ); + + obj(std::move(key),std::move(val)); + skip_white_space(in); + } + if( in.peek() == '}' ) + { + in.get(); + return obj; + } + FC_THROW_EXCEPTION( parse_error_exception, "Expected '}' after ${variant}", ("variant", obj ) ); + + + } FC_RETHROW_EXCEPTIONS( warn, "Error parsing object" ); + } + + template + variants arrayFromStream( T& in ) + { + variants ar; + try + { + if( in.peek() != '[' ) + FC_THROW_EXCEPTION( parse_error_exception, "Expected '['" ); + in.get(); + skip_white_space(in); + + while( in.peek() != ']' ) + { + while( in.peek() == ',' ) + in.get(); + ar.push_back( variant_from_stream(in) ); + skip_white_space(in); + } + if( in.peek() != ']' ) + FC_THROW_EXCEPTION( parse_error_exception, "Expected ']' after parsing ${variant}", + ("variant", ar) ); + + in.get(); + } FC_RETHROW_EXCEPTIONS( warn, "Attempting to parse array ${array}", + ("array", ar ) ); + return ar; + } + + template + variant number_from_stream( T& in ) + { + char buf[30]; + memset( buf, 0, sizeof(buf) ); + char* pos = buf; + bool dot = false; + bool neg = false; + if( in.peek() == '-') + { + neg = true; + *pos = in.get(); + ++pos; + } + bool done = false; + while( !done) + { + char c = in.peek(); + switch( c ) + { + case '.': + { + if( dot ) + { + done = true; + break; + } + dot = true; + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + *pos = c; + ++pos; + in.get(); + break; + default: + done = true; + break; + } + } + if( dot ) return to_double(buf); + if( neg ) return to_int64(buf); + return to_uint64(buf); + } + template + variant token_from_stream( T& in ) + { + fc::stringstream ss; + while( char c = in.peek() ) + { + switch( c ) + { + case 'n': + case 'u': + case 'l': + case 't': + case 'r': + case 'e': + case 'f': + case 'a': + case 's': + ss.put( in.get() ); + break; + default: + { + fc::string str = ss.str(); + if( str == "null" ) return variant(); + if( str == "true" ) return true; + if( str == "false" ) return false; + else + { + FC_THROW_EXCEPTION( parse_error_exception, "Invalid token '${token}'", + ("token",str) ); + } + } + } + } + FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF" ); + } + + + template + variant variant_from_stream( T& in ) + { + skip_white_space(in); + variant var; + while( char c = in.peek() ) + { + switch( c ) + { + case ' ': + case '\t': + case '\n': + case '\r': + in.get(); + continue; + case '"': + return stringFromStream( in ); + case '{': + return objectFromStream( in ); + case '[': + return arrayFromStream( in ); + case '-': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return number_from_stream( in ); + // null, true, false, or 'warning' / string + case 'n': + case 't': + case 'f': + return token_from_stream( in ); + case 0x04: // ^D end of transmission + FC_THROW_EXCEPTION( eof_exception, "unexpected end of file" ); + default: + ilog( "unhandled char '${c}' int ${int}", ("c", fc::string( &c, 1 ) )("int", int(c)) ); + } + } + return variant(); + } + variant json::from_string( const fc::string& utf8_str ) + { + fc::stringstream in( utf8_str ); + return variant_from_stream( in ); + } + + /* + void toUTF8( const char str, ostream& os ) + { + // validate str == valid utf8 + utf8::replace_invalid( &str, &str + 1, ostream_iterator(os) ); + } + + void toUTF8( const wchar_t c, ostream& os ) + { + utf8::utf16to8( &c, (&c)+1, ostream_iterator(os) ); + } + */ + + /** + * Convert '\t', '\a', '\n', '\\' and '"' to "\t\a\n\\\"" + * + * All other characters are printed as UTF8. + */ + void escape_string( const string& str, ostream& os ) + { + os << '"'; + for( auto itr = str.begin(); itr != str.end(); ++itr ) + { + switch( *itr ) + { + case '\t': + os << "\\t"; + break; + case '\n': + os << "\\n"; + break; + case '\\': + os << "\\\\"; + break; + case '\r': + os << "\\r"; + break; + case '\a': + os << "\\a"; + break; + case '\"': + os << "\\\""; + break; + default: + os << *itr; + //toUTF8( *itr, os ); + } + } + os << '"'; + } + ostream& json::to_stream( ostream& out, const fc::string& str ) + { + escape_string( str, out ); + return out; + } + + template + void to_stream( T& os, const variants& a ) + { + os << '['; + auto itr = a.begin(); + + while( itr != a.end() ) + { + to_stream( os, *itr ); + ++itr; + if( itr != a.end() ) + os << ','; + } + os << ']'; + } + template + void to_stream( T& os, const variant_object& o ) + { + os << '{'; + auto itr = o.begin(); + + while( itr != o.end() ) + { + escape_string( itr->key(), os ); + os << ':'; + to_stream( os, itr->value() ); + ++itr; + if( itr != o.end() ) + os << ','; + } + os << '}'; + } + + template + void to_stream( T& os, const variant& v ) + { + switch( v.get_type() ) + { + case variant::null_type: + os << "null"; + return; + case variant::int64_type: + os << v.as_int64(); + return; + case variant::uint64_type: + os << v.as_uint64(); + return; + case variant::double_type: + os << v.as_double(); + return; + case variant::bool_type: + os << v.as_string(); + return; + case variant::string_type: + escape_string( v.get_string(), os ); + return; + case variant::array_type: + { + const variants& a = v.get_array(); + to_stream( os, a ); + return; + } + case variant::object_type: + { + const variant_object& o = v.get_object(); + to_stream(os, o ); + return; + } + } + } + + fc::string json::to_string( const variant& v ) + { + fc::stringstream ss; + fc::to_stream( ss, v ); + return ss.str(); + } + + fc::string json::to_pretty_string( const variant& v ) + { + return to_string(v); + } + + void json::save_to_file( const variant& v, const string& fi, bool pretty ) + { + fc::ofstream o( fi.c_str() ); + fc::to_stream( o, v ); + } + variant json::from_file( const fc::path& p ) + { + auto tmp = std::make_shared( p, ifstream::binary ); + buffered_istream bi( tmp ); + return variant_from_stream( bi ); + } + variant json::from_stream( buffered_istream& in ) + { + return variant_from_stream( in ); + } + + ostream& json::to_stream( ostream& out, const variant& v ) + { + fc::to_stream( out, v ); + return out; + } + ostream& json::to_stream( ostream& out, const variants& v ) + { + fc::to_stream( out, v ); + return out; + } + ostream& json::to_stream( ostream& out, const variant_object& v ) + { + fc::to_stream( out, v ); + return out; + } + +} // fc diff --git a/src/sstream.cpp b/src/io/sstream.cpp similarity index 73% rename from src/sstream.cpp rename to src/io/sstream.cpp index 7767479..1534f08 100644 --- a/src/sstream.cpp +++ b/src/io/sstream.cpp @@ -1,6 +1,7 @@ -#include +#include #include -#include +#include +#include #include namespace fc { @@ -31,23 +32,42 @@ namespace fc { return my->ss.str();//.c_str();//*reinterpret_cast(&st); } + void stringstream::str(const fc::string& s) { + my->ss.str(s); + } + + void stringstream::clear() { + my->ss.clear(); + } + + bool stringstream::eof()const { return my->ss.eof(); } - ostream& stringstream::write( const char* buf, size_t len ) { + size_t stringstream::writesome( const char* buf, size_t len ) { my->ss.write(buf,len); - return *this; + if( my->ss.eof() ) + { + FC_THROW_EXCEPTION( eof_exception, "stringstream" ); + } + return len; } size_t stringstream::readsome( char* buf, size_t len ) { - return static_cast(my->ss.readsome(buf,len)); - } - istream& stringstream::read( char* buf, size_t len ) { - my->ss.read(buf,len); - return *this; + size_t r = static_cast(my->ss.readsome(buf,len)); + if( my->ss.eof() || r == 0 ) + { + FC_THROW_EXCEPTION( eof_exception, "stringstream" ); + } + return r; } void stringstream::close(){ my->ss.flush(); }; void stringstream::flush(){ my->ss.flush(); }; + /* + istream& stringstream::read( char* buf, size_t len ) { + my->ss.read(buf,len); + return *this; + } istream& stringstream::read( int64_t& v ) { my->ss >> v; return *this; } istream& stringstream::read( uint64_t& v ) { my->ss >> v; return *this; } istream& stringstream::read( int32_t& v ) { my->ss >> v; return *this; } @@ -66,7 +86,17 @@ namespace fc { my->ss.write( s.c_str(), s.size() ); return *this; } + */ + char stringstream::peek() + { + char c = my->ss.peek(); + if( my->ss.eof() ) + { + FC_THROW_EXCEPTION( eof_exception, "stringstream" ); + } + return c; + } } diff --git a/src/io/varint.cpp b/src/io/varint.cpp new file mode 100644 index 0000000..a3eaac2 --- /dev/null +++ b/src/io/varint.cpp @@ -0,0 +1,10 @@ +#include +#include + +namespace fc +{ +void to_variant( const signed_int& var, variant& vo ) { vo = var.value; } +void from_variant( const variant& var, signed_int& vo ) { vo.value = static_cast(var.as_int64()); } +void to_variant( const unsigned_int& var, variant& vo ) { vo = var.value; } +void from_variant( const variant& var, unsigned_int& vo ) { vo.value = static_cast(var.as_uint64()); } +} diff --git a/src/iostream.cpp b/src/iostream.cpp deleted file mode 100644 index c53e050..0000000 --- a/src/iostream.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { - ostream& operator<<( ostream& o, const char* v ) { - o.write( v, strlen(v) ); - return o; - } - - struct cin_buffer { - cin_buffer():eof(false),write_pos(0),read_pos(0),cinthread("cin"){ - - cinthread.async( [=](){read();} ); - } - - void read() { - char c; - std::cin.read(&c,1); - while( !std::cin.eof() ) { - while( write_pos - read_pos > 0xfffff ) { - fc::promise::ptr wr( new fc::promise() ); - write_ready = wr; - if( write_pos - read_pos <= 0xfffff ) { - wr->wait(); - } - write_ready.reset(); - } - buf[write_pos&0xfffff] = c; - ++write_pos; - - fc::promise::ptr tmp; - { // copy read_ready because it is accessed from multiple threads - fc::scoped_lock lock( read_ready_mutex ); - tmp = read_ready; - } - if( tmp && !tmp->ready() ) { - tmp->set_value(); - } - std::cin.read(&c,1); - } - eof = true; - fc::promise::ptr tmp; - { // copy read_ready because it is accessed from multiple threads - fc::scoped_lock lock( read_ready_mutex ); - tmp = read_ready; - } - if( tmp && !tmp->ready() ) { - tmp->set_value(); - } - } - boost::mutex read_ready_mutex; - fc::promise::ptr read_ready; - fc::promise::ptr write_ready; - - volatile bool eof; - - volatile uint64_t write_pos; - char buf[0xfffff+1]; // 1 mb buffer - volatile uint64_t read_pos; - fc::thread cinthread; - }; - - cin_buffer& get_cin_buffer() { - static cin_buffer* b = new cin_buffer(); - return *b; - } - - - fc::thread& cin_thread() { static fc::thread i("cin"); return i; } - - fc::istream& getline( fc::istream& i, fc::string& s, char delim ) { - fc::stringstream ss; - char c; - i.read( &c, 1 ); - while( !i.eof() ) { - if( c == delim ) { s = ss.str(); return i; } - if( c != '\r' ) ss.write(&c,1); - i.read( &c, 1 ); - } - s = ss.str(); - return i; - } - - - ostream& cout_t::write( const char* buf, size_t len ) { std::cout.write(buf,len); return *this; } - void cout_t::close() {} - void cout_t::flush() { std::cout.flush(); } - - ostream& cout_t::write( const fc::string& s ) { std::cout.write(s.c_str(),s.size()); return *this; } - - ostream& cerr_t::write( const char* buf, size_t len ) { std::cerr.write(buf,len); return *this; } - void cerr_t::close() {}; - void cerr_t::flush() { std::cerr.flush(); } - - ostream& cerr_t::write( const fc::string& s ) { std::cerr<< static_cast(s); return *this; } - - size_t cin_t::readsome( char* buf, size_t len ) { - cin_buffer& b = get_cin_buffer(); - int64_t avail = b.write_pos - b.read_pos; - avail = (fc::min)(int64_t(len),avail); - int64_t u = 0; - while( (avail>0) && (len>0) ) { - *buf = b.buf[b.read_pos&0xfffff]; - ++b.read_pos; - ++buf; - --avail; - --len; - ++u; - } - return size_t(u); - } - - cin_t::~cin_t() { - /* - cin_buffer& b = get_cin_buffer(); - if( b.read_ready ) { - b.read_ready->wait(); - } - */ - } - istream& cin_t::read( char* buf, size_t len ) { - cin_buffer& b = get_cin_buffer(); - do { - while( !b.eof && (b.write_pos - b.read_pos)==0 ){ - // wait for more... - fc::promise::ptr rr( new fc::promise() ); - { // copy read_ready because it is accessed from multiple threads - fc::scoped_lock lock( b.read_ready_mutex ); - b.read_ready = rr; - } - if( b.write_pos - b.read_pos == 0 ) { - rr->wait(); - } - // b.read_ready.reset(); - { // copy read_ready because it is accessed from multiple threads - fc::scoped_lock lock( b.read_ready_mutex ); - b.read_ready.reset(); - } - } - if( b.eof ) return *this; - size_t r = readsome( buf, len ); - buf += r; - len -= r; - - auto tmp = b.write_ready; // copy write_writey because it is accessed from multiple thwrites - if( tmp && !tmp->ready() ) { - tmp->set_value(); - } - - - } while( len > 0 && !b.eof ); - return *this; - } - - bool cin_t::eof()const { return get_cin_buffer().eof; } - - cout_t cout; - cerr_t cerr; - cin_t cin; -} diff --git a/src/json.cpp b/src/json.cpp deleted file mode 100644 index c187bb9..0000000 --- a/src/json.cpp +++ /dev/null @@ -1,1055 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace fc { namespace json { - /** - * Placeholder for unparsed json data. - */ - class string { - public: - template - string( T&& v ):json_data( fc::forward(v) ){} - string( const string& s ):json_data(s.json_data){} - string( string&& s ):json_data(fc::move(s.json_data)){} - string(){} - - string& operator=( const fc::string& s ) { - json_data = std::vector(s.begin(),s.end()); - return *this; - } - template - string& operator=( T&& t ) { - json_data = fc::forward(t); - return *this; - } - string& operator=( string&& s ) { - json_data = fc::move(s.json_data); - return *this; - } - string& operator=( const string& s ) - { - json_data = s.json_data; - return *this; - } - std::vector json_data; - }; - -} } - -typedef std::map jmap; - - - namespace errors { - enum error_type { - unknown_error = 0x0001, // Other errors not specified below - warning = 0x0002, // Other warnigns not specified below - sytnax_error = 0x0004, // fatal syntax errors unclosed brace - sytnax_warning = 0x0008, // recoverable syntax error (missing, missing ':', unquoted string) - missing_comma = 0x0010, // if the error was related to json syntax and not semantic - string_to_int = 0x0020, // any time lexical cast from string to int is required - double_to_int = 0x0040, // any time a double is received for an int - int_overflow = 0x0080, // any time int value is greater than underlying type - signed_to_unsigned = 0x0100, // any time a negative value is read for an unsigned field - int_to_bool = 0x0200, // any time an int is read for a bool - string_to_bool = 0x0400, // any time a string is read for a bool - bad_array_index = 0x0800, // atempt to read a vector field beyond end of sequence - unexpected_key = 0x1000, // fields in object - missing_key = 0x2000, // check required fields - type_mismatch = 0x4000, // expected a fundamental, got object, expected object, got array, etc. - type_conversion = 0x8000, // also set any time a conversion occurs - all = 0xffff, - none = 0x0000 - }; - } // namespace errors - - /** - * Stores information about errors that occurred durring the parse. - * - * By default extra fields are 'ignored' as warning - * Loss of presision errors are warning. - * String to Int conversion warnings - * Double to Int - * Int to bool - * - */ - struct parse_error { - parse_error( int32_t ec, fc::string msg, char* s = 0, char* e = 0 ) - :message(fc::move(msg)),type(ec),start(s),end(e){} - - parse_error( parse_error&& m ) - :message(fc::move(m.message)),type(m.type),start(m.start),end(m.end){} - - fc::string message; - int32_t type; - char* start; - char* end; - }; - - /** - * Collects errors and manages how they are responded to. - */ - class error_collector { - public: - error_collector( error_collector&& e ) - :m_errors(fc::move(e.m_errors)){ - memcpy((char*)m_eclass,(char*)e.m_eclass, sizeof(m_eclass) ); - } - /* - error_collector( const error_collector&& e ) - :m_errors(e.m_errors){ - memcpy((char*)m_eclass,(char*)e.m_eclass, sizeof(m_eclass) ); - } - */ - ~error_collector() throw() { - try { - m_errors.clear(); - }catch(...){} - } - - enum error_defaults { - default_report = errors::all, - default_recover = errors::all, - default_throw = errors::none, - default_ignore = ~(default_report|default_recover|default_throw) - }; - - error_collector(){ - m_eclass[report_error_t] = default_report; - m_eclass[recover_error_t] = default_recover; - m_eclass[throw_error_t] = default_throw; - m_eclass[ignore_error_t] = default_ignore; - } - - inline bool report( int32_t e )const { - return 0 != (m_eclass[report_error_t] & e); - } - inline bool recover( int32_t e )const { - return 0 != (m_eclass[recover_error_t] & e); - } - inline bool ignore( int32_t e )const { - return 0 != (m_eclass[ignore_error_t] & e); - } - - void report_error( int32_t e ) { - m_eclass[report_error_t] |= e; - m_eclass[ignore_error_t] &= ~e; - } - void recover_error( int32_t e ) { - m_eclass[recover_error_t] |= e; - m_eclass[ignore_error_t] &= ~e; - } - void throw_error( int32_t e ) { - m_eclass[throw_error_t] |= e; - m_eclass[ignore_error_t] &= ~e; - } - void ignore_error( int32_t e ) { - m_eclass[ignore_error_t] |= e; - m_eclass[report_error_t] &= ~m_eclass[ignore_error_t]; - m_eclass[recover_error_t] &= ~m_eclass[ignore_error_t]; - m_eclass[throw_error_t] &= ~m_eclass[ignore_error_t]; - } - - void post_error( int32_t ec, fc::string msg, char* s = 0, char* e = 0 ) { - m_errors.push_back( parse_error( ec, fc::move(msg), s, e ) ); - if( ec & m_eclass[throw_error_t] ) { - throw fc::move(*this); - } - } - const fc::vector& get_errors()const { - return m_errors; - } - - private: - enum error_class { - ignore_error_t, - report_error_t, - recover_error_t, - throw_error_t, - num_error_classes - }; - uint32_t m_eclass[num_error_classes]; - fc::vector m_errors; - }; - fc::value to_value( char* start, char* end, error_collector& ec ); - - - - - - - - - - -namespace fc { namespace json { - fc::string escape_string( const fc::string& s ) { - // calculate escape string size. - uint32_t ecount = 0; - for( auto i = s.begin(); i != s.end(); ++i ) { - if( ' '<= *i && *i <= '~' && *i !='\\' && *i != '"' ) { - ecount+=1; - } else { - switch( *i ) { - case '\t' : - case '\n' : - case '\r' : - case '\\' : - case '"' : - ecount += 2; break; - default: - ecount += 4; - } - } - } - // unless the size changed, just return it. - if( ecount == s.size() ) { return s; } - - // reserve the bytes - fc::string out; out.reserve(ecount); - // print it out. - for( auto i = s.begin(); i != s.end(); ++i ) { - if( ' '<= *i && *i <= '~' && *i !='\\' && *i != '"' ) { - out += *i; - } else { - out += '\\'; - switch( *i ) { - case '\t' : out += 't'; break; - case '\n' : out += 'n'; break; - case '\r' : out += 'r'; break; - case '\\' : out += '\\'; break; - case '"' : out += '"'; break; - default: - out += "x"; - const char* const hexdig = "0123456789abcdef"; - out += hexdig[*i >> 4]; - out += hexdig[*i & 0xF]; - } - } - } - return out; - } - - fc::string unescape_string( const fc::string& s ) { - fc::string out; out.reserve(s.size()); - for( auto i = s.begin(); i != s.end(); ++i ) { - if( *i != '\\' ) { - if( *i != '"' ) out += *i; - } - else { - ++i; - if( i == out.end() ) return out; - switch( *i ) { - case 't' : out += '\t'; break; - case 'n' : out += '\n'; break; - case 'r' : out += '\r'; break; - case '\\' : out += '\\'; break; - case '"' : out += '"'; break; - case 'x' : { - ++i; if( i == out.end() ) return out; - char c = fc::from_hex(*i); - ++i; if( i == out.end() ) { out += c; return out; } - c = c<<4 | fc::from_hex(*i); - out += c; - break; - } - default: - out += '\\'; - out += *i; - } - } - } - return out; - } - - /** - * Any unescaped quotes are dropped. - * Because unescaped strings are always shorter, we can simply reuse - * the memory of s. - * - * @param s a null terminated string that contains one or more escape chars - */ - char* inplace_unescape_string( char* s ) { - while( *s == '"' ) ++s; - char* out = s; - - for( auto i = s; *i != '\0'; ++i ) { - if( *i != '\\' ) { - if( *i != '"' ) { - *out = *i; - ++out; - } - } - else { - ++i; - if( *i == '\0' ) { *out = '\0'; return s; } - switch( *i ) { - case 't' : *out = '\t'; ++out; break; - case 'n' : *out = '\n'; ++out; break; - case 'r' : *out = '\r'; ++out; break; - case '\\': *out = '\\'; ++out; break; - case '"' : *out = '"'; ++out; break; - case 'x' : { - ++i; if( *i == '\0' ){ *out = '\0'; return s; } - char c = fc::from_hex(*i); - ++i; if( *i == '\0' ){ *out = c; ++out; *out = '\0'; return s; } - c = c<<4 | fc::from_hex(*i); - *out = c; - ++out; - break; - } - default: - *out = '\\'; - ++out; - *out = *i; - ++out; - } - } - } - *out = '\0'; - return s; - } - } }// fc::json - -/** - * Ignores leading white space. - * If it starts with [,", or { reads until matching ],", or } - * If it starts with something else it reads until [{",}]: or whitespace only - * allowing a starting - or a single . - * - * @note internal json syntax errors are not caught, only bracket errors - * are caught by this method. This makes it easy for error recovery - * when values are read recursivley. - * - * @param in start of input - * @param end end of input - * @param oend output parameter to the end of the value - * - * @return a pointer to the start of the value - */ -char* read_value( char* in, char* end, char*& oend ) { - char* start = in; - char* oin = in; - // ignore leading whitespace - while( (in < end) && ((*in == ' ') || (*in == '\t') || (*in == '\n') || (*in == '\r')) ) { - ++in; - } - start = in; - if( start == end ) { - oend = end; - return start; - } - - bool found_dot = false; - // check for literal vs object, array or string - switch( *in ) { - case ':': - case ',': - case '=': - oend = in+1; - return start; - case '[': - case '{': - case '"': - break; - default: { // literal - // read until non-literal character - // allow it to start with - - // allow only one '.' - while( in != end ) { - switch( *in ) { - case '[': case ']': - case '{': case '}': - case ':': case '=': - case ',': case '"': - case ' ': case '\t': case '\n': case '\r': { - oend = in; - return start; - } - case '.': - if( found_dot ) { - oend = in; - return start; - } - found_dot = true; - break; - case '-': - if( in-start ){ oend = in; return start; } - } - ++in; - } - oend = in; - return start; - } - } // end literal check - - int depth = 0; - bool in_quote = false; - bool in_escape = false; - // read until closing ]} or " ignoring escaped " - while( in != end ) { - if( !in_quote ) { - switch( *in ) { - case '[': - case '{': ++depth; break; - case ']': - case '}': --depth; break; - case '"': - ++depth; - in_quote = true; - break; - default: // do nothing; - break; - } - } else { // in quote - switch( *in ) { - case '"': if( !in_escape ) { - --depth; - in_quote = false; - break; - } - case '\\': - in_escape = !in_escape; - break; - default: - in_escape = false; - } - } - ++in; - if( !depth ) { oend = in; return start; } - } - if( depth != 0 ) { - // TODO: Throw Parse Error! - elog("Parse Error!! '%s' size: %d", fc::string( oin, end ).c_str(), (oin-start)); - } - oend = in; return start; -} - -struct temp_set { - temp_set( char* v, char t ) - :old(*v),val(v) { *val = t; } - ~temp_set() { *val = old; } - char old; - char* val; -}; - -/** - * A,B,C - * Warn on extra ',' or missing ',' - */ -void read_values( fc::value::array& a, char* in, char* end, error_collector& ec ) { - if( in >= end ) return; - char* ve = 0; - char* v = read_value( in, end, ve ); - while( *v == ',' ) { - wlog( "unexpected ','"); - v = read_value( ve, end, ve ); - } - if( v == ve ) return; // no values - - { temp_set temp(ve,'\0'); a.push_back( to_value( v, ve, ec ) ); } - - char* c; - char* ce = 0; - do { // expect comma + value | '' - - // expect comma or '' - c = read_value( ve, end, ce ); - - // '' means we are done, no errors - if( c == ce ) return; - - if( *c != ',' ) // we got a value when expecting ',' - { - wlog( "missing ," ); - temp_set temp(ce,'\0'); a.push_back( to_value(c, ce, ec) ); - ve = ce; - continue; // start back at start - } - - // expect value - v = read_value( ce, end, ve ); - while ( *v == ',' ) { // but got comma - // expect value - wlog( "extra comma at c->ce" ); - c = v; ce = ve; - v = read_value( ve, end, ve ); - } - if( v == ve ) { - wlog( "trailing comma at c->ce" ); - } else { // got value - temp_set temp(ve,'\0'); - a.push_back( to_value( v, ve, ec) ); - } - } while( ve < end );// expect comma + value | '' -} - - -/** - * Reads one level deep, does not recruse into sub objects. - */ -char* read_key_val( std::map& obj, bool sc, char* in, char* end, error_collector& ec ) { - char* name_end = 0; - char* name = in; - do { - // read first char - name = read_value( name, end, name_end ); - if( sc ) { // if we expect a , - if( *name != ',' ) { // but didn't get one - wlog( "expected ',' but got %1%", name ); // warn and accept name - } else { // we got the exepcted , read the expected name - name = read_value( name_end, end, name_end ); - } - } else { // don't start with ',' - while( *name == ',' ) { // while we don't have a name, keep looking - wlog( "unexpected ',' " ); - name = read_value( name_end, end, name_end ); - } - } - } while( *name == ',' ); - - - // now we should have a name. - if( name_end >= end -1 ) { - temp_set ntemp(name_end,'\0'); - elog( "early end after reading name %1%", name ); - return name_end; - } - if( *name != '"' ) { - temp_set ntemp(name_end,'\0'); - wlog( "unquoted name '%1%'", name ); - } else { - temp_set ntemp(name_end,'\0'); - name = fc::json::inplace_unescape_string(name); - } - - char* col_end = 0; - char* col = read_value( name_end, end, col_end ); - - char* val_end = 0; - char* val = 0; - - bool sep_error = false; - if( col_end-col == 1 ) { - switch( *col ) { - case ':': break; - case ';': - case '=': - wlog( "found %1% instead of ':'", *col ); - break; - default: - sep_error = true; - } - } else { - sep_error = true; - } - - if( sep_error ) { - temp_set ntemp(name_end,'\0'); - temp_set vtemp(col_end,'\0'); - wlog( "expected ':' but got %1%", col ); - wlog( "assuming this is the value... " ); - val = col; - val_end = col_end; - } else { - if( name_end >= end -1 ) { - temp_set ntemp(name_end,'\0'); - temp_set vtemp(col_end,'\0'); - elog( "early end after reading name '%1%' and col '%2%'", name, col ); - return name_end; - } - val = read_value( col_end, end, val_end ); - if( val == end ) { - wlog( "no value specified" ); - } - } - temp_set ntemp(name_end,'\0'); - temp_set vtemp(val_end,'\0'); - //slog( "name: '%1%'", fc::string(name,name_end) ); - obj[name] = std::vector(val,val_end); -// obj.fields.push_back( key_val( name, to_value( val, val_end, ec ) ) ); - return val_end; -} - - - - - -/** - * Reads an optional ',' followed by key : value, returning the next input position - * @param sc - start with ',' - */ -char* read_key_val( fc::value::object& obj, bool sc, char* in, char* end, error_collector& ec ) { - char* name_end = 0; - char* name = in; - do { - // read first char - name = read_value( name, end, name_end ); - if( name == name_end ) - return name; - if( sc ) { // if we expect a , - if( *name != ',' ) { // but didn't get one - if( *name != '}' ) - wlog( "expected ',' or '}' but got '%s'", name ); // warn and accept name - } else { // we got the exepcted , read the expected name - name = read_value( name_end, end, name_end ); - } - } else { // don't start with ',' - while( *name == ',' ) { // while we don't have a name, keep looking - wlog( "unexpected ',' " ); - name = read_value( name_end, end, name_end ); - } - } - } while( *name == ',' ); - - - // now we should have a name. - if( name_end >= end -1 ) { - temp_set ntemp(name_end,'\0'); - elog( "early end after reading name '%s'", name ); - return name_end; - } - if( *name != '"' ) { - temp_set ntemp(name_end,'\0'); - wlog( "unquoted name '%1%'", name ); - } else { - temp_set ntemp(name_end,'\0'); - name = fc::json::inplace_unescape_string(name); - } - - char* col_end = 0; - char* col = read_value( name_end, end, col_end ); - - char* val_end = 0; - char* val = 0; - - bool sep_error = false; - if( col_end-col == 1 ) { - switch( *col ) { - case ':': break; - case ';': - case '=': - wlog( "found %1% instead of ':'", *col ); - break; - default: - sep_error = true; - } - } else { - sep_error = true; - } - - if( sep_error ) { - temp_set ntemp(name_end,'\0'); - temp_set vtemp(col_end,'\0'); - wlog( "expected ':' but got %1%", col ); - wlog( "assuming this is the value... " ); - val = col; - val_end = col_end; - } else { - if( name_end >= end -1 ) { - temp_set ntemp(name_end,'\0'); - temp_set vtemp(col_end,'\0'); - elog( "early end after reading name '%1%' and col '%2%'", name, col ); - return name_end; - } - val = read_value( col_end, end, val_end ); - if( val == end ) { - wlog( "no value specified" ); - } - } - temp_set ntemp(name_end,'\0'); - temp_set vtemp(val_end,'\0'); - obj.fields.push_back( fc::value::key_val( name, to_value( val, val_end, ec ) ) ); - return val_end; -} - -// first_key =:: '' | "name" : VALUE *list_key -// list_key '' | ',' "name" : VALUE -void read_key_vals( fc::value::object& obj, char* in, char* end, error_collector& ec ) { - bool ex_c = false; - char* kv_end = in; - do { - //slog( "%1% bytes to read", (end-kv_end) ); - kv_end = read_key_val( obj, ex_c, kv_end, end, ec ); - ex_c = true; - } while( kv_end < end ); -} -// first_key =:: '' | "name" : VALUE *list_key -// list_key '' | ',' "name" : VALUE -std::map read_key_vals( char* in, char* end, error_collector& ec ) { - std::map m; - bool ex_c = false; - char* kv_end = in; - do { - //slog( "%1% bytes to read", (end-kv_end) ); - kv_end = read_key_val( m, ex_c, kv_end, end, ec ); - ex_c = true; - } while( kv_end < end ); - return m; -} - - - -/** - * @brief adaptor for to_value( char*, char*, error_collector& ) - */ -fc::value to_value( fc::vector&& v, error_collector& ec ) { - if( v.size() == 0 ) return fc::value(); - return to_value( v.data(), v.data() + v.size(), ec ); -} - -/** - * Returns a fc::value containing from the json string. - * - * @param ec - determines how to respond to parse errors and logs - * any errors that occur while parsing the string. - */ -fc::value to_value( char* start, char* end, error_collector& ec ) { - if( start == end ) return fc::value(); - - char* ve = 0; - char* s = read_value( start, end, ve ); - //slog( "'%1%'", fc::string(start,ve) ); - switch( s[0] ) { - case '[': { - fc::value::array a; - read_values( a, s+1, ve -1, ec ); - return a; - } - case '{': { - fc::value::object o; - read_key_vals( o, s+1, ve -1, ec ); - fc::value v = fc::move(o); - return v; - } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - temp_set move_end(ve,'\0'); - for( char* n = s+1; n != ve; ++n ) { - if( *n == '.' ) { - return fc::lexical_cast(s); - } - } - return fc::lexical_cast(s); - } - case '-': { - temp_set move_end(ve,'\0'); - for( char* n = s+1; n != ve; ++n ) { - if( *n == '.' ) { - return fc::lexical_cast(s); - } - } - return fc::lexical_cast(s); - } - case '.': { - temp_set move_end(ve,'\0'); - return fc::lexical_cast(s); - } - case '\"': { - temp_set move_end(ve,'\0'); - return fc::json::inplace_unescape_string( s ); - } - case 'n': { - temp_set move_end(ve,'\0'); - if( strcmp(s,"null" ) == 0) return fc::value(); - } - case 't': { - temp_set move_end(ve,'\0'); - if( strcmp(s,"true" ) == 0) return true; - } - case 'f': { - temp_set move_end(ve,'\0'); - if( strcmp(s,"false" ) == 0) return false; - } - - default: - wlog( "return unable to parse... return as string '%s'", fc::string(s,ve).c_str() ); - return fc::value( fc::string( s, ve) ); - } -} -namespace fc { namespace json { - -fc::string pretty_print( const fc::string& v, uint8_t indent ) { - int level = 0; - fc::stringstream ss; - bool first = false; - bool quote = false; - bool escape = false; - for( uint32_t i = 0; i < v.size(); ++i ) { - switch( v[i] ) { - case '\\': - if( !escape ) { - if( quote ) - escape = true; - } else { escape = false; } - ss<&& v, uint8_t indent ) { - int level = 0; - fc::stringstream ss; - bool first = false; - bool quote = false; - bool escape = false; - for( uint32_t i = 0; i < v.size(); ++i ) { - switch( v[i] ) { - case '\\': - if( !escape ) { - if( quote ) - escape = true; - } else { escape = false; } - ss< - struct value_visitor : value::const_visitor { - value_visitor( Stream& s ):os(s){} - Stream& os; - virtual void operator()( const int8_t& v ){ os << v; } - virtual void operator()( const int16_t& v ){ os << v; } - virtual void operator()( const int32_t& v ){ os << v; } - virtual void operator()( const int64_t& v ){ os << v; } - virtual void operator()( const uint8_t& v ){ os << v; } - virtual void operator()( const uint16_t& v ){ os << v; } - virtual void operator()( const uint32_t& v ){ os << v; } - virtual void operator()( const uint64_t& v ){ os << v; } - virtual void operator()( const float& v ){ os << v; } - virtual void operator()( const double& v ){ os << v; } - virtual void operator()( const bool& v ){ os << (v ? "true" : "false"); } - virtual void operator()( const fc::string& v ){ os << '"' << fc::json::escape_string(v) <<'"'; } - virtual void operator()( const fc::value::object& o ){ - os << '{'; - for( uint32_t i = 0; i < o.fields.size(); ++i ) { - if( i ) os <<','; - (*this)( o.fields[i].key ); - os<<':'; - o.fields[i].val.visit( value_visitor(*this) ); - } - os << '}'; - } - virtual void operator()( const value::array& o ){ - os << '['; - for( auto i = o.begin(); i != o.end(); ++i ) { - if( i != o.begin() ) os <<','; - i->visit( value_visitor(*this) ); - } - os << ']'; - } - virtual void operator()( ){ os << "null"; } - }; - - template - void to_json( const fc::value& v, Stream& os ) { - v.visit( value_visitor(os) ); - } - - void write( ostream& out, const value& val ) { - to_json( val, out ); - } - - fc::string to_string( const fc::value& v ) { - fc::stringstream ss; - to_json( v, ss ); - return ss.str(); - } - - fc::string to_pretty_string( const fc::value& v ) { - return pretty_print( to_string(v), 4 ); - } - - value from_file( const fc::path& local_path ) { - if( !exists(local_path) ) { - FC_THROW_REPORT( "Source file ${filename} does not exist", value().set("filename",local_path.string()) ); - } - if( is_directory( local_path ) ) { - FC_THROW_REPORT( "Source path ${path} is a directory; a file was expected", - value().set("path",local_path.string()) ); - } - try { - // memory map the file - size_t fsize = static_cast(file_size(local_path)); - if( fsize == 0 ) { return value(); } - file_mapping fmap( local_path.string().c_str(), read_only ); - - - mapped_region mr( fmap, fc::read_only, 0, fsize ); - - const char* pos = reinterpret_cast(mr.get_address()); - const char* end = pos + fsize; - - // TODO: implement a const version of to_value - fc::vector tmp(pos,end); - - error_collector ec; - return to_value(tmp.data(), tmp.data()+fsize,ec); - } catch ( ... ) { - FC_THROW_REPORT( "Error loading JSON object from file '${path}'", - fc::value().set( "file", local_path ) - .set( "exception", fc::except_str() ) - ); - } - } - - value from_string( const fc::string& s ) { - std::vector v(s.begin(),s.end()); - //slog( "from_string( '%s' )", s.c_str() ); - return from_string( v.data(), v.data()+v.size() ); - } - value from_string( fc::vector&& v ) { - error_collector ec; - return to_value( v.data(), v.data() + v.size(), ec ); - } - - value from_string( const char* s, const char* e ) { - return from_string( fc::vector(s,e) ); - } - -} } diff --git a/src/json_rpc_connection.cpp b/src/json_rpc_connection.cpp deleted file mode 100644 index 4f96cba..0000000 --- a/src/json_rpc_connection.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { namespace json { - - namespace detail { - - void pending_result::handle_error( const fc::string& e ) { - try { - FC_THROW_MSG( "%s", e ); - } catch ( ... ) { - set_exception( fc::current_exception() ); - } - } - - } - - class rpc_connection::impl : public fc::retainable { - public: - impl():_next_req_id(0){ } - ~impl(){ cancel_pending_requests(); } - int64_t _next_req_id; - std::unordered_map _methods; - - detail::pending_result::ptr _pr_head; - detail::pending_result::ptr _pr_tail; - - void cancel_pending_requests() { - auto cur = _pr_head; - while( cur ) { - cur->set_exception( fc::copy_exception( fc::generic_exception("canceled") ) ); - cur = cur->next; - } - _pr_head.reset(); - _pr_tail.reset(); - } - }; - - - void rpc_connection::add_method( const fc::string& name, fc::shared_ptr&& p ) { - my->_methods[name] = fc::move(p); - } - void rpc_connection::handle_message( const value& v ) { - auto id_itr = v.find( "id" ); - auto m_itr = v.find( "method" ); - auto end = v.end(); - - if( m_itr != end ) { - fc::string mname = value_cast(m_itr->val); - - auto smeth = my->_methods.find( mname ); - if( smeth == my->_methods.end() ) { - if( id_itr != end ) { - // TODO: send invalid method reply - auto id = value_cast(id_itr->val); - send_error( id, fc::json::error_object( "Unknown method '"+mname+"'" )); - } - // nothing to do, unknown method - } else { // known method, attempt to call it and send reply; - auto p_itr = v.find( "params" ); - - value nul; - const value& params = (p_itr != end) ? p_itr->val : nul; - // slog( "params '%s'", to_string( params ).c_str() ); - - if( id_itr != end ) { // capture reply - auto id = value_cast(id_itr->val); - try { - send_result( id, smeth->second->call(params) ); - } catch ( fc::error_report& eo ) { - if( eo.stack.size() ) { - send_error( id, error_object( eo.current().desc, fc::value(eo) ) ); - } else { - send_error( id, error_object( "error report", fc::value(eo) ) ); - } - } catch ( const fc::json::error_object& eo ) { - wlog( "%s", eo.message.c_str() ); - send_error( id, eo ); - } catch ( ... ) { - wlog( "%s", fc::except_str().c_str() ); - send_error( id, error_object( fc::except_str(), fc::value() ) ); - } - } else { // ignore exception + result - try { smeth->second->call( params ); }catch(...){} - } - } - return; - } else if( id_itr != end ) { // we id but no method, therefore potential reply - int id = value_cast(id_itr->val); - auto cur = my->_pr_head; - decltype(cur) prev; - while( cur ) { - if( cur->id == id ) { - if( prev ) prev->next = cur->next; - else my->_pr_head = cur->next; - if( !cur->next ) my->_pr_tail = cur->next; - - try { - auto r_itr = v.find( "result" ); - if( r_itr != end ) { - cur->handle_result( r_itr->val ); - } else { - auto e_itr = v.find( "error" ); - if( e_itr != end ) { - cur->set_exception( fc::value_cast(e_itr->val["data"]).copy_exception() ); - } else { - elog( "no result nor error field" ); - } - } - } catch( ... ) { - cur->set_exception( fc::current_exception() ); - } - return; - } - cur = cur->next; - } - FC_THROW_REPORT( "Unexpected reply with id ${id}", id_itr->val ); - } - FC_THROW_REPORT( "Method with no 'id' or 'method' field" ); - } - - - rpc_connection::rpc_connection() - :my( new impl() ){ } - - rpc_connection::rpc_connection( const rpc_connection& c ) - :my(c.my){ } - rpc_connection::rpc_connection( rpc_connection&& c ) { - fc_swap(my,c.my); - } - rpc_connection::~rpc_connection() { - } - - rpc_connection& rpc_connection::operator=(const rpc_connection& m) { - my= m.my; - return *this; - } - rpc_connection& rpc_connection::operator=(rpc_connection&& m) { - fc_swap(m.my,my); - return *this; - } - - void rpc_connection::cancel_pending_requests() { - my->cancel_pending_requests(); - } - - void rpc_connection::invoke( detail::pending_result::ptr&& p, - const fc::string& m, value&& param ) { - p->id = my->_next_req_id; - if( my->_pr_tail ) { - my->_pr_tail->next = p; - my->_pr_tail = my->_pr_tail->next; - } else { - my->_pr_tail = p; - my->_pr_head = my->_pr_tail; - } - send_invoke( my->_next_req_id++, m, fc::move(param) ); - } - - -} } // fc::json diff --git a/src/json_rpc_error_object.cpp b/src/json_rpc_error_object.cpp deleted file mode 100644 index 0c6a189..0000000 --- a/src/json_rpc_error_object.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include - - -namespace fc { namespace json { - error_object::error_object( const fc::string& m, const fc::value& v, int64_t c ) - :code(c),message(m),data(v){ } - error_object::error_object(const fc::string& m, int64_t c) - :code(c),message(m){ } - error_object::error_object(const error_object& e) - :code(e.code),message(e.message),data(e.data){} - error_object::~error_object(){} -}} diff --git a/src/json_rpc_stream_connection.cpp b/src/json_rpc_stream_connection.cpp deleted file mode 100644 index e00d11a..0000000 --- a/src/json_rpc_stream_connection.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include - -namespace fc { namespace json { - - class rpc_stream_connection::impl : public fc::retainable { - public: - fc::istream& in; - fc::ostream& out; - rpc_stream_connection& self; - std::function on_close; - - fc::logger log; - - impl( fc::istream& i, fc::ostream& o, rpc_stream_connection& s ) - :in(i),out(o),self(s){ - _read_loop_complete = fc::async( [=](){ read_loop(); } ); - log = logger::get( "fc::json::rpc_stream_connection" ); - } - - ~impl() { - try { - self.cancel_pending_requests(); - _read_loop_complete.cancel(); - _read_loop_complete.wait(); - } catch ( ... ) {} - } - - fc::future _read_loop_complete; - void read_loop() { - try { - fc::string line; - fc::getline( in, line ); - while( !in.eof() ) { - fc::async( [=]() { - try { - fc_dlog( log, "Received: '${line}'", ("line",line) ); - fc::value v= fc::json::from_string( line ); - self.handle_message(v); - } catch ( fc::error_report& er ) { - fc_wlog( log, "Error handling request '${line}'\n ${report}", ("line",line)("report",er.to_detail_string() ) ); - } catch (...) { - fc_wlog( log, "Error handling request '${exception}'",("exception",fc::except_str()) ); - return; - } - }); - fc::getline( in, line ); - } - } catch ( ... ) { - wlog( "%s", fc::except_str().c_str() ); - } - // slog( "cancel..."); - self.cancel_pending_requests(); - // slog( "close!" ); - if( !!on_close ) on_close(); - } - }; - - rpc_stream_connection::rpc_stream_connection( fc::istream& i, fc::ostream& o ) - :my( new impl(i,o,*this) ){ - } - rpc_stream_connection::rpc_stream_connection(){ } - rpc_stream_connection::rpc_stream_connection(const rpc_stream_connection& c):my(c.my){ } - rpc_stream_connection::~rpc_stream_connection(){ - close(); - } - - // the life of the streams must exceed the life of all copies - // of this rpc_stream_connection - void rpc_stream_connection::open( fc::istream& i, fc::ostream& o) { - my.reset( new impl(i,o,*this) ); - } - - // cancels all pending requests, closes the ostream - // results on_close() being called if the stream is not already closed. - void rpc_stream_connection::close() { - if( my ) my->out.close(); - my.reset(nullptr); - } - - /** - * When the connection is closed, call the given method - */ - void rpc_stream_connection::on_close( const std::function& oc ) { - my->on_close = oc; - } - - void rpc_stream_connection::send_invoke( uint64_t id, const fc::string& m, value&& param ) { - fc::stringstream ss; - ss<<"{\"id\":"<log, "Sent: '${line}'", ("line",o) ); - my->out.write( o.c_str(), o.size() ); - my->out.flush(); - } - void rpc_stream_connection::send_notice( const fc::string& m, value&& param ) { - fc::stringstream ss; - ss<<"{\"method\":\""<log, "Sent: '${line}'", ("line",o) ); - my->out.write( o.c_str(), o.size() ); - my->out.flush(); - } - void rpc_stream_connection::send_error( uint64_t id, const json::error_object& eo ) { - fc::stringstream ss; - ss<<"{\"id\":"<log, "Sent: '${line}'", ("line",o) ); - my->out.write( o.c_str(), o.size() ); - my->out.flush(); - } - void rpc_stream_connection::send_result( uint64_t id, value&& r ) { - fc::stringstream ss; - ss<<"{\"id\":"<log, "Sent: '${line}'", ("line",o) ); - my->out.write( o.c_str(), o.size() ); - my->out.flush(); - } - -} } // fc::json - - - diff --git a/src/json_rpc_tcp_connection.cpp b/src/json_rpc_tcp_connection.cpp deleted file mode 100644 index 52dfee9..0000000 --- a/src/json_rpc_tcp_connection.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include - -namespace fc { - - namespace json { - class rpc_tcp_connection::impl : public fc::retainable { - public: - tcp_socket sock; - ~impl(){ } - }; - - rpc_tcp_connection::rpc_tcp_connection() - :my( new impl() ){ - } - rpc_tcp_connection::rpc_tcp_connection( const rpc_tcp_connection& c ) - :rpc_stream_connection(c),my(c.my){} - - rpc_tcp_connection::~rpc_tcp_connection(){ - close(); - } - - void rpc_tcp_connection::connect_to( const fc::ip::endpoint& ep ) { - my->sock.connect_to(ep); - open( my->sock, my->sock ); - } - void rpc_tcp_connection::start() { - open( my->sock, my->sock ); - } - void rpc_tcp_connection::close() { - rpc_stream_connection::close(); - //my->sock.close(); - } - - tcp_socket& rpc_tcp_connection::get_socket()const { return my->sock; } - - - } - -} diff --git a/src/json_rpc_tcp_server.cpp b/src/json_rpc_tcp_server.cpp deleted file mode 100644 index f5e6d39..0000000 --- a/src/json_rpc_tcp_server.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include - -namespace fc { - namespace json { - class rpc_tcp_server::impl { - public: - std::function on_con; - fc::tcp_server tcp_serv; - fc::vector cons; - }; - rpc_tcp_server::rpc_tcp_server() - :my( new impl() ){} - rpc_tcp_server::~rpc_tcp_server() { - delete my; - } - - void rpc_tcp_server::on_new_connection( const std::function& c ) { - my->on_con = c; - } - - void rpc_tcp_server::listen( uint16_t port ) { - - my->tcp_serv.listen(port); - fc::async([this](){ - try { - rpc_tcp_connection::ptr con(new rpc_tcp_connection() ); - while( my->tcp_serv.accept( con->get_socket() ) ) { - slog( "new connection!" ); - my->on_con( *con ); - con->start(); - rpc_tcp_connection* tcpc = con.get(); - my->cons.push_back(con); - con->on_close( [=]() { - for( int i = 0; i < my->cons.size(); ++i ) { - if( my->cons[i].get() == tcpc ) { - fc_swap( my->cons[i], my->cons.back() ); - auto tmp = my->cons.back(); - my->cons.pop_back(); - fc::async([tmp](){slog("free con");}); - // TODO: swap to end, pop back - return; - } - } - }); - con.reset(new rpc_tcp_connection() ); - } - } catch ( ... ) { - wlog( "tcp listen failed..." ); - } - }); - } - - - } -} diff --git a/src/lexical_cast.cpp b/src/lexical_cast.cpp deleted file mode 100644 index 142e200..0000000 --- a/src/lexical_cast.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -namespace fc { - - namespace detail { - double to_double( const fc::string& s ) { - return boost::lexical_cast(s.c_str()); - } - int64_t to_int64( const fc::string& s ) { - return boost::lexical_cast(s.c_str()); - } - uint64_t to_uint64( const fc::string& s ) { - return boost::lexical_cast(s.c_str()); - } - fc::string to_string( double d ){ return boost::lexical_cast(d); } - #ifdef __APPLE__ - fc::string to_string( size_t d ){ return boost::lexical_cast(d); } - #endif - fc::string to_string( uint64_t d ){ return boost::lexical_cast(d); } - fc::string to_string( uint32_t d ){ return boost::lexical_cast(d); } - fc::string to_string( uint16_t d ){ return boost::lexical_cast(d); } - fc::string to_string( uint8_t d ){ return boost::lexical_cast(d); } - fc::string to_string( int64_t d ){ return boost::lexical_cast(d); } - fc::string to_string( int32_t d ){ return boost::lexical_cast(d); } - fc::string to_string( int16_t d ){ return boost::lexical_cast(d); } - fc::string to_string( int8_t d ){ return boost::lexical_cast(d); } - fc::string to_string( char d ){ return boost::lexical_cast(d); } - } -} diff --git a/src/log.cpp b/src/log.cpp deleted file mode 100644 index fa10025..0000000 --- a/src/log.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif - -#include -#include - -namespace fc { - const char* thread_name(); - void* thread_ptr(); - - const char* short_name( const char* file_name ) { - const char* end = file_name + strlen(file_name); - --end; - while( end >= file_name ) { - if( *end == '/' || *end == '\\' ) { - return end + 1; - } - --end; - } - return file_name; - } - boost::mutex& log_mutex() { - static boost::mutex* m = new boost::mutex(); return *m; - } - - #ifdef WIN32 - #define isatty _isatty - #define fileno _fileno - #endif // WIN32 - - void log( const char* color, const char* file_name, size_t line_num, - const char* method_name, const char* format, ... ) { - #ifndef WIN32 - if(isatty(fileno(stderr))) - fprintf( stderr, "\r%s",color); - #endif - fc::unique_lock lock(log_mutex()); - // fc::string sname = fc::path(file_name).filename().generic_string(); - fprintf( stderr, "%-15s %-15s %-5d %-15s ", thread_name(), short_name(file_name), int(line_num), method_name ); - va_list args; - va_start(args,format); - vfprintf( stderr, format, args ); - va_end(args); - #ifndef WIN32 - if (isatty(fileno(stderr))) - fprintf( stderr, "%s", CONSOLE_DEFAULT ); - #endif - fprintf( stderr, "\n" ); - fflush( stderr ); - return; - } - - /** used to add extra fields to be printed (thread,fiber,time,etc) */ - void add_log_field( void (*f)( ) ) { - } - - void remove_log_field( void (*f)( ) ) { - } -} diff --git a/src/appender.cpp b/src/log/appender.cpp similarity index 59% rename from src/appender.cpp rename to src/log/appender.cpp index 6140479..737625c 100644 --- a/src/appender.cpp +++ b/src/log/appender.cpp @@ -1,14 +1,14 @@ -#include -#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include "console_defines.h" namespace fc { @@ -22,6 +22,8 @@ namespace fc { return lm; } appender::ptr appender::get( const fc::string& s ) { + static fc::spin_lock appender_spinlock; + scoped_lock lock(appender_spinlock); return get_appender_map()[s]; } bool appender::register_appender( const fc::string& type, const appender_factory::ptr& f ) @@ -29,11 +31,11 @@ namespace fc { get_appender_factory_map()[type] = f; return true; } - appender::ptr appender::create( const fc::string& name, const fc::string& type, const value& args ) + appender::ptr appender::create( const fc::string& name, const fc::string& type, const variant& args ) { auto fact_itr = get_appender_factory_map().find(type); if( fact_itr == get_appender_factory_map().end() ) { - wlog( "Unknown appender type '%s'", type.c_str() ); + //wlog( "Unknown appender type '%s'", type.c_str() ); return appender::ptr(); } auto ap = fact_itr->second->create( args ); @@ -41,4 +43,6 @@ namespace fc { return ap; } + static bool reg_console_appender = appender::register_appender( "console" ); + static bool reg_file_appender = appender::register_appender( "file" ); } // namespace fc diff --git a/src/log/console_appender.cpp b/src/log/console_appender.cpp new file mode 100644 index 0000000..31341f3 --- /dev/null +++ b/src/log/console_appender.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#define COLOR_CONSOLE 1 +#include "console_defines.h" +#include +#include + +namespace fc { + console_appender::console_appender( const variant& args ) + { + try + { + cfg = args.as();//fc::variant_cast(args); + for( int i = 0; i < log_level::off+1; ++i ) + lc[i] = color::console_default; + for( auto itr = cfg.level_colors.begin(); itr != cfg.level_colors.end(); ++itr ) + lc[itr->level] = itr->color; + } + catch ( exception& e ) + { + fc::cerr< lock(log_mutex()); + #ifndef WIN32 + if(isatty(fileno(out))) fprintf( out, "\r%s", get_color( m.get_context().get_log_level() ) ); + #endif + + fprintf( out, "%s", fmt_str.c_str() ); + + #ifndef WIN32 + if(isatty(fileno(out))) fprintf( out, "\r%s", CONSOLE_DEFAULT ); + #endif + fprintf( out, "\n" ); + if( cfg.flush ) fflush( out ); + } + +} diff --git a/include/fc/console_defines.h b/src/log/console_defines.h similarity index 100% rename from include/fc/console_defines.h rename to src/log/console_defines.h diff --git a/src/file_appender.cpp b/src/log/file_appender.cpp similarity index 54% rename from src/file_appender.cpp rename to src/log/file_appender.cpp index 7e9b6ad..b30ec3b 100644 --- a/src/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -1,10 +1,11 @@ -#include +#include #include -#include +#include #include -#include -#include -#include +#include +#include +#include + namespace fc { class file_appender::impl : public fc::retainable { @@ -14,27 +15,27 @@ namespace fc { boost::mutex slock; }; file_appender::config::config( const fc::path& p ) - :format( "${when} ${thread} ${context} ${file}:${line} ${method} ${level}] ${message}" ), + :format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ), filename(p),flush(true),truncate(true){} - file_appender::file_appender( const value& args ) + file_appender::file_appender( const variant& args ) :my( new impl() ) { try { - my->cfg = fc::value_cast(args); + my->cfg = args.as(); my->out.open( my->cfg.filename.string().c_str() ); } catch ( ... ) { - elog( "%s", fc::except_str().c_str() ); + //elog( "%s", fc::except_str().c_str() ); } } file_appender::~file_appender(){} void file_appender::log( const log_message& m ) { - fc::string message = fc::substitute( m.format, m.args ); - fc::value lmsg(m); + fc::string message = fc::format_string( m.get_format(), m.get_data() ); + fc::variant lmsg(m); - fc::string fmt_str = fc::substitute( my->cfg.format, value(m).set( "message", message) ); + fc::string fmt_str = fc::format_string( my->cfg.format, mutable_variant_object(lmsg.get_object())( "message", message) ); { fc::scoped_lock lock(my->slock); my->out << fmt_str << "\n"; diff --git a/src/log/log_message.cpp b/src/log/log_message.cpp new file mode 100644 index 0000000..42e9491 --- /dev/null +++ b/src/log/log_message.cpp @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc +{ + namespace detail + { + class log_context_impl + { + public: + log_level level; + string file; + uint64_t line; + string method; + string thread_name; + string hostname; + string context; + time_point timestamp; + }; + + class log_message_impl + { + public: + log_message_impl( log_context&& ctx ) + :context( std::move(ctx) ){} + log_message_impl(){} + + log_context context; + string format; + variant_object args; + }; + } + + + + log_context::log_context() + :my( std::make_shared() ){} + + log_context::log_context( log_level ll, const char* file, uint64_t line, + const char* method ) + :my( std::make_shared() ) + { + my->level = ll; + my->file = fc::path(file).filename().generic_string(); // TODO truncate filename + my->line = line; + my->method = method; + my->timestamp = time_point::now(); + my->thread_name = fc::thread::current().name(); + } + + log_context::log_context( const variant& v ) + :my( std::make_shared() ) + { + auto obj = v.get_object(); + my->level = obj["level"].as(); + my->file = obj["file"].as_string(); + my->line = obj["line"].as_uint64(); + my->method = obj["method"].as_string(); + my->method = obj["hostname"].as_string(); + my->thread_name = obj["thread_name"].as_string(); + my->timestamp = obj["timestamp"].as(); + if( obj.contains( "context" ) ) + my->context = obj["context"].as(); + } + + fc::string log_context::to_string()const + { + return my->thread_name + " " + my->file + ":" + fc::to_string(my->line) + " " + my->method; + + } + + void log_context::append_context( const fc::string& s ) + { + my->context += "->" + s; + } + + log_context::~log_context(){} + + + void to_variant( const log_context& l, variant& v ) + { + v = l.to_variant(); + } + + void from_variant( const variant& l, log_context& c ) + { + c = log_context(l); + } + + void from_variant( const variant& l, log_message& c ) + { + c = log_message(l); + } + void to_variant( const log_message& m, variant& v ) + { + v = m.to_variant(); + } + + void to_variant( log_level e, variant& v ) + { + switch( e ) + { + case log_level::all: + v = "all"; + return; + case log_level::debug: + v = "debug"; + return; + case log_level::info: + v = "info"; + return; + case log_level::warn: + v = "warn"; + return; + case log_level::error: + v = "error"; + return; + case log_level::off: + v = "off"; + return; + } + } + void from_variant( const variant& v, log_level& e ) + { + try + { + if( v.as_string() == "all" ) e = log_level::all; + else if( v.as_string() == "debug" ) e = log_level::debug; + else if( v.as_string() == "info" ) e = log_level::info; + else if( v.as_string() == "warn" ) e = log_level::warn; + else if( v.as_string() == "error" ) e = log_level::error; + else if( v.as_string() == "off" ) e = log_level::off; + else FC_THROW_EXCEPTION( bad_cast_exception, "Failed to cast from Variant to log_level" ); + } FC_RETHROW_EXCEPTIONS( error, + "Expected 'all|debug|info|warn|error|off', but got '${variant}'", + ("variant",v) ); + } + + + + string log_context::get_file()const { return my->file; } + uint64_t log_context::get_line_number()const { return my->line; } + string log_context::get_method()const { return my->method; } + string log_context::get_thread_name()const { return my->thread_name; } + string log_context::get_host_name()const { return my->hostname; } + time_point log_context::get_timestamp()const { return my->timestamp; } + log_level log_context::get_log_level()const{ return my->level; } + + + variant log_context::to_variant()const + { + mutable_variant_object o; + o( "level", variant(my->level) ) + ( "file", my->file ) + ( "line", my->line ) + ( "method", my->method ) + ( "hostname", my->hostname ) + ( "thread_name", my->thread_name ) + ( "timestamp", variant(my->timestamp) ); + + if( my->context.size() ) + o( "context", my->context ); + + return o; + } + + log_message::~log_message(){} + log_message::log_message() + :my( std::make_shared() ){} + + log_message::log_message( log_context ctx, const char* format, variant_object args ) + :my( std::make_shared(std::move(ctx)) ) + { + my->format = format; + my->args = std::move(args); + } + + log_message::log_message( const variant& v ) + :my( std::make_shared( log_context( v.get_object()["context"] ) ) ) + { + my->format = v.get_object()["format"].as_string(); + my->args = v.get_object()["data"].get_object(); + } + + variant log_message::to_variant()const + { + return mutable_variant_object( "context", my->context ) + ( "format", my->format ) + ( "data", my->args ); + } + + log_context log_message::get_context()const { return my->context; } + string log_message::get_format()const { return my->format; } + variant_object log_message::get_data()const { return my->args; } + + string log_message::get_message()const + { + return format_string( my->format, my->args ); + } + + +} // fc + diff --git a/src/logger.cpp b/src/log/logger.cpp similarity index 59% rename from src/logger.cpp rename to src/log/logger.cpp index f1615fd..830a279 100644 --- a/src/logger.cpp +++ b/src/log/logger.cpp @@ -1,36 +1,14 @@ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include -// tmp... -#include - namespace fc { - log_message::log_message(){} - log_message::log_message(log_level::type ll, const string& f, int l, const string& fun, const string& fmt ) - :when( fc::time_point::now() ), level(ll), thread( fc::thread::current().name() ),file(fc::path(f).filename().generic_string()),line(l),method(fun),format(fmt){} - - log_message& log_message::operator()( const fc::string& k, fc::value&& v ) { - args[k] = fc::move(v); - return *this; - } - log_message& log_message::operator()( fc::value&& v ) { - args.push_back( fc::move(v) ); - return *this; - } - log_message& log_message::operator()( const fc::string& k, const fc::value& v ) { - args[k] = v; - return *this; - } - log_message& log_message::operator()( const fc::value& v ) { - args.push_back( v ); - return *this; - } class logger::impl : public fc::retainable { public: @@ -40,7 +18,7 @@ namespace fc { logger _parent; bool _enabled; bool _additivity; - log_level::type _level; + log_level _level; fc::vector _appenders; }; @@ -49,7 +27,15 @@ namespace fc { logger::logger() :my( new impl() ){} - logger::logger(std::nullptr_t){} + logger::logger(nullptr_t){} + + logger::logger( const string& name, const logger& parent ) + :my( new impl() ) + { + my->_name = name; + my->_parent = parent; + } + logger::logger( const logger& l ) :my(l.my){} @@ -70,13 +56,13 @@ namespace fc { bool operator==( const logger& l, std::nullptr_t ) { return !l.my; } bool operator!=( const logger& l, std::nullptr_t ) { return l.my; } - bool logger::is_enabled( log_level::type e )const { + bool logger::is_enabled( log_level e )const { return e >= my->_level; } void logger::log( log_message m ) { - if( !m.context ) m.context = my->_name; - else m.context = *m.context + "->" + my->_name; + m.get_context().append_context( my->_name ); + for( auto itr = my->_appenders.begin(); itr != my->_appenders.end(); ++itr ) (*itr)->log( m ); @@ -87,8 +73,12 @@ namespace fc { void logger::set_name( const fc::string& n ) { my->_name = n; } const fc::string& logger::name()const { return my->_name; } + extern bool do_default_config; + std::unordered_map& get_logger_map() { + static bool force_link_default_config = fc::do_default_config; static std::unordered_map lm; + (void)force_link_default_config; // hide warning; return lm; } @@ -101,8 +91,8 @@ namespace fc { logger logger::get_parent()const { return my->_parent; } logger& logger::set_parent(const logger& p) { my->_parent = p; return *this; } - log_level::type logger::get_log_level()const { return my->_level; } - logger& logger::set_log_level(log_level::type ll) { my->_level = ll; return *this; } + log_level logger::get_log_level()const { return my->_level; } + logger& logger::set_log_level(log_level ll) { my->_level = ll; return *this; } void logger::add_appender( const fc::shared_ptr& a ) { my->_appenders.push_back(a); } diff --git a/src/logger_config.cpp b/src/log/logger_config.cpp similarity index 57% rename from src/logger_config.cpp rename to src/log/logger_config.cpp index 95619ba..5762b8d 100644 --- a/src/logger_config.cpp +++ b/src/log/logger_config.cpp @@ -1,15 +1,18 @@ -#include -#include -#include +#include +#include +#include #include #include #include -#include -#include +#include +#include +#include +#include +#include namespace fc { - std::unordered_map& get_logger_map(); - std::unordered_map& get_appender_map(); + extern std::unordered_map& get_logger_map(); + extern std::unordered_map& get_appender_map(); logger_config& logger_config::add_appender( const string& s ) { appenders.push_back(s); return *this; } void configure_logging( const fc::path& lc ) @@ -18,6 +21,7 @@ namespace fc { } bool configure_logging( const logging_config& cfg ) { + try { static bool reg_console_appender = appender::register_appender( "console" ); static bool reg_file_appender = appender::register_appender( "file" ); get_logger_map().clear(); @@ -43,34 +47,35 @@ namespace fc { auto ap = appender::get( *a ); if( ap ) { lgr.add_appender(ap); } } + return reg_console_appender || reg_file_appender; } - return true; + } catch ( exception& e ) + { + fc::cerr< -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -FC_START_SHARED_IMPL(fc::http::connection) +class fc::http::connection::impl +{ + public: fc::tcp_socket sock; fc::ip::endpoint ep; impl() { @@ -17,7 +20,7 @@ FC_START_SHARED_IMPL(fc::http::connection) int read_until( char* buffer, char* end, char c = '\n' ) { char* p = buffer; // try { - while( p < end && !sock.read(p,1).eof() ) { + while( p < end && 1 == sock.readsome(p,1) ) { if( *p == c ) { *p = '\0'; return (p - buffer)-1; @@ -37,7 +40,7 @@ FC_START_SHARED_IMPL(fc::http::connection) fc::vector line(1024*8); int s = read_until( line.data(), line.data()+line.size(), ' ' ); // HTTP/1.1 s = read_until( line.data(), line.data()+line.size(), ' ' ); // CODE - rep.status = fc::lexical_cast(fc::string(line.data())); + rep.status = static_cast(to_int64(fc::string(line.data()))); s = read_until( line.data(), line.data()+line.size(), '\n' ); // DESCRIPTION while( (s = read_until( line.data(), line.data()+line.size(), '\n' )) > 1 ) { @@ -52,31 +55,29 @@ FC_START_SHARED_IMPL(fc::http::connection) h.val = fc::string(skey,end); rep.headers.push_back(h); if( h.key == "Content-Length" ) { - rep.body.resize( fc::lexical_cast( fc::string(h.val) ) ); + rep.body.resize( static_cast(to_uint64( fc::string(h.val) ) )); } } if( rep.body.size() ) { - //slog( "Reading body size %d", rep.body.size() ); sock.read( rep.body.data(), rep.body.size() ); } return rep; - } catch ( ... ) { - elog( "%s", fc::except_str().c_str() ); + } catch ( fc::exception& e ) { + elog( "${exception}", ("exception",e.to_detail_string() ) ); sock.close(); - FC_THROW_REPORT( "Error parsing reply" ); rep.status = http::reply::InternalServerError; return rep; } } - -FC_END_SHARED_IMPL -#include +}; namespace fc { namespace http { -FC_REFERENCE_TYPE_IMPL( connection ) + connection::connection() + :my( new connection::impl() ){} + connection::~connection(){} // used for clients @@ -87,7 +88,7 @@ void connection::connect_to( const fc::ip::endpoint& ep ) { http::reply connection::request( const fc::string& method, const fc::string& url, - const fc::string& body ) { + const fc::string& body, const headers& he ) { if( !my->sock.is_open() ) { wlog( "Re-open socket!" ); @@ -98,6 +99,10 @@ http::reply connection::request( const fc::string& method, req << method <<" "<key <<": " << i->val<<"\r\n"; + } if( body.size() ) req << "Content-Length: "<< body.size() << "\r\n"; req << "\r\n"; fc::string head = req.str(); @@ -114,7 +119,7 @@ http::reply connection::request( const fc::string& method, return my->parse_reply(); } catch ( ... ) { my->sock.close(); - FC_THROW_REPORT( "Error Sending HTTP Request" ); // TODO: provide more info + FC_THROW_EXCEPTION( exception, "Error Sending HTTP Request" ); // TODO: provide more info // return http::reply( http::reply::InternalServerError ); // TODO: replace with connection error } } @@ -145,14 +150,16 @@ http::request connection::read_request()const { h.val = fc::string(skey,end); req.headers.push_back(h); if( h.key == "Content-Length" ) { - req.body.resize( fc::lexical_cast( fc::string(h.val) ) ); + req.body.resize( static_cast(to_uint64( fc::string(h.val) ) )); } if( h.key == "Host" ) { req.domain = h.val; } } + // TODO: some common servers won't give a Content-Length, they'll use + // Transfer-Encoding: chunked. handle that here. + if( req.body.size() ) { - slog( "Reading body size %d", req.body.size() ); my->sock.read( req.body.data(), req.body.size() ); } return req; diff --git a/src/http_server.cpp b/src/network/http/http_server.cpp similarity index 77% rename from src/http_server.cpp rename to src/network/http/http_server.cpp index 6349f06..e658a78 100644 --- a/src/http_server.cpp +++ b/src/network/http/http_server.cpp @@ -1,14 +1,17 @@ -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include namespace fc { namespace http { - class server::response::impl : public fc::retainable { + class server::response::impl : public fc::retainable + { public: - impl( const fc::http::connection& c, const std::function& cont = std::function() ) + impl( const fc::http::connection_ptr& c, const std::function& cont = std::function() ) :body_bytes_sent(0),body_length(0),con(c),handle_next_req(cont) {} @@ -27,18 +30,20 @@ namespace fc { namespace http { } ss << "Content-Length: "<get_socket().write( s.c_str(), s.size() ); } http::reply rep; int64_t body_bytes_sent; uint64_t body_length; - http::connection con; + http::connection_ptr con; std::function handle_next_req; }; - class server::impl : public fc::retainable { + class server::impl + { public: impl(){} impl(uint16_t p ) { @@ -53,28 +58,25 @@ namespace fc { namespace http { }catch(...){} } void accept_loop() { - try { - http::connection con; - while( tcp_serv.accept( con.get_socket() ) ) { - slog( "Accept Connection" ); + http::connection_ptr con = std::make_shared(); + while( tcp_serv.accept( con->get_socket() ) ) { + ilog( "Accept Connection" ); fc::async( [=](){ handle_connection( con, on_req ); } ); - con = http::connection(); + con = std::make_shared(); } - } catch ( ... ) { - wlog( "tcp listen failed...%s", fc::except_str().c_str() ); - } } - void handle_connection( const http::connection& c, + void handle_connection( const http::connection_ptr& c, std::function do_on_req ) { - wlog( "reading request.." ); try { http::server::response rep( fc::shared_ptr( new response::impl(c, [=](){ this->handle_connection(c,do_on_req); } ) ) ); - auto req = c.read_request(); + auto req = c->read_request(); if( do_on_req ) do_on_req( req, rep ); - } catch ( ... ) { - wlog( "unable to read request %s", fc::except_str().c_str()); + c->get_socket().close(); + } catch ( fc::exception& e ) { + wlog( "unable to read request ${1}", ("1", e.to_detail_string() ) );//fc::except_str().c_str()); } + wlog( "done handle connection" ); } std::function on_req; fc::tcp_server tcp_serv; @@ -84,10 +86,8 @@ namespace fc { namespace http { server::server(){} server::server( uint16_t port ) :my( new impl(port) ){} - server::server( const server& s ):my(s.my){} server::server( server&& s ):my(fc::move(s.my)){} - server& server::operator=(const server& s) { my = s.my; return *this; } server& server::operator=(server&& s) { fc_swap(my,s.my); return *this; } server::~server(){} @@ -131,10 +131,10 @@ namespace fc { namespace http { my->send_header(); } my->body_bytes_sent += len; - my->con.get_socket().write( data, len ); + my->con->get_socket().write( data, static_cast(len) ); if( my->body_bytes_sent == int64_t(my->body_length) ) { if( my->handle_next_req ) { - slog( "handle next request..." ); + ilog( "handle next request..." ); //fc::async( std::function(my->handle_next_req) ); fc::async( my->handle_next_req ); } diff --git a/src/ip.cpp b/src/network/ip.cpp similarity index 76% rename from src/ip.cpp rename to src/network/ip.cpp index f7f8840..9a906bd 100644 --- a/src/ip.cpp +++ b/src/network/ip.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include #include #include @@ -54,12 +54,24 @@ namespace fc { namespace ip { return string(_ip) + ':' + fc::string(boost::lexical_cast(_port).c_str()); } -} - void pack( fc::value& v, const fc::ip::endpoint& s ) { - v = fc::string(s); +} // namespace ip + + void to_variant( const ip::endpoint& var, variant& vo ) + { + vo = fc::string(var); } - void unpack( const fc::value& v, fc::ip::endpoint& s ) { - s = fc::ip::endpoint::from_string(fc::value_cast(v)); + void from_variant( const variant& var, ip::endpoint& vo ) + { + vo = ip::endpoint::from_string(var.as_string()); + } + + void to_variant( const ip::address& var, variant& vo ) + { + vo = fc::string(var); + } + void from_variant( const variant& var, ip::address& vo ) + { + vo = ip::address(var.as_string()); } } diff --git a/src/network/resolve.cpp b/src/network/resolve.cpp new file mode 100644 index 0000000..ec6b159 --- /dev/null +++ b/src/network/resolve.cpp @@ -0,0 +1,15 @@ +#include +#include + +namespace fc +{ + fc::vector resolve( const fc::string& host, uint16_t port ) + { + auto ep = fc::asio::tcp::resolve( host, std::to_string(uint64_t(port)) ); + fc::vector eps; + eps.reserve(ep.size()); + for( auto itr = ep.begin(); itr != ep.end(); ++itr ) + eps.push_back( fc::ip::endpoint(itr->address().to_v4().to_ulong(), itr->port()) ); + return eps; + } +} diff --git a/src/network/tcp_socket.cpp b/src/network/tcp_socket.cpp new file mode 100644 index 0000000..daabd2e --- /dev/null +++ b/src/network/tcp_socket.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include + +namespace fc { + + class tcp_socket::impl { + public: + impl():_sock( fc::asio::default_io_service() ){ } + ~impl(){ + if( _sock.is_open() ) _sock.close(); + } + boost::asio::ip::tcp::socket _sock; + }; + bool tcp_socket::is_open()const { + return my->_sock.is_open(); + } + + tcp_socket::tcp_socket(){}; + + tcp_socket::~tcp_socket(){}; + + void tcp_socket::flush() {} + void tcp_socket::close() { + if( is_open() ) my->_sock.close(); + } + + bool tcp_socket::eof()const { + return !my->_sock.is_open(); + } + + size_t tcp_socket::writesome( const char* buf, size_t len ) { + fc::cerr.write( buf, len ); + return fc::asio::write_some( my->_sock, boost::asio::buffer( buf, len ) ); + } + + + size_t tcp_socket::readsome( char* buf, size_t len ) { + auto r = fc::asio::read_some( my->_sock, boost::asio::buffer( buf, len ) ); + //fc::cerr.write( buf, r ); + return r; + } + + void tcp_socket::connect_to( const fc::ip::endpoint& e ) { + fc::asio::tcp::connect(my->_sock, fc::asio::tcp::endpoint( boost::asio::ip::address_v4(e.get_address()), e.port() ) ); + } + + class tcp_server::impl { + public: + impl(uint16_t port): + _accept( fc::asio::default_io_service(), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port) ){ + } + ~impl(){ + _accept.close(); + } + + boost::asio::ip::tcp::acceptor _accept; + }; + void tcp_server::close() { + if( my && my->_accept.is_open() ) my->_accept.close(); + delete my; my = nullptr; + } + tcp_server::tcp_server() + :my(nullptr) { + } + tcp_server::~tcp_server() { + delete my; + } + + + bool tcp_server::accept( tcp_socket& s ) { + if( !my ) return false; + fc::promise::ptr p( new promise("tcp::accept") ); + my->_accept.async_accept( s.my->_sock, [=]( const boost::system::error_code& e ) { + p->set_value(e); + } ); + auto ec = p->wait(); + if( ec ) FC_THROW_EXCEPTION( exception, "system error: ${message}", ("message", fc::string(boost::system::system_error(ec).what()) )); + return true; + } + void tcp_server::listen( uint16_t port ) { + if( my ) delete my; + my = new impl(port); + } + + + +} // namespace fc diff --git a/src/udp_socket.cpp b/src/network/udp_socket.cpp similarity index 85% rename from src/udp_socket.cpp rename to src/network/udp_socket.cpp index 334570e..45df767 100644 --- a/src/udp_socket.cpp +++ b/src/network/udp_socket.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include #include @@ -40,7 +40,10 @@ namespace fc { my->_sock.async_send_to( boost::asio::buffer(b,l), to_asio_ep(to), [=]( const boost::system::error_code& ec, size_t bt ) { if( !ec ) p->set_value(bt); - else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + else + p->set_exception( fc::exception_ptr( new fc::exception( + FC_LOG_MESSAGE( error, "${message} ", + ("message", boost::system::system_error(ec).what())) ) ) ); }); return p->wait(); } @@ -70,7 +73,9 @@ namespace fc { my->_sock.async_receive_from( boost::asio::buffer(b,l), from, [=]( const boost::system::error_code& ec, size_t bt ) { if( !ec ) p->set_value(bt); - else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + else p->set_exception( fc::exception_ptr( new fc::exception( + FC_LOG_MESSAGE( error, "${message} ", + ("message", boost::system::system_error(ec).what())) ) ) ); }); auto r = p->wait(); _from = to_fc_ep(from); diff --git a/src/network/url.cpp b/src/network/url.cpp new file mode 100644 index 0000000..23a7e79 --- /dev/null +++ b/src/network/url.cpp @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include + +namespace fc +{ + namespace detail + { + class url_impl + { + public: + void parse( const fc::string& s ) + { + fc::stringstream ss(s); + fc::string skip,_lpath,_largs,luser,lpass; + fc::getline( ss, _proto, ':' ); + fc::getline( ss, skip, '/' ); + fc::getline( ss, skip, '/' ); + + if( s.find('@') != size_t(fc::string::npos) ) { + fc::string user_pass; + fc::getline( ss, user_pass, '@' ); + fc::stringstream upss(user_pass); + if( user_pass.find( ':' ) != size_t(fc::string::npos) ) { + fc::getline( upss, luser, ':' ); + fc::getline( upss, lpass, ':' ); + _user = fc::move(luser); + _pass = fc::move(lpass); + } else { + _user = fc::move(user_pass); + } + } + fc::string host_port; + fc::getline( ss, host_port, '/' ); + auto pos = host_port.find( ':' ); + if( pos != fc::string::npos ) { + try { + _port = static_cast(to_uint64( host_port.substr( pos+1 ) )); + } catch ( ... ) { + FC_THROW_EXCEPTION( parse_error_exception, "Unable to parse port field in url",( "url", s ) ); + } + _host = host_port.substr(0,pos); + } else { + _host = fc::move(host_port); + } + fc::getline( ss, _lpath, '?' ); +#ifdef WIN32 + // On windows, a URL like file:///c:/autoexec.bat would result in _lpath = c:/autoexec.bat + // which is what we really want (it's already an absolute path) + if (!stricmp(_proto.c_str(), "file")) + _path = _lpath; + else + _path = fc::path( "/" ) / _lpath; // let other schemes behave like unix +#else + // On unix, a URL like file:///etc/rc.local would result in _lpath = etc/rc.local + // but we really want to make it the absolute path /etc/rc.local + _path = fc::path( "/" ) / _lpath; +#endif + fc::getline( ss, _largs ); + if( _args && _args->size() ) + { + // TODO: args = fc::move(_args); + } + } + + string _proto; + ostring _host; + ostring _user; + ostring _pass; + opath _path; + ovariant_object _args; + fc::optional _port; + }; + } + + void to_variant( const url& u, fc::variant& v ) + { + v = fc::string(u); + } + void from_variant( const fc::variant& v, url& u ) + { + u = url( v.as_string() ); + } + + url::operator string()const + { + fc::stringstream ss; + ss<_proto<<"://"; + if( my->_user ) { + ss << *my->_user; + if( my->_pass ) { + ss<<":"<<*my->_pass; + } + ss<<"@"; + } + if( my->_host ) ss<<*my->_host; + if( my->_port ) ss<<":"<<*my->_port; + if( my->_path ) ss<_path->generic_string(); + // if( my->_args ) ss<<"?"<<*my->_args; + return ss.str(); + } + + url::url( const fc::string& u ) + :my( std::make_shared() ) + { + my->parse(u); + } + + std::shared_ptr get_null_url() + { + static auto u = std::make_shared(); + return u; + } + + url::url() + :my( get_null_url() ) + { } + + url::url( const url& u ) + :my(u.my){} + + url::url( url&& u ) + :my( fc::move(u.my) ) + { + u.my = get_null_url(); + } + + url::url( const mutable_url& mu ) + :my( std::make_shared(*mu.my) ) + { + + } + url::url( mutable_url&& mu ) + :my( fc::move( mu.my ) ) + { } + + url::~url(){} + + url& url::operator=(const url& u ) + { + my = u.my; + return *this; + } + + url& url::operator=(url&& u ) + { + if( this != &u ) + { + my = fc::move(u.my); + u.my= get_null_url(); + } + return *this; + } + url& url::operator=(const mutable_url& u ) + { + my = std::make_shared(*u.my); + return *this; + } + url& url::operator=(mutable_url&& u ) + { + my = fc::move(u.my); + return *this; + } + + string url::proto()const + { + return my->_proto; + } + ostring url::host()const + { + return my->_host; + } + ostring url::user()const + { + return my->_user; + } + ostring url::pass()const + { + return my->_pass; + } + opath url::path()const + { + return my->_path; + } + ovariant_object url::args()const + { + return my->_args; + } + fc::optional url::port()const + { + return my->_port; + } + + + +} + diff --git a/src/pke.cpp b/src/pke.cpp deleted file mode 100644 index ad0e7d7..0000000 --- a/src/pke.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { - void pack( fc::value& v, const fc::public_key_t& s ) { - fc::vector ve = fc::raw::pack( s ); - v = to_base58( ve.data(), size_t(ve.size()) ); - } - void unpack( const fc::value& v, fc::public_key_t& s ) { - try { - auto ve = from_base58(fc::value_cast(v)); - s = fc::raw::unpack(ve); - } catch ( ... ) { - wlog( "error unpacking signature" ); - } - } - - void pack( fc::value& v, const fc::private_key_t& s ) { - fc::vector ve = fc::raw::pack( s ); - v = to_base58( ve.data(), ve.size() ); - } - void unpack( const fc::value& v, fc::private_key_t& s ) { - try { - auto ve = from_base58(fc::value_cast(v)); - s = fc::raw::unpack(ve); - } catch ( ... ) { - wlog( "error unpacking private_key" ); - } - } - void pack( fc::value& v, const fc::signature_t& s ) { - fc::vector ve = fc::raw::pack( s ); - v = to_base58( ve.data(), ve.size() ); - } - void unpack( const fc::value& v, fc::signature_t& s ) { - try { - auto ve = from_base58(fc::value_cast(v)); - s = fc::raw::unpack(ve); - } catch ( ... ) { - wlog( "error unpacking signature" ); - } - } - - RSA* get_pub( const char* key, uint32_t key_size, uint32_t pe ) - { - RSA* rsa = RSA_new(); - rsa->n = BN_bin2bn( (unsigned char*)key, key_size, NULL ); - rsa->e = BN_new(); - BN_set_word(rsa->e, pe ); - return rsa; - } - RSA* get_priv( const fc::vector& d, uint32_t /*key_size*/, uint32_t /*pe*/ ) - { - BIO* mem = (BIO*)BIO_new_mem_buf( (void*)&d.front(), d.size() ); - RSA* rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL ); - BIO_free(mem); - return rsa; - } - - bool verify_data( const char* key, uint32_t key_size, uint32_t pe, const sha1& digest, const char* sig ) - { - RSA* pub = get_pub( key,key_size,pe); - auto v = RSA_verify( NID_sha1, (const uint8_t*)digest.data(), 20, (uint8_t*)sig, key_size, pub ); - RSA_free(pub); - return 0 != v; - } - bool sign_data( const fc::vector& key, uint32_t key_size, uint32_t pe, const sha1& digest, char* sig ) - { - RSA* priv = get_priv( key,key_size,pe); - if( !priv ) { - generic_exception g(fc::generic_exception("Error loading private key: " + fc::string(ERR_error_string( ERR_get_error(),NULL))) ); - FC_THROW(g); - } - uint32_t slen = 0; - if( 1 != RSA_sign( NID_sha1, (uint8_t*)digest.data(), sizeof(digest), (unsigned char*)sig, &slen, priv ) ) - { - RSA_free(priv); - generic_exception g(fc::generic_exception("Error signing data: " + fc::string(ERR_error_string( ERR_get_error(),NULL))) ); - FC_THROW(g); - - } - RSA_free(priv); - return true; - } - - bool public_encrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ) - { - RSA* pub = get_pub( key,key_size/8,pe); - out.resize(RSA_size(pub)); - int rtn = RSA_public_encrypt( in.size(), (unsigned char*)&in.front(), (unsigned char*)&out.front(), pub, RSA_PKCS1_OAEP_PADDING ); - RSA_free(pub); - if( rtn >= 0 ) - { - out.resize(rtn); - return true; - } - out.resize(0); - FC_THROW( fc::generic_exception( ERR_error_string( ERR_get_error(), NULL ) ) ); - return false; - } - bool public_decrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ) - { - RSA* pub = get_pub( key,key_size/8,pe); - out.resize(RSA_size(pub)); - int rtn = RSA_public_decrypt( RSA_size(pub), (unsigned char*)&in.front(), (unsigned char*)&out.front(), pub, RSA_PKCS1_OAEP_PADDING ); - RSA_free(pub); - if( rtn >= 0 ) - { - out.resize(rtn); - return true; - } - out.resize(0); - FC_THROW( fc::generic_exception( ERR_error_string( ERR_get_error(), NULL ) ) ); - return false;; - } - bool private_encrypt( const fc::vector& key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ) - { - RSA* priv = get_priv( key,key_size/8,pe); - int rtn = RSA_private_encrypt( in.size(), (unsigned char*)&in.front(), (unsigned char*)&out.front(), priv, RSA_PKCS1_OAEP_PADDING ); - RSA_free(priv); - if( rtn >= 0 ) - { - out.resize(rtn); - return true; - } - out.resize(0); - return false;; - } - bool private_decrypt( const fc::vector& key, uint32_t key_size, uint32_t pe, const fc::vector& in, fc::vector& out ) - { - - RSA* priv = get_priv( key,key_size/8,pe); - out.resize(RSA_size(priv)); - int rtn = RSA_private_decrypt( in.size(), (unsigned char*)&in.front(), (unsigned char*)&out.front(), priv, RSA_PKCS1_OAEP_PADDING ); - RSA_free(priv); - if( rtn >= 0 ) - { - out.resize(rtn); - return true; - } - out.resize(0); - FC_THROW( fc::generic_exception( ERR_error_string( ERR_get_error(), NULL ) ) ); - return false; - } - - bool generate_keys( char* pubkey, fc::vector& privkey, uint32_t key_size, uint32_t pe ) - { - static bool init = true; - if( init ) { ERR_load_crypto_strings(); init = false; } - - RSA* rsa = RSA_generate_key( key_size, pe, NULL, NULL ); - BN_bn2bin( rsa->n, (unsigned char*)pubkey ); - - BIO *mem = BIO_new(BIO_s_mem()); - int e = PEM_write_bio_RSAPrivateKey(mem, rsa, NULL, NULL, 0, NULL, NULL ); - if( e != 1 ) - { - BIO_free(mem); - RSA_free(rsa); - FC_THROW(generic_exception("Error writing PrivateKey") ); - } - - char* dat; - uint32_t l = BIO_get_mem_data( mem, &dat ); - privkey.resize(l); - memcpy( &privkey.front(), dat, l ); - - BIO_free(mem); - RSA_free(rsa); - return true; - } -} diff --git a/src/process.cpp b/src/process.cpp deleted file mode 100644 index 4a79311..0000000 --- a/src/process.cpp +++ /dev/null @@ -1,221 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { - namespace bp = boost::process; - namespace io = boost::iostreams; - - fc::path find_executable_in_path( const fc::string name ) { - try { - return fc::string(bp::find_executable_in_path( std::string(name), "" )); - } catch (...) { - const char* p = std::getenv("PATH"); - FC_THROW_REPORT( "Unable to find executable ${exe} in path.", - fc::value().set("exe", name) - .set("inner", fc::except_str() ) - .set("PATH", fc::string(p!=nullptr?p:"") ) ); - } - return fc::path(); - } - - class process_sink : public io::sink { - public: - struct category : io::sink::category, io::flushable_tag {}; - typedef char type; - - process_sink( std::shared_ptr& p ):m_in(p){} - - std::streamsize write( const char* s, std::streamsize n ) { - if( !m_in ) return -1; - return static_cast(fc::asio::write( *m_in, - boost::asio::const_buffers_1( s, static_cast(n) ) )); - } - void close() { if(m_in) m_in->close(); } - bool flush() { return true; } - - private: - std::shared_ptr& m_in; - }; - - class process_source : public io::source { - public: - typedef char type; - - process_source( std::shared_ptr& pi ) - :m_pi(pi){} - - std::streamsize read( char* s, std::streamsize n ) { - if( !m_pi ) return -1; - try { - return static_cast(fc::asio::read_some( *m_pi, boost::asio::buffer( s, static_cast(n) ) )); - } catch ( const boost::system::system_error& e ) { - // wlog( "%s", fc::except_str().c_str() ); - if( e.code() == boost::asio::error::eof ) - return -1; - wlog( "%s", fc::except_str().c_str() ); - throw; - } catch ( ... ) { - //wlog( "%s", fc::except_str().c_str() ); - return -1; - } - } - private: - std::shared_ptr& m_pi; - }; -} // namespace fc - -FC_START_SHARED_IMPL( fc::process ) - public: - impl() - :stat( fc::asio::default_io_service() ), - std_out(process_source(outp)), - std_err(process_source(errp)), - std_in(process_sink(inp)), - _ins(std_in), - _outs(std_out), - _errs(std_err){} - - ~impl() { - try { - if( inp ) { - inp->close(); - } - if( _exited.valid() && !_exited.ready()) { - //child->terminate(); - _exited.wait(); - } - }catch(...) { - wlog( "caught exception cleaning up process: %s", fc::except_str().c_str() ); - } - } - - std::shared_ptr child; - std::shared_ptr outp; - std::shared_ptr errp; - std::shared_ptr inp; - - bp::status stat; - bp::context pctx; - - // provide useful buffering - io::stream std_out; - io::stream std_err; - io::stream std_in; - - fc::future _exited; - - // adapt to ostream and istream interfaces - fc::ostream_wrapper _ins; - fc::istream_wrapper _outs; - fc::istream_wrapper _errs; -FC_END_SHARED_IMPL -#include - -namespace fc { - -FC_REFERENCE_TYPE_IMPL( process ) - - -fc::future process::exec( const fc::path& exe, fc::vector&& args, - const fc::path& work_dir, int opt ) { - - my->pctx.work_dir = work_dir.string(); - - if( opt&open_stdout) - my->pctx.streams[boost::process::stdout_id] = bp::behavior::async_pipe(); - else - my->pctx.streams[boost::process::stdout_id] = bp::behavior::null(); - - - if( opt& open_stderr ) - my->pctx.streams[boost::process::stderr_id] = bp::behavior::async_pipe(); - else - my->pctx.streams[boost::process::stderr_id] = bp::behavior::null(); - - if( opt& open_stdout ) - my->pctx.streams[boost::process::stdin_id] = bp::behavior::async_pipe(); - else - my->pctx.streams[boost::process::stdin_id] = bp::behavior::close(); - - std::vector a; - a.reserve(size_t(args.size())); - for( uint32_t i = 0; i < args.size(); ++i ) { - a.push_back( args[i] ); - } - my->child.reset( new bp::child( bp::create_child( exe.string(), fc::move(a), my->pctx ) ) ); - - if( opt & open_stdout ) { - bp::handle outh = my->child->get_handle( bp::stdout_id ); - my->outp.reset( new bp::pipe( fc::asio::default_io_service(), outh.release() ) ); - } - if( opt & open_stderr ) { - bp::handle errh = my->child->get_handle( bp::stderr_id ); - my->errp.reset( new bp::pipe( fc::asio::default_io_service(), errh.release() ) ); - } - if( opt & open_stdin ) { - bp::handle inh = my->child->get_handle( bp::stdin_id ); - my->inp.reset( new bp::pipe( fc::asio::default_io_service(), inh.release() ) ); - } - - - promise::ptr p(new promise("process")); - my->stat.async_wait( my->child->get_id(), [=]( const boost::system::error_code& ec, int exit_code ) - { - //slog( "process::result %d", exit_code ); - if( !ec ) { - #ifdef BOOST_POSIX_API - try { - if( WIFEXITED(exit_code) ) - p->set_value( WEXITSTATUS(exit_code) ); - else { - FC_THROW_MSG( "process exited with: %s ", strsignal(WTERMSIG(exit_code)) ); - } - } catch ( ... ) { - p->set_exception( fc::current_exception() ); - } - #else - p->set_value(exit_code); - #endif - } - else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); - }); - return my->_exited = p; -} - -/** - * Forcefully kills the process. - */ -void process::kill() { - my->child->terminate(); -} - -/** - * @brief returns a stream that writes to the process' stdin - */ -fc::ostream& process::in_stream() { - return my->_ins; -} - -/** - * @brief returns a stream that reads from the process' stdout - */ -fc::istream& process::out_stream() { - return my->_outs; -} -/** - * @brief returns a stream that reads from the process' stderr - */ -fc::istream& process::err_stream() { - return my->_errs; -} - -} diff --git a/src/program_options.cpp b/src/program_options.cpp deleted file mode 100644 index eebc192..0000000 --- a/src/program_options.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include -#include - -namespace fc { namespace program_options { - - class options_description::impl { - public: - impl( const char* c ) - :opts(c){} - - boost::program_options::options_description opts; - }; - - options_description::options_description( const char* c ) - :my(c) - { } - - options_description::~options_description(){ - - } - - - options_description& options_description::add_options(){ - return *this; - } - - options_description& options_description::operator()( const char* o, const char* desc ){ - my->opts.add_options()( o, desc ); - return *this; - } - - options_description& options_description::operator()( const char* o, const value& v, const char* desc ){ - my->opts.add_options()( o, boost::program_options::value(reinterpret_cast(v.get())), desc ); - return *this; - } - - options_description& options_description::operator()( const char* o, const value& v, const char* desc ){ - my->opts.add_options()( o, boost::program_options::value(v.get()), desc ); - return *this; - } - - options_description& options_description::operator()( const char* o, const value >& v, const char* desc ){ - my->opts.add_options()( o, boost::program_options::value >(v.get()), desc ); - //my->opts.add_options()( o, desc ); - return *this; - } - - class variables_map::impl { - public: - boost::program_options::variables_map vm; - }; - - variables_map::variables_map(){} - variables_map::~variables_map(){} - - void variables_map::parse_command_line( int argc, char** argv, const options_description& d ) { - boost::program_options::store( boost::program_options::parse_command_line( argc, argv, d.my->opts ), my->vm ); - } - int variables_map::count( const char* opt ) { - return my->vm.count(opt); - } - - fc::ostream& operator<<( fc::ostream& o, const options_description& od ) { - std::stringstream ss; ss << od.my->opts; - fc::cout << ss.str().c_str(); - return o; - } - -} } diff --git a/src/reflect.cpp b/src/reflect.cpp deleted file mode 100644 index b5897fe..0000000 --- a/src/reflect.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include - -namespace fc { - void throw_bad_enum_cast( int64_t i, const char* e ) { - FC_THROW_REPORT( "Unknown field ${field} not in enum ${enum}", - fc::value().set("field",i).set("enum",e) ); - } - void throw_bad_enum_cast( const char* k, const char* e ){ - FC_THROW_REPORT( "Field '${field}' not in enum ${enum}", - fc::value().set("field",k).set("enum",e) ); - } -} diff --git a/src/rpc/json_connection.cpp b/src/rpc/json_connection.cpp new file mode 100644 index 0000000..c5f95a4 --- /dev/null +++ b/src/rpc/json_connection.cpp @@ -0,0 +1,464 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc { namespace rpc { + + namespace detail + { + class json_connection_impl + { + public: + json_connection_impl( fc::buffered_istream_ptr&& in, fc::buffered_ostream_ptr&& out ) + :_in(fc::move(in)),_out(fc::move(out)),_eof(false),_next_id(0),_logger("json_connection"){} + + fc::buffered_istream_ptr _in; + fc::buffered_ostream_ptr _out; + + fc::future _done; + bool _eof; + + uint64_t _next_id; + boost::unordered_map::ptr> _awaiting; + boost::unordered_map _methods; + boost::unordered_map _named_param_methods; + + fc::mutex _write_mutex; + //std::function _on_close; + + logger _logger; + + void send_result( variant id, variant result ) + { + { + fc::scoped_lock lock(_write_mutex); + *_out << "{\"id\":"; + json::to_stream( *_out, id ); + *_out << ",\"result\":"; + json::to_stream( *_out, result); + *_out << "}\n"; + } + _out->flush(); + } + void send_error( variant id, fc::exception& e ) + { + { + fc::scoped_lock lock(_write_mutex); + *_out << "{\"id\":"; + json::to_stream( *_out, id ); + *_out << ",\"error\":{\"message\":"; + json::to_stream( *_out, fc::string(e.what()) ); + *_out <<",\"code\":0,\"data\":"; + json::to_stream( *_out, variant(e)); + *_out << "}}\n"; + } + wlog( "exception: ${except}", ("except", variant(e)) ); + _out->flush(); + } + + void handle_message( const variant_object& obj ) + { + wlog( "recv: ${msg}", ("msg", obj) ); + try + { + auto m = obj.find("method"); + auto i = obj.find("id"); + if( m != obj.end() ) + { + try + { + auto p = obj.find("params"); + variant result; + if( p == obj.end() ) + { + auto pmi = _methods.find(m->value().as_string()); + auto nmi = _named_param_methods.find(m->value().as_string()); + if( pmi != _methods.end() ) + { + result = pmi->second( variants() ); + } + else if( nmi != _named_param_methods.end() ) + { + result = nmi->second( variant_object() ); + } + else // invalid method + { + FC_THROW_EXCEPTION( exception, "Invalid Method '${method}'", ("method",m->value().as_string())); + } + } + else if( p->value().is_array() ) + { + auto pmi = _methods.find(m->value().as_string()); + if( pmi != _methods.end() ) + { + result = pmi->second( p->value().get_array() ); + } + else // invalid method / param combo + { + FC_THROW_EXCEPTION( exception, "Invalid method or params '${method}'", + ("method",m->value().as_string())); + } + + } + else if( p->value().is_object() ) + { + auto nmi = _named_param_methods.find(m->value().as_string()); + if( nmi != _named_param_methods.end() ) + { + result = nmi->second( p->value().get_object() ); + } + else // invalid method / param combo? + { + FC_THROW_EXCEPTION( exception, "Invalid method or params '${method}'", + ("method",m->value().as_string())); + } + } + else // invalid params + { + FC_THROW_EXCEPTION( exception, "Invalid Params for method ${method}", + ("method",m->value().as_string())); + } + if( i != obj.end() ) + { + send_result( i->value(), result ); + } + } + catch ( fc::exception& e ) + { + if( i != obj.end() ) + { + send_error( i->value(), e ); + } + else + { + fc_wlog( _logger, "json rpc exception: ${exception}", ("exception",e) ); + } + } + } + else if( i != obj.end() ) + { + uint64_t id = i->value().as_int64(); + auto await = _awaiting.find(id); + if( await != _awaiting.end() ) + { + auto r = obj.find("result"); + auto e = obj.find("error"); + if( r != obj.end() ) + { + await->second->set_value( r->value() ); + } + else if( e != obj.end() ) + { + try + { + auto err = e->value().get_object(); + auto data = err.find( "data" ); + if( data != err.end() ) + { + wlog( "exception: ${except}", ("except", data->value() ) ); + await->second->set_exception( data->value().as().dynamic_copy_exception() ); + } + else + await->second->set_exception( exception_ptr(new FC_EXCEPTION( exception, "${error}", ("error",e->value()) ) ) ); + } + catch ( fc::exception& e ) + { + elog( "Error parsing exception: ${e}", ("e", e.to_detail_string() ) ); + await->second->set_exception( e.dynamic_copy_exception() ); + } + } + else // id found without error, result, nor method field + { + fc_wlog( _logger, "no error or result specified in '${message}'", ("message",obj) ); + } + } + } + else // no method nor request id... invalid message + { + + } + } + catch ( fc::exception& e ) // catch all other errors... + { + fc_elog( _logger, "json rpc exception: ${exception}", ("exception",e )); + elog( "json rpc exception: ${exception}", ("exception",e )); + close(e.dynamic_copy_exception()); + } + } + + void read_loop() + { + try + { + fc::string line; + while( true ) + { + variant v = json::from_stream(*_in); + ///ilog( "input: ${in}", ("in", v ) ); + wlog( "recv: ${line}", ("line", line) ); + fc::async([=](){ handle_message(v.get_object()); }); + } + } + catch ( eof_exception& eof ) + { + _eof = true; + wlog( "close" ); + close( eof.dynamic_copy_exception() ); + } + catch ( exception& e ) + { + wlog( "close" ); + close( e.dynamic_copy_exception() ); + } + catch ( ... ) + { + wlog( "close" ); + close( fc::exception_ptr(new FC_EXCEPTION( unhandled_exception, "json connection read error" )) ); + } + wlog( "close" ); + } + + void close( fc::exception_ptr e ) + { + wlog( "close ${reason}", ("reason", e->to_detail_string() ) ); + for( auto itr = _awaiting.begin(); itr != _awaiting.end(); ++itr ) + { + itr->second->set_exception( e->dynamic_copy_exception() ); + } + } + }; + }//namespace detail + + json_connection::json_connection( fc::buffered_istream_ptr in, fc::buffered_ostream_ptr out ) + :my( new detail::json_connection_impl(fc::move(in),fc::move(out)) ) + {} + + json_connection::~json_connection() + { + try + { + if( my->_done.valid() && !my->_done.ready() ) + { + my->_done.cancel(); + my->_done.wait(); + } + } + catch ( fc::canceled_exception& ){} // expected exception + catch ( fc::eof_exception& ){} // expected exception + catch ( fc::exception& e ) + { + // unhandled, unexpected exception cannot throw from destructor, so log it. + wlog( "${exception}", ("exception",e.to_detail_string()) ); + } + } + + fc::future json_connection::exec() + { + if( my->_done.valid() ) + { + FC_THROW_EXCEPTION( assert_exception, "start should only be called once" ); + } + + wlog( "EXEC!!!\n" ); + return my->_done = fc::async( [=](){ my->read_loop(); } ); + } + + void json_connection::add_method( const fc::string& name, method m ) + { + my->_methods.emplace(std::pair(name,fc::move(m))); + } + void json_connection::add_method( const fc::string& name, named_param_method m ) + { + my->_named_param_methods.emplace(std::pair(name,fc::move(m))); + } + void json_connection::remove_method( const fc::string& name ) + { + my->_methods.erase(name); + my->_named_param_methods.erase(name); + } + void json_connection::notice( const fc::string& method, const variants& args ) + { + fc::scoped_lock lock(my->_write_mutex); + *my->_out << "{\"method\":"; + json::to_stream( *my->_out, method ); + if( args.size() ) + { + *my->_out << ",\"params\":"; + fc::json::to_stream( *my->_out, args ); + *my->_out << "}\n"; + } + else + { + *my->_out << ",\"params\":[]}\n"; + } + } + void json_connection::notice( const fc::string& method, const variant_object& named_args ) + { + { + fc::scoped_lock lock(my->_write_mutex); + *my->_out << "{\"method\":"; + json::to_stream( *my->_out, method ); + *my->_out << ",\"params\":"; + fc::json::to_stream( *my->_out, named_args ); + *my->_out << "}\n"; + } + my->_out->flush(); + } + void json_connection::notice( const fc::string& method ) + { + { + fc::scoped_lock lock(my->_write_mutex); + *my->_out << "{\"method\":"; + json::to_stream( *my->_out, method ); + *my->_out << "}\n"; + } + my->_out->flush(); + } + + + future json_connection::async_call( const fc::string& method, const variants& args ) + { + auto id = my->_next_id++; + my->_awaiting[id] = fc::promise::ptr( new fc::promise() ); + + { + fc::scoped_lock lock(my->_write_mutex); + *my->_out << "{\"id\":"; + *my->_out << id; + *my->_out << ",\"method\":"; + json::to_stream( *my->_out, method ); + if( args.size() ) + { + *my->_out << ",\"params\":"; + fc::json::to_stream( *my->_out, args ); + *my->_out << "}\n"; + } + else + { + *my->_out << ",\"params\":[]}\n"; + } + } + my->_out->flush(); + return my->_awaiting[id]; + } + + future json_connection::async_call( const fc::string& method, const variant& a1 ) + { + ilog( ""); + auto id = my->_next_id++; + my->_awaiting[id] = fc::promise::ptr( new fc::promise() ); + + { + fc::scoped_lock lock(my->_write_mutex); + *my->_out << "{\"id\":"; + *my->_out << id; + *my->_out << ",\"method\":"; + json::to_stream( *my->_out, method ); + *my->_out << ",\"params\":["; + fc::json::to_stream( *my->_out, a1 ); + *my->_out << "]}\n"; + } + my->_out->flush(); + return my->_awaiting[id]; + } + future json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2 ) + { + ilog( ""); + auto id = my->_next_id++; + my->_awaiting[id] = fc::promise::ptr( new fc::promise() ); + + { + fc::scoped_lock lock(my->_write_mutex); + *my->_out << "{\"id\":"; + *my->_out << id; + *my->_out << ",\"method\":"; + json::to_stream( *my->_out, method ); + *my->_out << ",\"params\":["; + fc::json::to_stream( *my->_out, a1 ); + *my->_out << ","; + fc::json::to_stream( *my->_out, a2 ); + *my->_out << "]}\n"; + } + my->_out->flush(); + return my->_awaiting[id]; + } + future json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3 ) + { + ilog( ""); + auto id = my->_next_id++; + my->_awaiting[id] = fc::promise::ptr( new fc::promise() ); + + { + fc::scoped_lock lock(my->_write_mutex); + *my->_out << "{\"id\":"; + *my->_out << id; + *my->_out << ",\"method\":"; + json::to_stream( *my->_out, method ); + *my->_out << ",\"params\":["; + fc::json::to_stream( *my->_out, a1 ); + *my->_out << ","; + fc::json::to_stream( *my->_out, a2 ); + *my->_out << ","; + fc::json::to_stream( *my->_out, a3 ); + *my->_out << "]}\n"; + } + my->_out->flush(); + return my->_awaiting[id]; + } + + + + future json_connection::async_call( const fc::string& method, mutable_variant_object named_args ) + { + return async_call( method, variant_object( fc::move(named_args) ) ); + } + future json_connection::async_call( const fc::string& method, const variant_object& named_args ) + { + wlog( "${method} ${args}", ("method",method)("args",named_args) ); + auto id = my->_next_id++; + my->_awaiting[id] = fc::promise::ptr( new fc::promise() ); + fc::scoped_lock lock(my->_write_mutex); + { + *my->_out << "{\"id\":"; + *my->_out << id; + *my->_out << ",\"method\":"; + json::to_stream( *my->_out, method ); + *my->_out << ",\"params\":"; + fc::json::to_stream( *my->_out, named_args ); + *my->_out << "}\n"; + } + my->_out->flush(); + return my->_awaiting[id]; + } + future json_connection::async_call( const fc::string& method ) + { + auto id = my->_next_id++; + my->_awaiting[id] = fc::promise::ptr( new fc::promise() ); + fc::scoped_lock lock(my->_write_mutex); + { + *my->_out << "{\"id\":"; + *my->_out << id; + *my->_out << ",\"method\":"; + json::to_stream( *my->_out, method ); + *my->_out << "}\n"; + } + my->_out->flush(); + return my->_awaiting[id]; + } + + logger json_connection::get_logger()const + { + return my->_logger; + } + + void json_connection::set_logger( const logger& l ) + { + my->_logger = l; + } + +}} diff --git a/src/sha1.cpp b/src/sha1.cpp deleted file mode 100644 index 363a5c2..0000000 --- a/src/sha1.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { - - sha1::sha1() { memset( _hash, 0, sizeof(_hash) ); } - sha1::sha1( const fc::string& hex_str ) { - fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) ); - } - - fc::string sha1::str()const { - return to_hex( (char*)_hash, sizeof(_hash) ); - } - sha1::operator fc::string()const { return str(); } - - char* sha1::data()const { return (char*)&_hash[0]; } - - - struct sha1::encoder::impl { - SHA_CTX ctx; - }; - - sha1::encoder::~encoder() {} - sha1::encoder::encoder() { - reset(); - } - - sha1 sha1::hash( const char* d, uint32_t dlen ) { - encoder e; - e.write(d,dlen); - return e.result(); - } - sha1 sha1::hash( const fc::string& s ) { - return hash( s.c_str(), s.size() ); - } - sha1 sha1::hash( const fc::path& s ) { - file_mapping fmap( s.string().c_str(), read_only ); - size_t fsize = file_size(s); - mapped_region mr( fmap, fc::read_only, 0, fsize ); - - const char* pos = reinterpret_cast(mr.get_address()); - return hash( pos, fsize ); - } - - void sha1::encoder::write( const char* d, uint32_t dlen ) { - SHA1_Update( &my->ctx, d, dlen); - } - sha1 sha1::encoder::result() { - sha1 h; - SHA1_Final((uint8_t*)h.data(), &my->ctx ); - return h; - } - void sha1::encoder::reset() { - SHA1_Init( &my->ctx); - } - - fc::sha1 operator << ( const fc::sha1& h1, uint32_t i ) { - fc::sha1 result; - uint8_t* r = (uint8_t*)result._hash; - uint8_t* s = (uint8_t*)h1._hash; - for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p ) - r[p] = s[p] << i | (s[p+1]>>(8-i)); - r[19] = s[19] << i; - return result; - } - fc::sha1 operator ^ ( const fc::sha1& h1, const fc::sha1& h2 ) { - fc::sha1 result; - result._hash[0] = h1._hash[0] ^ h2._hash[0]; - result._hash[1] = h1._hash[1] ^ h2._hash[1]; - result._hash[2] = h1._hash[2] ^ h2._hash[2]; - result._hash[3] = h1._hash[3] ^ h2._hash[3]; - result._hash[4] = h1._hash[4] ^ h2._hash[4]; - return result; - } - bool operator >= ( const fc::sha1& h1, const fc::sha1& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) >= 0; - } - bool operator > ( const fc::sha1& h1, const fc::sha1& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0; - } - bool operator < ( const fc::sha1& h1, const fc::sha1& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0; - } - bool operator != ( const fc::sha1& h1, const fc::sha1& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0; - } - bool operator == ( const fc::sha1& h1, const fc::sha1& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0; - } - - void pack( fc::value& v, const fc::sha1& s ) { - v = fc::string(s); - } - void unpack( const fc::value& v, fc::sha1& s ) { - s = sha1(fc::value_cast(v)); - } - -} // namespace fc - diff --git a/src/sha256.cpp b/src/sha256.cpp deleted file mode 100644 index 7473839..0000000 --- a/src/sha256.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { - - sha256::sha256() { memset( _hash, 0, sizeof(_hash) ); } - sha256::sha256( const fc::string& hex_str ) { - fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) ); - } - - fc::string sha256::str()const { - return to_hex( (char*)_hash, sizeof(_hash) ); - } - sha256::operator fc::string()const { return str(); } - - char* sha256::data()const { return (char*)&_hash[0]; } - - - struct sha256::encoder::impl { - SHA_CTX ctx; - }; - - sha256::encoder::~encoder() {} - sha256::encoder::encoder() { - reset(); - } - - sha256 sha256::hash( const char* d, uint32_t dlen ) { - encoder e; - e.write(d,dlen); - return e.result(); - } - sha256 sha256::hash( const fc::string& s ) { - return hash( s.c_str(), s.size() ); - } - sha256 sha256::hash( const fc::path& s ) { - file_mapping fmap( s.string().c_str(), read_only ); - size_t fsize = file_size(s); - mapped_region mr( fmap, fc::read_only, 0, fsize ); - - const char* pos = reinterpret_cast(mr.get_address()); - return hash( pos, fsize ); - } - - void sha256::encoder::write( const char* d, uint32_t dlen ) { - SHA1_Update( &my->ctx, d, dlen); - } - sha256 sha256::encoder::result() { - sha256 h; - SHA1_Final((uint8_t*)h.data(), &my->ctx ); - return h; - } - void sha256::encoder::reset() { - SHA1_Init( &my->ctx); - } - - fc::sha256 operator << ( const fc::sha256& h1, uint32_t i ) { - fc::sha256 result; - uint8_t* r = (uint8_t*)result._hash; - uint8_t* s = (uint8_t*)h1._hash; - for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p ) - r[p] = s[p] << i | (s[p+1]>>(8-i)); - r[31] = s[31] << i; - return result; - } - fc::sha256 operator ^ ( const fc::sha256& h1, const fc::sha256& h2 ) { - fc::sha256 result; - result._hash[0] = h1._hash[0] ^ h2._hash[0]; - result._hash[1] = h1._hash[1] ^ h2._hash[1]; - result._hash[2] = h1._hash[2] ^ h2._hash[2]; - result._hash[3] = h1._hash[3] ^ h2._hash[3]; - return result; - } - bool operator >= ( const fc::sha256& h1, const fc::sha256& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) >= 0; - } - bool operator > ( const fc::sha256& h1, const fc::sha256& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0; - } - bool operator < ( const fc::sha256& h1, const fc::sha256& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0; - } - bool operator != ( const fc::sha256& h1, const fc::sha256& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0; - } - bool operator == ( const fc::sha256& h1, const fc::sha256& h2 ) { - return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0; - } - - void pack( fc::value& v, const fc::sha256& s ) { - v = fc::string(s); - } - void unpack( const fc::value& v, fc::sha256& s ) { - s = sha256(fc::value_cast(v)); - } - -} // namespace fc - diff --git a/src/ssh.cpp b/src/ssh.cpp deleted file mode 100644 index 04375cf..0000000 --- a/src/ssh.cpp +++ /dev/null @@ -1,1060 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { namespace ssh { - - namespace detail { - static int ssh_init = libssh2_init(0); - - class process_impl; - class process_istream : public fc::istream { - public: - process_istream( process_impl& p, int c ) - :proc(p),chan(c){} - - virtual size_t readsome( char* buf, size_t len ); - virtual istream& read( char* buf, size_t len ); - - virtual bool eof()const; - - process_impl& proc; - int chan; - }; - - class process_ostream : public fc::ostream { - public: - process_ostream( process_impl& p ) - :proc(p){} - - virtual ostream& write( const char* buf, size_t len ); - virtual void close(); - virtual void flush(); - - process_impl& proc; - }; - - class process_impl : public fc::retainable { - public: - process_impl( const client& c, const fc::string& cmd, const fc::string& pty_type ); - fc::string command; - fc::promise::ptr result; - LIBSSH2_CHANNEL* chan; - - int read_some( char* data, size_t len, int stream_id ); - int write_some( const char* data, size_t len, int stream_id ); - void flush(); - void send_eof(); - - client sshc; - process_istream std_err; - process_istream std_out; - process_ostream std_in; - - }; - - - class client_impl : public fc::retainable { - public: - client_impl() { - sftp = nullptr; - session = nullptr; - knownhosts = nullptr; - _trace_level = LIBSSH2_TRACE_ERROR; - logr = fc::logger::get( "fc::ssh::client" ); - logr.set_parent( fc::logger::get( "default" ) ); - } - LIBSSH2_SESSION* session; - LIBSSH2_KNOWNHOSTS* knownhosts; - LIBSSH2_SFTP* sftp; - - std::unique_ptr sock; - boost::asio::ip::tcp::endpoint endpt; - - fc::mutex scp_send_mutex; - fc::string uname; - fc::string upass; - fc::string pubkey; - fc::string privkey; - fc::string passphrase; - fc::string hostname; - uint16_t port; - bool session_connected; - fc::promise::ptr read_prom; - fc::promise::ptr write_prom; - fc::spin_lock _spin_lock; - - LIBSSH2_CHANNEL* open_channel( const fc::string& pty_type ); - static void kbd_callback(const char *name, int name_len, - const char *instruction, int instruction_len, int num_prompts, - const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, - LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, - void **abstract) - { - int i; - size_t n; - char buf[1024]; - client_impl* self = (client_impl*)*abstract; - - //slog( "Keyboard-interactive authentication" ); - // printf("Performing keyboard-interactive authentication.\n"); - - // printf("Authentication name: '"); - // fwrite(name, 1, name_len, stdout); - // printf("'\n"); - - // printf("Authentication instruction: '"); - // fwrite(instruction, 1, instruction_len, stdout); - // printf("'\n"); - - // printf("Number of prompts: %d\n\n", num_prompts); - - for (i = 0; i < num_prompts; i++) { - // printf("Prompt %d from server: '", i); - fwrite(prompts[i].text, 1, prompts[i].length, stdout); - // printf("'\n"); - - // printf("Please type response: "); - - if( self->upass.size() == 0 ) { - fgets(buf, sizeof(buf), stdin); - n = strlen(buf); - while (n > 0 && strchr("\r\n", buf[n - 1])) - n--; - buf[n] = 0; - - #ifdef WIN32 // fix warning - #define strdup _strdup - #endif - responses[i].text = strdup(buf); - responses[i].length = n; - } else { - responses[i].text = strdup(self->upass.c_str()); - responses[i].length = self->upass.size(); - } - - // printf("Response %d from user is '", i); - // fwrite(responses[i].text, 1, responses[i].length, stdout); - // printf("'\n\n"); - } - - // printf("Done. Sending keyboard-interactive responses to server now.\n"); - } // kbd_callback - - void connect() { - try { - if( libssh2_init(0) < 0 ) { FC_THROW_REPORT( "Unable to init libssh2" ); } - - auto eps = fc::asio::tcp::resolve( hostname, fc::lexical_cast(port) ); - if( eps.size() == 0 ) { - FC_THROW_REPORT( "Unable to resolve host '${host}'", fc::value().set("host",hostname) ); - } - sock.reset( new boost::asio::ip::tcp::socket( fc::asio::default_io_service() ) ); - - bool resolved = false; - for( uint32_t i = 0; i < eps.size(); ++i ) { - std::stringstream ss; ss << eps[i]; - try { - boost::system::error_code ec; - fc_ilog( logr, "Attempting to connect to ${endpoint}", ("endpoint",ss.str().c_str()) ); - fc::asio::tcp::connect( *sock, eps[i] ); - endpt = eps[i]; - resolved = true; - break; - } catch ( fc::error_report& er ) { - fc_ilog( logr, "Failed to connect to ${endpoint}\n${error_reprot}", - ("endpoint",ss.str().c_str())("error_report", er.to_detail_string()) ); - sock->close(); - } - } - if( !resolved ) { - FC_THROW_REPORT( "Unable to connect to any resolved endpoint for ${host}:${port}", - fc::value().set("host", hostname).set("port",port) ); - } - session = libssh2_session_init(); - libssh2_trace( session, _trace_level ); - libssh2_trace_sethandler( session, this, client_impl::handle_trace ); - - *libssh2_session_abstract(session) = this; - - libssh2_session_set_blocking( session, 0 ); - int ec = libssh2_session_handshake( session, sock->native() ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_session_handshake( session, sock->native() ); - } - if( ec < 0 ) { - char* msg; - libssh2_session_last_error( session, &msg, 0, 0 ); - FC_THROW_REPORT( "SSH Handshake error: ${code} - ${message}", - fc::value().set("code",ec).set("message", msg) ); - } - const char* fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); - //slog( "fingerprint: %s", fingerprint ); - - // try to authenticate, throw on error. - authenticate(); - //slog("."); - } catch ( error_report& er ) { - elog( "%s", er.to_detail_string().c_str() ); - close(); - throw FC_REPORT_PUSH( er, "Unable to connect to ssh server" );; - } catch ( ... ) { - close(); - FC_THROW_REPORT( "Unable to connect to ssh server", fc::value().set("exception", fc::except_str() ) ); - } - } - - static void handle_trace( LIBSSH2_SESSION* session, void* context, const char* data, size_t length ) { - client_impl* my = (client_impl*)context; - fc::string str(data,length); - fc_wlog( my->logr, "${message}", ("message",str) ); - } - - - void close() { - if( session ) { - if( sftp ) { - int ec = libssh2_sftp_shutdown(sftp); - try { - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_sftp_shutdown(sftp); - } - }catch(...){ - fc_wlog( logr, "caught closing sftp session" ); - } - sftp = 0; - } - try { - int ec = libssh2_session_disconnect(session, "exit cleanly" ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_session_disconnect(session, "exit cleanly" ); - } - ec = libssh2_session_free(session); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_session_free(session ); - } - session = 0; - } catch ( ... ){ - fc_wlog( logr, "caught freeing session" ); - session = 0; - } - try { - if( sock ) { - sock->close(); - } - } catch ( ... ){ - fc_wlog( logr, "caught error closing socket" ); - } - sock.reset(0); - try { - if( read_prom ) read_prom->wait(); - } catch ( ... ){ - fc_wlog( logr, "caught error waiting on read" ); - } - try { - if( write_prom ) write_prom->wait(); - } catch ( ... ){ - fc_wlog( logr, "caught error waiting on write" ); - } - } - } - - void authenticate() { - try { - char * alist = libssh2_userauth_list(session, uname.c_str(),uname.size()); - char * msg = 0; - int ec = 0; - - if(alist==NULL){ - if(libssh2_userauth_authenticated(session)){ - return; // CONNECTED! - } - ec = libssh2_session_last_error(session,&msg,NULL,0); - - while( !alist && (ec == LIBSSH2_ERROR_EAGAIN) ) { - wait_on_socket(); - alist = libssh2_userauth_list(session, uname.c_str(), uname.size()); - ec = libssh2_session_last_error(session,&msg,NULL,0); - } - if( !alist ) { - FC_THROW_REPORT( "Error getting authorization list: ${code} - ${message}", - fc::value().set("code",ec).set("message",msg)); - } - } - - std::vector split_alist; - bool pubkey = false; - bool pass = false; - bool keybd = false; - boost::split( split_alist, alist, boost::is_any_of(",") ); - std::for_each( split_alist.begin(), split_alist.end(), [&](const std::string& s){ - if( s == "publickey" ) { - pubkey = true; - } - else if( s == "password" ) { - pass = true; - } - else if( s == "keyboard-interactive" ) { - keybd = true; - } - else { - fc_wlog( logr, "Unknown/unsupported authentication type '${auth_type}'", ("auth_type",s.c_str())); - } - }); - - if( pubkey ) { - if( try_pub_key() ) - return; - } - if( pass ) { - if( try_pass() ) - return; - } - if( keybd ) { - if( try_keyboard() ) - return; - } - } catch ( error_report er ) { - throw FC_REPORT_PUSH( er, "Unable to authenticate ssh connection" ); - } - FC_THROW_REPORT( "Unable to authenticate ssh connection" ); - } // authenticate() - - bool try_pass() { - int ec = libssh2_userauth_password(session, uname.c_str(), upass.c_str() ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_userauth_password(session, uname.c_str(), upass.c_str() ); - } - - return !ec; - } - bool try_keyboard() { - int ec = libssh2_userauth_keyboard_interactive(session, uname.c_str(), - &client_impl::kbd_callback); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_userauth_keyboard_interactive(session, uname.c_str(), - &client_impl::kbd_callback); - } - return !ec; - } - - bool try_pub_key() { - int ec = libssh2_userauth_publickey_fromfile(session, - uname.c_str(), - pubkey.c_str(), - privkey.c_str(), - passphrase.c_str() ); - - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_userauth_publickey_fromfile(session, - uname.c_str(), - pubkey.c_str(), - privkey.c_str(), - passphrase.c_str() ); - } - return !ec; - } - - /** - * @todo figure out why this method results in deadlocks... - */ - void wait_on_socket() { - fc::usleep(fc::microseconds(5000)); - return; - - auto dir = libssh2_session_block_directions(session); - if( !dir ) return; - - fc::promise::ptr rprom, wprom; - if( dir & LIBSSH2_SESSION_BLOCK_INBOUND ) { - fc::scoped_lock lock(this->_spin_lock); - if( !read_prom ) { - read_prom.reset( new fc::promise("read_prom") ); - sock->async_read_some( boost::asio::null_buffers(), - [=]( const boost::system::error_code& e, size_t ) { - fc::scoped_lock lock(this->_spin_lock); - this->read_prom->set_value(e); - this->read_prom.reset(nullptr); - } ); - } - rprom = read_prom; - } - - if( dir & LIBSSH2_SESSION_BLOCK_OUTBOUND ) { - fc::scoped_lock lock(this->_spin_lock); - if( !write_prom ) { - write_prom.reset( new fc::promise("write_prom") ); - sock->async_write_some( boost::asio::null_buffers(), - [=]( const boost::system::error_code& e, size_t ) { - this->write_prom->set_value(e); - this->write_prom.reset(0); - } ); - } - wprom = write_prom; - } - - - boost::system::error_code ec; - if( rprom.get() && wprom.get() ) { - wlog( "wait both dir" ); - typedef fc::future fprom; - fprom fw(wprom); - fprom fr(rprom); - int r = fc::wait_any( fw, fr, fc::seconds(1) ); - switch( r ) { - case 0: - if( wprom->wait() ) { - FC_THROW_REPORT( "Socket Error ${message}", - fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) ); - } - break; - case 1: - if( rprom->wait() ) { - FC_THROW_REPORT( "Socket Error ${message}", - fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) ); - } - break; - } - } else if( rprom ) { - if( rprom->wait() ) { - FC_THROW_REPORT( "Socket Error ${message}", - fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) ); - } - } else if( wprom ) { - if( wprom->wait() ) { - FC_THROW_REPORT( "Socket Error ${message}", - fc::value().set( "message", boost::system::system_error(wprom->wait() ).what() ) ); - } - } - } - - void init_sftp() { - if( !sftp ) { - sftp = libssh2_sftp_init(session); - while( !sftp ) { - char* msg = 0; - int ec = libssh2_session_last_error(session,&msg,NULL,0); - if( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - sftp = libssh2_sftp_init(session); - } else { - FC_THROW_REPORT( "init sftp error ${code} - ${message}", fc::value().set("code",ec).set("message",msg) ); - } - } - } - } - - int _trace_level; - logger logr; - }; - - } - - client::client():my( new detail::client_impl() ){} - client::~client(){} - - void client::set_trace_level( int bitmask ) { my->_trace_level = bitmask; } - int client::get_trace_level()const { return my->_trace_level; } - const logger& client::get_logger()const { return my->logr; } - void client::set_logger( const logger& l ) { my->logr = l; } - - void client::connect( const fc::string& user, const fc::string& host, uint16_t port ) { - my->hostname = host; - my->uname = user; - my->port = port; - my->connect(); - } - void client::connect( const fc::string& user, const fc::string& pass, - const fc::string& host, uint16_t port ) { - my->hostname = host; - my->uname = user; - my->upass = pass; - my->port = port; - - my->connect(); - } - - - ssh::process client::exec( const fc::string& cmd, const fc::string& pty_type ) { - return ssh::process( *this, cmd, pty_type ); - } - - /** - * @todo implement progress reporting. - */ - void client::scp_send_dir( const fc::path& local_dir, const fc::path& remote_path, - std::function progress ) - { - fc::path remote_dir = remote_path; - if( remote_dir.filename() == fc::path(".") ) - remote_dir /= local_dir.filename(); - - fc_dlog( my->logr, "scp -r ${local} ${remote}", ("local",local_dir)("remote",remote_dir) ); - create_directories( remote_dir ); - - directory_iterator ditr(local_dir); - directory_iterator dend; - - while( ditr != dend ) { - if( (*ditr).filename() == "." || - (*ditr).filename() == ".." ) - { } - else if( fc::is_directory(*ditr) ) - { - scp_send_dir( (*ditr), remote_dir / (*ditr).filename() ); - } else if( fc::is_regular_file(*ditr) ) { - scp_send( *ditr, remote_dir / (*ditr).filename() ); - } else { - fc_wlog( my->logr, "Skipping '${path}", ("path",fc::canonical(*ditr)) ); - } - ++ditr; - } - } - - void client::scp_send( const fc::path& local_path, const fc::path& remote_path, - std::function progress ) { - fc_ilog( my->logr, "scp ${local} ${remote}", ("local",local_path)("remote",remote_path ) ); - /** - * Tests have shown that if one scp is 'blocked' by a need to read (presumably to - * ack recv for the trx window), and then a second transfer begins that the first - * transfer will never be acked. Placing this mutex limits the transfer of - * one file at a time via SCP which is just as well because there is a fixed - * amount of bandwidth. - */ - fc::unique_lock lock(my->scp_send_mutex); - - -// using namespace boost::filesystem; - if( !fc::exists(local_path) ) { - FC_THROW_REPORT( "Source file '${file}' does not exist", fc::value().set("file",local_path) ) ; - } - if( is_directory( local_path ) ) { - FC_THROW_REPORT( "Source file '${file}' is a directory, expected a file", fc::value().set("file",local_path) ) ; - } - - // memory map the file - size_t fsize = file_size(local_path); - if( fsize == 0 ) { - elog( "file size %d", fsize ); - // TODO: handle empty file case - if( progress ) progress(0,0); - return; - } - file_mapping fmap( local_path.string().c_str(), read_only ); - mapped_region mr( fmap, fc::read_only, 0, fsize ); - - LIBSSH2_CHANNEL* chan = 0; - time_t now; - memset( &now, 0, sizeof(now) ); - - // TODO: preserve creation / modification date - // TODO: perserve permissions / exec bit? - chan = libssh2_scp_send64( my->session, remote_path.generic_string().c_str(), 0700, fsize, now, now ); - while( chan == 0 ) { - char* msg; - int ec = libssh2_session_last_error( my->session, &msg, 0, 0 ); - if( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - chan = libssh2_scp_send64( my->session, local_path.generic_string().c_str(), 0700, fsize, now, now ); - } else { - FC_THROW_REPORT( "scp ${local_file} to ${remote_file} failed ${code} - ${message}", - fc::value().set("local_file", local_path).set("remote_file",remote_path).set("code",ec).set("message",msg) ); - } - } - try { - size_t wrote = 0; - char* pos = reinterpret_cast(mr.get_address()); - while( progress( wrote, fsize ) && wrote < fsize ) { - int r = libssh2_channel_write( chan, pos, fsize - wrote ); - while( r == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - r = libssh2_channel_write( chan, pos, fsize - wrote ); - } - if( r < 0 ) { - char* msg = 0; - int ec = libssh2_session_last_error( my->session, &msg, 0, 0 ); - FC_THROW_REPORT( "scp failed ${code} - ${message}", - fc::value().set("code",ec).set("message",msg) ); - } - wrote += r; - pos += r; - } - - auto ec = libssh2_channel_send_eof( chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_channel_send_eof( chan ); - } - ec = libssh2_channel_wait_eof( chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_channel_wait_eof( chan ); - } - - ec = libssh2_channel_close( chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_channel_close( chan ); - } - } catch ( error_report& er ) { - // clean up chan - int ec = libssh2_channel_free(chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_channel_free( chan ); - } - throw er; - } - int ec = libssh2_channel_free( chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_channel_free( chan ); - } - if( ec < 0 ) { - char* msg = 0; - int ec = libssh2_session_last_error( my->session, &msg, 0, 0 ); - FC_THROW_REPORT( "scp failed ${code} - ${message}", - fc::value().set("code",ec).set("message",msg) ); - } - - } - - - void client::rm( const fc::path& remote_path ) { - try { - auto s = stat(remote_path); - if( s.is_directory() ) { - FC_THROW_REPORT( "sftp cannot remove directory ${path}", fc::value().set("path",remote_path) ); - } - else if( !s.exists() ) { - return; // nothing to do - } - - int rc = libssh2_sftp_unlink(my->sftp, remote_path.generic_string().c_str() ); - while( rc == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - rc = libssh2_sftp_unlink(my->sftp, remote_path.generic_string().c_str() ); - } - if( 0 != rc ) { - rc = libssh2_sftp_last_error(my->sftp); - FC_THROW_REPORT( "sftp rm failed ${code}", fc::value().set("code",rc) ); - } - } catch ( error_report& er ) { - throw FC_REPORT_PUSH( er, "sftp remove '${remote_path}' failed", fc::value().set("remote_path",remote_path) ); - } - } - - file_attrib client::stat( const fc::path& remote_path ){ - my->init_sftp(); - LIBSSH2_SFTP_ATTRIBUTES att; - int ec = libssh2_sftp_stat( my->sftp, remote_path.generic_string().c_str(), &att ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_sftp_stat( my->sftp, remote_path.generic_string().c_str(), &att ); - } - if( ec ) { - return file_attrib(); - } - file_attrib ft; - ft.size = att.filesize; - ft.permissions = att.permissions; - return ft; - } - void client::create_directories( const fc::path& rdir, int mode ) { - boost::filesystem::path dir = rdir; - boost::filesystem::path p; - auto pitr = dir.begin(); - while( pitr != dir.end() ) { - p /= *pitr; - if( !stat( p ).exists() ) { - mkdir(p,mode); - } - ++pitr; - } - } - - void client::mkdir( const fc::path& rdir, int mode ) { - try { - auto s = stat(rdir); - if( s.is_directory() ) return; - else if( s.exists() ) { - FC_THROW_REPORT( "File already exists at path ${path}", fc::value().set("path",rdir) ); - } - - int rc = libssh2_sftp_mkdir(my->sftp, rdir.generic_string().c_str(), mode ); - while( rc == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - rc = libssh2_sftp_mkdir(my->sftp, rdir.generic_string().c_str(), mode ); - } - if( 0 != rc ) { - rc = libssh2_sftp_last_error(my->sftp); - FC_THROW_REPORT( "sftp mkdir error", fc::value().set("code",rc) ); - } - } catch ( error_report& er ) { - throw FC_REPORT_PUSH( er, "sftp failed to create directory '${directory}'", fc::value().set( "directory", rdir ) ); - } - } - - void client::close() { - if( my->session ) { - if( my->sftp ) { - int ec = libssh2_sftp_shutdown(my->sftp); - try { - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_sftp_shutdown(my->sftp); - } - }catch(...){ - fc_wlog( my->logr, "caught closing sftp sessionn" ); - } - my->sftp = 0; - } - try { - int ec = libssh2_session_disconnect(my->session, "exit cleanly" ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_session_disconnect(my->session, "exit cleanly" ); - } - ec = libssh2_session_free(my->session); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->wait_on_socket(); - ec = libssh2_session_free(my->session ); - } - my->session = 0; - } catch ( ... ){ - fc_wlog( my->logr, "caught error freeing session" ); - my->session = 0; - } - try { - if( my->sock ) { - my->sock->close(); - } - } catch ( ... ){ - fc_wlog( my->logr, "caught error closing socket" ); - } - my->sock.reset(0); - try { - if( my->read_prom ) my->read_prom->wait(); - } catch ( ... ){ - fc_wlog( my->logr,"caught error waiting on read prom" ); - } - try { - if( my->write_prom ) my->write_prom->wait(); - } catch ( ... ){ - fc_wlog( my->logr, "caught error waiting on write prom" ); - } - } - } - - file_attrib::file_attrib() - :size(0),uid(0),gid(0),permissions(0),atime(0),mtime(0) - { } - - bool file_attrib::is_directory() { - return LIBSSH2_SFTP_S_ISDIR(permissions); - } - bool file_attrib::is_file() { - return LIBSSH2_SFTP_S_ISREG(permissions); - } - bool file_attrib::exists() { - return 0 != permissions; - } - - - - - process::process() - {} - process::~process() - {} - bool process::valid()const { - return !!my; - } - - /** - * Blocks until the result code of the process has been returned. - */ - int process::result() { - char* msg = 0; - - int ec = libssh2_channel_wait_eof( my->chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->sshc.my->wait_on_socket(); - ec = libssh2_channel_wait_eof( my->chan ); - } - - ec = libssh2_channel_wait_closed( my->chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - my->sshc.my->wait_on_socket(); - ec = libssh2_channel_wait_closed( my->chan ); - } - ec = libssh2_session_last_error( my->sshc.my->session, &msg, 0, 0 ); - if( !ec ) { - FC_THROW_REPORT( "Error waiting on socket to close: ${message}", fc::value().set("message",msg) );//%ec %msg ); - } - return libssh2_channel_get_exit_status( my->chan ); - } - /** - * @brief returns a stream that writes to the procss' stdin - */ - fc::ostream& process::in_stream()const { - return my->std_in; - } - /** - * @brief returns a stream that reads from the process' stdout - */ - fc::istream& process::out_stream()const { - return my->std_out; - } - /** - * @brief returns a stream that reads from the process' stderr - */ - fc::istream& process::err_stream()const { - return my->std_err; - } - - process::process( const process& p ) - :my(p.my){ } - process::process( process&& p ) - :my(fc::move(p.my)){ } - - process::process( client& c, const fc::string& cmd, const fc::string& pty_type) - :my( new detail::process_impl( c, cmd, pty_type ) ) - { - } - - - void detail::process_impl::flush() { - if( !chan ) return; - /* channel_flush deleates input buffer, and does not ensure writes go out - * - int ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA ); - } - ec = libssh2_channel_flush( chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_flush( chan ); - } - if( ec < 0 ) { - FC_THROW_REPORT( "ssh flush failed", fc::value().set( "channel_error", ec) ); - } - */ - } - int detail::process_impl::read_some( char* data, size_t len, int stream_id ){ - if( !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); } - - int rc; - char* buf = data; - size_t buflen = len; - do { - rc = libssh2_channel_read_ex( chan, stream_id, buf, buflen ); - if( rc > 0 ) { - buf += rc; - buflen -= rc; - return buf-data; - } else if( rc == 0 ) { - if( libssh2_channel_eof( chan ) ) { - return -1; // eof - } - sshc.my->wait_on_socket(); - } else { - if( rc == LIBSSH2_ERROR_EAGAIN ) { - if( 0 < (buf-data) ) { - return buf-data; - } - else { - sshc.my->wait_on_socket(); - rc = 0; - continue; - } - } else { - char* msg; - if( !sshc.my || !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); } - rc = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 ); - FC_THROW_REPORT( "read failed: ${message}", fc::value().set("message", msg).set("code", rc) ); - } - } - } while( rc >= 0 && buflen); - return buf-data; - } - int detail::process_impl::write_some( const char* data, size_t len, int stream_id ) { - if( !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); } - - int rc; - const char* buf = data; - size_t buflen = len; - do { - rc = libssh2_channel_write_ex( chan, stream_id, buf, buflen ); - if( rc > 0 ) { - buf += rc; - buflen -= rc; - return buf-data; - } else if( rc == 0 ) { - if( libssh2_channel_eof( chan ) ) { - FC_THROW_REPORT( "EOF" ); - //return -1; // eof - } - } else { - - if( rc == LIBSSH2_ERROR_EAGAIN ) { - if( 0 < (buf-data) ) { - return buf-data; - } - else { - sshc.my->wait_on_socket(); - rc = 0; - continue; - } - } else { - char* msg; - rc = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 ); - FC_THROW_REPORT( "write failed: ${message}", fc::value().set("message",msg).set("code",rc) ); - return buf-data; - } - } - } while( rc >= 0 && buflen); - return buf-data; - } - void detail::process_impl::send_eof() { - if( sshc.my->session ) { - int ec = libssh2_channel_send_eof( chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_send_eof( chan ); - } - if( ec ) { - char* msg = 0; - ec = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 ); - FC_THROW_REPORT( "send eof failed: ${message}", fc::value().set("message",msg).set("code",ec) ); - } - } - } - - size_t detail::process_istream::readsome( char* buf, size_t len ) { - return proc.read_some( buf, len, chan ); - } - istream& detail::process_istream::read( char* buf, size_t len ) { - size_t r = 0; - do { - r += proc.read_some( buf + r, len - r, chan ); - } while( r < len ); - - return *this; - } - - bool detail::process_istream::eof()const { - return 0 != libssh2_channel_eof( proc.chan ); - } - - ostream& detail::process_ostream::write( const char* buf, size_t len ) { - size_t wrote = 0; - do { - wrote += proc.write_some( buf+wrote, len-wrote, 0 ); - } while( wrote < len ); - return *this; - } - void detail::process_ostream::close(){ - proc.send_eof(); - } - void detail::process_ostream::flush(){ - proc.flush(); - } - detail::process_impl::process_impl( const client& c, const fc::string& cmd, const fc::string& pty_type ) - :sshc(c),std_err(*this,SSH_EXTENDED_DATA_STDERR),std_out(*this,0),std_in(*this) - { - chan = c.my->open_channel(pty_type); - - int ec = libssh2_channel_handle_extended_data2(chan, LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_handle_extended_data2(chan, LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL ); - } - - if( cmd.size() == 0 ) { - ec = libssh2_channel_shell(chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_shell(chan); - } - } else { - ec = libssh2_channel_exec( chan, cmd.c_str() ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_exec( chan, cmd.c_str() ); - } - } - if( ec ) { - elog( "error starting process" ); - char* msg = 0; - ec = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 ); - FC_THROW_REPORT( "exec failed: ${message}", fc::value().set("message",msg).set("code",ec) ); - } - } - LIBSSH2_CHANNEL* detail::client_impl::open_channel( const fc::string& pty_type ) { - LIBSSH2_CHANNEL* chan = 0; - chan = libssh2_channel_open_session(session); - if( !chan ) { - char* msg; - int ec = libssh2_session_last_error( session, &msg, 0, 0 ); - while( !chan && ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - chan = libssh2_channel_open_session(session); - ec = libssh2_session_last_error( session, &msg, 0, 0 ); - } - if( !chan ) { - FC_THROW_REPORT( "libssh2_channel_open_session failed: ${message}", fc::value().set("message",msg).set("code",ec) ); - } - } - - if( pty_type.size() ) { - int ec = libssh2_channel_request_pty(chan,pty_type.c_str()); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = libssh2_channel_request_pty(chan,pty_type.c_str()); - } - if( 0 != ec ) { - char* msg; - ec = libssh2_session_last_error( session, &msg, 0, 0 ); - FC_THROW_REPORT( "libssh2_channel_req_pty failed: ${message}", fc::value().set("message",msg).set("code",ec) ); - } - } - return chan; - } - - process& process::operator=( const process& p ) { - my = p.my; - return *this; - } -} } diff --git a/src/ssh/client.cpp b/src/ssh/client.cpp new file mode 100644 index 0000000..80d8788 --- /dev/null +++ b/src/ssh/client.cpp @@ -0,0 +1,717 @@ +#define NOMINMAX // prevent windows from defining min and max macros +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "client_impl.hpp" + +namespace fc { namespace ssh { + + namespace detail { + static int ssh_init = libssh2_init(0); + } + + client::client():my( new detail::client_impl() ){ (void)detail::ssh_init; /* fix unused warning...*/ } + client::~client() { my->close(); } + + void client::set_trace_level( int bitmask ) { my->_trace_level = bitmask; } + int client::get_trace_level()const { return my->_trace_level; } + const logger& client::get_logger()const { return my->logr; } + void client::set_logger( const logger& l ) { my->logr = l; } + + void client::connect( const fc::string& user, const fc::string& host, uint16_t port ) { + my->hostname = host; + my->uname = user; + my->port = port; + my->connect(); + } + void client::connect( const fc::string& user, const fc::string& pass, + const fc::string& host, uint16_t port ) { + my->hostname = host; + my->uname = user; + my->upass = pass; + my->port = port; + + my->connect(); + } + + void client::close() { my->close(); } + + +// ssh::process client::exec( const fc::string& cmd, const fc::string& pty_type ) { +// return ssh::process( *this, cmd, pty_type ); +// } + + /** + * @todo implement progress reporting. + */ + void client::scp_send_dir( const fc::path& local_dir, const fc::path& remote_path, + std::function progress ) + { + fc::path remote_dir = remote_path; + if( remote_dir.filename() == fc::path(".") ) + remote_dir /= local_dir.filename(); + + fc_dlog( my->logr, "scp -r ${local} ${remote}", ("local",local_dir)("remote",remote_dir) ); + create_directories( remote_dir ); + + directory_iterator ditr(local_dir); + directory_iterator dend; + + while( ditr != dend ) { + if( (*ditr).filename() == "." || + (*ditr).filename() == ".." ) + { } + else if( fc::is_directory(*ditr) ) + { + scp_send_dir( (*ditr), remote_dir / (*ditr).filename() ); + } else if( fc::is_regular_file(*ditr) ) { + scp_send( *ditr, remote_dir / (*ditr).filename() ); + } else { + fc_wlog( my->logr, "Skipping '${path}", ("path",fc::canonical(*ditr)) ); + } + ++ditr; + } + } + + void client::scp_send( const fc::path& local_path, const fc::path& remote_path, + std::function progress ) { + fc_wlog( my->logr, "scp ${local} ${remote}", ("local",local_path)("remote",remote_path ) ); + if( !fc::exists(local_path) ) { + FC_THROW( "Source file '${file}' does not exist", ("file",local_path) ) ; + } + if( is_directory( local_path ) ) { + FC_THROW( "Source file '${file}' is a directory, expected a file", ("file",local_path) ) ; + } + + // memory map the file + uint64_t fsize = file_size(local_path); + if( fsize == 0 ) { + elog( "file size ${file_size}", ("file_size", fsize) ); + // TODO: handle empty file case + if( progress ) progress(0,0); + return; + } + file_mapping fmap( local_path.string().c_str(), read_only ); + + LIBSSH2_CHANNEL* chan = 0; + time_t now; + memset( &now, 0, sizeof(now) ); + + // TODO: preserve creation / modification date + // TODO: perserve permissions / exec bit? + try { + // libssh2_scp_send64 stores state data in the session object, and it calls channel_open which + // stores its own state data, so lock both. + fc::scoped_lock channel_open_lock(my->channel_open_mutex); + fc::scoped_lock scp_send_lock(my->scp_send_mutex); + chan = my->call_ssh2_ptr_function_throw(boost::bind(libssh2_scp_send64, my->session, remote_path.generic_string().c_str(), 0700, fsize, now, now )); + } catch (fc::exception& er) { + FC_RETHROW_EXCEPTION(er, error, "scp ${local_file} to ${remote_file} failed", ("local_file", local_path)("remote_file",remote_path)); + } + uint64_t total_bytes_written = 0; + try { + const size_t max_mapping_size = 1024*1024*1024; // 1GB + for (uint64_t current_offset = 0; current_offset < fsize; current_offset += max_mapping_size) { + uint64_t total_bytes_left_to_send = fsize - current_offset; + size_t bytes_to_send_this_iteration = (size_t)std::min(total_bytes_left_to_send, max_mapping_size); + mapped_region mr( fmap, fc::read_only, current_offset, bytes_to_send_this_iteration); + size_t bytes_written_this_iteration = 0; + char* pos = reinterpret_cast(mr.get_address()); + while( progress(total_bytes_written, fsize) && bytes_written_this_iteration < bytes_to_send_this_iteration) { + int r = my->call_ssh2_function_throw(boost::bind(libssh2_channel_write_ex, chan, 0, pos, + bytes_to_send_this_iteration - bytes_written_this_iteration), + "scp failed ${code} - ${message}"); + bytes_written_this_iteration += r; + total_bytes_written += r; + pos += r; + // fc_wlog( my->logr, "wrote ${bytes} bytes", ("bytes",r) ); + } + } + my->call_ssh2_function(boost::bind(libssh2_channel_send_eof, chan)); + my->call_ssh2_function(boost::bind(libssh2_channel_wait_eof, chan)); + my->call_ssh2_function(boost::bind(libssh2_channel_close, chan)); + } catch ( fc::exception& er ) { + // clean up chan + my->call_ssh2_function(boost::bind(libssh2_channel_free, chan)); + throw er; + } + my->call_ssh2_function_throw(boost::bind(libssh2_channel_free, chan), + "scp failed ${code} - ${message}"); + } + + + void client::rm( const fc::path& remote_path ) { + try { + auto s = stat(remote_path); + if( s.is_directory() ) { + FC_THROW( "sftp cannot remove directory ${path}", ("path",remote_path) ); + } + else if( !s.exists() ) { + return; // nothing to do + } + + { + fc::scoped_lock scp_unlink_lock(my->scp_unlink_mutex); + my->call_ssh2_function_throw(boost::bind(libssh2_sftp_unlink_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size()), + "sftp rm failed ${code}"); + } + } catch ( fc::exception& er ) { + FC_RETHROW_EXCEPTION( er, error, "sftp remove '${remote_path}' failed", ("remote_path",remote_path) ); + } + } + + void client::rmdir( const fc::path& remote_path ) { + try { + auto s = stat(remote_path); + if( !s.is_directory() ) + FC_THROW( "sftp cannot rmdir non-directory ${path}", ("path",remote_path) ); + else if( !s.exists() ) + return; // nothing to do + + { + fc::scoped_lock scp_rmdir_lock(my->scp_rmdir_mutex); + my->call_ssh2_function_throw(boost::bind(libssh2_sftp_rmdir_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size()), + "sftp rmdir failed ${code}"); + } + } catch ( fc::exception& er ) { + FC_RETHROW_EXCEPTION( er, error, "sftp rmdir '${remote_path}' failed", ("remote_path",remote_path) ); + } + } + + void client::rmdir_recursive( const fc::path& remote_path ) { + try { + auto s = stat(remote_path); + if( !s.is_directory() ) + FC_THROW( "sftp cannot rmdir non-directory ${path}", ("path",remote_path) ); + else if( !s.exists() ) + return; // nothing to do + + LIBSSH2_SFTP_HANDLE *dir_handle; + { + fc::scoped_lock scp_open_lock(my->scp_open_mutex); + dir_handle = + my->call_ssh2_ptr_function_throw(boost::bind(libssh2_sftp_open_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size(), 0, 0, LIBSSH2_SFTP_OPENDIR), + "sftp libssh2_sftp_opendir failed ${code}"); + } + do { + char mem[512]; + LIBSSH2_SFTP_ATTRIBUTES attrs; + + int rc; + { + fc::scoped_lock scp_readdir_lock(my->scp_readdir_mutex); + rc = my->call_ssh2_function_throw(boost::bind(libssh2_sftp_readdir_ex, dir_handle, mem, sizeof(mem), (char*)NULL, 0, &attrs), + "sftp readdir failed ${code}"); + } + if (rc > 0) { + fc::string file_or_dir_name(mem, rc); + if (file_or_dir_name == "." || file_or_dir_name == "..") + continue; + fc::path full_remote_path = remote_path / file_or_dir_name; + if (LIBSSH2_SFTP_S_ISDIR(attrs.permissions)) + rmdir_recursive(full_remote_path); + else if (LIBSSH2_SFTP_S_ISREG(attrs.permissions)) { + fc::scoped_lock scp_unlink_lock(my->scp_unlink_mutex); + my->call_ssh2_function_throw(boost::bind(libssh2_sftp_unlink_ex, my->sftp, full_remote_path.generic_string().c_str(), full_remote_path.generic_string().size()), + "sftp rm failed ${code}"); + } + } else + break; + } while (1); + + { + fc::scoped_lock scp_close_lock(my->scp_close_mutex); + my->call_ssh2_function_throw(boost::bind(libssh2_sftp_close_handle, dir_handle), "sftp libssh2_sftp_closedir failed ${code}"); + } + { + fc::scoped_lock scp_rmdir_lock(my->scp_rmdir_mutex); + my->call_ssh2_function_throw(boost::bind(libssh2_sftp_rmdir_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size()), + "sftp rmdir failed ${code}"); + } + } catch ( fc::exception& er ) { + FC_RETHROW_EXCEPTION( er, error, "sftp rmdir recursive '${remote_path}' failed", ("remote_path",remote_path) ); + } + } + + file_attrib client::stat( const fc::path& remote_path ){ + my->init_sftp(); + LIBSSH2_SFTP_ATTRIBUTES att; + int ec; + { + fc::scoped_lock scp_stat_lock(my->scp_stat_mutex); + ec = my->call_ssh2_function(boost::bind(libssh2_sftp_stat_ex, my->sftp, + remote_path.generic_string().c_str(), remote_path.generic_string().size(), + LIBSSH2_SFTP_STAT, &att)); + } + if( ec ) + return file_attrib(); + file_attrib ft; + ft.size = att.filesize; + ft.permissions = att.permissions; + return ft; + } + void client::create_directories( const fc::path& rdir, int mode ) { + boost::filesystem::path dir = rdir; + boost::filesystem::path p; + auto pitr = dir.begin(); + while( pitr != dir.end() ) { + p /= *pitr; + if( !stat( p ).exists() ) { + mkdir(p,mode); + } + ++pitr; + } + } + + void client::mkdir( const fc::path& rdir, int mode ) { + try { + auto s = stat(rdir); + if( s.is_directory() ) + return; + else if( s.exists() ) + FC_THROW( "File already exists at path ${path}", ("path",rdir) ); + + { + fc::scoped_lock scp_mkdir_lock(my->scp_mkdir_mutex); + my->call_ssh2_function_throw(boost::bind(libssh2_sftp_mkdir_ex, my->sftp, + rdir.generic_string().c_str(), rdir.generic_string().size(), mode), + "sftp mkdir error"); + } + } catch ( fc::exception& er ) { + FC_RETHROW_EXCEPTION( er, error, "sftp failed to create directory '${directory}'", ( "directory", rdir ) ); + } + } + + void client::set_remote_system_is_windows(bool is_windows /* = true */) { + my->remote_system_is_windows = is_windows; + } + + + file_attrib::file_attrib() + :size(0),uid(0),gid(0),permissions(0),atime(0),mtime(0) + { } + + bool file_attrib::is_directory() { + return LIBSSH2_SFTP_S_ISDIR(permissions); + } + bool file_attrib::is_file() { + return LIBSSH2_SFTP_S_ISREG(permissions); + } + bool file_attrib::exists() { + return 0 != permissions; + } + + detail::client_impl::client_impl() : + session(nullptr), + knownhosts(nullptr), + sftp(nullptr), + agent(nullptr), + _trace_level(0), // was LIBSSH2_TRACE_ERROR + logr(fc::logger::get( "fc::ssh::client" )), + remote_system_is_windows(false) { + logr.set_parent( fc::logger::get( "default" ) ); + } + + detail::client_impl::~client_impl() { + close(); + } + + /* static */ + void detail::client_impl::kbd_callback(const char *name, int name_len, + const char *instruction, int instruction_len, int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract) { + detail::client_impl* self = (client_impl*)*abstract; + + + for (int i = 0; i < num_prompts; i++) { + fwrite(prompts[i].text, 1, prompts[i].length, stdout); + + if( self->upass.size() == 0 ) { + /** TODO: add keyboard callback here... + fgets(buf, sizeof(buf), stdin); + n = strlen(buf); + while (n > 0 && strchr("\r\n", buf[n - 1])) + n--; + buf[n] = 0; + +#ifdef WIN32 // fix warning +# define strdup _strdup +#endif + responses[i].text = strdup(buf); + responses[i].length = n; + */ + responses[i].text = nullptr; + responses[i].length = 0; + } else { + responses[i].text = strdup(self->upass.c_str()); + responses[i].length = self->upass.size(); + } + } + } + + void detail::client_impl::connect() { + try { + if( libssh2_init(0) < 0 ) + FC_THROW( "Unable to init libssh2" ); + + auto eps = fc::asio::tcp::resolve( hostname, boost::lexical_cast(port) ); + if( eps.size() == 0 ) + FC_THROW( "Unable to resolve host '${host}'", ("host",hostname) ); + + sock.reset( new boost::asio::ip::tcp::socket( fc::asio::default_io_service() ) ); + + bool resolved = false; + for( uint32_t i = 0; i < eps.size(); ++i ) { + std::stringstream ss; ss << eps[i]; + try { + boost::system::error_code ec; + fc_ilog( logr, "Attempting to connect to ${endpoint}", ("endpoint",ss.str().c_str()) ); + fc::asio::tcp::connect( *sock, eps[i] ); + endpt = eps[i]; + resolved = true; + break; + } catch ( fc::exception& er ) { + fc_ilog( logr, "Failed to connect to ${endpoint}\n${error_reprot}", + ("endpoint",ss.str().c_str())("error_report", er.to_detail_string()) ); + sock->close(); + } + } + if( !resolved ) + FC_THROW( "Unable to connect to any resolved endpoint for ${host}:${port}", + ("host", hostname).set("port",port) ); + + session = libssh2_session_init(); + libssh2_trace( session, _trace_level ); + libssh2_trace_sethandler( session, this, client_impl::handle_trace ); + + *libssh2_session_abstract(session) = this; + + libssh2_session_set_blocking( session, 0 ); + try { + call_ssh2_function_throw(boost::bind(libssh2_session_handshake, session, sock->native()), + "SSH Handshake error: ${code} - ${message}"); + } catch (fc::exception& er) { + FC_RETHROW_EXCEPTION( er, error, "Error during SSH handshake" );; + } + //const char* fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); + //slog( "fingerprint: %s", fingerprint ); + + // try to authenticate, throw on error. + try { + authenticate(); + } catch (fc::exception& er) { + FC_RETHROW_EXCEPTION( er, error, "Error during SSH authentication" );; + } + //slog("."); + } catch ( fc::exception& er ) { + elog( "Unable to connect to ssh server: ${detail}", ("detail", er.to_detail_string().c_str()) ); + close(); + FC_RETHROW_EXCEPTION( er, error, "Unable to connect to ssh server" );; + } catch ( ... ) { + close(); + FC_THROW( "Unable to connect to ssh server", ("exception", fc::except_str() ) ); + } + } + + /* static */ + void detail::client_impl::handle_trace( LIBSSH2_SESSION* session, void* context, const char* data, size_t length ) { + client_impl* my = (client_impl*)context; + fc::string str(data,length); + fc_wlog( my->logr, "${message}", ("message",str) ); + } + + void detail::client_impl::close() { + if( session ) { + if( sftp ) { + try { + call_ssh2_function(boost::bind(libssh2_sftp_shutdown, sftp)); + }catch(...){ + fc_wlog( logr, "caught closing sftp session" ); + } + sftp = 0; + } + + if (agent) { + libssh2_agent_disconnect(agent); + libssh2_agent_free(agent); + agent = nullptr; + } + + try { + call_ssh2_function(boost::bind(libssh2_session_disconnect_ex, session, SSH_DISCONNECT_BY_APPLICATION, "exit cleanly", "")); + call_ssh2_function(boost::bind(libssh2_session_free, session), false); + } catch ( ... ){ + fc_wlog( logr, "caught freeing session" ); + } + session = 0; + try { + if( sock ) + sock->close(); + } catch ( ... ){ + fc_wlog( logr, "caught error closing socket" ); + } + sock.reset(0); + try { + if( read_prom ) + read_prom->wait(); + } catch ( ... ){ + fc_wlog( logr, "caught error waiting on read" ); + } + try { + if( write_prom ) + write_prom->wait(); + } catch ( ... ){ + fc_wlog( logr, "caught error waiting on write" ); + } + } + } + + void detail::client_impl::authenticate() { + try { + char * alist = NULL; + // libssh2_userauth_list has strange enough behavior that we can't use the + // call_blocking_libssh2_function-type functions to wait and retry, so we must + // explicitly lock around the libssh2_userauth_list calls. + // hence, this anonymous scope: + { + fc::unique_lock lock(ssh_session_mutex); + + alist = libssh2_userauth_list(session, uname.c_str(),uname.size()); + + if(alist==NULL) { + char * msg = 0; + int ec = 0; + if(libssh2_userauth_authenticated(session)) + return; // CONNECTED! + ec = libssh2_session_last_error(session,&msg,NULL,0); + + while( !alist && (ec == LIBSSH2_ERROR_EAGAIN) ) { + wait_on_socket(); + alist = libssh2_userauth_list(session, uname.c_str(), uname.size()); + ec = libssh2_session_last_error(session,&msg,NULL,0); + } + if( !alist ) { + FC_THROW( "Error getting authorization list: ${code} - ${message}", + ("code",ec).set("message",msg)); + } + } + } // end anonymous scope + + std::vector split_alist; + bool pubkey = false; + bool pass = false; + bool keybd = false; + boost::split( split_alist, alist, boost::is_any_of(",") ); + std::for_each( split_alist.begin(), split_alist.end(), [&](const std::string& s){ + if( s == "publickey" ) + pubkey = true; + else if( s == "password" ) + pass = true; + else if( s == "keyboard-interactive" ) + keybd = true; + else + fc_dlog( logr, "Unknown/unsupported authentication type '${auth_type}'", ("auth_type",s.c_str())); + }); + + if( pubkey && try_pub_key() ) + return; + if( pass && try_pass() ) + return; + if( keybd && try_keyboard() ) + return; + } catch ( fc::exception& er ) { + FC_RETHROW_EXCEPTION( er, error, "Unable to authenticate ssh connection" ); + } + FC_THROW( "Unable to authenticate ssh connection" ); + } // authenticate() + + bool detail::client_impl::try_pass() { + return !call_ssh2_function(boost::bind(libssh2_userauth_password_ex, session, uname.c_str(), uname.size(), + upass.c_str(), upass.size(), (LIBSSH2_PASSWD_CHANGEREQ_FUNC((*)))NULL)); + } + bool detail::client_impl::try_keyboard() { + return !call_ssh2_function(boost::bind(libssh2_userauth_keyboard_interactive_ex, session, + uname.c_str(), uname.size(), &client_impl::kbd_callback)); + } + bool detail::client_impl::try_pub_key() { + if (privkey.size()) { + if (!call_ssh2_function(boost::bind(libssh2_userauth_publickey_fromfile_ex, + session, + uname.c_str(), uname.size(), + pubkey.c_str(), + privkey.c_str(), + passphrase.c_str()))) + return true; // successful authentication from file + fc_ilog( logr, "failed to authenticate with private key from file '${privkey_filename}'", ("privkey_filename",privkey)); + } else + fc_ilog( logr, "no private key file set, skiping pubkey authorization from file"); + + agent = libssh2_agent_init(session); + if (!agent) { + fc_wlog( logr, "failed to initialize ssh-agent support"); + return false; + } + + if (call_ssh2_function(boost::bind(libssh2_agent_connect, agent))) { + fc_ilog( logr, "failed to connect to ssh-agent"); + return false; + } + + if (call_ssh2_function(boost::bind(libssh2_agent_list_identities, agent))) { + fc_ilog( logr, "failed requesting identities from ssh-agent"); + return false; + } + + struct libssh2_agent_publickey *prev_identity = NULL; + while (1) { + struct libssh2_agent_publickey *identity; + int ec = call_ssh2_function(boost::bind(libssh2_agent_get_identity, agent, &identity, prev_identity)); + if (ec == 1) + break; // done iterating over keys + if (ec < 0) { + fc_ilog( logr, "failed obtaining identity from ssh-agent"); + return false; + } + + if (call_ssh2_function(boost::bind(libssh2_agent_userauth, agent, uname.c_str(), identity))) + fc_ilog( logr, "unable to authenticate with public key '${key_comment}'", ("key_comment",identity->comment)); + else { + fc_ilog( logr, "authenticated with public key '${key_comment}'", ("key_comment",identity->comment)); + return true; + } + prev_identity = identity; + } + return false; + } + + void detail::client_impl::wait_on_socket(int additionalDirections /* = 0 */) { + int dir = libssh2_session_block_directions(session); + dir |= additionalDirections; + if( !dir ) + return; + + fc::promise::ptr rprom, wprom; + if( dir & LIBSSH2_SESSION_BLOCK_INBOUND ) { + fc::scoped_lock lock(this->_spin_lock); + if( !read_prom ) { + read_prom.reset( new fc::promise("read_prom") ); + sock->async_read_some( boost::asio::null_buffers(), + [=]( const boost::system::error_code& e, size_t ) { + fc::scoped_lock lock(this->_spin_lock); + this->read_prom->set_value(e); + this->read_prom.reset(nullptr); + } ); + } + rprom = read_prom; + } + + if( dir & LIBSSH2_SESSION_BLOCK_OUTBOUND ) { + fc::scoped_lock lock(this->_spin_lock); + if( !write_prom ) { + write_prom.reset( new fc::promise("write_prom") ); + sock->async_write_some( boost::asio::null_buffers(), + [=]( const boost::system::error_code& e, size_t ) { + fc::scoped_lock lock(this->_spin_lock); + this->write_prom->set_value(e); + this->write_prom.reset(0); + } ); + } + wprom = write_prom; + } + + boost::system::error_code ec; + if( rprom.get() && wprom.get() ) { + typedef fc::future fprom; + fprom fw(wprom); + fprom fr(rprom); +#if 0 + // EMF: at present there are known bugs in fc::wait_any, and it will fail to wake up + // when one of the futures is ready. + int r = fc::wait_any( fw, fr, fc::seconds(1) ); +#else + int r; + while (1) { + if (fw.ready()) { + r = 0; break; + } + if (fr.ready()) { + r = 1; break; + } + fc::usleep(fc::microseconds(5000)); + } +#endif + switch( r ) { + case 0: + if( wprom->wait() ) { + FC_THROW( "Socket Error ${message}", + ( "message", boost::system::system_error(rprom->wait() ).what() ) ); + } + break; + case 1: + if( rprom->wait() ) { + FC_THROW( "Socket Error ${message}", + ( "message", boost::system::system_error(rprom->wait() ).what() ) ); + } + break; + } + } else if( rprom ) { + if( rprom->wait() ) { + FC_THROW( "Socket Error ${message}", + ( "message", boost::system::system_error(rprom->wait() ).what() ) ); + } + } else if( wprom ) { + if( wprom->wait() ) { + FC_THROW( "Socket Error ${message}", + ( "message", boost::system::system_error(wprom->wait() ).what() ) ); + } + } + } + void detail::client_impl::init_sftp() { + if( !sftp ) + sftp = call_ssh2_ptr_function_throw(boost::bind(libssh2_sftp_init,session), + "init sftp error ${code} - ${message}"); + } + + + LIBSSH2_CHANNEL* detail::client_impl::open_channel( const fc::string& pty_type ) { + LIBSSH2_CHANNEL* chan = 0; + /* anonymous scope */ { + fc::scoped_lock channel_open_lock(channel_open_mutex); + + chan = call_ssh2_ptr_function_throw(boost::bind(libssh2_channel_open_ex, session, + "session", sizeof("session") - 1, + LIBSSH2_CHANNEL_WINDOW_DEFAULT, + LIBSSH2_CHANNEL_PACKET_DEFAULT, + (const char*)NULL, 0), + "libssh2_channel_open_session failed: ${message}"); + } + + if( pty_type.size() ) + call_ssh2_function_throw(boost::bind(libssh2_channel_request_pty_ex, chan, pty_type.c_str(), pty_type.size(), + (char *)NULL, 0, LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, + LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX), + "libssh2_channel_req_pty failed: ${message}"); + return chan; + } + +} } diff --git a/src/ssh/client_impl.hpp b/src/ssh/client_impl.hpp new file mode 100644 index 0000000..606bd36 --- /dev/null +++ b/src/ssh/client_impl.hpp @@ -0,0 +1,280 @@ +#define NOMINMAX +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// include this to get acess to the details of the LIBSSH2_SESSION structure, so +// we can verify that all data has really been sent when libssh2 says it has. +#include <../src/libssh2_priv.h> + +namespace fc { namespace ssh { + + namespace detail { + + class client_impl { + public: + client_impl(); + ~client_impl(); + + LIBSSH2_SESSION* session; + LIBSSH2_KNOWNHOSTS* knownhosts; + LIBSSH2_SFTP* sftp; + LIBSSH2_AGENT* agent; + + std::unique_ptr sock; + boost::asio::ip::tcp::endpoint endpt; + + fc::mutex ssh_session_mutex; + fc::mutex channel_open_mutex; + fc::mutex process_startup_mutex; + fc::mutex scp_send_mutex; + fc::mutex scp_stat_mutex; + fc::mutex scp_mkdir_mutex; + fc::mutex scp_rmdir_mutex; + fc::mutex scp_unlink_mutex; + fc::mutex scp_close_mutex; + fc::mutex scp_readdir_mutex; + fc::mutex scp_open_mutex; + + fc::string uname; + fc::string upass; + fc::string pubkey; + fc::string privkey; + fc::string passphrase; + fc::string hostname; + uint16_t port; + bool session_connected; + fc::promise::ptr read_prom; + fc::promise::ptr write_prom; + fc::spin_lock _spin_lock; + int _trace_level; + logger logr; + + bool remote_system_is_windows; // true if windows, false if unix, used for command-line quoting and maybe filename translation + + LIBSSH2_CHANNEL* open_channel( const fc::string& pty_type ); + static void kbd_callback(const char *name, int name_len, + const char *instruction, int instruction_len, int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract); + + void connect(); + + static void handle_trace( LIBSSH2_SESSION* session, void* context, const char* data, size_t length ); + + void close(); + void authenticate(); + + bool try_pass(); + bool try_keyboard(); + bool try_pub_key(); + + // don't call this "unlocked" version directly + template + int call_ssh2_function_unlocked(const T& lambda, bool check_for_errors = true); + + // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN + template + int call_ssh2_function(const T& lambda, bool check_for_errors = true); + + // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN + // if libssh2 returns an error, get extended info and throw a message with ${code} and ${message} + // set appropriately. + template + int call_ssh2_function_throw(const T& lambda, const char* message = "libssh2 call failed ${code} - ${message}", bool check_for_errors = true); + + // this version is a little different, it handles functions like libssh2_sftp_init which return + // a pointer instead of an int. These retry automatically if the result is NULL and the error + // is LIBSSH2_ERROR_EAGAIN + template + return_type call_ssh2_ptr_function_throw(std::function lambda, const char* message = "libssh2 call failed ${code} - ${message}", bool check_for_errors = true); + + void wait_on_socket(int additionalDirections = 0); + + void init_sftp(); + }; + + + // #define OLD_BLOCKING, + // the OLD_BLOCKING version of these functions will ensure that if a libssh2 function returns + // LIBSSH2_ERROR_EAGAIN, no other libssh2 functions will be called until that function has been + // called again and returned some other value. + // + // if you don't define this and use the new version of this, we will release the lock and let + // other libssh2 functions be called *unless* it appears that there was unwritten data. + // + // the OLD_BLOCKING version is too conservative -- if you try to read on a channel that doesn't + // have any data, you're likely to deadlock. The new version is not heavily tested and may be + // too lax, time will tell. +#ifdef OLD_BLOCKING + // don't call this "unlocked" version directly + template + int client_impl::call_ssh2_function_unlocked(const T& lambda, bool check_for_errors /* = true */) { + int ec = lambda(); + while (ec == LIBSSH2_ERROR_EAGAIN ) { + wait_on_socket(); + ec = lambda(); + } + + // this assert catches bugs in libssh2 if libssh2 returns ec != LIBSSH2_ERROR_EAGAIN + // but the internal session data indicates a data write is still in progress + // set check_for_errors to false when closing the connection + assert(!check_for_errors || !session->packet.olen); + + return ec; + } + + // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN + template + int client_impl::call_ssh2_function(const T& lambda, bool check_for_errors /* = true */) { + fc::scoped_lock lock(ssh_session_mutex); + return call_ssh2_function_unlocked(lambda, check_for_errors); + } +#else + // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN + template + int client_impl::call_ssh2_function(const T& lambda, bool check_for_errors /* = true */) { + fc::unique_lock lock(ssh_session_mutex); + int ec = lambda(); + while (ec == LIBSSH2_ERROR_EAGAIN) { + bool unlock_to_wait = !session->packet.olen; + if (unlock_to_wait) + lock.unlock(); + wait_on_socket(); + if (unlock_to_wait) + lock.lock(); + ec = lambda(); + } + // this assert catches bugs in libssh2 if libssh2 returns ec != LIBSSH2_ERROR_EAGAIN + // but the internal session data indicates a data write is still in progress + // set check_for_errors to false when closing the connection + assert(!check_for_errors || !session->packet.olen); + return ec; + } +#endif + +#ifdef OLD_BLOCKING + // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN + // if libssh2 returns an error, get extended info and throw a message with ${code} and ${message} + // set appropriately. + template + int client_impl::call_ssh2_function_throw(const T& lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { + fc::scoped_lock lock(ssh_session_mutex); + int ec = call_ssh2_function_unlocked(lambda, check_for_errors); + + if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { + ec = libssh2_sftp_last_error(sftp); + FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); + } else if( ec < 0 ) { + char* msg = 0; + ec = libssh2_session_last_error( session, &msg, 0, 0 ); + FC_THROW(message, ("code",ec).set("message",msg)); + } + return ec; + } +#else + // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN + // if libssh2 returns an error, get extended info and throw a message with ${code} and ${message} + // set appropriately. + template + int client_impl::call_ssh2_function_throw(const T& lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { + fc::unique_lock lock(ssh_session_mutex); + int ec = lambda(); + while (ec == LIBSSH2_ERROR_EAGAIN) { + bool unlock_to_wait = !session->packet.olen; + if (unlock_to_wait) + lock.unlock(); + wait_on_socket(); + if (unlock_to_wait) + lock.lock(); + ec = lambda(); + } + // this assert catches bugs in libssh2 if libssh2 returns ec != LIBSSH2_ERROR_EAGAIN + // but the internal session data indicates a data write is still in progress + // set check_for_errors to false when closing the connection + assert(!check_for_errors || !session->packet.olen); + + if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { + ec = libssh2_sftp_last_error(sftp); + FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); + } else if( ec < 0 ) { + char* msg = 0; + ec = libssh2_session_last_error( session, &msg, 0, 0 ); + FC_THROW(message, ("code",ec).set("message",msg)); + } + return ec; + } +#endif + +#ifdef OLD_BLOCKING + // this version is a little different, it handles functions like libssh2_sftp_init which return + // a pointer instead of an int. These retry automatically if the result is NULL and the error + // is LIBSSH2_ERROR_EAGAIN + template + return_type client_impl::call_ssh2_ptr_function_throw(std::function lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { + fc::scoped_lock lock(ssh_session_mutex); + return_type ret = lambda(); + while (!ret) { + char* msg = 0; + int ec = libssh2_session_last_error(session,&msg,NULL,0); + if ( ec == LIBSSH2_ERROR_EAGAIN ) { + wait_on_socket(); + ret = lambda(); + } else if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { + ec = libssh2_sftp_last_error(sftp); + FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); + } else { + ec = libssh2_session_last_error( session, &msg, 0, 0 ); + FC_THROW(message, ("code",ec).set("message",msg)); + } + } + assert(!check_for_errors || !session->packet.olen); + + return ret; + } +#else + // this version is a little different, it handles functions like libssh2_sftp_init which return + // a pointer instead of an int. These retry automatically if the result is NULL and the error + // is LIBSSH2_ERROR_EAGAIN + template + return_type client_impl::call_ssh2_ptr_function_throw(std::function lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { + fc::unique_lock lock(ssh_session_mutex); + return_type ret = lambda(); + while (!ret) { + char* msg = 0; + int ec = libssh2_session_last_error(session,&msg,NULL,0); + if ( ec == LIBSSH2_ERROR_EAGAIN ) { + bool unlock_to_wait = !session->packet.olen; + if (unlock_to_wait) + lock.unlock(); + wait_on_socket(); + if (unlock_to_wait) + lock.lock(); + ret = lambda(); + } else if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { + ec = libssh2_sftp_last_error(sftp); + FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); + } else { + ec = libssh2_session_last_error( session, &msg, 0, 0 ); + FC_THROW(message, ("code",ec).set("message",msg)); + } + } + assert(!check_for_errors || !session->packet.olen); + + return ret; + } +#endif + } + +} } diff --git a/src/ssh/process.cpp b/src/ssh/process.cpp new file mode 100644 index 0000000..8794c11 --- /dev/null +++ b/src/ssh/process.cpp @@ -0,0 +1,334 @@ +#define NOMINMAX // prevent windows from defining min and max macros +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "client_impl.hpp" + +#if defined (_MSC_VER) +#pragma warning (disable : 4355) +#endif + +namespace fc { namespace ssh { + + namespace detail { + class process_impl; + class process_istream : public fc::istream { + public: + process_istream( process_impl& p, int c ) + :proc(p),chan(c){} + + virtual size_t readsome( char* buf, size_t len ); + + virtual bool eof() const; + + process_impl& proc; + int chan; + }; + + class process_ostream : public fc::ostream { + public: + process_ostream( process_impl& p ) + :proc(p){} + + virtual size_t writesome( const char* buf, size_t len ); + virtual void close(); + virtual void flush(); + + process_impl& proc; + }; + + class process_impl { + public: + process_impl( client_ptr c ); + ~process_impl(); + //process_impl( const client& c, const fc::string& cmd, const fc::string& pty_type ); + void exec(const fc::path& exe, vector args, + const fc::path& work_dir /* = fc::path() */, fc::iprocess::exec_opts opts /* = open_all */); + + + int read_some( char* data, size_t len, int stream_id ); + int write_some( const char* data, size_t len, int stream_id ); + void flush(); + void send_eof(); + + LIBSSH2_CHANNEL* chan; + client_ptr sshc; + buffered_ostream_ptr buffered_std_in; + buffered_istream_ptr buffered_std_out; + buffered_istream_ptr buffered_std_err; + + fc::string command; + fc::promise::ptr result; + + fc::optional return_code; + fc::ostring return_signal; + fc::ostring return_signal_message; + private: + static fc::string windows_shell_escape(const fc::string& str); + static fc::string unix_shell_escape(const fc::string& str); + static fc::string windows_shell_escape_command(const fc::path& exe, const vector& args); + static fc::string unix_shell_escape_command(const fc::path& exe, const vector& args); + }; + + } // end namespace detail + + + process::process(client_ptr c) : + my(new detail::process_impl(c)) + {} + + process::~process() + {} + + iprocess& process::exec( const fc::path& exe, vector args, + const fc::path& work_dir /* = fc::path() */, exec_opts opts /* = open_all */ ) { + my->exec(exe, args, work_dir, opts); + return *this; + } + + /** + * Blocks until the result code of the process has been returned. + */ + int process::result() { + if (!my->return_code && !my->return_signal) { + // we don't have any cached exit status, so wait and obtain the values now + my->sshc->my->call_ssh2_function(boost::bind(libssh2_channel_wait_eof, my->chan)); + my->sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_wait_closed, my->chan), + "Error waiting on socket to close: ${message}"); + + char* exit_signal; + char* error_message; + libssh2_channel_get_exit_signal(my->chan, &exit_signal, NULL, &error_message, NULL, NULL, NULL); + if (exit_signal) { + // process terminated with a signal + my->return_signal = exit_signal; + libssh2_free(my->chan->session, exit_signal); + if (error_message) { + my->return_signal_message = error_message; + libssh2_free(my->chan->session, error_message); + } + } else + my->return_code = libssh2_channel_get_exit_status(my->chan); + } + if (my->return_signal) + FC_THROW("process terminated with signal ${signal}: ${signal_message}", ("signal", *my->return_signal) + ("signal_message", my->return_signal_message ? *my->return_signal_message : "")); + else + return *my->return_code; + } + + void process::kill() { + elog("error: fc::ssh::process::kill() not supported"); + } + + + /** + * @brief returns a stream that writes to the procss' stdin + */ + fc::buffered_ostream_ptr process::in_stream() { + return my->buffered_std_in; + } + + /** + * @brief returns a stream that reads from the process' stdout + */ + fc::buffered_istream_ptr process::out_stream() { + return my->buffered_std_out; + } + + /** + * @brief returns a stream that reads from the process' stderr + */ + fc::buffered_istream_ptr process::err_stream() { + return my->buffered_std_err; + } + + void detail::process_impl::flush() { + if( !chan ) return; + /* channel_flush deleates input buffer, and does not ensure writes go out + * + int ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA); + while( ec == LIBSSH2_ERROR_EAGAIN ) { + sshc.my->wait_on_socket(); + ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA ); + } + ec = libssh2_channel_flush( chan ); + while( ec == LIBSSH2_ERROR_EAGAIN ) { + sshc.my->wait_on_socket(); + ec = libssh2_channel_flush( chan ); + } + if( ec < 0 ) { + FC_THROW( "ssh flush failed", ( "channel_error", ec) ); + } + */ + } + + int detail::process_impl::read_some( char* data, size_t len, int stream_id ){ + if( !sshc->my->session ) { FC_THROW( "Session closed" ); } + int rc; + char* buf = data; + size_t buflen = len; + do { + rc = sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_read_ex, chan, stream_id, buf, buflen), + "read failed: ${message}"); + if( rc > 0 ) { + buf += rc; + buflen -= rc; + return buf-data; + } else if( rc == 0 ) { + if( libssh2_channel_eof( chan ) ) + return -1; // eof + sshc->my->wait_on_socket(); + } + } while( rc >= 0 && buflen); + return buf-data; + } + + int detail::process_impl::write_some( const char* data, size_t len, int stream_id ) { + if( !sshc->my->session ) { FC_THROW( "Session closed" ); } + + int rc; + const char* buf = data; + size_t buflen = len; + do { + rc = sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_write_ex, chan, stream_id, buf, buflen), + "write failed: ${message}"); + if( rc > 0 ) { + buf += rc; + buflen -= rc; + return buf-data; + } else if( rc == 0 ) { + if( libssh2_channel_eof( chan ) ) { + FC_THROW( "EOF" ); + //return -1; // eof + } + } + } while( rc >= 0 && buflen); + return buf-data; + } + + void detail::process_impl::send_eof() { + if( sshc->my->session ) + sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_send_eof, chan), + "send eof failed: ${message}"); + } + + size_t detail::process_istream::readsome( char* buf, size_t len ) { + int bytesRead = proc.read_some(buf, len, chan); + if (bytesRead < 0) + FC_THROW("EOF"); + else + return bytesRead; + } + + bool detail::process_istream::eof()const { + return 0 != libssh2_channel_eof( proc.chan ); + } + + size_t detail::process_ostream::writesome( const char* buf, size_t len ) { + return proc.write_some(buf, len, 0); + } + + void detail::process_ostream::close(){ + proc.send_eof(); + } + + void detail::process_ostream::flush(){ + proc.flush(); + } + + detail::process_impl::process_impl( client_ptr c ) + :chan(nullptr), + sshc(c), + buffered_std_in(new buffered_ostream(ostream_ptr(new process_ostream(*this)))), + buffered_std_out(new buffered_istream(istream_ptr(new process_istream(*this, 0)))), + buffered_std_err(new buffered_istream(istream_ptr(new process_istream(*this, SSH_EXTENDED_DATA_STDERR)))) + { + } + + detail::process_impl::~process_impl() { + if (chan) { + sshc->my->call_ssh2_function(boost::bind(libssh2_channel_free, chan)); + chan = NULL; + } + } + + // these rules work pretty well for a standard bash shell on unix + fc::string detail::process_impl::unix_shell_escape(const fc::string& str) { + if (str.find_first_of(" ;&|><*?`$(){}[]!#'\"") == fc::string::npos) + return str; + fc::string escaped_quotes(str); + for (size_t start = escaped_quotes.find("'"); + start != fc::string::npos; + start = escaped_quotes.find("'", start + 5)) + escaped_quotes.replace(start, 1, "'\"'\"'"); + fc::string escaped_str("\'"); + escaped_str += escaped_quotes; + escaped_str += "\'"; + return escaped_str; + } + fc::string detail::process_impl::unix_shell_escape_command(const fc::path& exe, const vector& args) { + fc::stringstream command_line; + command_line << unix_shell_escape(exe.string()); + for (unsigned i = 0; i < args.size(); ++i) + command_line << " " << unix_shell_escape(args[i]); + return command_line.str(); + } + + // windows command-line escaping rules are a disaster, partly because how the command-line is + // parsed depends on what program you're running. In windows, the command line is passed in + // as a single string, and the process is left to interpret it as it sees fit. The standard + // C runtime uses one set of rules, the function CommandLineToArgvW usually used by + // GUI-mode programs uses a different set. + // Here we try to find a common denominator that works well for simple cases + // it's only minimally tested right now due to time constraints. + fc::string detail::process_impl::windows_shell_escape(const fc::string& str) { + if (str.find_first_of(" \"") == fc::string::npos) + return str; + fc::string escaped_quotes(str); + for (size_t start = escaped_quotes.find("\""); + start != fc::string::npos; + start = escaped_quotes.find("\"", start + 2)) + escaped_quotes.replace(start, 1, "\\\""); + fc::string escaped_str("\""); + escaped_str += escaped_quotes; + escaped_str += "\""; + return escaped_str; + } + fc::string detail::process_impl::windows_shell_escape_command(const fc::path& exe, const vector& args) { + fc::stringstream command_line; + command_line << windows_shell_escape(exe.string()); + for (unsigned i = 0; i < args.size(); ++i) + command_line << " " << windows_shell_escape(args[i]); + return command_line.str(); + } + + void detail::process_impl::exec(const fc::path& exe, vector args, + const fc::path& work_dir /* = fc::path() */, + fc::iprocess::exec_opts opts /* = open_all */) { + chan = sshc->my->open_channel(""); + + sshc->my->call_ssh2_function(boost::bind(libssh2_channel_handle_extended_data2, chan, LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL)); + + try { + fc::scoped_lock process_startup_lock(sshc->my->process_startup_mutex); + fc::string command_line = sshc->my->remote_system_is_windows ? windows_shell_escape_command(exe, args) : unix_shell_escape_command(exe, args); + sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_process_startup, chan, "exec", sizeof("exec") - 1, command_line.c_str(), command_line.size()), + "exec failed: ${message}"); // equiv to libssh2_channel_exec(chan, cmd) macro + } catch (fc::exception& er) { + elog( "error starting process" ); + FC_RETHROW_EXCEPTION(er, error, "error starting process"); + } + } + +} } diff --git a/src/string.cpp b/src/string.cpp index 0f164f8..b4945de 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -9,7 +10,6 @@ */ namespace fc { - string::string(const char* s, int l) :my(s,l){ } string::string(){} string::string( const fc::string& c ):my(*c.my) { } @@ -21,6 +21,7 @@ namespace fc { string::~string() { } string::operator std::string&() { return *my; } string::operator const std::string&()const { return *my; } + char* string::data() { return &my->front(); } string::iterator string::begin() { return &(*this)[0]; } string::iterator string::end() { return &(*this)[size()]; } @@ -33,9 +34,17 @@ namespace fc { void string::reserve(size_t r) { my->reserve(r); } size_t string::size()const { return my->size(); } size_t string::find(char c, size_t p)const { return my->find(c,p); } + size_t string::find(const fc::string& str, size_t pos /* = 0 */) const { return my->find(str, pos); } + size_t string::find(const char* s, size_t pos /* = 0 */) const { return my->find(s,pos); } size_t string::rfind(char c, size_t p)const { return my->rfind(c,p); } size_t string::rfind(const char* c, size_t p)const { return my->rfind(c,p); } size_t string::rfind(const fc::string& c, size_t p)const { return my->rfind(c,p); } + size_t string::find_first_of(const fc::string& str, size_t pos /* = 0 */) const { return my->find_first_of(str, pos); } + size_t string::find_first_of(const char* s, size_t pos /* = 0 */) const { return my->find_first_of(s, pos); } + + fc::string& string::replace(size_t pos, size_t len, const string& str) { my->replace(pos, len, str); return *this; } + fc::string& string::replace(size_t pos, size_t len, const char* s) { my->replace(pos, len, s); return *this; } + void string::clear() { my->clear(); } void string::resize( size_t s ) { my->resize(s); } @@ -56,6 +65,38 @@ namespace fc { string operator + ( const string& s, const string& c ) { return string(s) += c; } string operator + ( const string& s, char c ) { return string(s) += c; } + + int64_t to_int64( const fc::string& i ) + { + return boost::lexical_cast(i.c_str()); + } + + uint64_t to_uint64( const fc::string& i ) + { + return boost::lexical_cast(i.c_str()); + } + + double to_double( const fc::string& i) + { + return boost::lexical_cast(i.c_str()); + } + + fc::string to_string( double d) + { + return boost::lexical_cast(d); + } + + fc::string to_string( uint64_t d) + { + return boost::lexical_cast(d); + } + + fc::string to_string( int64_t d) + { + return boost::lexical_cast(d); + } + + } // namespace fc diff --git a/src/super_fast_hash.cpp b/src/super_fast_hash.cpp deleted file mode 100644 index ac1bbca..0000000 --- a/src/super_fast_hash.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/** - Initial Publish Date: Thu, 16 Oct 2008 - Initial Author: Paul Hsieh - @file SuperFastHash.c - @version $Revision$ - @date $LastChangedDate$ - @author $LastChangeAuthor$ - @author Paul Hsieh - - The code below appears to be the fastest hashing algorithm available and is licensed for - anyone to use. An article describing the has function can be found on the link below. This - function is used by Safari and some other big-name programs (so it must be good right?) - - http://www.azillionmonkeys.com/qed/hash.html -*/ -#include -#include - -namespace fc { - - #undef get16bits - #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) - #define get16bits(d) (*((const uint16_t *) (d))) - #endif - - #if !defined (get16bits) - #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ - +(uint32_t)(((const uint8_t *)(d))[0]) ) - #endif - - uint32_t super_fast_hash (const fc::string& str ) { - return super_fast_hash( str.c_str(), str.size() ); - } - - uint32_t super_fast_hash (const char * data, int len) - { - uint32_t hash = len, tmp; - int rem; - - if (len <= 0 || data == 0) return 0; - - rem = len & 3; - len >>= 2; - - /* Main loop */ - for (;len > 0; len--) - { - hash += get16bits (data); - tmp = (get16bits (data+2) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2*sizeof (uint16_t); - hash += hash >> 11; - } - - /* Handle end cases */ - switch (rem) - { - case 3: hash += get16bits (data); - hash ^= hash << 16; - hash ^= data[sizeof (uint16_t)] << 18; - hash += hash >> 11; - break; - case 2: hash += get16bits (data); - hash ^= hash << 11; - hash += hash >> 17; - break; - case 1: hash += *data; - hash ^= hash << 10; - hash += hash >> 1; - } - - /* Force "avalanching" of final 127 bits */ - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 4; - hash += hash >> 17; - hash ^= hash << 25; - hash += hash >> 6; - - return hash; - } -} // namespace fc - diff --git a/src/task.cpp b/src/task.cpp deleted file mode 100644 index d17f173..0000000 --- a/src/task.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include -#include -#include - - -namespace fc { - task_base::task_base(void* func) - :_functor(func){ - } - - void task_base::run() { - try { - _run_functor( _functor, _promise_impl ); - } catch ( ... ) { - set_exception( current_exception() ); - } - } - task_base::~task_base() { - _destroy_functor( _functor ); - } - - void task_base::_set_active_context(context* c) { - { synchronized( *_spinlock ) - _active_context = c; - } - } -} diff --git a/src/tcp_socket.cpp b/src/tcp_socket.cpp deleted file mode 100644 index 6b0a440..0000000 --- a/src/tcp_socket.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -namespace fc { - - class tcp_socket::impl { - public: - impl():_sock( fc::asio::default_io_service() ){ } - ~impl(){ - if( _sock.is_open() ) _sock.close(); - } - - boost::asio::ip::tcp::socket _sock; - }; - bool tcp_socket::is_open()const { - return my->_sock.is_open(); - } - - tcp_socket::tcp_socket(){}; - - tcp_socket::~tcp_socket(){}; - - void tcp_socket::flush() {} - void tcp_socket::close() { - if( is_open() ) my->_sock.close(); - } - - bool tcp_socket::eof()const { - return !my->_sock.is_open(); - } - - fc::ostream& tcp_socket::write( const char* buf, size_t len ) { - boost::system::error_code ec; - size_t w = my->_sock.write_some( boost::asio::buffer( buf, len ), ec ); - - if( w < len ) { - buf += w; - len -= w; - } - - if( ec == boost::asio::error::would_block ) { - promise::ptr p(new promise("tcp_socket::write")); - boost::asio::async_write( my->_sock, boost::asio::buffer(buf, len), - [=]( const boost::system::error_code& ec, size_t bt ) { - if( !ec ) p->set_value(bt); - else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); - }); - p->wait(); - } else if( ec ) { - elog( "throw... write data failed %s", boost::system::system_error(ec).what() ); - FC_THROW_REPORT( "Failed to write data to tcp socket", - fc::value().set("reason", fc::string(boost::system::system_error(ec).what())) - .set("data", fc::to_hex(buf,len) ) ); - } - return *this; - } - size_t tcp_socket::readsome( char* buf, size_t len ) { - boost::system::error_code ec; - size_t w = my->_sock.read_some( boost::asio::buffer( buf, len ), ec ); - if( ec == boost::asio::error::would_block ) { - promise::ptr p(new promise("tcp_socket::readsome")); - my->_sock.async_read_some( boost::asio::buffer(buf, len), - [=]( const boost::system::error_code& ec, size_t bt ) { - slog( "%d ec: %s", bt, boost::system::system_error(ec).what() ); - if( !ec ) p->set_value(bt); - else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); - }); - return p->wait(); - } else if (ec ) { - slog( "throw!" ); - throw boost::system::system_error(ec); - } - return w; - } - fc::istream& tcp_socket::read( char* buffer, size_t s ) { - size_t r = readsome( buffer, s ); - while( r < s ) { - r += readsome( buffer + r, s - r ); - } - return *this; - } - void tcp_socket::connect_to( const fc::ip::endpoint& e ) { - fc::asio::tcp::connect(my->_sock, fc::asio::tcp::endpoint( boost::asio::ip::address_v4(e.get_address()), e.port() ) ); - } - - class tcp_server::impl { - public: - impl(uint16_t port): - _accept( fc::asio::default_io_service(), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port) ){ - } - ~impl(){ - _accept.close(); - } - - boost::asio::ip::tcp::acceptor _accept; - }; - void tcp_server::close() { - if( my && my->_accept.is_open() ) my->_accept.close(); - delete my; my = nullptr; - } - tcp_server::tcp_server() - :my(nullptr) { - } - tcp_server::~tcp_server() { - delete my; - } - - - bool tcp_server::accept( tcp_socket& s ) { - if( !my ) return false; - fc::promise::ptr p( new promise("tcp::accept") ); - my->_accept.async_accept( s.my->_sock, [=]( const boost::system::error_code& e ) { - p->set_value(e); - } ); - auto ec = p->wait(); - if( !ec ) s.my->_sock.non_blocking(true); - if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); - return true; - } - void tcp_server::listen( uint16_t port ) { - if( my ) delete my; - my = new impl(port); - } - - - -} // namespace fc diff --git a/src/context.hpp b/src/thread/context.hpp similarity index 68% rename from src/context.hpp rename to src/thread/context.hpp index fb1cfe4..6b827b0 100644 --- a/src/context.hpp +++ b/src/thread/context.hpp @@ -1,18 +1,27 @@ -#ifndef _FC_CONTEXT_HPP_ -#define _FC_CONTEXT_HPP_ -#include -#include +#pragma once +#include #include -#include +#include #include +#include + +#if BOOST_VERSION >= 105300 + #include + namespace bc = boost::context; + namespace bco = boost::coroutines; +#elif BOOST_VERSION >= 105200 + namespace bc = boost::context; +#else + namespace bc = boost::ctx; + namespace bco = boost::ctx; +#endif + namespace fc { class thread; class promise_base; class task_base; - namespace bc = boost::ctx; - /** * maintains information associated with each context such as * where it is blocked, what time it should resume, priority, @@ -22,7 +31,7 @@ namespace fc { typedef fc::context* ptr; - context( void (*sf)(intptr_t), bc::stack_allocator& alloc, fc::thread* t ) + context( void (*sf)(intptr_t), bco::stack_allocator& alloc, fc::thread* t ) : caller_context(0), stack_alloc(&alloc), next_blocked(0), @@ -33,14 +42,23 @@ namespace fc { complete(false), cur_task(0) { - my_context.fc_stack.base = alloc.allocate( bc::default_stacksize() ); - my_context.fc_stack.limit = - static_cast( my_context.fc_stack.base) - bc::default_stacksize(); - make_fcontext( &my_context, sf ); +#if BOOST_VERSION >= 105300 + size_t stack_size = bco::stack_allocator::default_stacksize(); + my_context = bc::make_fcontext(alloc.allocate(stack_size), stack_size, sf); +#else + size_t stack_size = bc::default_stacksize(); + my_context.fc_stack.base = alloc.allocate( stack_size ); + my_context.fc_stack.limit = + static_cast( my_context.fc_stack.base) - stack_size; + make_fcontext( &my_context, sf ); +#endif } - context( fc::thread* t) - :caller_context(0), + context( fc::thread* t) : +#if BOOST_VERSION >= 105300 + my_context(new bc::fcontext_t), +#endif + caller_context(0), stack_alloc(0), next_blocked(0), next_blocked_mutex(0), @@ -52,10 +70,16 @@ namespace fc { {} ~context() { - if(stack_alloc) { + +#if BOOST_VERSION >= 105300 + if(stack_alloc) + stack_alloc->deallocate( my_context->fc_stack.sp, bco::stack_allocator::default_stacksize() ); + else + delete my_context; +#else + if(stack_alloc) stack_alloc->deallocate( my_context.fc_stack.base, bc::default_stacksize() ); - // slog("deallocate stack" ); - } +#endif } struct blocked_promise { @@ -112,13 +136,12 @@ namespace fc { void timeout_blocking_promises() { for( auto i = blocking_prom.begin(); i != blocking_prom.end(); ++i ) { - i->prom->set_exception( fc::copy_exception( future_wait_timeout() ) ); + i->prom->set_exception( std::make_shared() ); } } - template - void except_blocking_promises( const Exception& e ) { + void except_blocking_promises( const exception_ptr& e ) { for( auto i = blocking_prom.begin(); i != blocking_prom.end(); ++i ) { - i->prom->set_exception( fc::copy_exception( e ) ); + i->prom->set_exception( e ); } } void clear_blocking_promises() { @@ -129,9 +152,13 @@ namespace fc { +#if BOOST_VERSION >= 105300 + bc::fcontext_t* my_context; +#else bc::fcontext_t my_context; +#endif fc::context* caller_context; - bc::stack_allocator* stack_alloc; + bco::stack_allocator* stack_alloc; priority prio; //promise_base* prom; std::vector blocking_prom; @@ -148,4 +175,3 @@ namespace fc { } // naemspace fc -#endif // _FC_CONTEXT_HPP_ diff --git a/src/future.cpp b/src/thread/future.cpp similarity index 62% rename from src/future.cpp rename to src/thread/future.cpp index b022646..ebf68a6 100644 --- a/src/future.cpp +++ b/src/thread/future.cpp @@ -1,9 +1,8 @@ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include @@ -13,7 +12,10 @@ namespace fc { promise_base::promise_base( const char* desc ) :_ready(false), _blocked_thread(nullptr), - _timeout(time_point::max()), +#ifndef NDEBUG + _blocked_fiber_count(0), +#endif + _timeout(time_point::maximum()), _canceled(false), _desc(desc), _compl(nullptr) @@ -31,7 +33,7 @@ namespace fc { } bool promise_base::error()const { { synchronized(_spin_yield) - return _exceptp; + return _exceptp != nullptr; } } @@ -41,26 +43,40 @@ namespace fc { } void promise_base::_wait( const microseconds& timeout_us ){ - if( timeout_us == microseconds::max() ) _wait_until( time_point::max() ); + if( timeout_us == microseconds::maximum() ) _wait_until( time_point::maximum() ); else _wait_until( time_point::now() + timeout_us ); } void promise_base::_wait_until( const time_point& timeout_us ){ { synchronized(_spin_yield) if( _ready ) { - if( _exceptp ) fc::rethrow_exception( _exceptp ); + if( _exceptp ) _exceptp->dynamic_rethrow_exception(); return; } _enqueue_thread(); } thread::current().wait_until( ptr(this,true), timeout_us ); + _dequeue_thread(); if( _ready ) { - if( _exceptp ) fc::rethrow_exception( _exceptp ); + if( _exceptp ) _exceptp->dynamic_rethrow_exception(); return; } - FC_THROW( future_wait_timeout() ); + FC_THROW_EXCEPTION( timeout_exception, "" ); } void promise_base::_enqueue_thread(){ - _blocked_thread =&thread::current(); +#ifndef NDEBUG + ++_blocked_fiber_count; + // only one thread can wait on a promise at any given time + assert(!_blocked_thread || + _blocked_thread == &thread::current()); +#endif + _blocked_thread = &thread::current(); + } + void promise_base::_dequeue_thread(){ +#ifndef NDEBUG + synchronized(_spin_yield) + if (!--_blocked_fiber_count) + _blocked_thread = nullptr; +#endif } void promise_base::_notify(){ if( _blocked_thread != nullptr ) @@ -70,7 +86,7 @@ namespace fc { void promise_base::_set_timeout(){ if( _ready ) return; - set_exception( fc::copy_exception( future_wait_timeout() ) ); + set_exception( std::make_shared() ); } void promise_base::_set_value(const void* s){ // slog( "%p == %d", &_ready, int(_ready)); diff --git a/src/mutex.cpp b/src/thread/mutex.cpp similarity index 85% rename from src/mutex.cpp rename to src/thread/mutex.cpp index 5d59f64..40e2039 100644 --- a/src/mutex.cpp +++ b/src/thread/mutex.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include +#include +#include +#include #include "context.hpp" #include "thread_d.hpp" @@ -15,7 +15,7 @@ namespace fc { auto c = m_blist; fc::thread::current().debug("~mutex"); while( c ) { - elog( "still blocking on context %p (%s)", m_blist, (m_blist->cur_task ? m_blist->cur_task->get_desc() : "no current task") ); + // elog( "still blocking on context %p (%s)", m_blist, (m_blist->cur_task ? m_blist->cur_task->get_desc() : "no current task") ); c = c->next_blocked_mutex; } } @@ -125,6 +125,11 @@ namespace fc { // allow recusive locks if ( get_tail( m_blist, n ) == cc ) { + assert(false); + // EMF: I think recursive locks are currently broken -- we need to + // keep track of how many times this mutex has been locked by the + // current context. Unlocking should decrement this count and unblock + // the next context only if the count drops to zero return; } cc->next_blocked_mutex = m_blist; @@ -136,14 +141,14 @@ namespace fc { i = i->next_blocked_mutex; ++cnt; } - wlog( "wait queue len %1%", cnt ); + //wlog( "wait queue len %1%", cnt ); } try { fc::thread::current().yield(false); BOOST_ASSERT( cc->next_blocked_mutex == 0 ); } catch ( ... ) { - wlog( "lock with throw %p %s",this, fc::current_exception().diagnostic_information().c_str() ); + wlog( "lock threw" ); cleanup( *this, m_blist_lock, m_blist, cc); throw; } diff --git a/src/spin_lock.cpp b/src/thread/spin_lock.cpp similarity index 96% rename from src/spin_lock.cpp rename to src/thread/spin_lock.cpp index 8bf72c6..97989c5 100644 --- a/src/spin_lock.cpp +++ b/src/thread/spin_lock.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/src/spin_yield_lock.cpp b/src/thread/spin_yield_lock.cpp similarity index 96% rename from src/spin_yield_lock.cpp rename to src/thread/spin_yield_lock.cpp index 07d2560..17206da 100644 --- a/src/spin_yield_lock.cpp +++ b/src/thread/spin_yield_lock.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/src/thread/task.cpp b/src/thread/task.cpp new file mode 100644 index 0000000..c6c6a0e --- /dev/null +++ b/src/thread/task.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +#include +#include + +namespace fc { + task_base::task_base(void* func) + :_functor(func){ + } + + void task_base::run() { + try { + _run_functor( _functor, _promise_impl ); + } + catch ( const exception& e ) + { + set_exception( e.dynamic_copy_exception() ); + } + catch ( ... ) + { + set_exception( std::make_shared( FC_LOG_MESSAGE( warn, "unhandled exception: ${diagnostic}", ("diagnostic",boost::current_exception_diagnostic_information()) ) ) ); + } + } + task_base::~task_base() { + _destroy_functor( _functor ); + } + + void task_base::_set_active_context(context* c) { + { synchronized( *_spinlock ) + _active_context = c; + } + } +} diff --git a/src/thread.cpp b/src/thread/thread.cpp similarity index 84% rename from src/thread.cpp rename to src/thread/thread.cpp index 4aec978..701936a 100644 --- a/src/thread.cpp +++ b/src/thread/thread.cpp @@ -1,6 +1,7 @@ -#include +#include #include -#include +#include +#include #include "thread_d.hpp" namespace fc { @@ -28,11 +29,15 @@ namespace fc { current_thread() = this; p->set_value(); exec(); + } catch ( fc::exception& e ) { + wlog( "unhandled exception" ); + p->set_exception( e.dynamic_copy_exception() ); } catch ( ... ) { - elog( "Caught unhandled exception %s", boost::current_exception_diagnostic_information().c_str() ); + wlog( "unhandled exception" ); + p->set_exception( std::make_shared( FC_LOG_MESSAGE( warn, "unhandled exception: ${diagnostic}", ("diagnostic",boost::current_exception_diagnostic_information()) ) ) ); + //assert( !"unhandled exception" ); + //elog( "Caught unhandled exception %s", boost::current_exception_diagnostic_information().c_str() ); } - delete this->my; - this->my = 0; } ); p->wait(); my->boost_thread = t; @@ -53,11 +58,13 @@ namespace fc { } thread::~thread() { - if( is_current() ) { //slog( "my %p", my ); - delete my; + if( is_current() ) + { + wlog( "delete my" ); + delete my; + } my = 0; - } } thread& thread::current() { @@ -66,20 +73,26 @@ namespace fc { } const string& thread::name()const { return my->name; } void thread::set_name( const fc::string& n ) { my->name = n; } - void thread::debug( const fc::string& d ) { my->debug(d); } + void thread::debug( const fc::string& d ) { /*my->debug(d);*/ } void thread::quit() { + //if quiting from a different thread, start quit task on thread. + //If we have and know our attached boost thread, wait for it to finish, then return. if( ¤t() != this ) { async( [=](){quit();} );//.wait(); if( my->boost_thread ) { auto n = name(); - slog( "joining... %s", n.c_str() ); + ilog( "joining... ${n}", ("n",n) );//n.c_str() ); my->boost_thread->join(); - slog( "done joining... %s", n.c_str() ); + delete my; + my = nullptr; + ilog( "done joining...${n}", ("n",n) ); //n.c_str() ); } return; } - wlog( "%s", my->name.c_str() ); + + // wlog( "%s", my->name.c_str() ); + // We are quiting from our own thread... // break all promises, thread quit! while( my->blocked ) { @@ -88,12 +101,14 @@ namespace fc { fc::context* n = cur->next; // this will move the context into the ready list. //cur->prom->set_exception( boost::copy_exception( error::thread_quit() ) ); - cur->except_blocking_promises( thread_quit() ); + //cur->except_blocking_promises( thread_quit() ); + cur->except_blocking_promises( std::make_shared() ); + cur = n; } if( my->blocked ) { - wlog( "still blocking... whats up with that?"); - debug( "on quit" ); + // wlog( "still blocking... whats up with that?"); + // debug( "on quit" ); } } BOOST_ASSERT( my->blocked == 0 ); @@ -135,7 +150,13 @@ namespace fc { void thread::exec() { if( !my->current ) my->current = new fc::context(&fc::thread::current()); + try { my->process_tasks(); + } + catch( canceled_exception& ) + { + wlog( "thread canceled" ); + } delete my->current; my->current = 0; } @@ -171,7 +192,7 @@ namespace fc { my->sleep_pqueue.end(), sleep_priority_less() ); my->start_next_fiber(); - my->current->resume_time = time_point::max(); + my->current->resume_time = time_point::maximum(); my->check_fiber_exceptions(); } @@ -185,7 +206,7 @@ namespace fc { for( auto i = p.begin(); i != p.end(); ++i ) { ss << (*i)->get_desc() <<", "; } - BOOST_THROW_EXCEPTION( future_wait_timeout( ss.str() ) ); + FC_THROW_EXCEPTION( timeout_exception, "${task}", ("task",ss.str()) ); } if( !my->current ) { @@ -197,7 +218,7 @@ namespace fc { }; // if not max timeout, added to sleep pqueue - if( timeout != time_point::max() ) { + if( timeout != time_point::maximum() ) { my->current->resume_time = timeout; my->sleep_pqueue.push_back(my->current); std::push_heap( my->sleep_pqueue.begin(), @@ -216,7 +237,7 @@ namespace fc { for( uint32_t i = 0; i < p.size(); ++i ) { if( p[i]->ready() ) return i; } - BOOST_THROW_EXCEPTION( wait_any_error() ); + //BOOST_THROW_EXCEPTION( wait_any_error() ); return -1; } @@ -270,7 +291,7 @@ namespace fc { void thread::wait_until( promise_base::ptr&& p, const time_point& timeout ) { if( p->ready() ) return; if( timeout < time_point::now() ) - BOOST_THROW_EXCEPTION( future_wait_timeout( p->get_desc() ) ); + FC_THROW_EXCEPTION( timeout_exception, "${task}", ("task", p->get_desc()) ); if( !my->current ) { my->current = new fc::context(&fc::thread::current()); @@ -280,7 +301,7 @@ namespace fc { my->current->add_blocking_promise(p.get(),true); // if not max timeout, added to sleep pqueue - if( timeout != time_point::max() ) { + if( timeout != time_point::maximum() ) { my->current->resume_time = timeout; my->sleep_pqueue.push_back(my->current); std::push_heap( my->sleep_pqueue.begin(), diff --git a/src/thread_d.hpp b/src/thread/thread_d.hpp similarity index 80% rename from src/thread_d.hpp rename to src/thread/thread_d.hpp index 5c4d852..dbb877a 100644 --- a/src/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -1,15 +1,13 @@ -#include +#include #include #include - #include #include "context.hpp" #include #include #include #include -#include -#include +//#include namespace fc { struct sleep_priority_less { @@ -18,6 +16,7 @@ namespace fc { } }; class thread_d { + public: thread_d(fc::thread& s) :self(s), boost_thread(0), @@ -29,16 +28,43 @@ namespace fc { ready_tail(0), blocked(0) { - static char cnt = 0; - name = fc::string("th_") + char('a'+cnt); - cnt++; + static boost::atomic cnt(0); + name = fc::string("th_") + char('a'+cnt++); +// printf("thread=%p\n",this); } ~thread_d(){ - fc_ilog( logger::get("fc_context"), "thread ${name} exited}", ( "name", name) ); + delete current; + fc::context* temp; + while (ready_head) + { + temp = ready_head->next; + delete ready_head; + ready_head = temp; + } + while (blocked) + { + temp = blocked->next; + delete blocked; + blocked = temp; + } + /* + while (pt_head) + { + temp = pt_head->next; + delete pt_head; + pt_head = temp; + } + */ + ilog(""); + if (boost_thread) + { + boost_thread->detach(); + delete boost_thread; + } } fc::thread& self; boost::thread* boost_thread; - bc::stack_allocator stack_alloc; + bco::stack_allocator stack_alloc; boost::condition_variable task_ready; boost::mutex task_ready_mutex; @@ -61,50 +87,51 @@ namespace fc { +#if 0 void debug( const fc::string& s ) { return; - boost::unique_lock lock(log_mutex()); + //boost::unique_lock lock(log_mutex()); - std::cerr<<"--------------------- "<cur_task ) std::cerr<<'('<cur_task->get_desc()<<')'; - std::cerr<<" ---------------------------\n"; - std::cerr<<" Ready\n"; + fc::cerr<<"--------------------- "<cur_task ) fc::cerr<<'('<cur_task->get_desc()<<')'; + fc::cerr<<" ---------------------------\n"; + fc::cerr<<" Ready\n"; fc::context* c = ready_head; while( c ) { - std::cerr<<" "<cur_task ) std::cerr<<'('<cur_task->get_desc()<<')'; + fc::cerr<<" "<cur_task ) fc::cerr<<'('<cur_task->get_desc()<<')'; fc::context* p = c->caller_context; while( p ) { - std::cerr<<" -> "< "<caller_context; } - std::cerr<<"\n"; + fc::cerr<<"\n"; c = c->next; } - std::cerr<<" Blocked\n"; + fc::cerr<<" Blocked\n"; c = blocked; while( c ) { - std::cerr<<" ctx: "<< c; - if( c->cur_task ) std::cerr<<'('<cur_task->get_desc()<<')'; - std::cerr << " blocked on prom: "; + fc::cerr<<" ctx: "<< c; + if( c->cur_task ) fc::cerr<<'('<cur_task->get_desc()<<')'; + fc::cerr << " blocked on prom: "; for( uint32_t i = 0; i < c->blocking_prom.size(); ++i ) { - std::cerr<blocking_prom[i].prom<<'('<blocking_prom[i].prom->get_desc()<<')'; + fc::cerr<blocking_prom[i].prom<<'('<blocking_prom[i].prom->get_desc()<<')'; if( i + 1 < c->blocking_prom.size() ) { - std::cerr<<","; + fc::cerr<<","; } } fc::context* p = c->caller_context; while( p ) { - std::cerr<<" -> "< "<caller_context; } - std::cerr<<"\n"; + fc::cerr<<"\n"; c = c->next_blocked; } - std::cerr<<"-------------------------------------------------\n"; + fc::cerr<<"-------------------------------------------------\n"; } - +#endif // insert at from of blocked linked list inline void add_to_blocked( fc::context* c ) { c->next_blocked = blocked; @@ -217,9 +244,10 @@ namespace fc { */ void check_fiber_exceptions() { if( current && current->canceled ) { - BOOST_THROW_EXCEPTION( task_canceled() ); + FC_THROW_EXCEPTION( canceled_exception, "" ); } else if( done ) { - BOOST_THROW_EXCEPTION( thread_quit() ); + FC_THROW_EXCEPTION( canceled_exception, "" ); + // BOOST_THROW_EXCEPTION( thread_quit() ); } } @@ -236,7 +264,8 @@ namespace fc { if( ready_head ) { fc::context* next = ready_pop_front(); if( next == current ) { - elog( "next == current... something went wrong" ); + // elog( "next == current... something went wrong" ); + assert(next != current); return false; } BOOST_ASSERT( next != current ); @@ -246,8 +275,12 @@ namespace fc { current = next; if( reschedule ) ready_push_back(prev); // slog( "jump to %p from %p", next, prev ); - fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); + // fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); +#if BOOST_VERSION >= 105300 + bc::jump_fcontext( prev->my_context, next->my_context, 0 ); +#else bc::jump_fcontext( &prev->my_context, &next->my_context, 0 ); +#endif BOOST_ASSERT( current ); BOOST_ASSERT( current == prev ); //current = prev; @@ -269,15 +302,19 @@ namespace fc { if( reschedule ) ready_push_back(prev); // slog( "jump to %p from %p", next, prev ); - fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); + // fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); +#if BOOST_VERSION >= 105300 + bc::jump_fcontext( prev->my_context, next->my_context, (intptr_t)this ); +#else bc::jump_fcontext( &prev->my_context, &next->my_context, (intptr_t)this ); +#endif BOOST_ASSERT( current ); BOOST_ASSERT( current == prev ); //current = prev; } if( current->canceled ) - BOOST_THROW_EXCEPTION( task_canceled() ); + FC_THROW_EXCEPTION( canceled_exception, "" ); return true; } @@ -286,9 +323,13 @@ namespace fc { thread_d* self = (thread_d*)my; try { self->process_tasks(); + } catch ( canceled_exception& ) { + // allowed exception... } catch ( ... ) { - std::cerr<<"fiber exited with uncaught exception:\n "<< - boost::current_exception_diagnostic_information() <name) ); + // assert( !"fiber exited with uncaught exception" ); + //TODO replace errror fc::cerr<<"fiber exited with uncaught exception:\n "<< + // boost::current_exception_diagnostic_information() <free_list.push_back(self->current); self->start_next_fiber( false ); @@ -341,7 +382,7 @@ namespace fc { time_point timeout_time = check_for_timeouts(); if( done ) return; - if( timeout_time == time_point::max() ) { + if( timeout_time == time_point::maximum() ) { task_ready.wait( lock ); } else if( timeout_time != time_point::min() ) { task_ready.wait_until( lock, boost::chrono::system_clock::time_point() + @@ -357,11 +398,11 @@ namespace fc { */ time_point check_for_timeouts() { if( !sleep_pqueue.size() && !task_sch_queue.size() ) { - return time_point::max(); + return time_point::maximum(); } - time_point next = time_point::max(); + time_point next = time_point::maximum(); if( task_sch_queue.size() && next > task_sch_queue.front()->_when ) next = task_sch_queue.front()->_when; if( sleep_pqueue.size() && next > sleep_pqueue.front()->resume_time ) @@ -423,14 +464,14 @@ namespace fc { } } - current->resume_time = time_point::max(); + current->resume_time = time_point::maximum(); check_fiber_exceptions(); } void wait( const promise_base::ptr& p, const time_point& timeout ) { if( p->ready() ) return; if( timeout < time_point::now() ) - BOOST_THROW_EXCEPTION( future_wait_timeout() ); + FC_THROW_EXCEPTION( timeout_exception, "" ); if( !current ) { current = new fc::context(&fc::thread::current()); @@ -440,7 +481,7 @@ namespace fc { current->add_blocking_promise(p.get(),true); // if not max timeout, added to sleep pqueue - if( timeout != time_point::max() ) { + if( timeout != time_point::maximum() ) { current->resume_time = timeout; sleep_pqueue.push_back(current); std::push_heap( sleep_pqueue.begin(), diff --git a/src/time.cpp b/src/time.cpp index 93aa57f..abf93bc 100644 --- a/src/time.cpp +++ b/src/time.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -18,13 +18,13 @@ namespace fc { } time_point time_point::from_iso_string( const fc::string& s ) { auto pt = boost::posix_time::from_iso_string(s); - return fc::time_point(fc::seconds( (pt - boost::posix_time::from_time_t(0)).total_seconds() )); + //return fc::time_point(fc::seconds( (pt - boost::posix_time::from_time_t(0)).total_seconds() )); + return fc::time_point(fc::microseconds( (pt - boost::posix_time::from_time_t(0)).total_microseconds() )); } - class value; - void pack( fc::value& v, const fc::time_point& t ) { + void to_variant( const fc::time_point& t, variant& v ) { v = fc::string(t); } - void unpack( const fc::value& v, fc::time_point& t ) { - t = fc::time_point::from_iso_string(v.cast()); + void from_variant( const fc::variant& v, fc::time_point& t ) { + t = fc::time_point::from_iso_string(v.as_string()); } } diff --git a/src/url.cpp b/src/url.cpp deleted file mode 100644 index 54ebf6e..0000000 --- a/src/url.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace fc { - -// url::url( const url& u ); -#if 0 - url::url( url&& u ) - :proto(fc::move(u.proto)), - host(fc::move(u.host)), - user(fc::move(u.user)), - pass(fc::move(u.pass)), - path(fc::move(u.path)), - args(fc::move(u.args)), - port(u.port){} - - url& url::operator=(url&& c) - { - fc::swap(*this,c); - return *this; - } - - // url::url& operator=(const url& c) { - // } -#endif - url::url( const string& s ) { - from_string(s); - } - string url::to_string()const { - fc::stringstream ss; - ss<( host_port.substr( pos+1 ) ); - } catch ( ... ) { - FC_THROW_REPORT( "Unable to parse port field in url", value().set( "url", s ) ); - } - host = host_port.substr(0,pos); - } else { - host = fc::move(host_port); - } - fc::getline( ss, _path, '?' ); - fc::getline( ss, _args ); - path = fc::move(_path); - if( _args.size() ) args = fc::move(_args); - - return *this; - } - - bool url::operator==( const url& cmp )const { - return cmp.proto == proto && - cmp.host == host && - cmp.user == user && - cmp.pass == pass && - cmp.path == path && - cmp.args == args && - cmp.port == port; - } - -} // namespace fc diff --git a/src/value.cpp b/src/value.cpp deleted file mode 100644 index 3a11de4..0000000 --- a/src/value.cpp +++ /dev/null @@ -1,734 +0,0 @@ -#include -#include -#include -#include -#include - - -namespace fc { - - namespace detail { - class value_visitor { - public: - virtual void operator()( int8_t& v ){}; - virtual void operator()( int16_t& v ){}; - virtual void operator()( int32_t& v ){}; - virtual void operator()( int64_t& v ){}; - virtual void operator()( uint8_t& v ){}; - virtual void operator()( uint16_t& v ){}; - virtual void operator()( uint32_t& v ){}; - virtual void operator()( uint64_t& v ){}; - virtual void operator()( float& v ){}; - virtual void operator()( double& v ){}; - virtual void operator()( bool& v ){}; - virtual void operator()( fc::string& v ){}; - virtual void operator()( value::object& ){}; - virtual void operator()( value::array& ){}; - virtual void operator()( ){}; - }; - template - struct cast_visitor : value::const_visitor { - cast_visitor( T& out ) - :m_out(out){} - virtual void operator()( const int8_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const int16_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const int32_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const int64_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const uint8_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const uint16_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const uint32_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const uint64_t& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const float& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const double& v ) { m_out = fc::numeric_cast(v); } - virtual void operator()( const bool& v ) { m_out = v; } - virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to ${type} from object", - fc::value().set("type",fc::get_typename::name())); } - virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to ${type} from array", - fc::value().set("type",fc::get_typename::name())); } - virtual void operator()( ) { FC_THROW_REPORT("bad cast to ${type} from null", - fc::value().set("type",fc::get_typename::name())); } - private: - T& m_out; - }; - - template<> - struct cast_visitor : value::const_visitor { - cast_visitor( bool& out ) - :m_out(out){} - virtual void operator()( const int8_t& v ){ m_out = v != 0; } - virtual void operator()( const int16_t& v ){ m_out = v != 0; } - virtual void operator()( const int32_t& v ){ m_out = v != 0; } - virtual void operator()( const int64_t& v ){ m_out = v != 0; } - virtual void operator()( const uint8_t& v ){ m_out = v != 0; } - virtual void operator()( const uint16_t& v ){ m_out = v != 0; } - virtual void operator()( const uint32_t& v ){ m_out = v != 0; } - virtual void operator()( const uint64_t& v ){ m_out = v != 0; } - virtual void operator()( const float& v ){ m_out = v != 0; } - virtual void operator()( const double& v ){ m_out = v != 0; } - virtual void operator()( const bool& v ){ m_out = v; } - virtual void operator()( const fc::string& v ) { m_out = !(v != "true"); } - virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to bool from object"); } - virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to bool from array"); } - virtual void operator()( ) { FC_THROW_REPORT("bad cast to bool from null"); } - private: - bool& m_out; - }; - - template<> - struct cast_visitor : value::const_visitor { - cast_visitor( fc::string& out ) - :m_out(out){} - virtual void operator()( const int8_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const int16_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const int32_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const int64_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const uint8_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const uint16_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const uint32_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const uint64_t& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const float& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const double& v ) { m_out = fc::lexical_cast(v); } - virtual void operator()( const bool& v ) { m_out = v != 0 ? "true" : "false"; } - virtual void operator()( const fc::string& v ) { m_out = v; } - virtual void operator()( const value::object& ){ FC_THROW_REPORT("bad cast to string from object"); } - virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to string from array"); } - virtual void operator()( ) { m_out = fc::string(); } - - private: - fc::string& m_out; - }; - - template<> - struct cast_visitor : value::const_visitor { - cast_visitor( value::array& out ) - :m_out(out){} - virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast to array from int8");} - virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast to array from int16");} - virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast to array from int32");} - virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast to array from int32");} - virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast to array from uint8");} - virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast to array from uint16");} - virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast to array from uint32");} - virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast to array from uint64");} - virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to array from float");} - virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to array from double");} - virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast to array from bool");} - virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to array from string");} - virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to array from object");} - virtual void operator()( const value::array& a ) { m_out = a; } - virtual void operator()( ) { m_out = value::array(); } - - private: - value::array& m_out; - }; - - template<> - struct cast_visitor : value::const_visitor { - cast_visitor( value::object& out ) - :m_out(out){} - virtual void operator()( const int8_t& v ){ FC_THROW_REPORT("bad cast to array from int8");} - virtual void operator()( const int16_t& v ){ FC_THROW_REPORT("bad cast to array from int16");} - virtual void operator()( const int32_t& v ){ FC_THROW_REPORT("bad cast to array from int32");} - virtual void operator()( const int64_t& v ){ FC_THROW_REPORT("bad cast to array from int32");} - virtual void operator()( const uint8_t& v ){ FC_THROW_REPORT("bad cast to array from uint8");} - virtual void operator()( const uint16_t& v ){ FC_THROW_REPORT("bad cast to array from uint16");} - virtual void operator()( const uint32_t& v ){ FC_THROW_REPORT("bad cast to array from uint32");} - virtual void operator()( const uint64_t& v ){ FC_THROW_REPORT("bad cast to array from uint64");} - virtual void operator()( const float& v ){ FC_THROW_REPORT("bad cast to array from float");} - virtual void operator()( const double& v ){ FC_THROW_REPORT("bad cast to array from double");} - virtual void operator()( const bool& v ){ FC_THROW_REPORT("bad cast to array from bool");} - virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to array from string");} - virtual void operator()( const value::object& a ) { m_out = a; } - virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( ) { m_out = value::object(); } - - private: - value::object& m_out; - }; - template<> - struct cast_visitor : value::const_visitor { - cast_visitor( value& out ) - :m_out(out){} - virtual void operator()( const int8_t& v ) { m_out = v; } - virtual void operator()( const int16_t& v ) { m_out = v; } - virtual void operator()( const int32_t& v ) { m_out = v; } - virtual void operator()( const int64_t& v ) { m_out = v; } - virtual void operator()( const uint8_t& v ) { m_out = v; } - virtual void operator()( const uint16_t& v ) { m_out = v; } - virtual void operator()( const uint32_t& v ) { m_out = v; } - virtual void operator()( const uint64_t& v ) { m_out = v; } - virtual void operator()( const float& v ) { m_out = v; } - virtual void operator()( const double& v ) { m_out = v; } - virtual void operator()( const bool& v ) { m_out = v; } - virtual void operator()( const fc::string& v ) { m_out = v; } - virtual void operator()( const value::object& a ) { m_out = a; } - virtual void operator()( const value::array& a ) { m_out = a; } - virtual void operator()( ) { m_out = value(); } - - value& m_out; - }; - - template<> - struct cast_visitor : value::const_visitor { - virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");} - virtual void operator()( ) { } - }; - - void cast_value( const value& v, int8_t& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, int16_t& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, int32_t& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, int64_t& out ){ - v.visit( cast_visitor(out) ); - slog( "cast_value( v, int64: %lld )", out ); - } - - void cast_value( const value& v, uint8_t& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, uint16_t& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, uint32_t& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, uint64_t& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, double& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, float& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, bool& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, fc::string& out ){ - v.visit( cast_visitor(out) ); - } - - void cast_value( const value& v, value& out ){ - out = v; - } - - - struct value_holder { - virtual ~value_holder(); - virtual value::value_type type()const; - const char* get_typename()const { return fc::reflector::to_string(type()); } - virtual void visit( value::const_visitor&& v )const; - virtual void visit( value_visitor&& v ); - - virtual void clear(); - virtual size_t size()const; - virtual void resize( size_t ); - virtual void reserve( size_t ); - virtual value& at( size_t ); - virtual const value& at( size_t )const; - virtual void push_back( value&& v ); - - virtual value_holder* move_helper( char* c ); - virtual value_holder* copy_helper( char* c )const; - }; - - void value_holder::visit( value::const_visitor&& v )const {v(); } - void value_holder::visit( value_visitor&& v ) {v(); } - - template - struct get_value_type{}; - template<> struct get_value_type { static value::value_type type(){ return value::null_type; } }; - template<> struct get_value_type { static value::value_type type(){ return value::int8_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::int16_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::int32_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::int64_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::uint8_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::uint16_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::uint32_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::uint64_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::double_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::float_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::string_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::bool_type; } }; - template<> struct get_value_type>{ static value::value_type type(){ return value::array_type; } }; - template<> struct get_value_type{ static value::value_type type(){ return value::object_type; } }; - - // fundamental values... - template - struct value_holder_impl : value_holder { - static_assert( !fc::is_class::value, "only fundamental types can be stored without specialization" ); - - value_holder_impl(){ - static_assert( sizeof(value_holder_impl) <= 40, "Validate size" ); - } - virtual value::value_type type()const { return get_value_type::type(); } - virtual void visit( value::const_visitor&& v )const{ v(val); } - virtual void visit( value_visitor&& v ) { v(val); } - virtual void clear() { val = T(); } - virtual size_t size()const { return 0; } - - virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); } - virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(val); } - - template - value_holder_impl( V&& v ):val( fc::forward(v) ){} - - T val; - }; - - - template<> - struct value_holder_impl : value_holder { - value_holder_impl(){}; - virtual void visit( value::const_visitor&& v )const{ v(); } - virtual void visit( value_visitor&& v ) { v(); } - virtual value_holder* move_helper( char* c ) { return new(c) value_holder_impl(); } - virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(); } - }; - - - template<> - struct value_holder_impl : value_holder { - template - value_holder_impl( V&& v ):val( fc::forward(v) ){ - static_assert( sizeof(value_holder_impl) <= 40, "Validate size" ); - } - - virtual value::value_type type()const { return value::string_type; } - virtual void visit( value::const_visitor&& v )const { v(val); } - virtual void visit( value_visitor&& v ) { v(val); } - - virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); } - virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(val); } - - virtual void clear() { val = fc::string(); } - virtual size_t size()const { FC_THROW_REPORT( "Attempt to access string as array" ); } - - fc::string val; - }; - - template<> - struct value_holder_impl : value_holder { - virtual value::value_type type()const { return value::object_type; } - virtual void visit( value::const_visitor&& v )const; - virtual void visit( value_visitor&& v ); - virtual value_holder* move_helper( char* c ); - virtual value_holder* copy_helper( char* c )const; - virtual void reserve( size_t s ); - - virtual void clear(); - virtual size_t size()const; - - template - value_holder_impl( V&& v ):val( fc::forward(v) ){} - - value::object val; - }; - - template<> - struct value_holder_impl : value_holder { - virtual value::value_type type()const { return value::array_type; } - virtual void visit( value::const_visitor&& v )const; - virtual void visit( value_visitor&& v ); - virtual value_holder* move_helper( char* c ); - virtual value_holder* copy_helper( char* c )const; - - virtual void resize( size_t s ); - virtual void reserve( size_t s ); - virtual value& at( size_t i); - virtual const value& at( size_t i)const; - virtual void push_back( value&& v ); - - template - value_holder_impl( V&& v ):val( fc::forward(v) ){} - - virtual void clear(); - virtual size_t size()const; - - value::array val; - }; - static_assert( sizeof( value_holder_impl ) <= 40, "sanity check" ); - static_assert( sizeof( value_holder_impl ) <= 40, "sanity check" ); - - value_holder::~value_holder(){} - value::value_type value_holder::type()const { return value::null_type; } - value_holder* value_holder::move_helper( char* c ) { return new(c) value_holder_impl(); } - value_holder* value_holder::copy_helper( char* c )const { return new(c) value_holder_impl(); } - - void new_value_holder_void( value* v ) { - new (v) value_holder_impl(); - } - - void value_holder::clear() {} - size_t value_holder::size()const { return 0; } - void value_holder::resize( size_t ) { FC_THROW_MSG("value type '%s' not an array", get_typename()); } - void value_holder::reserve( size_t ) { FC_THROW_MSG("value type '%s' not an array or object", get_typename()); } - value& value_holder::at( size_t ) { FC_THROW_MSG("value type '%s' not an array", get_typename()); return *((value*)0); } - const value& value_holder::at( size_t )const { FC_THROW_MSG("value type '%s' not an array", get_typename()); return *((const value*)0); } - void value_holder::push_back( value&& v ) { FC_THROW_MSG("value type '%s' not an array", get_typename()); } - - - void value_holder_impl::resize( size_t s ) { val.resize(s); } - void value_holder_impl::reserve( size_t s ) { val.reserve(s); } - value& value_holder_impl::at( size_t i) { return val[i]; } - const value& value_holder_impl::at( size_t i)const { return val[i]; } - value_holder* value_holder_impl::move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); } - value_holder* value_holder_impl::copy_helper( char* c )const{ return new(c) value_holder_impl(val); } - - void value_holder_impl::clear() { val.clear(); } - size_t value_holder_impl::size()const { return static_cast(val.size()); } - void value_holder_impl::visit( value::const_visitor&& v )const { v(val); } - void value_holder_impl::visit( value_visitor&& v ) { v(val); } - void value_holder_impl::push_back( value&& v ) { val.push_back( fc::move(v) ); } - - - void value_holder_impl::visit( value::const_visitor&& v )const { v(val); } - void value_holder_impl::visit( value_visitor&& v ) { v(val); } - value_holder* value_holder_impl::move_helper( char* c ) { return new(c) value_holder_impl( fc::move(val) ); } - value_holder* value_holder_impl::copy_helper( char* c )const { return new(c) value_holder_impl(val); } - void value_holder_impl::reserve( size_t s ) { val.fields.reserve(s); } - - void value_holder_impl::clear() { val = value::object(); } - size_t value_holder_impl::size()const { return val.fields.size(); } - } // namespace detail - -static detail::value_holder* gh( aligned<40>& h ) { - return (detail::value_holder*)h._store._data; -} -static const detail::value_holder* gh( const aligned<40>& h ) { - return (const detail::value_holder*)h._store._data; -} - -value::value() { - new (holder) detail::value_holder_impl(); -} -value::value( value&& m ) { - gh(m.holder)->move_helper(holder._store._data); -} -value::value( const value& m ){ - gh(m.holder)->copy_helper(holder._store._data); -} -value::value( const char* c ) { - new (holder) detail::value_holder_impl( c ); -} -value::value( char* c ) { - new (holder) detail::value_holder_impl( c ); -} -value::~value() { - gh(holder)->~value_holder(); -} -value::value( int8_t v){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(v); -} -value::value( int16_t v){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(v); -} -value::value( int32_t v){ - new (holder) detail::value_holder_impl(v); -} -value::value( int64_t v){ - new (holder) detail::value_holder_impl(v); -} -value::value( uint8_t v){ - new (holder) detail::value_holder_impl(v); -} -value::value( uint16_t v){ - new (holder) detail::value_holder_impl(v); -} -value::value( uint32_t v){ - new (holder) detail::value_holder_impl(v); -} -value::value( uint64_t v){ - new (holder) detail::value_holder_impl(v); -} -value::value( double v){ - new (holder) detail::value_holder_impl(v); -} -value::value( float v){ - new (holder) detail::value_holder_impl(v); -} -value::value( bool v){ - new (holder) detail::value_holder_impl(v); -} -value::value( fc::string&& v){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(fc::move(v)); -} -value::value( fc::string& v){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(v); -} -value::value( const fc::string& v){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(v); -} -value::value( const fc::string& v, const value& val ) { - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(value::object()); - set( v, val ); -} -value::value( value::object&& o ){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(fc::move(o)); -} -value::value( value::array&& a ){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(fc::move(a)); -} -value::value( const value::array& a ){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(a); -} -value::value( value::array& a ){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(a); -} -value::value( const value::object& a ){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(a); -} -value::value( value::object& a ){ - static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl ), "size check" ); - new (holder) detail::value_holder_impl(a); -} -bool operator == ( const value& v, std::nullptr_t ) { - return v.is_null(); -} -bool operator != ( const value& v, std::nullptr_t ) { - return v.is_null(); -} - -value& value::operator=( value&& v ){ - decltype(holder) tmp; - gh(holder)->move_helper(tmp); - gh(v.holder)->move_helper(holder); - gh(tmp)->move_helper(v.holder); - return *this; -} -value& value::operator=( const value& v ){ - if( this == &v ) return *this; - gh(holder)->~value_holder(); - gh(v.holder)->copy_helper(holder); - return *this; -} -bool value::is_null()const { - return gh(holder)->type() == null_type; -} -bool value::is_object()const { - return gh(holder)->type() == object_type; -} -bool value::is_array()const { - return gh(holder)->type() == array_type; -} -bool value::is_string()const { - return gh(holder)->type() == string_type; -} - -const fc::vector& value::as_array()const { - if( gh(holder)->type() != array_type ) { - FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value array", value("type",gh(holder)->get_typename() ) ); - } - const detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val; -} -fc::vector& value::as_array(){ - if( gh(holder)->type() != array_type ) { - FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value array", value("type",gh(holder)->get_typename() ) ); - } - detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val; -} -const value::object& value::as_object()const { - if( gh(holder)->type() != object_type ) { - FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value object", value("type",gh(holder)->get_typename() ) ); - } - const detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val; -} -value::object& value::as_object(){ - if( gh(holder)->type() != object_type ) { - FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value object", value("type",gh(holder)->get_typename() ) ); - } - detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val; -} -const fc::string& value::as_string()const { - if( gh(holder)->type() != string_type ) { - FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value string", value("type",gh(holder)->get_typename() ) ); - } - const detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val; -} -fc::string& value::as_string(){ - if( gh(holder)->type() != string_type ) { - FC_THROW_REPORT( "Attempt to dereference value of type ${type} as value string", value("type",gh(holder)->get_typename() ) ); - } - detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val; -} - - -value::object::const_iterator value::find( const char* key )const { - if( gh(holder)->type() == object_type ) { - const detail::value_holder_impl* o = static_cast*>(gh(holder)); - for( auto i = o->val.fields.begin(); - i != o->val.fields.end(); ++i ) { - if( strcmp( i->key.c_str(), key ) == 0 ) - return i; - } - return o->val.fields.end(); - } - //FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() ); - return value::object::const_iterator(); -} -value::object::const_iterator value::begin()const { - if( gh(holder)->type() == object_type ) { - const detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val.fields.begin(); - } - //// FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() ); - return value::object::const_iterator(); - //return nullptr; -} -value::object::const_iterator value::end()const { - if( gh(holder)->type()== object_type ) { - const detail::value_holder_impl* o = static_cast*>(gh(holder)); - return o->val.fields.end(); - } - ////FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() ); - return value::object::const_iterator(); - //return nullptr; -} -/** - * If this value is an object, remove key from the object - * - * @return *this; - */ -value& value::clear( const fc::string& key ) { - if( gh(holder)->type()== object_type ) { - detail::value_holder_impl* o = dynamic_cast*>(gh(holder)); - for( auto i = o->val.fields.begin(); - i != o->val.fields.end(); ++i ) { - if( strcmp( i->key.c_str(), key.c_str() ) == 0 ) { - o->val.fields.erase(i); - return *this; - } - } - } - return *this; -} -value& value::operator[]( const char* key ) { - if( gh(holder)->type()== object_type ) { - detail::value_holder_impl* o = dynamic_cast*>(gh(holder)); - for( auto i = o->val.fields.begin(); - i != o->val.fields.end(); ++i ) { - if( strcmp( i->key.c_str(), key ) == 0 ) - return i->val; - } - o->val.fields.reserve(o->val.fields.size()+1); - o->val.fields.push_back( key_val(key) ); - return o->val.fields.back().val; - } else if (gh(holder)->type() == null_type ) { - new (gh(holder)) detail::value_holder_impl(value::object()); - return (*this)[key]; - } - FC_THROW_REPORT( "Bad cast of ${type} to object", fc::value().set("type", gh(holder)->get_typename()) ); - return *((value*)0); -} -value& value::operator[]( const fc::string& key ) { return (*this)[key.c_str()]; } -const value& value::operator[]( const fc::string& key )const { return (*this)[key.c_str()]; } -const value& value::operator[]( const char* key )const { - auto i = find(key); - if( i == end() ) { - FC_THROW_MSG( "Key '%s' not found in object", key ); - } - return i->val; -} - -void value::clear() { - gh(holder)->clear(); -} -size_t value::size()const { - return gh(holder)->size(); -} -void value::resize( size_t s ) { - gh(holder)->resize(s); -} -void value::reserve( size_t s ) { - gh(holder)->reserve(s); -} -value& value::push_back( value&& v ) { - if (gh(holder)->type() == null_type ) { - new (gh(holder)) detail::value_holder_impl(value::array()); - return push_back( fc::move(v) ); - } - gh(holder)->push_back(fc::move(v)); - return *this; -} -value& value::push_back( const value& v ) { - if (gh(holder)->type() == null_type ) { - new (gh(holder)) detail::value_holder_impl(value::array()); - return push_back( v ); - } - gh(holder)->push_back(value(v)); - return *this; -} -value& value::operator[]( int32_t idx ) { - return gh(holder)->at(idx); -} -const value& value::operator[]( int32_t idx )const { - return gh(holder)->at(idx); -} - -value::value_type value::type()const { return gh(holder)->type(); } - -void value::visit( value::const_visitor&& v )const { - auto h = ((detail::value_holder*)&holder[0]); - h->visit( fc::move(v) ); -} -/* sets the subkey key with v and return *this */ -value& value::set( const char* key, fc::value v ) { - (*this)[key] = fc::move(v); - return *this; -} -value& value::operator()( const char* key, fc::value v ) { - (*this)[key] = fc::move(v); - return *this; -} -value& value::set( const fc::string& key, fc::value v ) { - (*this)[key.c_str()] = fc::move(v); - return *this; -} - -} // namepace fc diff --git a/src/value_cast.cpp b/src/value_cast.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/variant.cpp b/src/variant.cpp new file mode 100644 index 0000000..90e4cf7 --- /dev/null +++ b/src/variant.cpp @@ -0,0 +1,647 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc +{ + + void to_variant( const uint16_t& var, variant& vo ) { vo = uint64_t(var); } + // TODO: warn on overflow? + void from_variant( const variant& var, uint16_t& vo ){ vo = static_cast(var.as_uint64()); } +void to_variant( const vector& var, variant& vo ) +{ + if( var.size() ) + vo = variant(base64_encode((unsigned char*)var.data(),var.size())); + else vo = ""; +} +void from_variant( const variant& var, vector& vo ) +{ + std::string b64 = base64_decode( var.as_string() ); + vo = fc::vector( b64.c_str(), b64.c_str() + b64.size() ); +} +/** + * The TypeID is stored in the 'last byte' of the variant. + */ +void set_variant_type( variant* v, variant::type_id t) +{ + char* data = reinterpret_cast(v); + data[ sizeof(variant) -1 ] = t; +} + +variant::variant() +{ + set_variant_type( this, null_type ); +} + +variant::variant( fc::nullptr_t ) +{ + set_variant_type( this, null_type ); +} + +variant::variant( int64_t val ) +{ + *reinterpret_cast(this) = val; + set_variant_type( this, int64_type ); +} + +variant::variant( int val ) +{ + *reinterpret_cast(this) = val; + set_variant_type( this, int64_type ); +} +variant::variant( float val ) +{ + *reinterpret_cast(this) = val; + set_variant_type( this, double_type ); +} + +variant::variant( uint64_t val ) +{ + *reinterpret_cast(this) = val; + set_variant_type( this, uint64_type ); +} + +variant::variant( double val ) +{ + *reinterpret_cast(this) = val; + set_variant_type( this, double_type ); +} + +variant::variant( bool val ) +{ + *reinterpret_cast(this) = val; + set_variant_type( this, bool_type ); +} + +variant::variant( char* str ) +{ + *reinterpret_cast(this) = new string( str ); + set_variant_type( this, string_type ); +} + +variant::variant( const char* str ) +{ + *reinterpret_cast(this) = new string( str ); + set_variant_type( this, string_type ); +} + +// TODO: do a proper conversion to utf8 +variant::variant( wchar_t* str ) +{ + size_t len = wcslen(str); + boost::scoped_array buffer(new char[len]); + for (unsigned i = 0; i < len; ++i) + buffer[i] = (char)str[i]; + *reinterpret_cast(this) = new string(buffer.get(), len); + set_variant_type( this, string_type ); +} + +// TODO: do a proper conversion to utf8 +variant::variant( const wchar_t* str ) +{ + size_t len = wcslen(str); + boost::scoped_array buffer(new char[len]); + for (unsigned i = 0; i < len; ++i) + buffer[i] = (char)str[i]; + *reinterpret_cast(this) = new string(buffer.get(), len); + set_variant_type( this, string_type ); +} + +variant::variant( fc::string val ) +{ + *reinterpret_cast(this) = new string( fc::move(val) ); + set_variant_type( this, string_type ); +} + +variant::variant( variant_object obj) +{ + *reinterpret_cast(this) = new variant_object(fc::move(obj)); + set_variant_type(this, object_type ); +} +variant::variant( mutable_variant_object obj) +{ + *reinterpret_cast(this) = new variant_object(fc::move(obj)); + set_variant_type(this, object_type ); +} + +variant::variant( variants arr ) +{ + *reinterpret_cast(this) = new variants(fc::move(arr)); + set_variant_type(this, array_type ); +} + + +typedef const variant_object* const_variant_object_ptr; +typedef const variants* const_variants_ptr; +typedef const string* const_string_ptr; + +variant::variant( const variant& v ) +{ + switch( v.get_type() ) + { + case object_type: + *reinterpret_cast(this) = + new variant_object(**reinterpret_cast(&v)); + set_variant_type( this, object_type ); + return; + case array_type: + *reinterpret_cast(this) = + new variants(**reinterpret_cast(&v)); + set_variant_type( this, array_type ); + return; + case string_type: + *reinterpret_cast(this) = + new string(**reinterpret_cast(&v) ); + set_variant_type( this, string_type ); + return; + + default: + memcpy( this, &v, sizeof(v) ); + } +} + +variant::variant( variant&& v ) +{ + memcpy( this, &v, sizeof(v) ); + set_variant_type( &v, null_type ); +} + +variant::~variant() +{ + switch( get_type() ) + { + case object_type: + delete *reinterpret_cast(this); + break; + case array_type: + delete *reinterpret_cast(this); + break; + case string_type: + delete *reinterpret_cast(this); + break; + default: + break; + } +} + +variant& variant::operator=( variant&& v ) +{ + switch( get_type() ) + { + set_variant_type( this, null_type ); + case object_type: + delete *reinterpret_cast(this); + break; + case array_type: + delete *reinterpret_cast(this); + break; + case string_type: + delete *reinterpret_cast(this); + break; + default: + break; + } + switch( v.get_type() ) + { + case object_type: + *reinterpret_cast(this) = new variant_object(fc::move(**reinterpret_cast(&v))); + set_variant_type( this, object_type ); + return *this; + case array_type: + *reinterpret_cast(this) = new variants(fc::move(**reinterpret_cast(&v))); + set_variant_type( this, array_type ); + return *this; + case string_type: + *reinterpret_cast(this) = new string(fc::move(**reinterpret_cast(&v)) ); + set_variant_type( this, string_type ); + return *this; + + default: + memcpy( this, &v, sizeof(v) ); + } + + return *this; +} +variant& variant::operator=( const variant& v ) +{ + if( this == &v ) + return *this; + switch( get_type() ) + { + set_variant_type( this, null_type ); + case object_type: + delete *reinterpret_cast(this); + break; + case array_type: + delete *reinterpret_cast(this); + break; + case string_type: + delete *reinterpret_cast(this); + break; + default: + break; + } + switch( v.get_type() ) + { + case object_type: + *reinterpret_cast(this) = + new variant_object((**reinterpret_cast(&v))); + break; + case array_type: + *reinterpret_cast(this) = + new variants((**reinterpret_cast(&v))); + break; + case string_type: + *reinterpret_cast(this) = new string((**reinterpret_cast(&v)) ); + break; + + default: + memcpy( this, &v, sizeof(v) ); + } + set_variant_type( this, v.get_type() ); + return *this; +} + +void variant::visit( const visitor& v )const +{ + switch( get_type() ) + { + case null_type: + v.handle(); + return; + case int64_type: + v.handle( *reinterpret_cast(this) ); + return; + case uint64_type: + v.handle( *reinterpret_cast(this) ); + return; + case double_type: + v.handle( *reinterpret_cast(this) ); + return; + case bool_type: + v.handle( *reinterpret_cast(this) ); + return; + case string_type: + v.handle( **reinterpret_cast(this) ); + return; + case array_type: + v.handle( **reinterpret_cast(this) ); + return; + case object_type: + v.handle( **reinterpret_cast(this) ); + return; + default: + FC_THROW_EXCEPTION( assert_exception, "Invalid Type / Corrupted Memory" ); + } +} + +variant::type_id variant::get_type()const +{ + return (type_id)reinterpret_cast(this)[sizeof(*this)-1]; +} + +bool variant::is_null()const +{ + return get_type() == null_type; +} + +bool variant::is_string()const +{ + return get_type() == string_type; +} +bool variant::is_bool()const +{ + return get_type() == bool_type; +} +bool variant::is_double()const +{ + return get_type() == double_type; +} +bool variant::is_uint64()const +{ + return get_type() == uint64_type; +} +bool variant::is_int64()const +{ + return get_type() == int64_type; +} + +bool variant::is_numeric()const +{ + switch( get_type() ) + { + case int64_type: + case uint64_type: + case double_type: + case bool_type: + return true; + default: + return false; + } + return false; +} + +bool variant::is_object()const +{ + return get_type() == object_type; +} + +bool variant::is_array()const +{ + return get_type() == array_type; +} + +int64_t variant::as_int64()const +{ + switch( get_type() ) + { + case string_type: + return to_int64(**reinterpret_cast(this)); + case double_type: + return int64_t(*reinterpret_cast(this)); + case int64_type: + return *reinterpret_cast(this); + case uint64_type: + return int64_t(*reinterpret_cast(this)); + case bool_type: + return *reinterpret_cast(this); + case null_type: + return 0; + default: + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to int64", ("type", "") ); + } +} + +uint64_t variant::as_uint64()const +{ + switch( get_type() ) + { + case string_type: + return to_uint64(**reinterpret_cast(this)); + case double_type: + return static_cast(*reinterpret_cast(this)); + case int64_type: + return static_cast(*reinterpret_cast(this)); + case uint64_type: + return *reinterpret_cast(this); + case bool_type: + return static_cast(*reinterpret_cast(this)); + case null_type: + return 0; + default: + FC_THROW_EXCEPTION( bad_cast_exception,"Invalid cast from ${type} to uint64", ("type","")); + } +} + + +double variant::as_double()const +{ + switch( get_type() ) + { + case string_type: + return to_double(**reinterpret_cast(this)); + case double_type: + return *reinterpret_cast(this); + case int64_type: + return static_cast(*reinterpret_cast(this)); + case uint64_type: + return static_cast(*reinterpret_cast(this)); + case bool_type: + return *reinterpret_cast(this); + case null_type: + return 0; + default: + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to double" ); + } +} + +bool variant::as_bool()const +{ + switch( get_type() ) + { + case string_type: + return **reinterpret_cast(this) == "true"; + case double_type: + return *reinterpret_cast(this) != 0.0; + case int64_type: + return *reinterpret_cast(this) != 0; + case uint64_type: + return *reinterpret_cast(this) != 0; + case bool_type: + return *reinterpret_cast(this); + case null_type: + return false; + default: + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to bool" ); + } +} + +string variant::as_string()const +{ + switch( get_type() ) + { + case string_type: + return **reinterpret_cast(this); + case double_type: + return to_string(*reinterpret_cast(this)); + case int64_type: + return to_string(*reinterpret_cast(this)); + case uint64_type: + return to_string(*reinterpret_cast(this)); + case bool_type: + return *reinterpret_cast(this) ? "true" : "false"; + case null_type: + return string(); + default: + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to string", ("type", int64_t(get_type()) ) ); + } +} + + +/// @throw if get_type() != array_type | null_type +variants& variant::get_array() +{ + if( get_type() == array_type ) + return **reinterpret_cast(this); + + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Array" ); +} + + +/// @throw if get_type() != array_type +const variants& variant::get_array()const +{ + if( get_type() == array_type ) + return **reinterpret_cast(this); + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Array" ); +} + + +/// @throw if get_type() != object_type | null_type +variant_object& variant::get_object() +{ + if( get_type() == object_type ) + return **reinterpret_cast(this); + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Object" ); +} + +const variant& variant::operator[]( const char* key )const +{ + return get_object()[key]; +} +const variant& variant::operator[]( size_t pos )const +{ + return get_array()[pos]; +} + /// @pre is_array() +size_t variant::size()const +{ + return get_array().size(); +} + +const string& variant::get_string()const +{ + if( get_type() == string_type ) + return **reinterpret_cast(this); + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Object" ); +} + + +/// @throw if get_type() != object_type +const variant_object& variant::get_object()const +{ + if( get_type() == object_type ) + return **reinterpret_cast(this); + FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Object" ); +} + +void to_variant( const std::string& s, variant& v ) +{ + v = variant( fc::string(s) ); +} + +//void from_variant( const variant& var, variant_object& vo ) +//{ +// vo = var.get_object(); +//} +void from_variant( const variant& var, string& vo ) +{ + vo = var.as_string(); +} + +void from_variant( const variant& var, variants& vo ) +{ + vo = var.get_array(); +} + +void from_variant( const variant& var, variant& vo ) { vo = var; } + +void from_variant( const variant& var, int64_t& vo ) +{ + vo = var.as_int64(); +} + +void from_variant( const variant& var, uint64_t& vo ) +{ + vo = var.as_uint64(); +} + +void from_variant( const variant& var, bool& vo ) +{ + vo = var.as_bool(); +} + +void from_variant( const variant& var, double& vo ) +{ + vo = var.as_double(); +} + +void from_variant( const variant& var, float& vo ) +{ + vo = static_cast(var.as_double()); +} + +void from_variant( const variant& var, int32_t& vo ) +{ + vo = static_cast(var.as_int64()); +} + +void to_variant( const uint32_t& var, variant& vo ) { vo = uint64_t(var); } +void from_variant( const variant& var, uint32_t& vo ) +{ + vo = static_cast(var.as_uint64()); +} +void to_variant( const uint8_t& var, variant& vo ) { vo = uint64_t(var); } +void from_variant( const variant& var, uint8_t& vo ) +{ + vo = static_cast(var.as_uint64()); +} + +string format_string( const string& format, const variant_object& args ) +{ + stringstream ss; + size_t prev = 0; + auto next = format.find( '$' ); + while( prev != size_t(string::npos) && prev < size_t(format.size()) ) + { + ss << format.substr( prev, size_t(next-prev) ); + + // if we got to the end, return it. + if( next == size_t(string::npos) ) + return ss.str(); + + // if we are not at the end, then update the start + prev = next + 1; + + if( format[prev] == '{' ) + { + // if the next char is a open, then find close + next = format.find( '}', prev ); + // if we found close... + if( next != size_t(string::npos) ) + { + // the key is between prev and next + string key = format.substr( prev+1, (next-prev-1) ); + + auto val = args.find( key ); + if( val != args.end() ) + { + if( val->value().is_object() || val->value().is_array() ) + { + ss << json::to_string( val->value() ); + } + else + { + ss << val->value().as_string(); + } + } + else + { + ss << "${"< +#include +#include + + +namespace fc +{ + // --------------------------------------------------------------- + // entry + + variant_object::entry::entry() {} + variant_object::entry::entry( string k, variant v ) : _key(fc::move(k)),_value(fc::move(v)) {} + variant_object::entry::entry( entry&& e ) : _key(fc::move(e._key)),_value(fc::move(e._value)) {} + variant_object::entry::entry( const entry& e ) : _key(e._key),_value(e._value) {} + variant_object::entry& variant_object::entry::operator=( const variant_object::entry& e ) + { + if( this != &e ) + { + _key = e._key; + _value = e._value; + } + return *this; + } + variant_object::entry& variant_object::entry::operator=( variant_object::entry&& e ) + { + fc_swap( _key, e._key ); + fc_swap( _value, e._value ); + return *this; + } + + const string& variant_object::entry::key()const + { + return _key; + } + + const variant& variant_object::entry::value()const + { + return _value; + } + variant& variant_object::entry::value() + { + return _value; + } + + void variant_object::entry::set( variant v ) + { + fc_swap( _value, v ); + } + + // --------------------------------------------------------------- + // variant_object + + variant_object::iterator variant_object::begin() const + { + assert( _key_value != nullptr ); + return _key_value->begin(); + } + + variant_object::iterator variant_object::end() const + { + return _key_value->end(); + } + + variant_object::iterator variant_object::find( const string& key )const + { + return find( key.c_str() ); + } + + variant_object::iterator variant_object::find( const char* key )const + { + for( auto itr = begin(); itr != end(); ++itr ) + { + if( itr->key() == key ) + { + return itr; + } + } + return end(); + } + + const variant& variant_object::operator[]( const string& key )const + { + return (*this)[key.c_str()]; + } + + const variant& variant_object::operator[]( const char* key )const + { + auto itr = find( key ); + if( itr != end() ) return itr->value(); + FC_THROW_EXCEPTION( key_not_found_exception, "Key ${key}", ("key",key) ); + } + + size_t variant_object::size() const + { + return _key_value->size(); + } + + variant_object::variant_object() + :_key_value(std::make_shared>() ) + { + } + + variant_object::variant_object( string key, variant val ) + : _key_value(std::make_shared>()) + { + //_key_value->push_back(entry(fc::move(key), fc::move(val))); + _key_value->emplace_back(entry(fc::move(key), fc::move(val))); + } + + variant_object::variant_object( const variant_object& obj ) + :_key_value( obj._key_value ) + { + assert( _key_value != nullptr ); + } + + variant_object::variant_object( variant_object&& obj) + : _key_value( fc::move(obj._key_value) ) + { + obj._key_value = std::make_shared>(); + assert( _key_value != nullptr ); + } + + variant_object::variant_object( const mutable_variant_object& obj ) + : _key_value(std::make_shared>(*obj._key_value)) + { + } + + variant_object::variant_object( mutable_variant_object&& obj ) + : _key_value(fc::move(obj._key_value)) + { + assert( _key_value != nullptr ); + } + + variant_object& variant_object::operator=( variant_object&& obj ) + { + if (this != &obj) + { + fc_swap(_key_value, obj._key_value ); + assert( _key_value != nullptr ); + } + return *this; + } + + variant_object& variant_object::operator=( const variant_object& obj ) + { + if (this != &obj) + { + _key_value = obj._key_value; + } + return *this; + } + + variant_object& variant_object::operator=( mutable_variant_object&& obj ) + { + _key_value = fc::move(obj._key_value); + obj._key_value.reset( new fc::vector() ); + return *this; + } + + variant_object& variant_object::operator=( const mutable_variant_object& obj ) + { + *_key_value = *obj._key_value; + return *this; + } + + void to_variant( const variant_object& var, variant& vo ) + { + vo = variant(var); + } + + void from_variant( const variant& var, variant_object& vo ) + { + vo = var.get_object(); + } + + // --------------------------------------------------------------- + // mutable_variant_object + + mutable_variant_object::iterator mutable_variant_object::begin() + { + return _key_value->begin(); + } + + mutable_variant_object::iterator mutable_variant_object::end() + { + return _key_value->end(); + } + + mutable_variant_object::iterator mutable_variant_object::begin() const + { + return _key_value->begin(); + } + + mutable_variant_object::iterator mutable_variant_object::end() const + { + return _key_value->end(); + } + + mutable_variant_object::iterator mutable_variant_object::find( const string& key )const + { + return find( key.c_str() ); + } + + mutable_variant_object::iterator mutable_variant_object::find( const char* key )const + { + for( auto itr = begin(); itr != end(); ++itr ) + { + if( itr->key() == key ) + { + return itr; + } + } + return end(); + } + + mutable_variant_object::iterator mutable_variant_object::find( const string& key ) + { + return find( key.c_str() ); + } + + mutable_variant_object::iterator mutable_variant_object::find( const char* key ) + { + for( auto itr = begin(); itr != end(); ++itr ) + { + if( itr->key() == key ) + { + return itr; + } + } + return end(); + } + + const variant& mutable_variant_object::operator[]( const string& key )const + { + return (*this)[key.c_str()]; + } + + const variant& mutable_variant_object::operator[]( const char* key )const + { + auto itr = find( key ); + if( itr != end() ) return itr->value(); + FC_THROW_EXCEPTION( key_not_found_exception, "Key ${key}", ("key",key) ); + } + variant& mutable_variant_object::operator[]( const string& key ) + { + return (*this)[key.c_str()]; + } + + variant& mutable_variant_object::operator[]( const char* key ) + { + auto itr = find( key ); + if( itr != end() ) return itr->value(); + _key_value->emplace_back(entry(key, variant())); + return _key_value->back().value(); + } + + size_t mutable_variant_object::size() const + { + return _key_value->size(); + } + + mutable_variant_object::mutable_variant_object() + :_key_value(new fc::vector) + { + } + + mutable_variant_object::mutable_variant_object( string key, variant val ) + : _key_value(new fc::vector()) + { + _key_value->push_back(entry(fc::move(key), fc::move(val))); + } + + mutable_variant_object::mutable_variant_object( const variant_object& obj ) + : _key_value( new fc::vector(*obj._key_value) ) + { + } + + mutable_variant_object::mutable_variant_object( const mutable_variant_object& obj ) + : _key_value( new fc::vector(*obj._key_value) ) + { + } + + mutable_variant_object::mutable_variant_object( mutable_variant_object&& obj ) + : _key_value(fc::move(obj._key_value)) + { + } + + mutable_variant_object& mutable_variant_object::operator=( const variant_object& obj ) + { + *_key_value = *obj._key_value; + return *this; + } + + mutable_variant_object& mutable_variant_object::operator=( mutable_variant_object&& obj ) + { + if (this != &obj) + { + _key_value = fc::move(obj._key_value); + } + return *this; + } + + mutable_variant_object& mutable_variant_object::operator=( const mutable_variant_object& obj ) + { + if (this != &obj) + { + *_key_value = *obj._key_value; + } + return *this; + } + + void mutable_variant_object::reserve( size_t s ) + { + _key_value->reserve(s); + } + + void mutable_variant_object::erase( const string& key ) + { + for( auto itr = begin(); itr != end(); ++itr ) + { + if( itr->key() == key ) + { + _key_value->erase(itr); + return; + } + } + } + + /** replaces the value at \a key with \a var or insert's \a key if not found */ + mutable_variant_object& mutable_variant_object::set( string key, variant var ) + { + auto itr = find( key.c_str() ); + if( itr != end() ) + { + itr->set( fc::move(var) ); + } + else + { + _key_value->push_back( entry( fc::move(key), fc::move(var) ) ); + } + return *this; + } + + /** Appends \a key and \a var without checking for duplicates, designed to + * simplify construction of dictionaries using (key,val)(key2,val2) syntax + */ + mutable_variant_object& mutable_variant_object::operator()( string key, variant var ) + { + _key_value->push_back( entry( fc::move(key), fc::move(var) ) ); + return *this; + } + + void to_variant( const mutable_variant_object& var, variant& vo ) + { + vo = variant(var); + } + + void from_variant( const variant& var, mutable_variant_object& vo ) + { + vo = var.get_object(); + } + +} // namesapce fc diff --git a/src/vector.cpp b/src/vector.cpp deleted file mode 100644 index 48b88e8..0000000 --- a/src/vector.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include - -namespace fc { - struct vector_impl_d { - abstract_value_type& _vtbl; - char* _data; - size_t _size; - size_t _capacity; - - vector_impl_d( abstract_value_type& r, size_t size, size_t cap= 0 ) - :_vtbl(r),_data(0),_size(size),_capacity(cap) { - if( _size > _capacity ) _capacity = _size; - if( _capacity ) { - const unsigned int so = _vtbl.size_of(); - _data = new char[_capacity*so]; - char* end = _data + _size *so; - for( char* idx = _data; idx < end; idx += so ) { - _vtbl.construct( idx ); - } - } - } - - vector_impl_d( const vector_impl_d& cpy ) - :_vtbl(cpy._vtbl),_data(0),_size(cpy._size),_capacity(cpy._size) { - if( _size ) { - _data = new char[_size*_vtbl.size_of()]; - copy_from( cpy._data, cpy._size ); - } - } - - void copy_from( char* src, int cnt ) { - const unsigned int so = _vtbl.size_of(); - char* end = _data + cnt * so; - char* cpy_idx = src; - for( char* idx = _data; idx < end; idx += so ) { - _vtbl.copy_construct( idx, cpy_idx ); - cpy_idx += so; - } - } - void move_from( char* src, int cnt ) { - const unsigned int so = _vtbl.size_of(); - char* end = _data + cnt * so; - char* cpy_idx = src; - for( char* idx = _data; idx < end; idx += so ) { - _vtbl.move_construct( idx, cpy_idx ); - cpy_idx += so; - } - } - void destruct( char* src, int cnt ) { - const unsigned int so = _vtbl.size_of(); - char* end = src + cnt * so; - for( char* idx = src; idx < end; idx += so ) { - _vtbl.destructor( idx ); - } - } - - ~vector_impl_d() { - clear(); - delete[] _data; - } - - void clear() { - const unsigned int so = _vtbl.size_of(); - char* end = _data + _size * so; - for( char* idx = _data; idx < end; idx += so ) { - _vtbl.destructor( idx ); - } - _size = 0; - } - }; - - vector_impl::vector_impl( abstract_value_type& r, size_t s ) { - my = new vector_impl_d(r,s); - } - - vector_impl::vector_impl( const vector_impl& cpy ) { - my = new vector_impl_d(*cpy.my); - } - - vector_impl::vector_impl( vector_impl&& cpy ){ - my = cpy.my; - cpy.my = 0; - } - - vector_impl::~vector_impl() { - delete my; - } - - vector_impl& vector_impl::operator=( const vector_impl& v ) { - clear(); - reserve(v.size()); - size_t s = v.size(); - for( size_t i = 0; i < s; ++i ) { - _push_back( v._at(i) ); - } - return *this; - } - vector_impl& vector_impl::operator=( vector_impl&& v ) { - fc::swap(my,v.my); - return *this; - } - - void vector_impl::_push_back( const void* v ) { - reserve( my->_size + 1 ); - my->_vtbl.copy_construct( _back(), v ); - my->_size++; - } - void vector_impl::_push_back_m( void* v ) { - reserve( my->_size + 1 ); - my->_vtbl.move_construct( _back(), v ); - my->_size++; - } - - void* vector_impl::_back() { - return my->_data + my->_vtbl.size_of() * (my->_size-1); - } - const void* vector_impl::_back()const { - return my->_data + my->_vtbl.size_of() * (my->_size-1); - } - - void* vector_impl::_at(size_t p) { - return my->_data + my->_vtbl.size_of() * p; - } - const void* vector_impl::_at(size_t p)const { - return my->_data + my->_vtbl.size_of() * p; - } - - void vector_impl::pop_back() { - my->_vtbl.destructor( _back() ); - my->_size--; - } - void vector_impl::clear() { - my->clear(); - } - - size_t vector_impl::size()const { - return my->_size; - } - - void vector_impl::reserve( size_t s ) { - if( s < my->_capacity ) { - return; - } - char* new_data = new char[s*my->_vtbl.size_of()]; - fc::swap(new_data,my->_data); - my->move_from(new_data,my->_size); - my->destruct(new_data,my->_size); - delete[] new_data; - } - void vector_impl::resize( size_t s ) { - if( s <= my->_size ) { - for( size_t i = s; i < my->_size; ++i ) { - my->_vtbl.destructor( _at(i) ); - } - my->_size = s; - return; - } - if( s <= my->_capacity ) { - - return; - } - const unsigned int so = my->_vtbl.size_of(); - char* new_data = new char[s*so]; - fc::swap(new_data,my->_data); - my->_capacity = s; - // move from old to new location - my->move_from(new_data,my->_size); - // destroy old location - my->destruct(new_data,my->_size); - delete[] new_data; - - // default construct any left overs. - char* cur = (char*)_back(); - char* end = (char*)my->_data + s * so; - while( cur < end ) { - my->_vtbl.construct(cur); - cur += so; - my->_size++; - } - } - - size_t vector_impl::capacity()const { - return my->_capacity; - } - -} // namespace fc diff --git a/tests/json_rpc_test.cpp b/tests/json_rpc_test.cpp deleted file mode 100644 index 25b8d69..0000000 --- a/tests/json_rpc_test.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -struct namep { - fc::string a; - double b; -}; - -FC_REFLECT( namep, (a)(b) ) -FC_JSON_NAMED_PARAMS( namep ) - -struct test { - int add(int x){ return x+1; } - int sub(int x){ return x-1; } - int sub1(int x){ return 3; } - int namep_test(namep x){ return 3; } - int sub2(float x){ return 3; } - int sub3(double x, int y){ return x-y; } - int sub4(uint16_t x){ return 3; } - int sub5(char x){ return 3; } - int sub6(uint64_t x){ return 3; } - int sub7(int x){ return 3; } - int sub8(int x){ return 3; } - int sub9(int x){ return 3; } -}; - -FC_STUB( test, (add)(namep_test)(sub)(sub1)(sub2)(sub3)(sub4)(sub5)(sub6)(sub7)(sub8)(sub9) ) - -int main( int argc, char** argv ) { - try { - slog( "Hello World\n" ); - fc::value v = fc::string("goodbye"); - slog("."); - fc::value v2; - slog(".."); - v2["a"]; - slog("........ v2[a] %p = v %p", &v2["a"], &v); - v2["a"] = v; - slog("..."); - fc::value& b = v2["b"]; - slog( "...."); - b = fc::string("hello"); - slog("....."); - return 0; - - fc::ptr t( new test() ); - fc::json::rpc_tcp_server serv; - serv.add_interface( t ); - serv.listen(8001); - slog( "%s", fc::json::to_string( fc::json::detail::named_param >::to_value(fc::tuple() ) ).c_str() ); - slog("..."); - { - wlog( "create new connection" ); - fc::json::rpc_tcp_connection::ptr con(new fc::json::rpc_tcp_connection()); - wlog( "connnect to..." ); - con->connect_to( fc::ip::endpoint::from_string("127.0.0.1:8001") ); - wlog( "connected, " ); - - fc::json::rpc_client rpcc( con ); - slog( "5+1=%d", rpcc->add(5).wait() ); - slog( "sub3 4-5=%d", rpcc->sub3(4,5).wait() ); - slog( "namep=%d", rpcc->namep_test(namep()).wait() ); - } - slog( "exit serv" ); - /* - fc::json::rpc_connection::ptr con( new fc::json::rpc_stream_connection( fc::cin, fc::cout ) ); - fc::json::rpc_client c( con ); - - slog( "%d", c->add( 5 ).wait() ); - slog( "%d", c->add( 6 ).wait() ); - */ - - slog( "Exiting" ); - } catch ( ... ) { - elog( "%s", fc::except_str().c_str() ); - } - - return 0; -} diff --git a/tests/logger.cpp b/tests/logger.cpp deleted file mode 100644 index 350cb85..0000000 --- a/tests/logger.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - -int main( int argc, char** argv ) { - auto lgr = fc::logger::get(); - auto dconfig = fc::logging_config::default_config(); - dconfig.appenders.push_back( fc::appender_config("logfile", "file", fc::value(fc::file_appender::config("test.log")) ) ); - dconfig.loggers.push_back( fc::logger_config("main").add_appender("stderr").add_appender("logfile") ); - fc::configure_logging( dconfig ); - fc_dlog( lgr, "Hello Debug" ); - fc_ilog( lgr, "Hello Info" ); - fc_wlog( lgr, "Hello Warn" ); - fc_elog( lgr, "Hello Error" ); - fc_flog( lgr, "Hello Fatal" ); - - - auto main_lgr = fc::logger::get( "main" ); - fc_dlog( main_lgr, "Hello Debug" ); - fc_ilog( main_lgr, "Hello Info" ); - fc_wlog( main_lgr, "Hello Warn" ); - fc_elog( main_lgr, "Hello Error" ); - fc_flog( main_lgr, "Hello Fatal" ); - return 0; -} diff --git a/tests/ssh.cpp b/tests/ssh.cpp deleted file mode 100644 index d3c0e31..0000000 --- a/tests/ssh.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include -#include -//#include - -int main( int argc, char** argv ) { - try { - slog( "create ssh client" ); - fc::ssh::client c; - c.connect( "dlarimer", "rapture", "10.10.10.112" ); - slog( "connected" ); - fc::ssh::process proc = c.exec( "/bin/cat -u" ); - slog( "proc!"); - fc::string hello( "hello.............." ); - hello += hello; - hello += hello; - hello += hello; - hello += hello; - hello += hello; - hello += "\n"; - /* - hello += hello2; - */ - fc::string line; - proc.in_stream().write(hello.c_str(), hello.size() ); - fc::getline( proc.out_stream(), line ); - fc::cout< +#include +#include + +#endif // BOOST_CTX_ALL_H diff --git a/vendor/boost_1.51/include/boost/context/detail/config.hpp b/vendor/boost_1.51/include/boost/context/detail/config.hpp new file mode 100644 index 0000000..50ada3c --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/config.hpp @@ -0,0 +1,42 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_CONFIG_H +#define BOOST_CTX_DETAIL_CONFIG_H + +#include +#include + +#ifdef BOOST_CONTEXT_DECL +# undef BOOST_CONTEXT_DECL +#endif + +#if defined(BOOST_HAS_DECLSPEC) +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTEXT_DYN_LINK) +# if ! defined(BOOST_DYN_LINK) +# define BOOST_DYN_LINK +# endif +# if defined(BOOST_CONTEXT_SOURCE) +# define BOOST_CONTEXT_DECL BOOST_SYMBOL_EXPORT +# else +# define BOOST_CONTEXT_DECL BOOST_SYMBOL_IMPORT +# endif +# endif +#endif + +#if ! defined(BOOST_CONTEXT_DECL) +# define BOOST_CONTEXT_DECL +#endif + +#if ! defined(BOOST_CONTEXT_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_CONTEXT_NO_LIB) +# define BOOST_LIB_NAME boost_context +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTEXT_DYN_LINK) +# define BOOST_DYN_LINK +# endif +# include +#endif + +#endif // BOOST_CTX_DETAIL_CONFIG_H diff --git a/vendor/boost_1.51/include/boost/context/detail/fcontext_arm.hpp b/vendor/boost_1.51/include/boost/context/detail/fcontext_arm.hpp new file mode 100644 index 0000000..b4ed2fa --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/fcontext_arm.hpp @@ -0,0 +1,66 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_FCONTEXT_ARM_H +#define BOOST_CTX_DETAIL_FCONTEXT_ARM_H + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * base; + void * limit; + + stack_t() : + base( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[16]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[11]; + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_ARM_H diff --git a/vendor/boost_1.51/include/boost/context/detail/fcontext_i386.hpp b/vendor/boost_1.51/include/boost/context/detail/fcontext_i386.hpp new file mode 100644 index 0000000..573a22c --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/fcontext_i386.hpp @@ -0,0 +1,68 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_FCONTEXT_I386H +#define BOOST_CTX_DETAIL_FCONTEXT_I386H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL __attribute__((cdecl)) + +struct stack_t +{ + void * base; + void * limit; + + stack_t() : + base( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[2]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[6]; + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_I386_H diff --git a/vendor/boost_1.51/include/boost/context/detail/fcontext_i386_win.hpp b/vendor/boost_1.51/include/boost/context/detail/fcontext_i386_win.hpp new file mode 100644 index 0000000..e250ec5 --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/fcontext_i386_win.hpp @@ -0,0 +1,83 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_FCONTEXT_I386H +#define BOOST_CTX_DETAIL_FCONTEXT_I386H + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +#include + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4351) +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL __cdecl + +struct stack_t +{ + void * base; + void * limit; + + stack_t() : + base( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[2]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[6]; + stack_t fc_stack; + void * fc_excpt_lst; + void * fc_local_storage; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_excpt_lst( 0), + fc_local_storage( 0), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_I386_H diff --git a/vendor/boost_1.51/include/boost/context/detail/fcontext_mips.hpp b/vendor/boost_1.51/include/boost/context/detail/fcontext_mips.hpp new file mode 100644 index 0000000..1645adf --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/fcontext_mips.hpp @@ -0,0 +1,68 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_FCONTEXT_MIPS_H +#define BOOST_CTX_DETAIL_FCONTEXT_MIPS_H + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +// on MIPS we assume 64bit regsiters - even for 32bit ABIs + +struct stack_t +{ + void * base; + void * limit; + + stack_t() : + base( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint64_t fc_freg[6]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint64_t fc_greg[13]; + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_MIPS_H diff --git a/vendor/boost_1.51/include/boost/context/detail/fcontext_ppc.hpp b/vendor/boost_1.51/include/boost/context/detail/fcontext_ppc.hpp new file mode 100644 index 0000000..5e6c64c --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/fcontext_ppc.hpp @@ -0,0 +1,70 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_FCONTEXT_PPC_H +#define BOOST_CTX_DETAIL_FCONTEXT_PPC_H + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * base; + void * limit; + + stack_t() : + base( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint64_t fc_freg[19]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ +# if defined(__powerpc64__) + boost::uint64_t fc_greg[23]; +# else + boost::uint32_t fc_greg[23]; +# endif + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_PPC_H diff --git a/vendor/boost_1.51/include/boost/context/detail/fcontext_x86_64.hpp b/vendor/boost_1.51/include/boost/context/detail/fcontext_x86_64.hpp new file mode 100644 index 0000000..106ee74 --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/fcontext_x86_64.hpp @@ -0,0 +1,66 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_FCONTEXT_X86_64_H +#define BOOST_CTX_DETAIL_FCONTEXT_X86_64_H + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * base; + void * limit; + + stack_t() : + base( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[2]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint64_t fc_greg[8]; + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_X86_64_H diff --git a/vendor/boost_1.51/include/boost/context/detail/fcontext_x86_64_win.hpp b/vendor/boost_1.51/include/boost/context/detail/fcontext_x86_64_win.hpp new file mode 100644 index 0000000..96f153b --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/detail/fcontext_x86_64_win.hpp @@ -0,0 +1,90 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_DETAIL_FCONTEXT_X86_64_H +#define BOOST_CTX_DETAIL_FCONTEXT_X86_64_H + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +#include + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4351) +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * base; + void * limit; + + stack_t() : + base( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[2]; + void * fc_xmm; + char fc_buffer[175]; + + fp_t() : + fc_freg(), + fc_xmm( 0), + fc_buffer() + { + fc_xmm = fc_buffer; + if ( 0 != ( ( ( uintptr_t) fc_xmm) & 15) ) + fc_xmm = ( char *) ( ( ( ( uintptr_t) fc_xmm) + 15) & ~0x0F); + } +}; + +struct fcontext_t +{ + boost::uint64_t fc_greg[10]; + stack_t fc_stack; + void * fc_local_storage; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_local_storage( 0), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_X86_64_H diff --git a/vendor/boost_1.51/include/boost/context/fcontext.hpp b/vendor/boost_1.51/include/boost/context/fcontext.hpp new file mode 100644 index 0000000..d2cc030 --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/fcontext.hpp @@ -0,0 +1,82 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_FCONTEXT_H +#define BOOST_CTX_FCONTEXT_H + +#if defined(__PGI) +#include +#endif + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +// x86_64 +// test x86_64 before i386 because icc might +// define __i686__ for x86_64 too +#if defined(__x86_64__) || defined(__x86_64) \ + || defined(__amd64__) || defined(__amd64) \ + || defined(_M_X64) || defined(_M_AMD64) +# if defined(BOOST_WINDOWS) +# include +# else +# include +# endif +// i386 +#elif defined(i386) || defined(__i386__) || defined(__i386) \ + || defined(__i486__) || defined(__i586__) || defined(__i686__) \ + || defined(__X86__) || defined(_X86_) || defined(__THW_INTEL__) \ + || defined(__I86__) || defined(__INTEL__) || defined(__IA32__) \ + || defined(_M_IX86) || defined(_I86_) +# if defined(BOOST_WINDOWS) +# include +# else +# include +# endif +// arm +#elif defined(__arm__) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) \ + || defined(__TARGET_ARCH_THUMB) || defined(_ARM) +# include +// mips +#elif (defined(__mips) && __mips == 1) || defined(_MIPS_ISA_MIPS1) \ + || defined(_R3000) +# include +// powerpc +#elif defined(__powerpc) || defined(__powerpc__) || defined(__ppc) \ + || defined(__ppc__) || defined(_ARCH_PPC) || defined(__POWERPC__) \ + || defined(__PPCGECKO__) || defined(__PPCBROADWAY) || defined(_XENON) +# include +#else +# error "platform not supported" +#endif + +namespace boost { +namespace ctx { +namespace detail { + +extern "C" BOOST_CONTEXT_DECL void * BOOST_CONTEXT_CALLDECL align_stack( void * vp); + +} + +extern "C" BOOST_CONTEXT_DECL +intptr_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t * ofc, fcontext_t const* nfc, intptr_t vp, bool preserve_fpu = true); +extern "C" BOOST_CONTEXT_DECL +void BOOST_CONTEXT_CALLDECL make_fcontext( fcontext_t * fc, void (* fn)( intptr_t) ); + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_FCONTEXT_H + diff --git a/vendor/boost_1.51/include/boost/context/stack_allocator.hpp b/vendor/boost_1.51/include/boost/context/stack_allocator.hpp new file mode 100644 index 0000000..0db5015 --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/stack_allocator.hpp @@ -0,0 +1,37 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_STACK_ALLOCATOR_H +#define BOOST_CTX_STACK_ALLOCATOR_H + +#include + +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +class BOOST_CONTEXT_DECL stack_allocator +{ +public: + void * allocate( std::size_t) const; + + void deallocate( void *, std::size_t) const; +}; + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_STACK_ALLOCATOR_H diff --git a/vendor/boost_1.51/include/boost/context/stack_utils.hpp b/vendor/boost_1.51/include/boost/context/stack_utils.hpp new file mode 100644 index 0000000..ca3ed21 --- /dev/null +++ b/vendor/boost_1.51/include/boost/context/stack_utils.hpp @@ -0,0 +1,41 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_CTX_STACK_UTILS_H +#define BOOST_CTX_STACK_UTILS_H + +#include + +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +BOOST_CONTEXT_DECL std::size_t default_stacksize(); + +BOOST_CONTEXT_DECL std::size_t minimum_stacksize(); + +BOOST_CONTEXT_DECL std::size_t maximum_stacksize(); + +BOOST_CONTEXT_DECL std::size_t pagesize(); + +BOOST_CONTEXT_DECL std::size_t page_count( std::size_t stacksize); + +BOOST_CONTEXT_DECL bool is_stack_unbound(); + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_STACK_UTILS_H diff --git a/include/boost/process.hpp b/vendor/boost_1.51/include/boost/process.hpp similarity index 100% rename from include/boost/process.hpp rename to vendor/boost_1.51/include/boost/process.hpp diff --git a/include/boost/process/all.hpp b/vendor/boost_1.51/include/boost/process/all.hpp similarity index 100% rename from include/boost/process/all.hpp rename to vendor/boost_1.51/include/boost/process/all.hpp diff --git a/include/boost/process/child.hpp b/vendor/boost_1.51/include/boost/process/child.hpp similarity index 100% rename from include/boost/process/child.hpp rename to vendor/boost_1.51/include/boost/process/child.hpp diff --git a/include/boost/process/config.hpp b/vendor/boost_1.51/include/boost/process/config.hpp similarity index 100% rename from include/boost/process/config.hpp rename to vendor/boost_1.51/include/boost/process/config.hpp diff --git a/include/boost/process/context.hpp b/vendor/boost_1.51/include/boost/process/context.hpp similarity index 100% rename from include/boost/process/context.hpp rename to vendor/boost_1.51/include/boost/process/context.hpp diff --git a/include/boost/process/detail/basic_status.hpp b/vendor/boost_1.51/include/boost/process/detail/basic_status.hpp similarity index 100% rename from include/boost/process/detail/basic_status.hpp rename to vendor/boost_1.51/include/boost/process/detail/basic_status.hpp diff --git a/include/boost/process/detail/basic_status_service.hpp b/vendor/boost_1.51/include/boost/process/detail/basic_status_service.hpp similarity index 94% rename from include/boost/process/detail/basic_status_service.hpp rename to vendor/boost_1.51/include/boost/process/detail/basic_status_service.hpp index 97c8162..2fd1a39 100644 --- a/include/boost/process/detail/basic_status_service.hpp +++ b/vendor/boost_1.51/include/boost/process/detail/basic_status_service.hpp @@ -152,6 +152,11 @@ public: boost::unique_lock lock(work_thread_mutex_); if (++pids_ == 1) { + // if there was a previous worker thread that exited because + // pids_ dropped to 0, we must join it now to free the thread's + // memory before launching a new worker thread + if (work_thread_.joinable()) + work_thread_.join(); work_.reset(new boost::asio::io_service::work( this->get_io_service())); work_thread_ = boost::thread( diff --git a/include/boost/process/detail/posix_helpers.hpp b/vendor/boost_1.51/include/boost/process/detail/posix_helpers.hpp similarity index 100% rename from include/boost/process/detail/posix_helpers.hpp rename to vendor/boost_1.51/include/boost/process/detail/posix_helpers.hpp diff --git a/include/boost/process/detail/status_impl.hpp b/vendor/boost_1.51/include/boost/process/detail/status_impl.hpp similarity index 100% rename from include/boost/process/detail/status_impl.hpp rename to vendor/boost_1.51/include/boost/process/detail/status_impl.hpp diff --git a/include/boost/process/detail/systembuf.hpp b/vendor/boost_1.51/include/boost/process/detail/systembuf.hpp similarity index 100% rename from include/boost/process/detail/systembuf.hpp rename to vendor/boost_1.51/include/boost/process/detail/systembuf.hpp diff --git a/include/boost/process/detail/windows_helpers.hpp b/vendor/boost_1.51/include/boost/process/detail/windows_helpers.hpp similarity index 100% rename from include/boost/process/detail/windows_helpers.hpp rename to vendor/boost_1.51/include/boost/process/detail/windows_helpers.hpp diff --git a/include/boost/process/environment.hpp b/vendor/boost_1.51/include/boost/process/environment.hpp similarity index 100% rename from include/boost/process/environment.hpp rename to vendor/boost_1.51/include/boost/process/environment.hpp diff --git a/include/boost/process/handle.hpp b/vendor/boost_1.51/include/boost/process/handle.hpp similarity index 100% rename from include/boost/process/handle.hpp rename to vendor/boost_1.51/include/boost/process/handle.hpp diff --git a/include/boost/process/operations.hpp b/vendor/boost_1.51/include/boost/process/operations.hpp similarity index 93% rename from include/boost/process/operations.hpp rename to vendor/boost_1.51/include/boost/process/operations.hpp index 5fcdd04..0c8f96a 100644 --- a/include/boost/process/operations.hpp +++ b/vendor/boost_1.51/include/boost/process/operations.hpp @@ -239,8 +239,8 @@ inline child create_child(const std::string &executable, Arguments args, { if (chdir(work_dir) == -1) { - write(STDERR_FILENO, "chdir() failed\n", 15); - _exit(127); + auto r = write(STDERR_FILENO, "chdir() failed\n", 15); + if( r || !r ) _exit(127); } for (handles_t::iterator it = handles.begin(); it != handles.end(); @@ -258,7 +258,8 @@ inline child create_child(const std::string &executable, Arguments args, it->first + 1); if (fd == -1) { - write(STDERR_FILENO, "fcntl() failed\n", 15); + auto r = write(STDERR_FILENO, "chdir() failed\n", 15); + (void)r; _exit(127); } it2->second.child = fd; @@ -267,8 +268,8 @@ inline child create_child(const std::string &executable, Arguments args, if (dup2(it->second.child.native(), it->first) == -1) { - write(STDERR_FILENO, "dup2() failed\n", 14); - _exit(127); + auto r = write(STDERR_FILENO, "chdir() failed\n", 15); + if( r || !r ) _exit(127); } closeflags[it->first] = false; } @@ -287,7 +288,8 @@ inline child create_child(const std::string &executable, Arguments args, // Actually we should delete argv and envp data. As we must not // call any non-async-signal-safe functions though we simply exit. - write(STDERR_FILENO, "execve() failed\n", 16); + auto r = write(STDERR_FILENO, "execve() failed\n", 16); + if( r || !r ) _exit(127); _exit(127); } else diff --git a/include/boost/process/pid_type.hpp b/vendor/boost_1.51/include/boost/process/pid_type.hpp similarity index 100% rename from include/boost/process/pid_type.hpp rename to vendor/boost_1.51/include/boost/process/pid_type.hpp diff --git a/include/boost/process/pipe.hpp b/vendor/boost_1.51/include/boost/process/pipe.hpp similarity index 100% rename from include/boost/process/pipe.hpp rename to vendor/boost_1.51/include/boost/process/pipe.hpp diff --git a/include/boost/process/pistream.hpp b/vendor/boost_1.51/include/boost/process/pistream.hpp similarity index 100% rename from include/boost/process/pistream.hpp rename to vendor/boost_1.51/include/boost/process/pistream.hpp diff --git a/include/boost/process/postream.hpp b/vendor/boost_1.51/include/boost/process/postream.hpp similarity index 100% rename from include/boost/process/postream.hpp rename to vendor/boost_1.51/include/boost/process/postream.hpp diff --git a/include/boost/process/process.hpp b/vendor/boost_1.51/include/boost/process/process.hpp similarity index 100% rename from include/boost/process/process.hpp rename to vendor/boost_1.51/include/boost/process/process.hpp diff --git a/include/boost/process/self.hpp b/vendor/boost_1.51/include/boost/process/self.hpp similarity index 100% rename from include/boost/process/self.hpp rename to vendor/boost_1.51/include/boost/process/self.hpp diff --git a/include/boost/process/status.hpp b/vendor/boost_1.51/include/boost/process/status.hpp similarity index 100% rename from include/boost/process/status.hpp rename to vendor/boost_1.51/include/boost/process/status.hpp diff --git a/include/boost/process/stream_behavior.hpp b/vendor/boost_1.51/include/boost/process/stream_behavior.hpp similarity index 100% rename from include/boost/process/stream_behavior.hpp rename to vendor/boost_1.51/include/boost/process/stream_behavior.hpp diff --git a/include/boost/process/stream_ends.hpp b/vendor/boost_1.51/include/boost/process/stream_ends.hpp similarity index 100% rename from include/boost/process/stream_ends.hpp rename to vendor/boost_1.51/include/boost/process/stream_ends.hpp diff --git a/include/boost/process/stream_id.hpp b/vendor/boost_1.51/include/boost/process/stream_id.hpp similarity index 100% rename from include/boost/process/stream_id.hpp rename to vendor/boost_1.51/include/boost/process/stream_id.hpp diff --git a/include/boost/process/stream_type.hpp b/vendor/boost_1.51/include/boost/process/stream_type.hpp similarity index 100% rename from include/boost/process/stream_type.hpp rename to vendor/boost_1.51/include/boost/process/stream_type.hpp diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S new file mode 100644 index 0000000..7724441 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S @@ -0,0 +1,101 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| 0x20| 0x24| * + * ------------------------------------------------------------- * + * | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | sp | lr | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | | * + * ------------------------------------------------------------- * + * | 0x28| | * + * ------------------------------------------------------------- * + * | pc | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 11 | 12 | | * + * ------------------------------------------------------------- * + * | 0x2c| 0x30| | * + * ------------------------------------------------------------- * + * |sbase|slimit| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | * + * ------------------------------------------------------------- * + * | 0x34| 0x38|0x3c| 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58 | * + * ------------------------------------------------------------- * + * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | s24 | s25 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 23 | 24 | 25 | 26 | 27 | 28 | | * + * ------------------------------------------------------------- * + * | 0x5c| 0x60| 0x64| 0x68| 0x6c| 0x70| | * + * ------------------------------------------------------------- * + * | s26 | s27 | s28 | s29 | s30 | s31 | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,%function +jump_fcontext: + stmia a1, {v1-v8,sp-lr} @ save V1-V8,SP-LR + str lr, [a1,#40] @ save LR as PC + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) + cmp a4, #0 @ test if fpu env should be preserved + beq 1f + + mov a4, a1 + add a4, #52 + fstmiax a4, {d8-d15} @ save S16-S31 + + mov a4, a2 + add a4, #52 + fldmiax a4, {d8-d15} @ restore S16-S31 +1: +#endif + + mov a1, a3 @ use third arg as return value after jump + @ and as first arg in context function + ldmia a2, {v1-v8,sp-pc} @ restore v1-V8,SP-PC +.size jump_fcontext,.-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,%function +make_fcontext: + str a1, [a1,#0] @ save the address of passed context + str a2, [a1,#40] @ save address of the context function + ldr a2, [a1,#44] @ load the stack base + + push {a1,lr} @ save pointer to fcontext_t + mov a1, a2 @ stack pointer as arg for align_stack + bl align_stack@PLT @ align stack + mov a2, a1 @ begin of aligned stack + pop {a1,lr} @ restore pointer to fcontext_t + + str a2, [a1,#32] @ save the aligned stack base + + adr a2, finish @ address of finish; called after context function returns + str a2, [a1,#36] + + mov a1, #0 + bx lr + +finish: + mov a1, #0 @ exit code is zero + bl _exit@PLT @ exit application +.size make_fcontext,.-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm b/vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm new file mode 100644 index 0000000..0f4dd67 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm @@ -0,0 +1,151 @@ + +; Copyright Oliver Kowalke 2009. +; Distributed under the Boost Software License, Version 1.0. +; (See accompanying file LICENSE_1_0.txt or copy at +; http://www.boost.org/LICENSE_1_0.txt) + +; -------------------------------------------------------------- +; | 0 | 1 | 2 | 3 | 4 | 5 | +; -------------------------------------------------------------- +; | 0h | 04h | 08h | 0ch | 010h | 014h | +; -------------------------------------------------------------- +; | EDI | ESI | EBX | EBP | ESP | EIP | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 6 | 7 | | +; -------------------------------------------------------------- +; | 018h | 01ch | | +; -------------------------------------------------------------- +; | ss_base | ss_limit| | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 8 | | +; -------------------------------------------------------------- +; | 020h | | +; -------------------------------------------------------------- +; |fc_execpt| | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 9 | | +; -------------------------------------------------------------- +; | 024h | | +; -------------------------------------------------------------- +; |fc_strage| | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 10 | 11 | | +; -------------------------------------------------------------- +; | 028h | 02ch | | +; -------------------------------------------------------------- +; | fc_mxcsr|fc_x87_cw| | +; -------------------------------------------------------------- + +.386 +.XMM +.model flat, c +_exit PROTO, value:SDWORD +align_stack PROTO, vp:DWORD +seh_fcontext PROTO, except:DWORD, frame:DWORD, context:DWORD, dispatch:DWORD +.code + +jump_fcontext PROC EXPORT + mov ecx, [esp+04h] ; load address of the first fcontext_t arg + mov [ecx], edi ; save EDI + mov [ecx+04h], esi ; save ESI + mov [ecx+08h], ebx ; save EBX + mov [ecx+0ch], ebp ; save EBP + + assume fs:nothing + mov edx, fs:[018h] ; load NT_TIB + assume fs:error + mov eax, [edx] ; load current SEH exception list + mov [ecx+020h], eax ; save current exception list + mov eax, [edx+04h] ; load current stack base + mov [ecx+018h], eax ; save current stack base + mov eax, [edx+08h] ; load current stack limit + mov [ecx+01ch], eax ; save current stack limit + mov eax, [edx+010h] ; load fiber local storage + mov [ecx+024h], eax ; save fiber local storage + + lea eax, [esp+04h] ; exclude the return address + mov [ecx+010h], eax ; save as stack pointer + mov eax, [esp] ; load return address + mov [ecx+014h], eax ; save return address + + mov edx, [esp+08h] ; load address of the second fcontext_t arg + mov edi, [edx] ; restore EDI + mov esi, [edx+04h] ; restore ESI + mov ebx, [edx+08h] ; restore EBX + mov ebp, [edx+0ch] ; restore EBP + + mov eax, [esp+010h] ; check if fpu enve preserving was requested + test eax, eax + je nxt + + stmxcsr [ecx+028h] ; save MMX control word + fnstcw [ecx+02ch] ; save x87 control word + ldmxcsr [edx+028h] ; restore MMX control word + fldcw [edx+02ch] ; restore x87 control word +nxt: + mov ecx, edx + assume fs:nothing + mov edx, fs:[018h] ; load NT_TIB + assume fs:error + mov eax, [ecx+020h] ; load SEH exception list + mov [edx], eax ; restore next SEH item + mov eax, [ecx+018h] ; load stack base + mov [edx+04h], eax ; restore stack base + mov eax, [ecx+01ch] ; load stack limit + mov [edx+08h], eax ; restore stack limit + mov eax, [ecx+024h] ; load fiber local storage + mov [edx+010h], eax ; restore fiber local storage + + mov eax, [esp+0ch] ; use third arg as return value after jump + + mov esp, [ecx+010h] ; restore ESP + mov [esp+04h], eax ; use third arg as first arg in context function + mov ecx, [ecx+014h] ; fetch the address to return to + + jmp ecx ; indirect jump to context +jump_fcontext ENDP + +make_fcontext PROC EXPORT + mov eax, [esp+04h] ; load address of the fcontext_t arg0 + mov [eax], eax ; save the address of passed context + mov ecx, [esp+08h] ; load the address of the context function + mov [eax+014h], ecx ; save the address of the context function + mov edx, [eax+018h] ; load the stack base + + push eax ; save pointer to fcontext_t + push edx ; stack pointer as arg for align_stack + call align_stack ; align stack + mov edx, eax ; begin of aligned stack + pop eax ; remove arg for align_stack + pop eax ; restore pointer to fcontext_t + + lea edx, [edx-014h] ; reserve space for last frame on stack, (ESP + 4) & 15 == 0 + mov [eax+010h], edx ; save the aligned stack + + mov ecx, seh_fcontext ; set ECX to exception-handler + mov [edx+0ch], ecx ; save ECX as SEH handler + mov ecx, 0ffffffffh ; set ECX to -1 + mov [edx+08h], ecx ; save ECX as next SEH item + lea ecx, [edx+08h] ; load address of next SEH item + mov [eax+02ch], ecx ; save next SEH + + stmxcsr [eax+028h] ; save MMX control word + fnstcw [eax+02ch] ; save x87 control word + + mov ecx, finish ; address of finish + mov [edx], ecx + + xor eax, eax + ret + +finish: + xor eax, eax + push eax ; exit code is zero + call _exit ; exit application + hlt +make_fcontext ENDP +END diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S new file mode 100644 index 0000000..7c94ea0 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S @@ -0,0 +1,122 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************** + * * + * -------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | * + * -------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | * + * -------------------------------------------------------------- * + * | EDI | ESI | EBX | EBP | ESP | EIP | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 6 | 7 | | * + * -------------------------------------------------------------- * + * | 0x18 | 0x1c | | * + * -------------------------------------------------------------- * + * | sbase | slimit | | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 8 | 9 | | * + * -------------------------------------------------------------- * + * | 0x20 | 0x24 | | * + * -------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * -------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,@function +jump_fcontext: + movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */ + movl %edi, (%ecx) /* save EDI */ + movl %esi, 0x4(%ecx) /* save ESI */ + movl %ebx, 0x8(%ecx) /* save EBX */ + movl %ebp, 0xc(%ecx) /* save EBP */ + + leal 0x4(%esp), %eax /* exclude the return address */ + movl %eax, 0x10(%ecx) /* save as stack pointer */ + movl (%esp), %eax /* load return address */ + movl %eax, 0x14(%ecx) /* save return address */ + + movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */ + movl (%edx), %edi /* restore EDI */ + movl 0x4(%edx), %esi /* restore ESI */ + movl 0x8(%edx), %ebx /* restore EBX */ + movl 0xc(%edx), %ebp /* restore EBP */ + + movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */ + test %eax, %eax + je 1f + + stmxcsr 0x20(%ecx) /* save MMX control and status word */ + fnstcw 0x24(%ecx) /* save x87 control word */ + ldmxcsr 0x20(%edx) /* restore MMX control and status word */ + fldcw 0x24(%edx) /* restore x87 control word */ +1: + movl 0xc(%esp), %eax /* use third arg as return value after jump */ + + movl 0x10(%edx), %esp /* restore ESP */ + movl %eax, 0x4(%esp) /* use third arg as first arg in context function */ + movl 0x14(%edx), %edx /* fetch the address to return to */ + + jmp *%edx /* indirect jump to context */ +.size jump_fcontext,.-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,@function +make_fcontext: + movl 0x4(%esp), %eax /* load address of the fcontext_t */ + movl %eax, (%eax) /* save the address of current context */ + movl 0x8(%esp), %ecx /* load the address of the context function */ + movl %ecx, 0x14(%eax) /* save the address of the context function */ + movl 0x18(%eax), %edx /* load the stack base */ + + pushl %eax /* save pointer to fcontext_t */ + pushl %ebx /* save EBX */ + pushl %edx /* stack pointer as arg for align_stack */ + call 1f +1: popl %ebx /* address of label 1 */ + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */ + call align_stack@PLT /* align stack */ + movl %eax, %edx /* begin of aligned stack */ + popl %eax /* remove arg for align_stack */ + popl %ebx /* restore EBX */ + popl %eax /* restore pointer to fcontext_t */ + + leal -0x14(%edx), %edx /* reserve space for the last frame on stack, (ESP + 4) % 16 == 0 */ + movl %edx, 0x10(%eax) /* save the aligned stack base */ + + stmxcsr 0x20(%eax) /* save MMX control and status word */ + fnstcw 0x24(%eax) /* save x87 control word */ + + call 2f +2: popl %ecx /* address of label 2 */ + addl $finish-2b, %ecx /* helper code executed after context function returns */ + movl %ecx, (%edx) + + xorl %eax, %eax + ret + +finish: + leal -0xc(%esp), %esp + + call 3f +3: popl %ebx /* address of label 3 */ + addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx /* compute address of GOT and store it in EBX */ + + xorl %eax, %eax + pushl %eax /* exit code is zero */ + call _exit@PLT /* exit application */ + hlt +.size make_fcontext,.-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_macho_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_macho_gas.S new file mode 100644 index 0000000..a28c875 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_macho_gas.S @@ -0,0 +1,118 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************** + * * + * -------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | * + * -------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | * + * -------------------------------------------------------------- * + * | EDI | ESI | EBX | EBP | ESP | EIP | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 6 | 7 | | * + * -------------------------------------------------------------- * + * | 0x18 | 0x1c | | * + * -------------------------------------------------------------- * + * | sbase | slimit | | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 8 | 9 | | * + * -------------------------------------------------------------- * + * | 0x20 | 0x24 | | * + * -------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * -------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl _jump_fcontext +.align 2 +_jump_fcontext: + movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */ + movl %edi, (%ecx) /* save EDI */ + movl %esi, 0x4(%ecx) /* save ESI */ + movl %ebx, 0x8(%ecx) /* save EBX */ + movl %ebp, 0xc(%ecx) /* save EBP */ + + leal 0x4(%esp), %eax /* exclude the return address */ + movl %eax, 0x10(%ecx) /* save as stack pointer */ + movl (%esp), %eax /* load return address */ + movl %eax, 0x14(%ecx) /* save return address */ + + movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */ + movl (%edx), %edi /* restore EDI */ + movl 0x4(%edx), %esi /* restore ESI */ + movl 0x8(%edx), %ebx /* restore EBX */ + movl 0xc(%edx), %ebp /* restore EBP */ + + movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */ + test %eax, %eax + je 1f + + stmxcsr 0x20(%ecx) /* save MMX control and status word */ + fnstcw 0x24(%ecx) /* save x87 control word */ + ldmxcsr 0x20(%edx) /* restore MMX control and status word */ + fldcw 0x24(%edx) /* restore x87 control word */ +1: + movl 0xc(%esp), %eax /* use third arg as return value after jump */ + + movl 0x10(%edx), %esp /* restore ESP */ + movl %eax, 0x4(%esp) /* use third arg as first arg in context function */ + movl 0x14(%edx), %edx /* fetch the address to return to */ + + jmp *%edx /* indirect jump to context */ + +.text +.globl _make_fcontext +.align 2 +_make_fcontext: + movl 0x4(%esp), %eax /* load address of the fcontext_t */ + movl %eax, (%eax) /* save the address of current context */ + movl 0x8(%esp), %ecx /* load the address of the context function */ + movl %ecx, 0x14(%eax) /* save the address of the context function */ + movl 0x18(%eax), %edx /* load the stack base */ + + pushl %eax /* save pointer to fcontext_t */ + pushl %ebx /* save EBX */ + pushl %edx /* stack pointer as arg for align_stack */ + call 1f +1: popl %ebx /* address of label 1 */ + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */ + call align_stack@PLT /* align stack */ + movl %eax, %edx /* begin of aligned stack */ + popl %eax /* remove arg for align_stack */ + popl %ebx /* restore EBX */ + popl %eax /* restore pointer to fcontext_t */ + + leal -0x14(%edx), %edx /* reserve space for the last frame on stack, (ESP + 4) % 16 == 0 */ + movl %edx, 0x10(%eax) /* save the aligned stack base */ + + stmxcsr 0x20(%eax) /* save MMX control and status word */ + fnstcw 0x24(%eax) /* save x87 control word */ + + call 2f +2: popl %ecx /* address of label 2 */ + addl $finish-2b, %ecx /* helper code executed after context function returns */ + movl %ecx, (%edx) + + xorl %eax, %eax + ret + +finish: + leal -0xc(%esp), %esp + + call 3f +3: popl %ebx /* address of label 3 */ + addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx /* compute address of GOT and store it in EBX */ + + xorl %eax, %eax + pushl %eax /* exit code is zero */ + call _exit@PLT /* exit application */ + hlt diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_mips32_o32_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_mips32_o32_elf_gas.S new file mode 100644 index 0000000..be86f18 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_mips32_o32_elf_gas.S @@ -0,0 +1,144 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 | * + * ------------------------------------------------------------- * + * | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | GP | SP | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | 11 | 12 | | * + * ------------------------------------------------------------- * + * | 80 | 88 | 96 | | * + * ------------------------------------------------------------- * + * | S8 | RA | PC | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 13 | 14 | | * + * ------------------------------------------------------------- * + * | 104 | 112 | | * + * ------------------------------------------------------------- * + * |sbase|slimt| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 15 | 16 | 17 | 18 | 19 | 20 | | * + * ------------------------------------------------------------- * + * | 120 | 128 | 136 | 144 | 152 | 160 | | * + * ------------------------------------------------------------- * + * | F20 | F22 | F24 | F26 | F28 | F30 | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,@function +.ent jump_fcontext +jump_fcontext: + sw $s0, ($a0) # save S0 + sw $s1, 8($a0) # save S1 + sw $s2, 16($a0) # save S2 + sw $s3, 24($a0) # save S3 + sw $s4, 32($a0) # save S4 + sw $s5, 40($a0) # save S5 + sw $s6, 48($a0) # save S6 + sw $s7, 56($a0) # save S7 + sw $gp, 64($a0) # save GP + sw $sp, 72($a0) # save SP + sw $s8, 80($a0) # save S8 + sw $ra, 88($a0) # save RA + sw $ra, 96($a0) # save RA as PC + +#if defined(__mips_hard_float) + beqz $a3, 1f # test if fpu env should be preserved + s.d $f20, 120($a0) # save F20 + s.d $f22, 128($a0) # save F22 + s.d $f24, 136($a0) # save F24 + s.d $f26, 144($a0) # save F26 + s.d $f28, 152($a0) # save F28 + s.d $f30, 160($a0) # save F30 + + l.d $f20, 120($a1) # restore F20 + l.d $f22, 128($a1) # restore F22 + l.d $f24, 136($a1) # restore F24 + l.d $f26, 144($a1) # restore F26 + l.d $f28, 152($a1) # restore F28 + l.d $f30, 160($a1) # restore F30 +1: +#endif + + lw $s0, ($a1) # restore S0 + lw $s1, 8($a1) # restore S1 + lw $s2, 16($a1) # restore S2 + lw $s3, 24($a1) # restore S3 + lw $s4, 32($a1) # restore S4 + lw $s5, 40($a1) # restore S5 + lw $s6, 48($a1) # restore S6 + lw $s7, 56($a1) # restore S7 + lw $gp, 64($a1) # restore GP + lw $sp, 72($a1) # restore SP + lw $s8, 80($a1) # restore S8 + lw $ra, 88($a1) # restore RA + move $a0, $s2 # restore void pointer as argument + + move $v0, $a2 # use third arg as return value after jump + move $a0, $a2 # use third arg as first arg in context function + + lw $t9, 96($a1) # load PC + jr $t9 # jump to context +.end jump_fcontext +.size jump_fcontext, .-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,@function +.ent make_fcontext +make_fcontext: +#ifdef __PIC__ +.set noreorder +.cpload $t9 +.set reorder +#endif + sw $a0, ($a0) # save the current context + sw $gp, 24($a0) # save global pointer + sw $a1, 96($a0) # save the address of the context function + lw $t0, 104($a0) # load the stack base + + sub $sp, $sp, 28 + sw $ra, 24($sp) + sw $a0, 20($sp) + move $a0, $t0 # stack pointer as arg for align_stack + lw $t9, %call16(align_stack)($gp) # align stack + jalr $t9 + nop + move $t0, $v0 # begin of aligned stack + lw $ra, 24($sp) + lw $a0, 20($sp) + addi $sp, $sp, 28 + + sub $t0, $t0, 16 # reserve 16 byte of argument space + sw $t0, 72($a0) # save the algned stack base + + la $t9, finish # helper code executed after context function returns + sw $t9, 88($a0) + + move $v0, $zero + jr $ra + +finish: + move $gp, $s3 # restore GP (global pointer) + move $a0, $zero # exit code is zero + lw $t9, %call16(_exit)($gp) # exit application + jalr $t9 +.end make_fcontext +.size make_fcontext, .-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_ppc32_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_ppc32_sysv_elf_gas.S new file mode 100644 index 0000000..69b6ed9 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_ppc32_sysv_elf_gas.S @@ -0,0 +1,222 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | * + * ------------------------------------------------------------- * + * | R13 | R14 | R15 | R16 | R17 | R18 | R19 | R20 | R21 | R22 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | * + * ------------------------------------------------------------- * + * | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | * + * ------------------------------------------------------------- * + * | R23 | R24 | R25 | R26 | R27 | R28 | R29 | R30 | R31 | SP | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 20 | 21 | 22 | | * + * ------------------------------------------------------------- * + * | 80 | 84 | 88 | | * + * ------------------------------------------------------------- * + * | CR | LR | PC | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 23 | 24 | | * + * ------------------------------------------------------------- * + * | 92 | 96 | | * + * ------------------------------------------------------------- * + * |sbase|slimt| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | * + * ------------------------------------------------------------- * + * | 100 | 104 | 108 | 112 | 116 | 120 | 124 | 128 | 132 | 136 | * + * ------------------------------------------------------------- * + * | F14 | F15 | F16 | F17 | F18 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | * + * ------------------------------------------------------------- * + * | 140 | 144 | 148 | 152 | 156 | 160 | 164 | 168 | 172 | 176 | * + * ------------------------------------------------------------- * + * | F19 | F20 | F21 | F22 | F23 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | * + * ------------------------------------------------------------- * + * | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 208 | 212 | 216 | * + * ------------------------------------------------------------- * + * | F24 | F25 | F26 | F27 | F28 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | | * + * ------------------------------------------------------------- * + * | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | | * + * ------------------------------------------------------------- * + * | F29 | F30 | F31 | fpscr | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,@function +jump_fcontext: + stw %r13, 0(%r3) # save R13 + stw %r14, 4(%r3) # save R14 + stw %r15, 8(%r3) # save R15 + stw %r16, 12(%r3) # save R16 + stw %r17, 16(%r3) # save R17 + stw %r18, 20(%r3) # save R18 + stw %r19, 24(%r3) # save R19 + stw %r20, 28(%r3) # save R20 + stw %r21, 32(%r3) # save R21 + stw %r22, 36(%r3) # save R22 + stw %r23, 40(%r3) # save R23 + stw %r24, 44(%r3) # save R24 + stw %r25, 48(%r3) # save R25 + stw %r26, 52(%r3) # save R26 + stw %r27, 56(%r3) # save R27 + stw %r28, 60(%r3) # save R28 + stw %r29, 64(%r3) # save R29 + stw %r30, 68(%r3) # save R30 + stw %r31, 72(%r3) # save R31 + stw %r1, 76(%r3) # save SP + + mfcr %r0 # load CR + stw %r0, 80(%r3) # save CR + mflr %r0 # load LR + stw %r0, 84(%r3) # save LR + stw %r0, 88(%r3) # save LR as PC + + cmpwi cr7, %r6, 0 # test if fpu env should be preserved + beq cr7, 1f + + stfd %f14, 100(%r3) # save F14 + stfd %f15, 108(%r3) # save F15 + stfd %f16, 116(%r3) # save F16 + stfd %f17, 124(%r3) # save F17 + stfd %f18, 132(%r3) # save F18 + stfd %f19, 140(%r3) # save F19 + stfd %f20, 148(%r3) # save F20 + stfd %f21, 156(%r3) # save F21 + stfd %f22, 164(%r3) # save F22 + stfd %f23, 172(%r3) # save F23 + stfd %f24, 180(%r3) # save F24 + stfd %f25, 188(%r3) # save F25 + stfd %f26, 196(%r3) # save F26 + stfd %f27, 204(%r3) # save F27 + stfd %f28, 212(%r3) # save F28 + stfd %f29, 220(%r3) # save F29 + stfd %f30, 228(%r3) # save F30 + stfd %f31, 236(%r3) # save F31 + mffs %f0 # load FPSCR + stfd %f0, 244(%r3) # save FPSCR + + lfd %f14, 100(%r4) # restore F14 + lfd %f15, 108(%r4) # restore F15 + lfd %f16, 116(%r4) # restore F16 + lfd %f17, 124(%r4) # restore F17 + lfd %f18, 132(%r4) # restore F18 + lfd %f19, 140(%r4) # restore F19 + lfd %f20, 148(%r4) # restore F20 + lfd %f21, 156(%r4) # restore F21 + lfd %f22, 164(%r4) # restore F22 + lfd %f23, 172(%r4) # restore F23 + lfd %f24, 180(%r4) # restore F24 + lfd %f25, 188(%r4) # restore F25 + lfd %f26, 196(%r4) # restore F26 + lfd %f27, 204(%r4) # restore F27 + lfd %f28, 212(%r4) # restore F28 + lfd %f29, 220(%r4) # restore F29 + lfd %f30, 228(%r4) # restore F30 + lfd %f31, 236(%r4) # restore F31 + lfd %f0, 244(%r4) # load FPSCR + mtfsf 0xff, %f0 # restore FPSCR +1: + + lwz %r13, 0(%r4) # restore R13 + lwz %r14, 4(%r4) # restore R14 + lwz %r15, 8(%r4) # restore R15 + lwz %r16, 12(%r4) # restore R16 + lwz %r17, 16(%r4) # restore R17 + lwz %r18, 20(%r4) # restore R18 + lwz %r19, 24(%r4) # restore R19 + lwz %r20, 28(%r4) # restore R20 + lwz %r21, 32(%r4) # restore R21 + lwz %r22, 36(%r4) # restore R22 + lwz %r23, 40(%r4) # restore R23 + lwz %r24, 44(%r4) # restore R24 + lwz %r25, 48(%r4) # restore R25 + lwz %r26, 52(%r4) # restore R26 + lwz %r27, 56(%r4) # restore R27 + lwz %r28, 60(%r4) # restore R28 + lwz %r29, 64(%r4) # restore R29 + lwz %r30, 68(%r4) # restore R30 + lwz %r31, 72(%r4) # restore R31 + lwz %r1, 76(%r4) # restore SP + + lwz %r0, 80(%r4) # load CR + mtcr %r0 # restore CR + lwz %r0, 84(%r4) # load LR + mtlr %r0 # restore LR + + mr. %r3, %r5 # use third arg as return value after jump + # and as first arg in context function + + lwz %r0, 88(%r4) # load PC + mtctr %r0 # restore CTR + + bctr # jump to context +.size jump_fcontext, .-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,@function +make_fcontext: + stw %r3, 0(%r3) # save the current context + stw %r4, 88(%r3) # save the address of the context function + lwz %r0, 92(%r3) # load the stack base + + li %r4, 28 + subf %r1, %r4, %r1 # reserve space on stack + stw %r3, 24(%r1) # store pointer to fcontext_t on stack + mflr %r4 # load LR + stw %r4, 20(%r1) # store LR on stack + mr. %r3, %r0 # context stack as arg to align_stack + bl align_stack@plt # call align_stack + mr. %r0, %r3 # load result into R0 + lwz %r4, 20(%r1) # pop LR from stack + mtlr %r4 # restore LR + lwz %r3, 24(%r1) # pop pointer to fcontext_t from stack + addi %r1, %r1, 28 # release space on stack + + li %r4, 32 + subf %r0, %r4, %r0 # 32 bytes on stack for parameter area(== 8 registers) + stw %r0, 76(%r3) # save the aligned stack base + + mflr %r0 # load LR + bl 1f # jump to label 1 +1: + mflr %r4 # load LR + addi %r4, %r4, finish - 1b # address of finish; called after context function returns + mtlr %r0 # restore LR + stw %r4, 84(%r3) + + li %r3, 0 + blr + +finish: + li %r3, 0 # exit code is zero + bl _exit@plt # exit application +.size make_fcontext, .-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_ppc64_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_ppc64_sysv_elf_gas.S new file mode 100644 index 0000000..0fcb387 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_ppc64_sysv_elf_gas.S @@ -0,0 +1,250 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | * + * ------------------------------------------------------------- * + * | R13 | R14 | R15 | R16 | R17 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | * + * ------------------------------------------------------------- * + * | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | * + * ------------------------------------------------------------- * + * | R18 | R19 | R20 | R21 | R22 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | * + * ------------------------------------------------------------- * + * | 80 | 84 | 88 | 92 | 96 | 100 | 104 | 108 | 112 | 116 | * + * ------------------------------------------------------------- * + * | R23 | R24 | R25 | R26 | R27 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------------------- * + * | 120 | 124 | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | * + * ------------------------------------------------------------- * + * | R28 | R29 | R30 | R31 | SP | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 40 | 41 | 42 | 43 | 44 | 45 | | * + * ------------------------------------------------------------- * + * | 160 | 164 | 168 | 172 | 176 | 180 | | * + * ------------------------------------------------------------- * + * | CR | LR | PC | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 46 | 47 | 48 | 49 | | * + * ------------------------------------------------------------- * + * | 184 | 188 | 192 | 196 | | * + * ------------------------------------------------------------- * + * | sbase | slimt | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | * + * ------------------------------------------------------------- * + * | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | * + * ------------------------------------------------------------- * + * | F14 | F15 | F16 | F17 | F18 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | * + * ------------------------------------------------------------- * + * | 240 | 244 | 248 | 252 | 256 | 260 | 264 | 268 | 272 | 276 | * + * ------------------------------------------------------------- * + * | F19 | F20 | F21 | F22 | F23 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | * + * ------------------------------------------------------------- * + * | 280 | 284 | 288 | 292 | 296 | 300 | 304 | 308 | 312 | 316 | * + * ------------------------------------------------------------- * + * | F24 | F25 | F26 | F27 | F28 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | | * + * ------------------------------------------------------------- * + * | 320 | 324 | 328 | 332 | 336 | 340 | 344 | 348 | | * + * ------------------------------------------------------------- * + * | F29 | F30 | F31 | fpscr | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.section ".text" +.align 2 +.globl jump_fcontext +.section ".opd","aw" +.align 3 +jump_fcontext: +.quad .jump_fcontext,.TOC.@tocbase,0 +.previous +.size jump_fcontext,24 +.type .jump_fcontext,@function +.globl .jump_fcontext +.jump_fcontext: + std %r13, 0(%r3) # save R13 + std %r14, 8(%r3) # save R14 + std %r15, 16(%r3) # save R15 + std %r16, 24(%r3) # save R16 + std %r17, 32(%r3) # save R17 + std %r18, 40(%r3) # save R18 + std %r19, 48(%r3) # save R19 + std %r20, 56(%r3) # save R20 + std %r21, 64(%r3) # save R21 + std %r22, 72(%r3) # save R22 + std %r23, 80(%r3) # save R23 + std %r24, 88(%r3) # save R24 + std %r25, 96(%r3) # save R25 + std %r26, 104(%r3) # save R26 + std %r27, 112(%r3) # save R27 + std %r28, 120(%r3) # save R28 + std %r29, 128(%r3) # save R29 + std %r30, 136(%r3) # save R30 + std %r31, 144(%r3) # save R31 + std %r1, 152(%r3) # save SP + + mfcr %r0 # load CR + std %r0, 160(%r3) # save CR + mflr %r0 # load LR + std %r0, 168(%r3) # save LR + std %r0, 176(%r3) # save LR as PC + + cmpwi cr7, %r6, 0 # test if fpu env should be preserved + beq cr7, 1f + + stfd %f14, 200(%r3) # save F14 + stfd %f15, 208(%r3) # save F15 + stfd %f16, 216(%r3) # save F16 + stfd %f17, 224(%r3) # save F17 + stfd %f18, 232(%r3) # save F18 + stfd %f19, 240(%r3) # save F19 + stfd %f20, 248(%r3) # save F20 + stfd %f21, 256(%r3) # save F21 + stfd %f22, 264(%r3) # save F22 + stfd %f23, 272(%r3) # save F23 + stfd %f24, 280(%r3) # save F24 + stfd %f25, 288(%r3) # save F25 + stfd %f26, 296(%r3) # save F26 + stfd %f27, 304(%r3) # save F27 + stfd %f28, 312(%r3) # save F28 + stfd %f29, 320(%r3) # save F29 + stfd %f30, 328(%r3) # save F30 + stfd %f31, 336(%r3) # save F31 + mffs %f0 # load FPSCR + stfd %f0, 344(%r3) # save FPSCR + + lfd %f14, 200(%r4) # restore F14 + lfd %f15, 208(%r4) # restore F15 + lfd %f16, 216(%r4) # restore F16 + lfd %f17, 224(%r4) # restore F17 + lfd %f18, 232(%r4) # restore F18 + lfd %f19, 240(%r4) # restore F19 + lfd %f20, 248(%r4) # restore F20 + lfd %f21, 256(%r4) # restore F21 + lfd %f22, 264(%r4) # restore F22 + lfd %f23, 272(%r4) # restore F23 + lfd %f24, 280(%r4) # restore F24 + lfd %f25, 288(%r4) # restore F25 + lfd %f26, 296(%r4) # restore F26 + lfd %f27, 304(%r4) # restore F27 + lfd %f28, 312(%r4) # restore F28 + lfd %f29, 320(%r4) # restore F29 + lfd %f30, 328(%r4) # restore F30 + lfd %f31, 336(%r4) # restore F31 + lfd %f0, 344(%r4) # load FPSCR + mtfsf 0xff, %f0 # restore FPSCR +1: + + ld %r13, 0(%r4) # restore R13 + ld %r14, 8(%r4) # restore R14 + ld %r15, 16(%r4) # restore R15 + ld %r16, 24(%r4) # restore R16 + ld %r17, 32(%r4) # restore R17 + ld %r18, 40(%r4) # restore R18 + ld %r19, 48(%r4) # restore R19 + ld %r20, 56(%r4) # restore R20 + ld %r21, 64(%r4) # restore R21 + ld %r22, 72(%r4) # restore R22 + ld %r23, 80(%r4) # restore R23 + ld %r24, 88(%r4) # restore R24 + ld %r25, 96(%r4) # restore R25 + ld %r26, 104(%r4) # restore R26 + ld %r27, 112(%r4) # restore R27 + ld %r28, 120(%r4) # restore R28 + ld %r29, 128(%r4) # restore R29 + ld %r30, 136(%r4) # restore r30 + ld %r31, 144(%r4) # restore r31 + ld %r1, 152(%r4) # restore SP + + ld %r0, 160(%r4) # load CR + mtcr %r0 # restore CR + ld %r0, 168(%r4) # load LR + mtlr %r0 # restore LR + + mr. %r3, %r5 # use third arg as return value after jump + # and as first arg in context function + + ld %r0, 176(%r4) # load PC + mtctr %r0 # restore CTR + + bctr # jump to context +.size .jump_fcontext, .-.jump_fcontext + +.section ".text" +.align 2 +.globl make_fcontext +.section ".opd","aw" +.align 3 +make_fcontext: +.quad .make_fcontext,.TOC.@tocbase,0 +.previous +.size make_fcontext,24 +.type .make_fcontext,@function +.globl .make_fcontext +.make_fcontext: + std %r3, 0(%r3) # save the current context + std %r4, 176(%r3) # save the address of the function supposed to be run + ld %r0, 184(%r3) # load the stack base + + li %r4, 56 + subf %r1, %r4, %r1 # reserve space on stack + stw %r3, 48(%r1) # store pointer to fcontext_t on stack + mflr %r4 # load LR + stw %r4, 40(%r1) # store LR on stack + mr. %r3, %r0 # context stack as arg to align_stack + bl align_stack@plt # call align_stack + mr. %r0, %r3 # load result into R0 + lwz %r4, 40(%r1) # pop LR from stack + mtlr %r4 # restore LR + lwz %r3, 48(%r1) # pop pointer to fcontext_t from stack + addi %r1, %r1, 56 # release space on stack + + li %r4, 64 + subf %r0, %r4, %r0 # 64 bytes on stack for parameter area (== 8 registers) + std %r0, 152(%r3) # save the stack base + + mflr %r0 # load LR + bl 1f # jump to label 1 +1: + mflr %r4 # load LR + addi %r4, %r4, finish - 1b # calulate absolute address of finish + mtlr %r0 # restore LR + std %r4, 168(%r3) # save address of finish + + li %r3, 0 # set return value to zero + blr + +finish: + li %r3, 0 # set return value to zero + bl _exit@plt # exit application +.size .make_fcontext, .-.make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm new file mode 100644 index 0000000..f1f8ca1 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm @@ -0,0 +1,207 @@ + +; Copyright Oliver Kowalke 2009. +; Distributed under the Boost Software License, Version 1.0. +; (See accompanying file LICENSE_1_0.txt or copy at +; http://www.boost.org/LICENSE_1_0.txt) + +; ---------------------------------------------------------------------------------- +; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +; ---------------------------------------------------------------------------------- +; | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | +; ---------------------------------------------------------------------------------- +; | R12 | R13 | R14 | R15 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | +; ---------------------------------------------------------------------------------- +; | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | +; ---------------------------------------------------------------------------------- +; | RDI | RSI | RBX | RBP | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 16 | 17 | 18 | 19 | | +; ---------------------------------------------------------------------------------- +; | 0x40 | 0x44 | 0x48 | 0x4c | | +; ---------------------------------------------------------------------------------- +; | RSP | RIP | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 20 | 21 | 22 | 23 | | +; ---------------------------------------------------------------------------------- +; | 0x50 | 0x54 | 0x58 | 0x5c | | +; ---------------------------------------------------------------------------------- +; | sbase | slimit | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 24 | 25 | | +; ---------------------------------------------------------------------------------- +; | 0x60 | 0x64 | | +; ---------------------------------------------------------------------------------- +; | fbr_strg | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 26 | 27 | 28 | 29 | | +; ---------------------------------------------------------------------------------- +; | 0x68 | 0x6c | 0x70 | 0x74 | | +; ---------------------------------------------------------------------------------- +; | fc_mxcsr|fc_x87_cw| fc_xmm | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | +; ---------------------------------------------------------------------------------- +; | 0x78 | 0x7c | 0x80 | 0x84 | 0x88 | 0x8c | 0x90 | 0x94 | +; ---------------------------------------------------------------------------------- +; | XMM6 | XMM7 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | +; ---------------------------------------------------------------------------------- +; | 0x98 | 0x9c | 0x100 | 0x104 | 0x108 | 0x10c | 0x110 | 0x114 | +; ---------------------------------------------------------------------------------- +; | XMM8 | XMM9 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | +; ---------------------------------------------------------------------------------- +; | 0x118 | 0x11c | 0x120 | 0x124 | 0x128 | 0x12c | 0x130 | 0x134 | +; ---------------------------------------------------------------------------------- +; | XMM10 | XMM11 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | +; ---------------------------------------------------------------------------------- +; | 0x138 | 0x13c | 0x140 | 0x144 | 0x148 | 0x14c | 0x150 | 0x154 | +; ---------------------------------------------------------------------------------- +; | XMM12 | XMM13 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | +; ---------------------------------------------------------------------------------- +; | 0x158 | 0x15c | 0x160 | 0x164 | 0x168 | 0x16c | 0x170 | 0x174 | +; ---------------------------------------------------------------------------------- +; | XMM14 | XMM15 | +; ---------------------------------------------------------------------------------- + +EXTERN _exit:PROC ; standard C library function +EXTERN align_stack:PROC ; stack alignment +EXTERN seh_fcontext:PROC ; exception handler +.code + +jump_fcontext PROC EXPORT FRAME:seh_fcontext + .endprolog + + mov [rcx], r12 ; save R12 + mov [rcx+08h], r13 ; save R13 + mov [rcx+010h], r14 ; save R14 + mov [rcx+018h], r15 ; save R15 + mov [rcx+020h], rdi ; save RDI + mov [rcx+028h], rsi ; save RSI + mov [rcx+030h], rbx ; save RBX + mov [rcx+038h], rbp ; save RBP + + mov r10, gs:[030h] ; load NT_TIB + mov rax, [r10+08h] ; load current stack base + mov [rcx+050h], rax ; save current stack base + mov rax, [r10+010h] ; load current stack limit + mov [rcx+058h], rax ; save current stack limit + mov rax, [r10+018h] ; load fiber local storage + mov [rcx+060h], rax ; save fiber local storage + + test r9, r9 + je nxt + + stmxcsr [rcx+068h] ; save MMX control and status word + fnstcw [rcx+06ch] ; save x87 control word + mov r10, [rcx+070h] ; address of aligned XMM storage + movaps [r10], xmm6 + movaps [r10+010h], xmm7 + movaps [r10+020h], xmm8 + movaps [r10+030h], xmm9 + movaps [r10+040h], xmm10 + movaps [r10+050h], xmm11 + movaps [r10+060h], xmm12 + movaps [r10+070h], xmm13 + movaps [r10+080h], xmm14 + movaps [r10+090h], xmm15 + + ldmxcsr [rdx+068h] ; restore MMX control and status word + fldcw [rdx+06ch] ; restore x87 control word + mov r10, [rdx+070h] ; address of aligned XMM storage + movaps xmm6, [r10] + movaps xmm7, [r10+010h] + movaps xmm8, [r10+020h] + movaps xmm9, [r10+030h] + movaps xmm10, [r10+040h] + movaps xmm11, [r10+050h] + movaps xmm12, [r10+060h] + movaps xmm13, [r10+070h] + movaps xmm14, [r10+080h] + movaps xmm15, [r10+090h] +nxt: + + lea rax, [rsp+08h] ; exclude the return address + mov [rcx+040h], rax ; save as stack pointer + mov rax, [rsp] ; load return address + mov [rcx+048h], rax ; save return address + + mov r12, [rdx] ; restore R12 + mov r13, [rdx+08h] ; restore R13 + mov r14, [rdx+010h] ; restore R14 + mov r15, [rdx+018h] ; restore R15 + mov rdi, [rdx+020h] ; restore RDI + mov rsi, [rdx+028h] ; restore RSI + mov rbx, [rdx+030h] ; restore RBX + mov rbp, [rdx+038h] ; restore RBP + + mov r10, gs:[030h] ; load NT_TIB + mov rax, [rdx+050h] ; load stack base + mov [r10+08h], rax ; restore stack base + mov rax, [rdx+058h] ; load stack limit + mov [r10+010h], rax ; restore stack limit + mov rax, [rdx+060h] ; load fiber local storage + mov [r10+018h], rax ; restore fiber local storage + + mov rsp, [rdx+040h] ; restore RSP + mov r10, [rdx+048h] ; fetch the address to returned to + + mov rax, r8 ; use third arg as return value after jump + mov rcx, r8 ; use third arg as first arg in context function + + jmp r10 ; indirect jump to caller +jump_fcontext ENDP + +make_fcontext PROC EXPORT FRAME ; generate function table entry in .pdata and unwind information in E + .endprolog ; .xdata for a function's structured exception handling unwind behavior + + mov [rcx], rcx ; store the address of current context + mov [rcx+048h], rdx ; save the address of the function supposed to run + mov rdx, [rcx+050h] ; load the address where the context stack beginns + + push rcx ; save pointer to fcontext_t + sub rsp, 028h ; reserve shadow space for align_stack + mov rcx, rdx ; stack pointer as arg for align_stack + mov [rsp+8], rcx + call align_stack ; align stack + mov rdx, rax ; begin of aligned stack + add rsp, 028h + pop rcx ; restore pointer to fcontext_t + + lea rdx, [rdx-028h] ; reserve 32byte shadow space + return address on stack, (RSP + 8) % 16 == 0 + mov [rcx+040h], rdx ; save the address where the context stack beginns + + stmxcsr [rcx+068h] ; save MMX control and status word + fnstcw [rcx+06ch] ; save x87 control word + + lea rax, finish ; helper code executed after fn() returns + mov [rdx], rax ; store address off the helper function as return address + + xor rax, rax ; set RAX to zero + ret + +finish: + xor rcx, rcx + mov [rsp+08h], rcx + call _exit ; exit application + hlt +make_fcontext ENDP +END diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S new file mode 100644 index 0000000..ad2d42b --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S @@ -0,0 +1,116 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/**************************************************************************************** + * * + * ---------------------------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ---------------------------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * + * ---------------------------------------------------------------------------------- * + * | RBX | R12 | R13 | R14 | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ---------------------------------------------------------------------------------- * + * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * + * ---------------------------------------------------------------------------------- * + * | R15 | RBP | RSP | RIP | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 16 | 17 | 18 | 19 | | * + * ---------------------------------------------------------------------------------- * + * | 0x40 | 0x44 | 0x48 | 0x4c | | * + * ---------------------------------------------------------------------------------- * + * | sbase | slimit | | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 20 | 21 | | * + * ---------------------------------------------------------------------------------- * + * | 0x50 | 0x54 | | * + * ---------------------------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * ---------------------------------------------------------------------------------- * + * * + * **************************************************************************************/ + +.text +.globl jump_fcontext +.type jump_fcontext,@function +.align 16 +jump_fcontext: + movq %rbx, (%rdi) /* save RBX */ + movq %r12, 0x8(%rdi) /* save R12 */ + movq %r13, 0x10(%rdi) /* save R13 */ + movq %r14, 0x18(%rdi) /* save R14 */ + movq %r15, 0x20(%rdi) /* save R15 */ + movq %rbp, 0x28(%rdi) /* save RBP */ + + cmp $0, %rcx + je 1f + + stmxcsr 0x50(%rdi) /* save MMX control and status word */ + fnstcw 0x54(%rdi) /* save x87 control word */ + + ldmxcsr 0x50(%rsi) /* restore MMX control and status word */ + fldcw 0x54(%rsi) /* restore x87 control word */ +1: + + leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */ + movq %rax, 0x30(%rdi) /* save as stack pointer */ + movq (%rsp), %rax /* save return address */ + movq %rax, 0x38(%rdi) /* save return address as RIP */ + + movq (%rsi), %rbx /* restore RBX */ + movq 0x8(%rsi), %r12 /* restore R12 */ + movq 0x10(%rsi), %r13 /* restore R13 */ + movq 0x18(%rsi), %r14 /* restore R14 */ + movq 0x20(%rsi), %r15 /* restore R15 */ + movq 0x28(%rsi), %rbp /* restore RBP */ + + movq 0x30(%rsi), %rsp /* restore RSP */ + movq 0x38(%rsi), %rcx /* fetch the address to return to */ + + movq %rdx, %rax /* use third arg as return value after jump */ + movq %rdx, %rdi /* use third arg as first arg in context function */ + + jmp *%rcx /* indirect jump to context */ +.size jump_fcontext,.-jump_fcontext + +.text +.globl make_fcontext +.type make_fcontext,@function +.align 16 +make_fcontext: + movq %rdi, (%rdi) /* save the address of passed context */ + movq %rsi, 0x38(%rdi) /* save the address of the context function */ + movq 0x40(%rdi), %rdx /* load the stack base */ + + pushq %rdi /* save pointer to fcontext_t */ + movq %rdx, %rdi /* stack pointer as arg for align_stack */ + call align_stack@PLT /* align stack */ + movq %rax, %rdx /* begin of aligned stack */ + popq %rdi /* restore pointer to fcontext_t */ + + leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) & 15 == 0 */ + movq %rdx, 0x30(%rdi) /* save the algined stack base */ + + stmxcsr 0x50(%rdi) /* save MMX control and status word */ + fnstcw 0x54(%rdi) /* save x87 control word */ + + leaq finish(%rip), %rcx /* address of finish; called after context function returns */ + movq %rcx, (%rdx) + + xorq %rax, %rax + ret + +finish: + xorq %rdi, %rdi /* exit code is zero */ + call _exit@PLT /* exit application */ + hlt +.size make_fcontext,.-make_fcontext + diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S new file mode 100644 index 0000000..eea76e4 --- /dev/null +++ b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S @@ -0,0 +1,111 @@ +/* + Copyright Oliver Kowalke 2009. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/**************************************************************************************** + * * + * ---------------------------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ---------------------------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * + * ---------------------------------------------------------------------------------- * + * | RBX | R12 | R13 | R14 | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ---------------------------------------------------------------------------------- * + * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * + * ---------------------------------------------------------------------------------- * + * | R15 | RBP | RSP | RIP | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 16 | 17 | 18 | 19 | | * + * ---------------------------------------------------------------------------------- * + * | 0x40 | 0x44 | 0x48 | 0x4c | | * + * ---------------------------------------------------------------------------------- * + * | sbase | slimit | | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 20 | 21 | | * + * ---------------------------------------------------------------------------------- * + * | 0x50 | 0x54 | | * + * ---------------------------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * ---------------------------------------------------------------------------------- * + * * + * **************************************************************************************/ + +.text +.globl _jump_fcontext +.align 8 +_jump_fcontext: + movq %rbx, (%rdi) /* save RBX */ + movq %r12, 0x8(%rdi) /* save R12 */ + movq %r13, 0x10(%rdi) /* save R13 */ + movq %r14, 0x18(%rdi) /* save R14 */ + movq %r15, 0x20(%rdi) /* save R15 */ + movq %rbp, 0x28(%rdi) /* save RBP */ + + cmp $0, %rcx + je 1f + + stmxcsr 0x50(%rdi) /* save MMX control and status word */ + fnstcw 0x54(%rdi) /* save x87 control word */ + + ldmxcsr 0x50(%rsi) /* restore MMX control and status word */ + fldcw 0x54(%rsi) /* restore x87 control word */ +1: + + leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */ + movq %rax, 0x30(%rdi) /* save as stack pointer */ + movq (%rsp), %rax /* save return address */ + movq %rax, 0x38(%rdi) /* save return address as RIP */ + + movq (%rsi), %rbx /* restore RBX */ + movq 0x8(%rsi), %r12 /* restore R12 */ + movq 0x10(%rsi), %r13 /* restore R13 */ + movq 0x18(%rsi), %r14 /* restore R14 */ + movq 0x20(%rsi), %r15 /* restore R15 */ + movq 0x28(%rsi), %rbp /* restore RBP */ + + movq 0x30(%rsi), %rsp /* restore RSP */ + movq 0x38(%rsi), %rcx /* fetch the address to return to */ + + movq %rdx, %rax /* use third arg as return value after jump */ + movq %rdx, %rdi /* use third arg as first arg in context function */ + + jmp *%rcx /* indirect jump to context */ + +.text +.globl _make_fcontext +.align 8 +_make_fcontext: + movq %rdi, (%rdi) /* save the address of current context */ + movq %rsi, 0x38(%rdi) /* save the address of the function supposed to run */ + movq 0x40(%rdi), %rdx /* load the stack base */ + + pushq %rdi /* save pointer to fcontext_t */ + movq %rdx, %rdi /* stack pointer as arg for align_stack */ + call _align_stack /* align stack */ + movq %rax, %rdx /* begin of aligned stack */ + popq %rdi /* restore pointer to fcontext_t */ + + leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) % 16 == 0 */ + movq %rdx, 0x30(%rdi) /* save the address */ + + stmxcsr 0x50(%rdi) /* save MMX control and status word */ + fnstcw 0x54(%rdi) /* save x87 control word */ + + leaq finish(%rip), %rcx /* helper code executed after context function returns */ + movq %rcx, (%rdx) + + xorq %rax, %rax /* set RAX to zero */ + ret + +finish: + xorq %rdi, %rdi /* exit code is zero */ + call _exit /* exit application */ + hlt diff --git a/vendor/boost_1.51/libs/context/fcontext.cpp b/vendor/boost_1.51/libs/context/fcontext.cpp new file mode 100644 index 0000000..596cbd8 --- /dev/null +++ b/vendor/boost_1.51/libs/context/fcontext.cpp @@ -0,0 +1,36 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CONTEXT_SOURCE + +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { +namespace detail { + +extern "C" BOOST_CONTEXT_DECL +void * BOOST_CONTEXT_CALLDECL align_stack( void * vp) +{ + void * base = vp; + if ( 0 != ( ( ( uintptr_t) base) & 15) ) + base = ( char * ) ( ( ( ( uintptr_t) base) - 15) & ~0x0F); + return base; +} + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif diff --git a/vendor/boost_1.51/libs/context/seh.cpp b/vendor/boost_1.51/libs/context/seh.cpp new file mode 100644 index 0000000..9363805 --- /dev/null +++ b/vendor/boost_1.51/libs/context/seh.cpp @@ -0,0 +1,83 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CONTEXT_SOURCE + +extern "C" { + +#include +#include + +#include +#include +#include + +#if defined(_MSC_VER) +# define SNPRINTF _snprintf +#else +# define SNPRINTF snprintf +#endif + +static const char * exception_description( + _EXCEPTION_RECORD const* record, char * description, size_t len) +{ + const DWORD code = record->ExceptionCode; + const ULONG_PTR * info = record->ExceptionInformation; + + switch ( code) + { + case EXCEPTION_ACCESS_VIOLATION: + { + const char * accessType = ( info[0]) ? "writing" : "reading"; + const ULONG_PTR address = info[1]; + SNPRINTF( description, len, "Access violation %s %p", accessType, reinterpret_cast< void * >( address) ); + return description; + } + case EXCEPTION_DATATYPE_MISALIGNMENT: return "Datatype misalignment"; + case EXCEPTION_BREAKPOINT: return "Breakpoint"; + case EXCEPTION_SINGLE_STEP: return "Single step"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "Array bounds exceeded"; + case EXCEPTION_FLT_DENORMAL_OPERAND: return "FPU denormal operand"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "FPU divide by zero"; + case EXCEPTION_FLT_INEXACT_RESULT: return "FPU inexact result"; + case EXCEPTION_FLT_INVALID_OPERATION: return "FPU invalid operation"; + case EXCEPTION_FLT_OVERFLOW: return "FPU overflow"; + case EXCEPTION_FLT_STACK_CHECK: return "FPU stack check"; + case EXCEPTION_FLT_UNDERFLOW: return "FPU underflow"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: return "Integer divide by zero"; + case EXCEPTION_INT_OVERFLOW: return "Integer overflow"; + case EXCEPTION_PRIV_INSTRUCTION: return "Privileged instruction"; + case EXCEPTION_IN_PAGE_ERROR: return "In page error"; + case EXCEPTION_ILLEGAL_INSTRUCTION: return "Illegal instruction"; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "Noncontinuable exception"; + case EXCEPTION_STACK_OVERFLOW: return "Stack overflow"; + case EXCEPTION_INVALID_DISPOSITION: return "Invalid disposition"; + case EXCEPTION_GUARD_PAGE: return "Guard page"; + case EXCEPTION_INVALID_HANDLE: return "Invalid handle"; + } + + SNPRINTF( description, len, "Unknown (0x%08lX)", code); + return description; +} + +EXCEPTION_DISPOSITION seh_fcontext( + struct _EXCEPTION_RECORD * record, + void *, + struct _CONTEXT *, + void *) +{ + char description[255]; + + fprintf( stderr, "exception: %s (%08lX)\n", + exception_description( record, description, sizeof( description) ), + record->ExceptionCode); + + ExitProcess( -1); + + return ExceptionContinueSearch; // never reached +} + +} diff --git a/vendor/boost_1.51/libs/context/stack_allocator_posix.cpp b/vendor/boost_1.51/libs/context/stack_allocator_posix.cpp new file mode 100644 index 0000000..64291e7 --- /dev/null +++ b/vendor/boost_1.51/libs/context/stack_allocator_posix.cpp @@ -0,0 +1,85 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CONTEXT_SOURCE + +#include + +extern "C" { +#include +#include +#include +#include +#include +} + +#include + +#include +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +void * +stack_allocator::allocate( std::size_t size) const +{ + if ( minimum_stacksize() > size) + throw std::invalid_argument( + boost::str( boost::format("invalid stack size: must be at least %d bytes") + % minimum_stacksize() ) ); + + if ( ! is_stack_unbound() && ( maximum_stacksize() < size) ) + throw std::invalid_argument( + boost::str( boost::format("invalid stack size: must not be larger than %d bytes") + % maximum_stacksize() ) ); + + const std::size_t pages( page_count( size) + 1); // add +1 for guard page + std::size_t size_ = pages * pagesize(); + + +# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); +# else + const int fd( ::open("/dev/zero", O_RDONLY) ); + BOOST_ASSERT( -1 != fd); + void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + ::close( fd); +# endif + if ( ! limit) throw std::bad_alloc(); + + const int result( ::mprotect( limit, pagesize(), PROT_NONE) ); + BOOST_ASSERT( 0 == result); + (void)result; // unused in release build + + return static_cast< char * >( limit) + size_; +} + +void +stack_allocator::deallocate( void * vp, std::size_t size) const +{ + if ( vp) + { + const std::size_t pages( page_count( size) + 1); // add +1 for guard page + std::size_t size_ = pages * pagesize(); + BOOST_ASSERT( 0 < size && 0 < size_); + void * limit = static_cast< char * >( vp) - size_; + ::munmap( limit, size_); + } +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif diff --git a/vendor/boost_1.51/libs/context/stack_allocator_windows.cpp b/vendor/boost_1.51/libs/context/stack_allocator_windows.cpp new file mode 100644 index 0000000..518239f --- /dev/null +++ b/vendor/boost_1.51/libs/context/stack_allocator_windows.cpp @@ -0,0 +1,86 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CONTEXT_SOURCE + +#include + +extern "C" { +#include +} + +#include + +#include +#include +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +# if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4244 4267) +# endif + +namespace boost { +namespace ctx { + +void * +stack_allocator::allocate( std::size_t size) const +{ + if ( minimum_stacksize() > size) + throw std::invalid_argument( + boost::str( boost::format("invalid stack size: must be at least %d bytes") + % minimum_stacksize() ) ); + + if ( ! is_stack_unbound() && ( maximum_stacksize() < size) ) + throw std::invalid_argument( + boost::str( boost::format("invalid stack size: must not be larger than %d bytes") + % maximum_stacksize() ) ); + + const std::size_t pages( page_count( size) + 1); // add +1 for guard page + std::size_t size_ = pages * pagesize(); + +#ifndef BOOST_CONTEXT_FIBER + void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE); + if ( ! limit) throw std::bad_alloc(); + + DWORD old_options; + const BOOL result = ::VirtualProtect( + limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options); + BOOST_ASSERT( FALSE != result); + + return static_cast< char * >( limit) + size_; +#endif +} + +void +stack_allocator::deallocate( void * vp, std::size_t size) const +{ + if ( vp) + { + const std::size_t pages( page_count( size) + 1); // add +1 for guard page + std::size_t size_ = pages * pagesize(); + BOOST_ASSERT( 0 < size && 0 < size_); + void * limit = static_cast< char * >( vp) - size_; + ::VirtualFree( limit, 0, MEM_RELEASE); + } +} + +}} + +# if defined(BOOST_MSVC) +# pragma warning(pop) +# endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif diff --git a/vendor/boost_1.51/libs/context/stack_utils_posix.cpp b/vendor/boost_1.51/libs/context/stack_utils_posix.cpp new file mode 100644 index 0000000..13c4e4e --- /dev/null +++ b/vendor/boost_1.51/libs/context/stack_utils_posix.cpp @@ -0,0 +1,81 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CONTEXT_SOURCE + +#include + +extern "C" { +#include +#include +#include +#include +} + +#include + +#include + +namespace { + +static rlimit stacksize_limit_() +{ + rlimit limit; + const int result = ::getrlimit( RLIMIT_STACK, & limit); + BOOST_ASSERT( 0 == result); + (void)result; // unused when in release mode... + return limit; +} + +static rlimit stacksize_limit() +{ + static rlimit limit = stacksize_limit_(); + return limit; +} + +} + +namespace boost { +namespace ctx { + +BOOST_CONTEXT_DECL +std::size_t default_stacksize() +{ + static std::size_t size = 256 * 1024; + return size; +} + +BOOST_CONTEXT_DECL +std::size_t minimum_stacksize() +{ return SIGSTKSZ; } + +BOOST_CONTEXT_DECL +std::size_t maximum_stacksize() +{ + BOOST_ASSERT( ! is_stack_unbound() ); + return static_cast< std::size_t >( stacksize_limit().rlim_max); +} + +BOOST_CONTEXT_DECL +bool is_stack_unbound() +{ return RLIM_INFINITY == stacksize_limit().rlim_max; } + +BOOST_CONTEXT_DECL +std::size_t pagesize() +{ + static std::size_t pagesize( ::getpagesize() ); + return pagesize; +} + +BOOST_CONTEXT_DECL +std::size_t page_count( std::size_t stacksize) +{ + return static_cast< std::size_t >( + std::ceil( + static_cast< float >( stacksize) / pagesize() ) ); +} + +}} diff --git a/vendor/boost_1.51/libs/context/stack_utils_windows.cpp b/vendor/boost_1.51/libs/context/stack_utils_windows.cpp new file mode 100644 index 0000000..373033d --- /dev/null +++ b/vendor/boost_1.51/libs/context/stack_utils_windows.cpp @@ -0,0 +1,84 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CONTEXT_SOURCE + +#include + +extern "C" { +#include +} + +#include +#include + +#include + +namespace { + +static SYSTEM_INFO system_info_() +{ + SYSTEM_INFO si; + ::GetSystemInfo( & si); + return si; +} + +static SYSTEM_INFO system_info() +{ + static SYSTEM_INFO si = system_info_(); + return si; +} + +} + +namespace boost { +namespace ctx { + +BOOST_CONTEXT_DECL +std::size_t default_stacksize() +{ + static std::size_t size = 256 * 1024; + return size; +} + +BOOST_CONTEXT_DECL +std::size_t minimum_stacksize() +{ + static std::size_t stacksize( + static_cast< std::size_t >( system_info().dwAllocationGranularity) ); + return stacksize; +} + +BOOST_CONTEXT_DECL +std::size_t maximum_stacksize() +{ + BOOST_ASSERT( ! is_stack_unbound() ); + static std::size_t stacksize = 8 * 1024 * 1024; + return stacksize; +} + +// Windows seams not to provide a limit for the stacksize +BOOST_CONTEXT_DECL +bool is_stack_unbound() +{ return true; } + +BOOST_CONTEXT_DECL +std::size_t pagesize() +{ + static std::size_t pagesize( + static_cast< std::size_t >( system_info().dwPageSize) ); + return pagesize; +} + +BOOST_CONTEXT_DECL +std::size_t page_count( std::size_t stacksize) +{ + return static_cast< std::size_t >( + std::ceil( + static_cast< float >( stacksize) / pagesize() ) ); +} + +}} diff --git a/vendor/libssh2-1.4.2/AUTHORS b/vendor/libssh2-1.4.2/AUTHORS deleted file mode 100644 index 214fca9..0000000 --- a/vendor/libssh2-1.4.2/AUTHORS +++ /dev/null @@ -1,48 +0,0 @@ - libssh2 is the result of many friendly people. This list is an attempt to - mention all contributors. If we've missed anyone, tell us! - - This list of names is a-z sorted. - -Adam Gobiowski -Alexander Holyapin -Alexander Lamaison -Ben Kibbey -Bjorn Stenborg -Carlo Bramini -Dan Casey -Dan Fandrich -Daniel Stenberg -David J Sullivan -David Robins -Edink Kadribasic -Erik Brossler -Francois Dupoux -Guenter Knauf -Heiner Steven -James Housleys -Jean-Louis Charton -Jussi Mononen -Mark McPherson -Markus Moeller -Mike Protts -Mikhail Gusarov -Neil Gierman -Olivier Hervieu -Paul Veldkamp -Peter Krempa -Peter O'Gorman -Peter Stuge -Romain Bondue -Sara Golemon -Satish Mittal -Sean Peterson -Selcuk Gueney -Simon Hart -Simon Josefsson -Steven Ayre -Steven Van Ingelgem -Tor Arntsen -Vincent Jaulin -Vlad Grachov -Wez Furlong -Yang Tse diff --git a/vendor/libssh2-1.4.2/CMakeLists.txt b/vendor/libssh2-1.4.2/CMakeLists.txt deleted file mode 100644 index 9ce81c1..0000000 --- a/vendor/libssh2-1.4.2/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -include_directories(include) -include_directories( ${OPENSSL_INCLUDE_DIR} ) -SET( sources - src/agent.c - src/channel.c - src/comp.c - src/crypt.c - src/global.c - src/hostkey.c - src/keepalive.c - src/kex.c - src/knownhost.c - src/libgcrypt.c - src/mac.c - src/misc.c - src/openssl.c - src/packet.c - src/pem.c - src/publickey.c - src/scp.c - src/session.c - src/sftp.c - src/transport.c - src/userauth.c - src/version.c -) -add_definitions( -DLIBSSH2DEBUG ) -SETUP_LIBRARY( ssh2 SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC ) diff --git a/vendor/libssh2-1.4.2/COPYING b/vendor/libssh2-1.4.2/COPYING deleted file mode 100644 index 1bd78c9..0000000 --- a/vendor/libssh2-1.4.2/COPYING +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2005,2006 Mikhail Gusarov - * Copyright (c) 2006-2007 The Written Word, Inc. - * Copyright (c) 2007 Eli Fant - * Copyright (c) 2009 Daniel Stenberg - * Copyright (C) 2008, 2009 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - */ - diff --git a/vendor/libssh2-1.4.2/ChangeLog b/vendor/libssh2-1.4.2/ChangeLog deleted file mode 100644 index 404c887..0000000 --- a/vendor/libssh2-1.4.2/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -see NEWS diff --git a/vendor/libssh2-1.4.2/HACKING b/vendor/libssh2-1.4.2/HACKING deleted file mode 100644 index 5da8e66..0000000 --- a/vendor/libssh2-1.4.2/HACKING +++ /dev/null @@ -1,13 +0,0 @@ - -libssh2 source code style guide: - - - 4 level indent - - spaces-only (no tabs) - - open braces on the if/for line: - - if (banana) { - go_nuts(); - } - - - keep source lines shorter than 80 columns - - See libssh2-style.el for how to achieve this within Emacs diff --git a/vendor/libssh2-1.4.2/README b/vendor/libssh2-1.4.2/README deleted file mode 100644 index d297f31..0000000 --- a/vendor/libssh2-1.4.2/README +++ /dev/null @@ -1,102 +0,0 @@ -libssh2 - SSH2 library -====================== - -libssh2 is a library implementing the SSH2 protocol, available under -the revised BSD license. - -Web site: http://www.libssh2.org/ - -Mailing list: http://cool.haxx.se/mailman/listinfo/libssh2-devel - -The rest of this readme does not apply as the build system has been replaced -with CMake for use in mace on windows/linux and mac. - - - -Generic installation instructions are in INSTALL. Some ./configure -options deserve additional comments: - - * --enable-crypt-none - - The SSH2 Transport allows for unencrypted data - transmission using the "none" cipher. Because this is - such a huge security hole, it is typically disabled on - SSH2 implementations and is disabled in libssh2 by - default as well. - - Enabling this option will allow for "none" as a - negotiable method, however it still requires that the - method be advertized by the remote end and that no - more-preferable methods are available. - - * --enable-mac-none - - The SSH2 Transport also allows implementations to - forego a message authentication code. While this is - less of a security risk than using a "none" cipher, it - is still not recommended as disabling MAC hashes - removes a layer of security. - - Enabling this option will allow for "none" as a - negotiable method, however it still requires that the - method be advertized by the remote end and that no - more-preferable methods are available. - - * --disable-gex-new - - The diffie-hellman-group-exchange-sha1 (dh-gex) key - exchange method originally defined an exchange - negotiation using packet type 30 to request a - generation pair based on a single target value. Later - refinement of dh-gex provided for range and target - values. By default libssh2 will use the newer range - method. - - If you experience trouble connecting to an old SSH - server using dh-gex, try this option to fallback on - the older more reliable method. - - * --with-libgcrypt - * --without-libgcrypt - * --with-libgcrypt-prefix=DIR - - libssh2 can use the Libgcrypt library - (http://www.gnupg.org/) for cryptographic operations. - Either Libgcrypt or OpenSSL is required. - - Configure will attempt to locate Libgcrypt - automatically. - - If your installation of Libgcrypt is in another - location, specify it using --with-libgcrypt-prefix. - - * --with-openssl - * --without-openssl - * --with-libssl-prefix=[DIR] - - libssh2 can use the OpenSSL library - (http://www.openssl.org) for cryptographic operations. - Either Libgcrypt or OpenSSL is required. - - Configure will attempt to locate OpenSSL in the - default location. - - If your installation of OpenSSL is in another - location, specify it using --with-libssl-prefix. - - * --with-libz - * --without-libz - * --with-libz-prefix=[DIR] - - If present, libssh2 will attempt to use the zlib - (http://www.zlib.org) for payload compression, however - zlib is not required. - - If your installation of Libz is in another location, - specify it using --with-libz-prefix. - - * --enable-debug - - Will make the build use more pedantic and strict compiler - options as well as enable the libssh2_trace() function (for - showing debug traces). diff --git a/vendor/libssh2-1.4.2/RELEASE-NOTES b/vendor/libssh2-1.4.2/RELEASE-NOTES deleted file mode 100644 index ee52e8c..0000000 --- a/vendor/libssh2-1.4.2/RELEASE-NOTES +++ /dev/null @@ -1,21 +0,0 @@ -libssh2 1.4.2 - -This release includes the following bugfixes: - - o Return LIBSSH2_ERROR_SOCKET_DISCONNECT on EOF when reading banner - o userauth.c: fread() from public key file to correctly detect any errors - o configure.ac: Add option to disable build of the example applications - o Added 'Requires.private:' line to libssh2.pc - o SFTP: filter off incoming "zombie" responses - o gettimeofday: no need for a replacement under cygwin - o SSH_MSG_CHANNEL_REQUEST: default to want_reply - o win32/libssh2_config.h: Remove hardcoded #define LIBSSH2_HAVE_ZLIB - -This release would not have looked like this without help, code, reports and -advice from friends like these: - - Alexander Lamaison, Rafael Kitover, Guenter Knauf, Peter Stuge, - Oleksiy Zagorskyi - - Thanks! (and sorry if I forgot to mention someone) - diff --git a/vendor/libssh2-1.4.2/include/libssh2.h b/vendor/libssh2-1.4.2/include/libssh2.h deleted file mode 100644 index 6af0028..0000000 --- a/vendor/libssh2-1.4.2/include/libssh2.h +++ /dev/null @@ -1,1188 +0,0 @@ -/* Copyright (c) 2004-2009, Sara Golemon - * Copyright (c) 2009-2012 Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 LIBSSH2_H -#define LIBSSH2_H 1 - -#define LIBSSH2_COPYRIGHT "2004-2012 The libssh2 project and its contributors." - -/* We use underscore instead of dash when appending DEV in dev versions just - to make the BANNER define (used by src/session.c) be a valid SSH - banner. Release versions have no appended strings and may of course not - have dashes either. */ -#define LIBSSH2_VERSION "1.4.2" - -/* The numeric version number is also available "in parts" by using these - defines: */ -#define LIBSSH2_VERSION_MAJOR 1 -#define LIBSSH2_VERSION_MINOR 4 -#define LIBSSH2_VERSION_PATCH 2 - -/* This is the numeric version of the libssh2 version number, meant for easier - parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will - always follow this syntax: - - 0xXXYYZZ - - Where XX, YY and ZZ are the main version, release and patch numbers in - hexadecimal (using 8 bits each). All three numbers are always represented - using two digits. 1.2 would appear as "0x010200" while version 9.11.7 - appears as "0x090b07". - - This 6-digit (24 bits) hexadecimal number does not show pre-release number, - and it is always a greater number in a more recent release. It makes - comparisons with greater than and less than work. -*/ -#define LIBSSH2_VERSION_NUM 0x010402 - -/* - * This is the date and time when the full source package was created. The - * timestamp is not stored in the source code repo, as the timestamp is - * properly set in the tarballs by the maketgz script. - * - * The format of the date should follow this template: - * - * "Mon Feb 12 11:35:33 UTC 2007" - */ -#define LIBSSH2_TIMESTAMP "Fri May 18 21:30:56 UTC 2012" - -#ifndef RC_INVOKED - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef _WIN32 -# include -# include -#endif - -#include -#include -#include -#include - -/* Allow alternate API prefix from CFLAGS or calling app */ -#ifndef LIBSSH2_API -# ifdef LIBSSH2_WIN32 -# ifdef LIBSSH2_LIBRARY -# define LIBSSH2_API __declspec(dllexport) -# else -# define LIBSSH2_API __declspec(dllimport) -# endif /* LIBSSH2_LIBRARY */ -# else /* !LIBSSH2_WIN32 */ -# define LIBSSH2_API -# endif /* LIBSSH2_WIN32 */ -#endif /* LIBSSH2_API */ - -#if defined(LIBSSH2_DARWIN) -# include -#endif - -#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) -# include -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -#endif - -#ifdef _MSC_VER -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef unsigned __int64 libssh2_uint64_t; -typedef __int64 libssh2_int64_t; -#ifndef ssize_t -typedef SSIZE_T ssize_t; -#endif -#else -typedef unsigned long long libssh2_uint64_t; -typedef long long libssh2_int64_t; -#endif - -#ifdef WIN32 -typedef SOCKET libssh2_socket_t; -#define LIBSSH2_INVALID_SOCKET INVALID_SOCKET -#else /* !WIN32 */ -typedef int libssh2_socket_t; -#define LIBSSH2_INVALID_SOCKET -1 -#endif /* WIN32 */ - -/* Part of every banner, user specified or not */ -#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION - -/* We *could* add a comment here if we so chose */ -#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER -#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n" - -/* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 */ -#define LIBSSH2_DH_GEX_MINGROUP 1024 -#define LIBSSH2_DH_GEX_OPTGROUP 1536 -#define LIBSSH2_DH_GEX_MAXGROUP 2048 - -/* Defaults for pty requests */ -#define LIBSSH2_TERM_WIDTH 80 -#define LIBSSH2_TERM_HEIGHT 24 -#define LIBSSH2_TERM_WIDTH_PX 0 -#define LIBSSH2_TERM_HEIGHT_PX 0 - -/* 1/4 second */ -#define LIBSSH2_SOCKET_POLL_UDELAY 250000 -/* 0.25 * 120 == 30 seconds */ -#define LIBSSH2_SOCKET_POLL_MAXLOOPS 120 - -/* Maximum size to allow a payload to compress to, plays it safe by falling - short of spec limits */ -#define LIBSSH2_PACKET_MAXCOMP 32000 - -/* Maximum size to allow a payload to deccompress to, plays it safe by - allowing more than spec requires */ -#define LIBSSH2_PACKET_MAXDECOMP 40000 - -/* Maximum size for an inbound compressed payload, plays it safe by - overshooting spec limits */ -#define LIBSSH2_PACKET_MAXPAYLOAD 40000 - -/* Malloc callbacks */ -#define LIBSSH2_ALLOC_FUNC(name) void *name(size_t count, void **abstract) -#define LIBSSH2_REALLOC_FUNC(name) void *name(void *ptr, size_t count, \ - void **abstract) -#define LIBSSH2_FREE_FUNC(name) void name(void *ptr, void **abstract) - -typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT -{ - char* text; - unsigned int length; - unsigned char echo; -} LIBSSH2_USERAUTH_KBDINT_PROMPT; - -typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE -{ - char* text; - unsigned int length; -} LIBSSH2_USERAUTH_KBDINT_RESPONSE; - -/* 'publickey' authentication callback */ -#define LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC(name) \ - int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, \ - const unsigned char *data, size_t data_len, void **abstract) - -/* 'keyboard-interactive' authentication callback */ -#define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) \ - void name_(const char* name, int name_len, const char* instruction, \ - int instruction_len, int num_prompts, \ - const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, \ - LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, void **abstract) - -/* Callbacks for special SSH packets */ -#define LIBSSH2_IGNORE_FUNC(name) \ - void name(LIBSSH2_SESSION *session, const char *message, int message_len, \ - void **abstract) - -#define LIBSSH2_DEBUG_FUNC(name) \ - void name(LIBSSH2_SESSION *session, int always_display, const char *message, \ - int message_len, const char *language, int language_len, \ - void **abstract) - -#define LIBSSH2_DISCONNECT_FUNC(name) \ - void name(LIBSSH2_SESSION *session, int reason, const char *message, \ - int message_len, const char *language, int language_len, \ - void **abstract) - -#define LIBSSH2_PASSWD_CHANGEREQ_FUNC(name) \ - void name(LIBSSH2_SESSION *session, char **newpw, int *newpw_len, \ - void **abstract) - -#define LIBSSH2_MACERROR_FUNC(name) \ - int name(LIBSSH2_SESSION *session, const char *packet, int packet_len, \ - void **abstract) - -#define LIBSSH2_X11_OPEN_FUNC(name) \ - void name(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, \ - const char *shost, int sport, void **abstract) - -#define LIBSSH2_CHANNEL_CLOSE_FUNC(name) \ - void name(LIBSSH2_SESSION *session, void **session_abstract, \ - LIBSSH2_CHANNEL *channel, void **channel_abstract) - -/* I/O callbacks */ -#define LIBSSH2_RECV_FUNC(name) ssize_t name(libssh2_socket_t socket, \ - void *buffer, size_t length, \ - int flags, void **abstract) -#define LIBSSH2_SEND_FUNC(name) ssize_t name(libssh2_socket_t socket, \ - const void *buffer, size_t length,\ - int flags, void **abstract) - -/* libssh2_session_callback_set() constants */ -#define LIBSSH2_CALLBACK_IGNORE 0 -#define LIBSSH2_CALLBACK_DEBUG 1 -#define LIBSSH2_CALLBACK_DISCONNECT 2 -#define LIBSSH2_CALLBACK_MACERROR 3 -#define LIBSSH2_CALLBACK_X11 4 -#define LIBSSH2_CALLBACK_SEND 5 -#define LIBSSH2_CALLBACK_RECV 6 - -/* libssh2_session_method_pref() constants */ -#define LIBSSH2_METHOD_KEX 0 -#define LIBSSH2_METHOD_HOSTKEY 1 -#define LIBSSH2_METHOD_CRYPT_CS 2 -#define LIBSSH2_METHOD_CRYPT_SC 3 -#define LIBSSH2_METHOD_MAC_CS 4 -#define LIBSSH2_METHOD_MAC_SC 5 -#define LIBSSH2_METHOD_COMP_CS 6 -#define LIBSSH2_METHOD_COMP_SC 7 -#define LIBSSH2_METHOD_LANG_CS 8 -#define LIBSSH2_METHOD_LANG_SC 9 - -/* flags */ -#define LIBSSH2_FLAG_SIGPIPE 1 -#define LIBSSH2_FLAG_COMPRESS 2 - -typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; -typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL; -typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER; -typedef struct _LIBSSH2_KNOWNHOSTS LIBSSH2_KNOWNHOSTS; -typedef struct _LIBSSH2_AGENT LIBSSH2_AGENT; - -typedef struct _LIBSSH2_POLLFD { - unsigned char type; /* LIBSSH2_POLLFD_* below */ - - union { - int socket; /* File descriptors -- examined with system select() call */ - LIBSSH2_CHANNEL *channel; /* Examined by checking internal state */ - LIBSSH2_LISTENER *listener; /* Read polls only -- are inbound - connections waiting to be accepted? */ - } fd; - - unsigned long events; /* Requested Events */ - unsigned long revents; /* Returned Events */ -} LIBSSH2_POLLFD; - -/* Poll FD Descriptor Types */ -#define LIBSSH2_POLLFD_SOCKET 1 -#define LIBSSH2_POLLFD_CHANNEL 2 -#define LIBSSH2_POLLFD_LISTENER 3 - -/* Note: Win32 Doesn't actually have a poll() implementation, so some of these - values are faked with select() data */ -/* Poll FD events/revents -- Match sys/poll.h where possible */ -#define LIBSSH2_POLLFD_POLLIN 0x0001 /* Data available to be read or - connection available -- - All */ -#define LIBSSH2_POLLFD_POLLPRI 0x0002 /* Priority data available to - be read -- Socket only */ -#define LIBSSH2_POLLFD_POLLEXT 0x0002 /* Extended data available to - be read -- Channel only */ -#define LIBSSH2_POLLFD_POLLOUT 0x0004 /* Can may be written -- - Socket/Channel */ -/* revents only */ -#define LIBSSH2_POLLFD_POLLERR 0x0008 /* Error Condition -- Socket */ -#define LIBSSH2_POLLFD_POLLHUP 0x0010 /* HangUp/EOF -- Socket */ -#define LIBSSH2_POLLFD_SESSION_CLOSED 0x0010 /* Session Disconnect */ -#define LIBSSH2_POLLFD_POLLNVAL 0x0020 /* Invalid request -- Socket - Only */ -#define LIBSSH2_POLLFD_POLLEX 0x0040 /* Exception Condition -- - Socket/Win32 */ -#define LIBSSH2_POLLFD_CHANNEL_CLOSED 0x0080 /* Channel Disconnect */ -#define LIBSSH2_POLLFD_LISTENER_CLOSED 0x0080 /* Listener Disconnect */ - -#define HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION -/* Block Direction Types */ -#define LIBSSH2_SESSION_BLOCK_INBOUND 0x0001 -#define LIBSSH2_SESSION_BLOCK_OUTBOUND 0x0002 - -/* Hash Types */ -#define LIBSSH2_HOSTKEY_HASH_MD5 1 -#define LIBSSH2_HOSTKEY_HASH_SHA1 2 - -/* Hostkey Types */ -#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0 -#define LIBSSH2_HOSTKEY_TYPE_RSA 1 -#define LIBSSH2_HOSTKEY_TYPE_DSS 2 - -/* Disconnect Codes (defined by SSH protocol) */ -#define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 -#define SSH_DISCONNECT_PROTOCOL_ERROR 2 -#define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3 -#define SSH_DISCONNECT_RESERVED 4 -#define SSH_DISCONNECT_MAC_ERROR 5 -#define SSH_DISCONNECT_COMPRESSION_ERROR 6 -#define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7 -#define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 -#define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 -#define SSH_DISCONNECT_CONNECTION_LOST 10 -#define SSH_DISCONNECT_BY_APPLICATION 11 -#define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12 -#define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13 -#define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 -#define SSH_DISCONNECT_ILLEGAL_USER_NAME 15 - -/* Error Codes (defined by libssh2) */ -#define LIBSSH2_ERROR_NONE 0 - -/* The library once used -1 as a generic error return value on numerous places - through the code, which subsequently was converted to - LIBSSH2_ERROR_SOCKET_NONE uses over time. As this is a generic error code, - the goal is to never ever return this code but instead make sure that a - more accurate and descriptive error code is used. */ -#define LIBSSH2_ERROR_SOCKET_NONE -1 - -#define LIBSSH2_ERROR_BANNER_RECV -2 -#define LIBSSH2_ERROR_BANNER_SEND -3 -#define LIBSSH2_ERROR_INVALID_MAC -4 -#define LIBSSH2_ERROR_KEX_FAILURE -5 -#define LIBSSH2_ERROR_ALLOC -6 -#define LIBSSH2_ERROR_SOCKET_SEND -7 -#define LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE -8 -#define LIBSSH2_ERROR_TIMEOUT -9 -#define LIBSSH2_ERROR_HOSTKEY_INIT -10 -#define LIBSSH2_ERROR_HOSTKEY_SIGN -11 -#define LIBSSH2_ERROR_DECRYPT -12 -#define LIBSSH2_ERROR_SOCKET_DISCONNECT -13 -#define LIBSSH2_ERROR_PROTO -14 -#define LIBSSH2_ERROR_PASSWORD_EXPIRED -15 -#define LIBSSH2_ERROR_FILE -16 -#define LIBSSH2_ERROR_METHOD_NONE -17 -#define LIBSSH2_ERROR_AUTHENTICATION_FAILED -18 -#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED LIBSSH2_ERROR_AUTHENTICATION_FAILED -#define LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED -19 -#define LIBSSH2_ERROR_CHANNEL_OUTOFORDER -20 -#define LIBSSH2_ERROR_CHANNEL_FAILURE -21 -#define LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED -22 -#define LIBSSH2_ERROR_CHANNEL_UNKNOWN -23 -#define LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED -24 -#define LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED -25 -#define LIBSSH2_ERROR_CHANNEL_CLOSED -26 -#define LIBSSH2_ERROR_CHANNEL_EOF_SENT -27 -#define LIBSSH2_ERROR_SCP_PROTOCOL -28 -#define LIBSSH2_ERROR_ZLIB -29 -#define LIBSSH2_ERROR_SOCKET_TIMEOUT -30 -#define LIBSSH2_ERROR_SFTP_PROTOCOL -31 -#define LIBSSH2_ERROR_REQUEST_DENIED -32 -#define LIBSSH2_ERROR_METHOD_NOT_SUPPORTED -33 -#define LIBSSH2_ERROR_INVAL -34 -#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35 -#define LIBSSH2_ERROR_PUBLICKEY_PROTOCOL -36 -#define LIBSSH2_ERROR_EAGAIN -37 -#define LIBSSH2_ERROR_BUFFER_TOO_SMALL -38 -#define LIBSSH2_ERROR_BAD_USE -39 -#define LIBSSH2_ERROR_COMPRESS -40 -#define LIBSSH2_ERROR_OUT_OF_BOUNDARY -41 -#define LIBSSH2_ERROR_AGENT_PROTOCOL -42 -#define LIBSSH2_ERROR_SOCKET_RECV -43 -#define LIBSSH2_ERROR_ENCRYPT -44 -#define LIBSSH2_ERROR_BAD_SOCKET -45 - -/* this is a define to provide the old (<= 1.2.7) name */ -#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV - -/* Global API */ -#define LIBSSH2_INIT_NO_CRYPTO 0x0001 - -/* - * libssh2_init() - * - * Initialize the libssh2 functions. This typically initialize the - * crypto library. It uses a global state, and is not thread safe -- - * you must make sure this function is not called concurrently. - * - * Flags can be: - * 0: Normal initialize - * LIBSSH2_INIT_NO_CRYPTO: Do not initialize the crypto library (ie. - * OPENSSL_add_cipher_algoritms() for OpenSSL - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int libssh2_init(int flags); - -/* - * libssh2_exit() - * - * Exit the libssh2 functions and free's all memory used internal. - */ -LIBSSH2_API void libssh2_exit(void); - -/* - * libssh2_free() - * - * Deallocate memory allocated by earlier call to libssh2 functions. - */ -LIBSSH2_API void libssh2_free(LIBSSH2_SESSION *session, void *ptr); - -/* - * libssh2_session_supported_algs() - * - * Fills algs with a list of supported acryptographic algorithms. Returns a - * non-negative number (number of supported algorithms) on success or a - * negative number (an eror code) on failure. - * - * NOTE: on success, algs must be deallocated (by calling libssh2_free) when - * not needed anymore - */ -LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, - int method_type, - const char*** algs); - -/* Session API */ -LIBSSH2_API LIBSSH2_SESSION * -libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), - LIBSSH2_FREE_FUNC((*my_free)), - LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract); -#define libssh2_session_init() libssh2_session_init_ex(NULL, NULL, NULL, NULL) - -LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session); - -LIBSSH2_API void *libssh2_session_callback_set(LIBSSH2_SESSION *session, - int cbtype, void *callback); -LIBSSH2_API int libssh2_session_banner_set(LIBSSH2_SESSION *session, - const char *banner); -LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, - const char *banner); - -LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int sock); -LIBSSH2_API int libssh2_session_handshake(LIBSSH2_SESSION *session, - libssh2_socket_t sock); -LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, - int reason, - const char *description, - const char *lang); -#define libssh2_session_disconnect(session, description) \ - libssh2_session_disconnect_ex((session), SSH_DISCONNECT_BY_APPLICATION, \ - (description), "") - -LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session); - -LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, - int hash_type); - -LIBSSH2_API const char *libssh2_session_hostkey(LIBSSH2_SESSION *session, - size_t *len, int *type); - -LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, - int method_type, - const char *prefs); -LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, - int method_type); -LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, - char **errmsg, - int *errmsg_len, int want_buf); -LIBSSH2_API int libssh2_session_last_errno(LIBSSH2_SESSION *session); -LIBSSH2_API int libssh2_session_block_directions(LIBSSH2_SESSION *session); - -LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, - int value); -LIBSSH2_API const char *libssh2_session_banner_get(LIBSSH2_SESSION *session); - -/* Userauth API */ -LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len); -LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session); - -LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const char *password, - unsigned int password_len, - LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))); - -#define libssh2_userauth_password(session, username, password) \ - libssh2_userauth_password_ex((session), (username), strlen(username), \ - (password), strlen(password), NULL) - -LIBSSH2_API int -libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const char *publickey, - const char *privatekey, - const char *passphrase); - -#define libssh2_userauth_publickey_fromfile(session, username, publickey, \ - privatekey, passphrase) \ - libssh2_userauth_publickey_fromfile_ex((session), (username), \ - strlen(username), (publickey), \ - (privatekey), (passphrase)) - -LIBSSH2_API int -libssh2_userauth_publickey(LIBSSH2_SESSION *session, - const char *username, - const unsigned char *pubkeydata, - size_t pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void **abstract); - -LIBSSH2_API int -libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const char *publickey, - const char *privatekey, - const char *passphrase, - const char *hostname, - unsigned int hostname_len, - const char *local_username, - unsigned int local_username_len); - -#define libssh2_userauth_hostbased_fromfile(session, username, publickey, \ - privatekey, passphrase, hostname) \ - libssh2_userauth_hostbased_fromfile_ex((session), (username), \ - strlen(username), (publickey), \ - (privatekey), (passphrase), \ - (hostname), strlen(hostname), \ - (username), strlen(username)) - -/* - * response_callback is provided with filled by library prompts array, - * but client must allocate and fill individual responses. Responses - * array is already allocated. Responses data will be freed by libssh2 - * after callback return, but before subsequent callback invokation. - */ -LIBSSH2_API int -libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION* session, - const char *username, - unsigned int username_len, - LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback))); - -#define libssh2_userauth_keyboard_interactive(session, username, \ - response_callback) \ - libssh2_userauth_keyboard_interactive_ex((session), (username), \ - strlen(username), (response_callback)) - -LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, - long timeout); - -/* Channel API */ -#define LIBSSH2_CHANNEL_WINDOW_DEFAULT (256*1024) -#define LIBSSH2_CHANNEL_PACKET_DEFAULT 32768 -#define LIBSSH2_CHANNEL_MINADJUST 1024 - -/* Extended Data Handling */ -#define LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL 0 -#define LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE 1 -#define LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE 2 - -#define SSH_EXTENDED_DATA_STDERR 1 - -/* Returned by any function that would block during a read/write opperation */ -#define LIBSSH2CHANNEL_EAGAIN LIBSSH2_ERROR_EAGAIN - -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *channel_type, - unsigned int channel_type_len, - unsigned int window_size, unsigned int packet_size, - const char *message, unsigned int message_len); - -#define libssh2_channel_open_session(session) \ - libssh2_channel_open_ex((session), "session", sizeof("session") - 1, \ - LIBSSH2_CHANNEL_WINDOW_DEFAULT, \ - LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0) - -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host, - int port, const char *shost, int sport); -#define libssh2_channel_direct_tcpip(session, host, port) \ - libssh2_channel_direct_tcpip_ex((session), (host), (port), "127.0.0.1", 22) - -LIBSSH2_API LIBSSH2_LISTENER * -libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host, - int port, int *bound_port, int queue_maxsize); -#define libssh2_channel_forward_listen(session, port) \ - libssh2_channel_forward_listen_ex((session), NULL, (port), NULL, 16) - -LIBSSH2_API int libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener); - -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener); - -LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, - const char *varname, - unsigned int varname_len, - const char *value, - unsigned int value_len); - -#define libssh2_channel_setenv(channel, varname, value) \ - libssh2_channel_setenv_ex((channel), (varname), strlen(varname), (value), \ - strlen(value)) - -LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, - const char *term, - unsigned int term_len, - const char *modes, - unsigned int modes_len, - int width, int height, - int width_px, int height_px); -#define libssh2_channel_request_pty(channel, term) \ - libssh2_channel_request_pty_ex((channel), (term), strlen(term), NULL, 0, \ - LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, \ - LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX) - -LIBSSH2_API int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, - int width, int height, - int width_px, - int height_px); -#define libssh2_channel_request_pty_size(channel, width, height) \ - libssh2_channel_request_pty_size_ex( (channel), (width), (height), 0, 0) - -LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, - int single_connection, - const char *auth_proto, - const char *auth_cookie, - int screen_number); -#define libssh2_channel_x11_req(channel, screen_number) \ - libssh2_channel_x11_req_ex((channel), 0, NULL, NULL, (screen_number)) - -LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, - const char *request, - unsigned int request_len, - const char *message, - unsigned int message_len); -#define libssh2_channel_shell(channel) \ - libssh2_channel_process_startup((channel), "shell", sizeof("shell") - 1, \ - NULL, 0) -#define libssh2_channel_exec(channel, command) \ - libssh2_channel_process_startup((channel), "exec", sizeof("exec") - 1, \ - (command), strlen(command)) -#define libssh2_channel_subsystem(channel, subsystem) \ - libssh2_channel_process_startup((channel), "subsystem", \ - sizeof("subsystem") - 1, (subsystem), \ - strlen(subsystem)) - -LIBSSH2_API ssize_t libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, - int stream_id, char *buf, - size_t buflen); -#define libssh2_channel_read(channel, buf, buflen) \ - libssh2_channel_read_ex((channel), 0, (buf), (buflen)) -#define libssh2_channel_read_stderr(channel, buf, buflen) \ - libssh2_channel_read_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen)) - -LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, - int extended); - -LIBSSH2_API unsigned long -libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, - unsigned long *read_avail, - unsigned long *window_size_initial); -#define libssh2_channel_window_read(channel) \ - libssh2_channel_window_read_ex((channel), NULL, NULL) - -/* libssh2_channel_receive_window_adjust is DEPRECATED, do not use! */ -LIBSSH2_API unsigned long -libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, - unsigned long adjustment, - unsigned char force); - -LIBSSH2_API int -libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel, - unsigned long adjustment, - unsigned char force, - unsigned int *storewindow); - -LIBSSH2_API ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, - int stream_id, const char *buf, - size_t buflen); - -#define libssh2_channel_write(channel, buf, buflen) \ - libssh2_channel_write_ex((channel), 0, (buf), (buflen)) -#define libssh2_channel_write_stderr(channel, buf, buflen) \ - libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen)) - -LIBSSH2_API unsigned long -libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, - unsigned long *window_size_initial); -#define libssh2_channel_window_write(channel) \ - libssh2_channel_window_write_ex((channel), NULL) - -LIBSSH2_API void libssh2_session_set_blocking(LIBSSH2_SESSION* session, - int blocking); -LIBSSH2_API int libssh2_session_get_blocking(LIBSSH2_SESSION* session); - -LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, - int blocking); - -LIBSSH2_API void libssh2_session_set_timeout(LIBSSH2_SESSION* session, - long timeout); -LIBSSH2_API long libssh2_session_get_timeout(LIBSSH2_SESSION* session); - -/* libssh2_channel_handle_extended_data is DEPRECATED, do not use! */ -LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, - int ignore_mode); -LIBSSH2_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, - int ignore_mode); - -/* libssh2_channel_ignore_extended_data() is defined below for BC with version - * 0.1 - * - * Future uses should use libssh2_channel_handle_extended_data() directly if - * LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE is passed, extended data will be read - * (FIFO) from the standard data channel - */ -/* DEPRECATED */ -#define libssh2_channel_ignore_extended_data(channel, ignore) \ - libssh2_channel_handle_extended_data((channel), \ - (ignore) ? \ - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : \ - LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL ) - -#define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA -1 -#define LIBSSH2_CHANNEL_FLUSH_ALL -2 -LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, - int streamid); -#define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0) -#define libssh2_channel_flush_stderr(channel) \ - libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR) - -LIBSSH2_API int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL* channel); -LIBSSH2_API int libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL* channel, - char **exitsignal, - size_t *exitsignal_len, - char **errmsg, - size_t *errmsg_len, - char **langtag, - size_t *langtag_len); -LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel); -LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel); -LIBSSH2_API int libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel); -LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel); -LIBSSH2_API int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel); -LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel); - -LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, - const char *path, - struct stat *sb); -LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, - const char *path, int mode, - size_t size, long mtime, - long atime); -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode, - libssh2_int64_t size, time_t mtime, time_t atime); - -#define libssh2_scp_send(session, path, mode, size) \ - libssh2_scp_send_ex((session), (path), (mode), (size), 0, 0) - -LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest, - unsigned int *dest_len, - const char *src, unsigned int src_len); - -LIBSSH2_API -const char *libssh2_version(int req_version_num); - -#define HAVE_LIBSSH2_KNOWNHOST_API 0x010101 /* since 1.1.1 */ -#define HAVE_LIBSSH2_VERSION_API 0x010100 /* libssh2_version since 1.1 */ - -struct libssh2_knownhost { - unsigned int magic; /* magic stored by the library */ - void *node; /* handle to the internal representation of this host */ - char *name; /* this is NULL if no plain text host name exists */ - char *key; /* key in base64/printable format */ - int typemask; -}; - -/* - * libssh2_knownhost_init - * - * Init a collection of known hosts. Returns the pointer to a collection. - * - */ -LIBSSH2_API LIBSSH2_KNOWNHOSTS * -libssh2_knownhost_init(LIBSSH2_SESSION *session); - -/* - * libssh2_knownhost_add - * - * Add a host and its associated key to the collection of known hosts. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -/* host format (2 bits) */ -#define LIBSSH2_KNOWNHOST_TYPE_MASK 0xffff -#define LIBSSH2_KNOWNHOST_TYPE_PLAIN 1 -#define LIBSSH2_KNOWNHOST_TYPE_SHA1 2 /* always base64 encoded */ -#define LIBSSH2_KNOWNHOST_TYPE_CUSTOM 3 - -/* key format (2 bits) */ -#define LIBSSH2_KNOWNHOST_KEYENC_MASK (3<<16) -#define LIBSSH2_KNOWNHOST_KEYENC_RAW (1<<16) -#define LIBSSH2_KNOWNHOST_KEYENC_BASE64 (2<<16) - -/* type of key (2 bits) */ -#define LIBSSH2_KNOWNHOST_KEY_MASK (3<<18) -#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18 -#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18) -#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18) -#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) - -LIBSSH2_API int -libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, - const char *salt, - const char *key, size_t keylen, int typemask, - struct libssh2_knownhost **store); - -/* - * libssh2_knownhost_addc - * - * Add a host and its associated key to the collection of known hosts. - * - * Takes a comment argument that may be NULL. A NULL comment indicates - * there is no comment and the entry will end directly after the key - * when written out to a file. An empty string "" comment will indicate an - * empty comment which will cause a single space to be written after the key. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -LIBSSH2_API int -libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, - const char *salt, - const char *key, size_t keylen, - const char *comment, size_t commentlen, int typemask, - struct libssh2_knownhost **store); - -/* - * libssh2_knownhost_check - * - * Check a host and its associated key against the collection of known hosts. - * - * The type is the type/format of the given host name. - * - * plain - ascii "hostname.domain.tld" - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * - * 'knownhost' may be set to NULL if you don't care about that info. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_* values, see below - * - */ - -#define LIBSSH2_KNOWNHOST_CHECK_MATCH 0 -#define LIBSSH2_KNOWNHOST_CHECK_MISMATCH 1 -#define LIBSSH2_KNOWNHOST_CHECK_NOTFOUND 2 -#define LIBSSH2_KNOWNHOST_CHECK_FAILURE 3 - -LIBSSH2_API int -libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **knownhost); - -/* this function is identital to the above one, but also takes a port - argument that allows libssh2 to do a better check */ -LIBSSH2_API int -libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, int port, - const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **knownhost); - -/* - * libssh2_knownhost_del - * - * Remove a host from the collection of known hosts. The 'entry' struct is - * retrieved by a call to libssh2_knownhost_check(). - * - */ -LIBSSH2_API int -libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *entry); - -/* - * libssh2_knownhost_free - * - * Free an entire collection of known hosts. - * - */ -LIBSSH2_API void -libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts); - -/* - * libssh2_knownhost_readline() - * - * Pass in a line of a file of 'type'. It makes libssh2 read this line. - * - * LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type. - * - */ -LIBSSH2_API int -libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts, - const char *line, size_t len, int type); - -/* - * libssh2_knownhost_readfile - * - * Add hosts+key pairs from a given file. - * - * Returns a negative value for error or number of successfully added hosts. - * - * This implementation currently only knows one 'type' (openssh), all others - * are reserved for future use. - */ - -#define LIBSSH2_KNOWNHOST_FILE_OPENSSH 1 - -LIBSSH2_API int -libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type); - -/* - * libssh2_knownhost_writeline() - * - * Ask libssh2 to convert a known host to an output line for storage. - * - * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given - * output buffer is too small to hold the desired output. - * - * This implementation currently only knows one 'type' (openssh), all others - * are reserved for future use. - * - */ -LIBSSH2_API int -libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *known, - char *buffer, size_t buflen, - size_t *outlen, /* the amount of written data */ - int type); - -/* - * libssh2_knownhost_writefile - * - * Write hosts+key pairs to a given file. - * - * This implementation currently only knows one 'type' (openssh), all others - * are reserved for future use. - */ - -LIBSSH2_API int -libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type); - -/* - * libssh2_knownhost_get() - * - * Traverse the internal list of known hosts. Pass NULL to 'prev' to get - * the first one. Or pass a poiner to the previously returned one to get the - * next. - * - * Returns: - * 0 if a fine host was stored in 'store' - * 1 if end of hosts - * [negative] on errors - */ -LIBSSH2_API int -libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost **store, - struct libssh2_knownhost *prev); - -#define HAVE_LIBSSH2_AGENT_API 0x010202 /* since 1.2.2 */ - -struct libssh2_agent_publickey { - unsigned int magic; /* magic stored by the library */ - void *node; /* handle to the internal representation of key */ - unsigned char *blob; /* public key blob */ - size_t blob_len; /* length of the public key blob */ - char *comment; /* comment in printable format */ -}; - -/* - * libssh2_agent_init - * - * Init an ssh-agent handle. Returns the pointer to the handle. - * - */ -LIBSSH2_API LIBSSH2_AGENT * -libssh2_agent_init(LIBSSH2_SESSION *session); - -/* - * libssh2_agent_connect() - * - * Connect to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_connect(LIBSSH2_AGENT *agent); - -/* - * libssh2_agent_list_identities() - * - * Request an ssh-agent to list identities. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_list_identities(LIBSSH2_AGENT *agent); - -/* - * libssh2_agent_get_identity() - * - * Traverse the internal list of public keys. Pass NULL to 'prev' to get - * the first one. Or pass a poiner to the previously returned one to get the - * next. - * - * Returns: - * 0 if a fine public key was stored in 'store' - * 1 if end of public keys - * [negative] on errors - */ -LIBSSH2_API int -libssh2_agent_get_identity(LIBSSH2_AGENT *agent, - struct libssh2_agent_publickey **store, - struct libssh2_agent_publickey *prev); - -/* - * libssh2_agent_userauth() - * - * Do publickey user authentication with the help of ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_userauth(LIBSSH2_AGENT *agent, - const char *username, - struct libssh2_agent_publickey *identity); - -/* - * libssh2_agent_disconnect() - * - * Close a connection to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_disconnect(LIBSSH2_AGENT *agent); - -/* - * libssh2_agent_free() - * - * Free an ssh-agent handle. This function also frees the internal - * collection of public keys. - */ -LIBSSH2_API void -libssh2_agent_free(LIBSSH2_AGENT *agent); - - -/* - * libssh2_keepalive_config() - * - * Set how often keepalive messages should be sent. WANT_REPLY - * indicates whether the keepalive messages should request a response - * from the server. INTERVAL is number of seconds that can pass - * without any I/O, use 0 (the default) to disable keepalives. To - * avoid some busy-loop corner-cases, if you specify an interval of 1 - * it will be treated as 2. - * - * Note that non-blocking applications are responsible for sending the - * keepalive messages using libssh2_keepalive_send(). - */ -LIBSSH2_API void libssh2_keepalive_config (LIBSSH2_SESSION *session, - int want_reply, - unsigned interval); - -/* - * libssh2_keepalive_send() - * - * Send a keepalive message if needed. SECONDS_TO_NEXT indicates how - * many seconds you can sleep after this call before you need to call - * it again. Returns 0 on success, or LIBSSH2_ERROR_SOCKET_SEND on - * I/O errors. - */ -LIBSSH2_API int libssh2_keepalive_send (LIBSSH2_SESSION *session, - int *seconds_to_next); - -/* NOTE NOTE NOTE - libssh2_trace() has no function in builds that aren't built with debug - enabled - */ -LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask); -#define LIBSSH2_TRACE_TRANS (1<<1) -#define LIBSSH2_TRACE_KEX (1<<2) -#define LIBSSH2_TRACE_AUTH (1<<3) -#define LIBSSH2_TRACE_CONN (1<<4) -#define LIBSSH2_TRACE_SCP (1<<5) -#define LIBSSH2_TRACE_SFTP (1<<6) -#define LIBSSH2_TRACE_ERROR (1<<7) -#define LIBSSH2_TRACE_PUBLICKEY (1<<8) -#define LIBSSH2_TRACE_SOCKET (1<<9) - -typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*, - void*, - const char *, - size_t); -LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session, - void* context, - libssh2_trace_handler_func callback); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* !RC_INVOKED */ - -#endif /* LIBSSH2_H */ diff --git a/vendor/libssh2-1.4.2/include/libssh2_publickey.h b/vendor/libssh2-1.4.2/include/libssh2_publickey.h deleted file mode 100644 index 7350e9f..0000000 --- a/vendor/libssh2-1.4.2/include/libssh2_publickey.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2004-2006, Sara Golemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - */ - -/* Note: This include file is only needed for using the - * publickey SUBSYSTEM which is not the same as publickey - * authentication. For authentication you only need libssh2.h - * - * For more information on the publickey subsystem, - * refer to IETF draft: secsh-publickey - */ - -#ifndef LIBSSH2_PUBLICKEY_H -#define LIBSSH2_PUBLICKEY_H 1 - -#include "libssh2.h" - -typedef struct _LIBSSH2_PUBLICKEY LIBSSH2_PUBLICKEY; - -typedef struct _libssh2_publickey_attribute { - const char *name; - unsigned long name_len; - const char *value; - unsigned long value_len; - char mandatory; -} libssh2_publickey_attribute; - -typedef struct _libssh2_publickey_list { - unsigned char *packet; /* For freeing */ - - const unsigned char *name; - unsigned long name_len; - const unsigned char *blob; - unsigned long blob_len; - unsigned long num_attrs; - libssh2_publickey_attribute *attrs; /* free me */ -} libssh2_publickey_list; - -/* Generally use the first macro here, but if both name and value are string literals, you can use _fast() to take advantage of preprocessing */ -#define libssh2_publickey_attribute(name, value, mandatory) \ - { (name), strlen(name), (value), strlen(value), (mandatory) }, -#define libssh2_publickey_attribute_fast(name, value, mandatory) \ - { (name), sizeof(name) - 1, (value), sizeof(value) - 1, (mandatory) }, - -#ifdef __cplusplus -extern "C" { -#endif - -/* Publickey Subsystem */ -LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session); - -LIBSSH2_API int libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, - const unsigned char *name, - unsigned long name_len, - const unsigned char *blob, - unsigned long blob_len, char overwrite, - unsigned long num_attrs, - const libssh2_publickey_attribute attrs[]); -#define libssh2_publickey_add(pkey, name, blob, blob_len, overwrite, \ - num_attrs, attrs) \ - libssh2_publickey_add_ex((pkey), (name), strlen(name), (blob), (blob_len), \ - (overwrite), (num_attrs), (attrs)) - -LIBSSH2_API int libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey, - const unsigned char *name, - unsigned long name_len, - const unsigned char *blob, - unsigned long blob_len); -#define libssh2_publickey_remove(pkey, name, blob, blob_len) \ - libssh2_publickey_remove_ex((pkey), (name), strlen(name), (blob), (blob_len)) - -LIBSSH2_API int -libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, - unsigned long *num_keys, - libssh2_publickey_list **pkey_list); -LIBSSH2_API void libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey, - libssh2_publickey_list *pkey_list); - -LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* ifndef: LIBSSH2_PUBLICKEY_H */ diff --git a/vendor/libssh2-1.4.2/include/libssh2_sftp.h b/vendor/libssh2-1.4.2/include/libssh2_sftp.h deleted file mode 100644 index 74884fb..0000000 --- a/vendor/libssh2-1.4.2/include/libssh2_sftp.h +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright (c) 2004-2008, Sara Golemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 LIBSSH2_SFTP_H -#define LIBSSH2_SFTP_H 1 - -#include "libssh2.h" - -#ifndef WIN32 -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Note: Version 6 was documented at the time of writing - * However it was marked as "DO NOT IMPLEMENT" due to pending changes - * - * Let's start with Version 3 (The version found in OpenSSH) and go from there - */ -#define LIBSSH2_SFTP_VERSION 3 - -typedef struct _LIBSSH2_SFTP LIBSSH2_SFTP; -typedef struct _LIBSSH2_SFTP_HANDLE LIBSSH2_SFTP_HANDLE; -typedef struct _LIBSSH2_SFTP_ATTRIBUTES LIBSSH2_SFTP_ATTRIBUTES; -typedef struct _LIBSSH2_SFTP_STATVFS LIBSSH2_SFTP_STATVFS; - -/* Flags for open_ex() */ -#define LIBSSH2_SFTP_OPENFILE 0 -#define LIBSSH2_SFTP_OPENDIR 1 - -/* Flags for rename_ex() */ -#define LIBSSH2_SFTP_RENAME_OVERWRITE 0x00000001 -#define LIBSSH2_SFTP_RENAME_ATOMIC 0x00000002 -#define LIBSSH2_SFTP_RENAME_NATIVE 0x00000004 - -/* Flags for stat_ex() */ -#define LIBSSH2_SFTP_STAT 0 -#define LIBSSH2_SFTP_LSTAT 1 -#define LIBSSH2_SFTP_SETSTAT 2 - -/* Flags for symlink_ex() */ -#define LIBSSH2_SFTP_SYMLINK 0 -#define LIBSSH2_SFTP_READLINK 1 -#define LIBSSH2_SFTP_REALPATH 2 - -/* SFTP attribute flag bits */ -#define LIBSSH2_SFTP_ATTR_SIZE 0x00000001 -#define LIBSSH2_SFTP_ATTR_UIDGID 0x00000002 -#define LIBSSH2_SFTP_ATTR_PERMISSIONS 0x00000004 -#define LIBSSH2_SFTP_ATTR_ACMODTIME 0x00000008 -#define LIBSSH2_SFTP_ATTR_EXTENDED 0x80000000 - -/* SFTP statvfs flag bits */ -#define LIBSSH2_SFTP_ST_RDONLY 0x00000001 -#define LIBSSH2_SFTP_ST_NOSUID 0x00000002 - -struct _LIBSSH2_SFTP_ATTRIBUTES { - /* If flags & ATTR_* bit is set, then the value in this struct will be - * meaningful Otherwise it should be ignored - */ - unsigned long flags; - - libssh2_uint64_t filesize; - unsigned long uid, gid; - unsigned long permissions; - unsigned long atime, mtime; -}; - -struct _LIBSSH2_SFTP_STATVFS { - libssh2_uint64_t f_bsize; /* file system block size */ - libssh2_uint64_t f_frsize; /* fragment size */ - libssh2_uint64_t f_blocks; /* size of fs in f_frsize units */ - libssh2_uint64_t f_bfree; /* # free blocks */ - libssh2_uint64_t f_bavail; /* # free blocks for non-root */ - libssh2_uint64_t f_files; /* # inodes */ - libssh2_uint64_t f_ffree; /* # free inodes */ - libssh2_uint64_t f_favail; /* # free inodes for non-root */ - libssh2_uint64_t f_fsid; /* file system ID */ - libssh2_uint64_t f_flag; /* mount flags */ - libssh2_uint64_t f_namemax; /* maximum filename length */ -}; - -/* SFTP filetypes */ -#define LIBSSH2_SFTP_TYPE_REGULAR 1 -#define LIBSSH2_SFTP_TYPE_DIRECTORY 2 -#define LIBSSH2_SFTP_TYPE_SYMLINK 3 -#define LIBSSH2_SFTP_TYPE_SPECIAL 4 -#define LIBSSH2_SFTP_TYPE_UNKNOWN 5 -#define LIBSSH2_SFTP_TYPE_SOCKET 6 -#define LIBSSH2_SFTP_TYPE_CHAR_DEVICE 7 -#define LIBSSH2_SFTP_TYPE_BLOCK_DEVICE 8 -#define LIBSSH2_SFTP_TYPE_FIFO 9 - -/* - * Reproduce the POSIX file modes here for systems that are not POSIX - * compliant. - * - * These is used in "permissions" of "struct _LIBSSH2_SFTP_ATTRIBUTES" - */ -/* File type */ -#define LIBSSH2_SFTP_S_IFMT 0170000 /* type of file mask */ -#define LIBSSH2_SFTP_S_IFIFO 0010000 /* named pipe (fifo) */ -#define LIBSSH2_SFTP_S_IFCHR 0020000 /* character special */ -#define LIBSSH2_SFTP_S_IFDIR 0040000 /* directory */ -#define LIBSSH2_SFTP_S_IFBLK 0060000 /* block special */ -#define LIBSSH2_SFTP_S_IFREG 0100000 /* regular */ -#define LIBSSH2_SFTP_S_IFLNK 0120000 /* symbolic link */ -#define LIBSSH2_SFTP_S_IFSOCK 0140000 /* socket */ - -/* File mode */ -/* Read, write, execute/search by owner */ -#define LIBSSH2_SFTP_S_IRWXU 0000700 /* RWX mask for owner */ -#define LIBSSH2_SFTP_S_IRUSR 0000400 /* R for owner */ -#define LIBSSH2_SFTP_S_IWUSR 0000200 /* W for owner */ -#define LIBSSH2_SFTP_S_IXUSR 0000100 /* X for owner */ -/* Read, write, execute/search by group */ -#define LIBSSH2_SFTP_S_IRWXG 0000070 /* RWX mask for group */ -#define LIBSSH2_SFTP_S_IRGRP 0000040 /* R for group */ -#define LIBSSH2_SFTP_S_IWGRP 0000020 /* W for group */ -#define LIBSSH2_SFTP_S_IXGRP 0000010 /* X for group */ -/* Read, write, execute/search by others */ -#define LIBSSH2_SFTP_S_IRWXO 0000007 /* RWX mask for other */ -#define LIBSSH2_SFTP_S_IROTH 0000004 /* R for other */ -#define LIBSSH2_SFTP_S_IWOTH 0000002 /* W for other */ -#define LIBSSH2_SFTP_S_IXOTH 0000001 /* X for other */ - -/* macros to check for specific file types, added in 1.2.5 */ -#define LIBSSH2_SFTP_S_ISLNK(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK) -#define LIBSSH2_SFTP_S_ISREG(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFREG) -#define LIBSSH2_SFTP_S_ISDIR(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFDIR) -#define LIBSSH2_SFTP_S_ISCHR(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFCHR) -#define LIBSSH2_SFTP_S_ISBLK(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFBLK) -#define LIBSSH2_SFTP_S_ISFIFO(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFIFO) -#define LIBSSH2_SFTP_S_ISSOCK(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFSOCK) - -/* SFTP File Transfer Flags -- (e.g. flags parameter to sftp_open()) - * Danger will robinson... APPEND doesn't have any effect on OpenSSH servers */ -#define LIBSSH2_FXF_READ 0x00000001 -#define LIBSSH2_FXF_WRITE 0x00000002 -#define LIBSSH2_FXF_APPEND 0x00000004 -#define LIBSSH2_FXF_CREAT 0x00000008 -#define LIBSSH2_FXF_TRUNC 0x00000010 -#define LIBSSH2_FXF_EXCL 0x00000020 - -/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */ -#define LIBSSH2_FX_OK 0 -#define LIBSSH2_FX_EOF 1 -#define LIBSSH2_FX_NO_SUCH_FILE 2 -#define LIBSSH2_FX_PERMISSION_DENIED 3 -#define LIBSSH2_FX_FAILURE 4 -#define LIBSSH2_FX_BAD_MESSAGE 5 -#define LIBSSH2_FX_NO_CONNECTION 6 -#define LIBSSH2_FX_CONNECTION_LOST 7 -#define LIBSSH2_FX_OP_UNSUPPORTED 8 -#define LIBSSH2_FX_INVALID_HANDLE 9 -#define LIBSSH2_FX_NO_SUCH_PATH 10 -#define LIBSSH2_FX_FILE_ALREADY_EXISTS 11 -#define LIBSSH2_FX_WRITE_PROTECT 12 -#define LIBSSH2_FX_NO_MEDIA 13 -#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM 14 -#define LIBSSH2_FX_QUOTA_EXCEEDED 15 -#define LIBSSH2_FX_UNKNOWN_PRINCIPLE 16 /* Initial mis-spelling */ -#define LIBSSH2_FX_UNKNOWN_PRINCIPAL 16 -#define LIBSSH2_FX_LOCK_CONFlICT 17 /* Initial mis-spelling */ -#define LIBSSH2_FX_LOCK_CONFLICT 17 -#define LIBSSH2_FX_DIR_NOT_EMPTY 18 -#define LIBSSH2_FX_NOT_A_DIRECTORY 19 -#define LIBSSH2_FX_INVALID_FILENAME 20 -#define LIBSSH2_FX_LINK_LOOP 21 - -/* Returned by any function that would block during a read/write opperation */ -#define LIBSSH2SFTP_EAGAIN LIBSSH2_ERROR_EAGAIN - -/* SFTP API */ -LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session); -LIBSSH2_API int libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp); -LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp); -LIBSSH2_API LIBSSH2_CHANNEL *libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp); - -/* File / Directory Ops */ -LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, - const char *filename, - unsigned int filename_len, - unsigned long flags, - long mode, int open_type); -#define libssh2_sftp_open(sftp, filename, flags, mode) \ - libssh2_sftp_open_ex((sftp), (filename), strlen(filename), (flags), \ - (mode), LIBSSH2_SFTP_OPENFILE) -#define libssh2_sftp_opendir(sftp, path) \ - libssh2_sftp_open_ex((sftp), (path), strlen(path), 0, 0, \ - LIBSSH2_SFTP_OPENDIR) - -LIBSSH2_API ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, - char *buffer, size_t buffer_maxlen); - -LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, \ - char *buffer, size_t buffer_maxlen, - char *longentry, - size_t longentry_maxlen, - LIBSSH2_SFTP_ATTRIBUTES *attrs); -#define libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs) \ - libssh2_sftp_readdir_ex((handle), (buffer), (buffer_maxlen), NULL, 0, \ - (attrs)) - -LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, - const char *buffer, size_t count); - -LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle); -#define libssh2_sftp_close(handle) libssh2_sftp_close_handle(handle) -#define libssh2_sftp_closedir(handle) libssh2_sftp_close_handle(handle) - -LIBSSH2_API void libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset); -LIBSSH2_API void libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, - libssh2_uint64_t offset); -#define libssh2_sftp_rewind(handle) libssh2_sftp_seek64((handle), 0) - -LIBSSH2_API size_t libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle); -LIBSSH2_API libssh2_uint64_t libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle); - -LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle, - LIBSSH2_SFTP_ATTRIBUTES *attrs, - int setstat); -#define libssh2_sftp_fstat(handle, attrs) \ - libssh2_sftp_fstat_ex((handle), (attrs), 0) -#define libssh2_sftp_fsetstat(handle, attrs) \ - libssh2_sftp_fstat_ex((handle), (attrs), 1) - -/* Miscellaneous Ops */ -LIBSSH2_API int libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, - const char *source_filename, - unsigned int srouce_filename_len, - const char *dest_filename, - unsigned int dest_filename_len, - long flags); -#define libssh2_sftp_rename(sftp, sourcefile, destfile) \ - libssh2_sftp_rename_ex((sftp), (sourcefile), strlen(sourcefile), \ - (destfile), strlen(destfile), \ - LIBSSH2_SFTP_RENAME_OVERWRITE | \ - LIBSSH2_SFTP_RENAME_ATOMIC | \ - LIBSSH2_SFTP_RENAME_NATIVE) - -LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, - const char *filename, - unsigned int filename_len); -#define libssh2_sftp_unlink(sftp, filename) \ - libssh2_sftp_unlink_ex((sftp), (filename), strlen(filename)) - -LIBSSH2_API int libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, - LIBSSH2_SFTP_STATVFS *st); - -LIBSSH2_API int libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, - const char *path, - size_t path_len, - LIBSSH2_SFTP_STATVFS *st); - -LIBSSH2_API int libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, - const char *path, - unsigned int path_len, long mode); -#define libssh2_sftp_mkdir(sftp, path, mode) \ - libssh2_sftp_mkdir_ex((sftp), (path), strlen(path), (mode)) - -LIBSSH2_API int libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, - const char *path, - unsigned int path_len); -#define libssh2_sftp_rmdir(sftp, path) \ - libssh2_sftp_rmdir_ex((sftp), (path), strlen(path)) - -LIBSSH2_API int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, - const char *path, - unsigned int path_len, - int stat_type, - LIBSSH2_SFTP_ATTRIBUTES *attrs); -#define libssh2_sftp_stat(sftp, path, attrs) \ - libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_STAT, \ - (attrs)) -#define libssh2_sftp_lstat(sftp, path, attrs) \ - libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_LSTAT, \ - (attrs)) -#define libssh2_sftp_setstat(sftp, path, attrs) \ - libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_SETSTAT, \ - (attrs)) - -LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, - const char *path, - unsigned int path_len, - char *target, - unsigned int target_len, int link_type); -#define libssh2_sftp_symlink(sftp, orig, linkpath) \ - libssh2_sftp_symlink_ex((sftp), (orig), strlen(orig), (linkpath), \ - strlen(linkpath), LIBSSH2_SFTP_SYMLINK) -#define libssh2_sftp_readlink(sftp, path, target, maxlen) \ - libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \ - LIBSSH2_SFTP_READLINK) -#define libssh2_sftp_realpath(sftp, path, target, maxlen) \ - libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \ - LIBSSH2_SFTP_REALPATH) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LIBSSH2_SFTP_H */ diff --git a/vendor/libssh2-1.4.2/src/agent.c b/vendor/libssh2-1.4.2/src/agent.c deleted file mode 100644 index 1c65149..0000000 --- a/vendor/libssh2-1.4.2/src/agent.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * Copyright (c) 2009 by Daiki Ueno - * Copyright (C) 2010 by Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include "misc.h" -#include -#ifdef HAVE_SYS_UN_H -#include -#else -/* Use the existence of sys/un.h as a test if Unix domain socket is - supported. winsock*.h define PF_UNIX/AF_UNIX but do not actually - support them. */ -#undef PF_UNIX -#endif -#include "userauth.h" -#include "session.h" - -/* Requests from client to agent for protocol 1 key operations */ -#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 -#define SSH_AGENTC_RSA_CHALLENGE 3 -#define SSH_AGENTC_ADD_RSA_IDENTITY 7 -#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 -#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 -#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 - -/* Requests from client to agent for protocol 2 key operations */ -#define SSH2_AGENTC_REQUEST_IDENTITIES 11 -#define SSH2_AGENTC_SIGN_REQUEST 13 -#define SSH2_AGENTC_ADD_IDENTITY 17 -#define SSH2_AGENTC_REMOVE_IDENTITY 18 -#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 -#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 - -/* Key-type independent requests from client to agent */ -#define SSH_AGENTC_ADD_SMARTCARD_KEY 20 -#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 -#define SSH_AGENTC_LOCK 22 -#define SSH_AGENTC_UNLOCK 23 -#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 - -/* Generic replies from agent to client */ -#define SSH_AGENT_FAILURE 5 -#define SSH_AGENT_SUCCESS 6 - -/* Replies from agent to client for protocol 1 key operations */ -#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 -#define SSH_AGENT_RSA_RESPONSE 4 - -/* Replies from agent to client for protocol 2 key operations */ -#define SSH2_AGENT_IDENTITIES_ANSWER 12 -#define SSH2_AGENT_SIGN_RESPONSE 14 - -/* Key constraint identifiers */ -#define SSH_AGENT_CONSTRAIN_LIFETIME 1 -#define SSH_AGENT_CONSTRAIN_CONFIRM 2 - -/* non-blocking mode on agent connection is not yet implemented, but - for future use. */ -typedef enum { - agent_NB_state_init = 0, - agent_NB_state_request_created, - agent_NB_state_request_length_sent, - agent_NB_state_request_sent, - agent_NB_state_response_length_received, - agent_NB_state_response_received -} agent_nonblocking_states; - -typedef struct agent_transaction_ctx { - unsigned char *request; - size_t request_len; - unsigned char *response; - size_t response_len; - agent_nonblocking_states state; -} *agent_transaction_ctx_t; - -typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent); -typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent, - agent_transaction_ctx_t transctx); -typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent); - -struct agent_publickey { - struct list_node node; - - /* this is the struct we expose externally */ - struct libssh2_agent_publickey external; -}; - -struct agent_ops { - agent_connect_func connect; - agent_transact_func transact; - agent_disconnect_func disconnect; -}; - -struct _LIBSSH2_AGENT -{ - LIBSSH2_SESSION *session; /* the session this "belongs to" */ - - libssh2_socket_t fd; - - struct agent_ops *ops; - - struct agent_transaction_ctx transctx; - struct agent_publickey *identity; - struct list_head head; /* list of public keys */ -}; - -#ifdef PF_UNIX -static int -agent_connect_unix(LIBSSH2_AGENT *agent) -{ - const char *path; - struct sockaddr_un s_un; - - path = getenv("SSH_AUTH_SOCK"); - if (!path) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "no auth sock variable"); - - agent->fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (agent->fd < 0) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET, - "failed creating socket"); - - s_un.sun_family = AF_UNIX; - strncpy (s_un.sun_path, path, sizeof s_un.sun_path); - if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) { - close (agent->fd); - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "failed connecting with agent"); - } - - return LIBSSH2_ERROR_NONE; -} - -static int -agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) -{ - unsigned char buf[4]; - int rc; - - /* Send the length of the request */ - if (transctx->state == agent_NB_state_request_created) { - _libssh2_htonu32(buf, transctx->request_len); - rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, - "agent send failed"); - transctx->state = agent_NB_state_request_length_sent; - } - - /* Send the request body */ - if (transctx->state == agent_NB_state_request_length_sent) { - rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request, - transctx->request_len, 0); - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, - "agent send failed"); - transctx->state = agent_NB_state_request_sent; - } - - /* Receive the length of a response */ - if (transctx->state == agent_NB_state_request_sent) { - rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc < 0) { - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV, - "agent recv failed"); - } - transctx->response_len = _libssh2_ntohu32(buf); - transctx->response = LIBSSH2_ALLOC(agent->session, - transctx->response_len); - if (!transctx->response) - return LIBSSH2_ERROR_ALLOC; - - transctx->state = agent_NB_state_response_length_received; - } - - /* Receive the response body */ - if (transctx->state == agent_NB_state_response_length_received) { - rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response, - transctx->response_len, 0); - if (rc < 0) { - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, - "agent recv failed"); - } - transctx->state = agent_NB_state_response_received; - } - - return 0; -} - -static int -agent_disconnect_unix(LIBSSH2_AGENT *agent) -{ - int ret; - ret = close(agent->fd); - - if(ret == -1) - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT, - "failed closing the agent socket"); - return LIBSSH2_ERROR_NONE; -} - -struct agent_ops agent_ops_unix = { - agent_connect_unix, - agent_transact_unix, - agent_disconnect_unix -}; -#endif /* PF_UNIX */ - -#ifdef WIN32 -/* Code to talk to Pageant was taken from PuTTY. - * - * Portions copyright Robert de Bath, Joris van Rantwijk, Delian - * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas - * Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, - * Markus Kuhn, Colin Watson, and CORE SDI S.A. - */ -#define PAGEANT_COPYDATA_ID 0x804e50ba /* random goop */ -#define PAGEANT_MAX_MSGLEN 8192 - -static int -agent_connect_pageant(LIBSSH2_AGENT *agent) -{ - HWND hwnd; - hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "failed connecting agent"); - agent->fd = 0; /* Mark as the connection has been established */ - return LIBSSH2_ERROR_NONE; -} - -static int -agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) -{ - HWND hwnd; - char mapname[23]; - HANDLE filemap; - unsigned char *p; - unsigned char *p2; - int id; - COPYDATASTRUCT cds; - - if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) - return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL, - "illegal input"); - - hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "found no pageant"); - - sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId()); - filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, PAGEANT_MAX_MSGLEN, mapname); - - if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "failed setting up pageant filemap"); - - p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); - _libssh2_store_str(&p2, (const char *)transctx->request, - transctx->request_len); - - cds.dwData = PAGEANT_COPYDATA_ID; - cds.cbData = 1 + strlen(mapname); - cds.lpData = mapname; - - id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds); - if (id > 0) { - transctx->response_len = _libssh2_ntohu32(p); - if (transctx->response_len > PAGEANT_MAX_MSGLEN) { - UnmapViewOfFile(p); - CloseHandle(filemap); - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "agent setup fail"); - } - transctx->response = LIBSSH2_ALLOC(agent->session, - transctx->response_len); - if (!transctx->response) { - UnmapViewOfFile(p); - CloseHandle(filemap); - return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC, - "agent malloc"); - } - memcpy(transctx->response, p + 4, transctx->response_len); - } - - UnmapViewOfFile(p); - CloseHandle(filemap); - return 0; -} - -static int -agent_disconnect_pageant(LIBSSH2_AGENT *agent) -{ - agent->fd = LIBSSH2_INVALID_SOCKET; - return 0; -} - -struct agent_ops agent_ops_pageant = { - agent_connect_pageant, - agent_transact_pageant, - agent_disconnect_pageant -}; -#endif /* WIN32 */ - -static struct { - const char *name; - struct agent_ops *ops; -} supported_backends[] = { -#ifdef WIN32 - {"Pageant", &agent_ops_pageant}, -#endif /* WIN32 */ -#ifdef PF_UNIX - {"Unix", &agent_ops_unix}, -#endif /* PF_UNIX */ - {NULL, NULL} -}; - -static int -agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, - const unsigned char *data, size_t data_len, void **abstract) -{ - LIBSSH2_AGENT *agent = (LIBSSH2_AGENT *) (*abstract); - agent_transaction_ctx_t transctx = &agent->transctx; - struct agent_publickey *identity = agent->identity; - ssize_t len = 1 + 4 + identity->external.blob_len + 4 + data_len + 4; - ssize_t method_len; - unsigned char *s; - int rc; - - /* Create a request to sign the data */ - if (transctx->state == agent_NB_state_init) { - s = transctx->request = LIBSSH2_ALLOC(session, len); - if (!transctx->request) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "out of memory"); - - *s++ = SSH2_AGENTC_SIGN_REQUEST; - /* key blob */ - _libssh2_store_str(&s, (const char *)identity->external.blob, - identity->external.blob_len); - /* data */ - _libssh2_store_str(&s, (const char *)data, data_len); - - /* flags */ - _libssh2_store_u32(&s, 0); - - transctx->request_len = s - transctx->request; - transctx->state = agent_NB_state_request_created; - } - - /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST) - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "illegal request"); - - if (!agent->ops) - /* if no agent has been connected, bail out */ - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "agent not connected"); - - rc = agent->ops->transact(agent, transctx); - if (rc) { - goto error; - } - LIBSSH2_FREE(session, transctx->request); - transctx->request = NULL; - - len = transctx->response_len; - s = transctx->response; - len--; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - if (*s != SSH2_AGENT_SIGN_RESPONSE) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s++; - - /* Skip the entire length of the signature */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s += 4; - - /* Skip signing method */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - method_len = _libssh2_ntohu32(s); - s += 4; - len -= method_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s += method_len; - - /* Read the signature */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - *sig_len = _libssh2_ntohu32(s); - s += 4; - len -= *sig_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - - *sig = LIBSSH2_ALLOC(session, *sig_len); - if (!*sig) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - memcpy(*sig, s, *sig_len); - - error: - LIBSSH2_FREE(session, transctx->request); - transctx->request = NULL; - - LIBSSH2_FREE(session, transctx->response); - transctx->response = NULL; - - return _libssh2_error(session, rc, "agent sign failure"); -} - -static int -agent_list_identities(LIBSSH2_AGENT *agent) -{ - agent_transaction_ctx_t transctx = &agent->transctx; - ssize_t len, num_identities; - unsigned char *s; - int rc; - unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES; - - /* Create a request to list identities */ - if (transctx->state == agent_NB_state_init) { - transctx->request = &c; - transctx->request_len = 1; - transctx->state = agent_NB_state_request_created; - } - - /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "illegal agent request"); - - if (!agent->ops) - /* if no agent has been connected, bail out */ - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "agent not connected"); - - rc = agent->ops->transact(agent, transctx); - if (rc) { - goto error; - } - transctx->request = NULL; - - len = transctx->response_len; - s = transctx->response; - len--; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - if (*s != SSH2_AGENT_IDENTITIES_ANSWER) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s++; - - /* Read the length of identities */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - num_identities = _libssh2_ntohu32(s); - s += 4; - - while (num_identities--) { - struct agent_publickey *identity; - ssize_t comment_len; - - identity = LIBSSH2_ALLOC(agent->session, sizeof *identity); - if (!identity) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - - /* Read the length of the blob */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - identity->external.blob_len = _libssh2_ntohu32(s); - s += 4; - - /* Read the blob */ - len -= identity->external.blob_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - identity->external.blob = LIBSSH2_ALLOC(agent->session, - identity->external.blob_len); - if (!identity->external.blob) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - memcpy(identity->external.blob, s, identity->external.blob_len); - s += identity->external.blob_len; - - /* Read the length of the comment */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - comment_len = _libssh2_ntohu32(s); - s += 4; - - /* Read the comment */ - len -= comment_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - identity->external.comment = LIBSSH2_ALLOC(agent->session, - comment_len + 1); - if (!identity->external.comment) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - identity->external.comment[comment_len] = '\0'; - memcpy(identity->external.comment, s, comment_len); - s += comment_len; - - _libssh2_list_add(&agent->head, &identity->node); - } - error: - LIBSSH2_FREE(agent->session, transctx->response); - transctx->response = NULL; - - return _libssh2_error(agent->session, rc, - "agent list id failed"); -} - -static void -agent_free_identities(LIBSSH2_AGENT *agent) { - struct agent_publickey *node; - struct agent_publickey *next; - - for (node = _libssh2_list_first(&agent->head); node; node = next) { - next = _libssh2_list_next(&node->node); - LIBSSH2_FREE(agent->session, node->external.blob); - LIBSSH2_FREE(agent->session, node->external.comment); - LIBSSH2_FREE(agent->session, node); - } - _libssh2_list_init(&agent->head); -} - -#define AGENT_PUBLICKEY_MAGIC 0x3bdefed2 -/* - * agent_publickey_to_external() - * - * Copies data from the internal to the external representation struct. - * - */ -static struct libssh2_agent_publickey * -agent_publickey_to_external(struct agent_publickey *node) -{ - struct libssh2_agent_publickey *ext = &node->external; - - ext->magic = AGENT_PUBLICKEY_MAGIC; - ext->node = node; - - return ext; -} - -/* - * libssh2_agent_init - * - * Init an ssh-agent handle. Returns the pointer to the handle. - * - */ -LIBSSH2_API LIBSSH2_AGENT * -libssh2_agent_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_AGENT *agent; - - agent = LIBSSH2_ALLOC(session, sizeof *agent); - if (!agent) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate space for agent connection"); - return NULL; - } - memset(agent, 0, sizeof *agent); - agent->session = session; - _libssh2_list_init(&agent->head); - - return agent; -} - -/* - * libssh2_agent_connect() - * - * Connect to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_connect(LIBSSH2_AGENT *agent) -{ - int i, rc = -1; - for (i = 0; supported_backends[i].name; i++) { - agent->ops = supported_backends[i].ops; - rc = agent->ops->connect(agent); - if (!rc) - return 0; - } - return rc; -} - -/* - * libssh2_agent_list_identities() - * - * Request ssh-agent to list identities. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_list_identities(LIBSSH2_AGENT *agent) -{ - memset(&agent->transctx, 0, sizeof agent->transctx); - /* Abondon the last fetched identities */ - agent_free_identities(agent); - return agent_list_identities(agent); -} - -/* - * libssh2_agent_get_identity() - * - * Traverse the internal list of public keys. Pass NULL to 'prev' to get - * the first one. Or pass a poiner to the previously returned one to get the - * next. - * - * Returns: - * 0 if a fine public key was stored in 'store' - * 1 if end of public keys - * [negative] on errors - */ -LIBSSH2_API int -libssh2_agent_get_identity(LIBSSH2_AGENT *agent, - struct libssh2_agent_publickey **ext, - struct libssh2_agent_publickey *oprev) -{ - struct agent_publickey *node; - if (oprev && oprev->node) { - /* we have a starting point */ - struct agent_publickey *prev = oprev->node; - - /* get the next node in the list */ - node = _libssh2_list_next(&prev->node); - } - else - node = _libssh2_list_first(&agent->head); - - if (!node) - /* no (more) node */ - return 1; - - *ext = agent_publickey_to_external(node); - - return 0; -} - -/* - * libssh2_agent_userauth() - * - * Do publickey user authentication with the help of ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_userauth(LIBSSH2_AGENT *agent, - const char *username, - struct libssh2_agent_publickey *identity) -{ - void *abstract = agent; - int rc; - - if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) { - memset(&agent->transctx, 0, sizeof agent->transctx); - agent->identity = identity->node; - } - - BLOCK_ADJUST(rc, agent->session, - _libssh2_userauth_publickey(agent->session, username, - strlen(username), - identity->blob, - identity->blob_len, - agent_sign, - &abstract)); - return rc; -} - -/* - * libssh2_agent_disconnect() - * - * Close a connection to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_disconnect(LIBSSH2_AGENT *agent) -{ - if (agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET) - return agent->ops->disconnect(agent); - return 0; -} - -/* - * libssh2_agent_free() - * - * Free an ssh-agent handle. This function also frees the internal - * collection of public keys. - */ -LIBSSH2_API void -libssh2_agent_free(LIBSSH2_AGENT *agent) { - /* Allow connection freeing when the socket has lost its connection */ - if (agent->fd != LIBSSH2_INVALID_SOCKET) { - libssh2_agent_disconnect(agent); - } - agent_free_identities(agent); - LIBSSH2_FREE(agent->session, agent); -} diff --git a/vendor/libssh2-1.4.2/src/channel.c b/vendor/libssh2-1.4.2/src/channel.c deleted file mode 100644 index 63e5d5b..0000000 --- a/vendor/libssh2-1.4.2/src/channel.c +++ /dev/null @@ -1,2570 +0,0 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2008-2011 by Daniel Stenberg - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#ifdef HAVE_INTTYPES_H -#include -#endif -#include - -#include "channel.h" -#include "transport.h" -#include "packet.h" -#include "session.h" - -/* - * _libssh2_channel_nextid - * - * Determine the next channel ID we can use at our end - */ -uint32_t -_libssh2_channel_nextid(LIBSSH2_SESSION * session) -{ - uint32_t id = session->next_channel; - LIBSSH2_CHANNEL *channel; - - channel = _libssh2_list_first(&session->channels); - - while (channel) { - if (channel->local.id > id) { - id = channel->local.id; - } - channel = _libssh2_list_next(&channel->node); - } - - /* This is a shortcut to avoid waiting for close packets on channels we've - * forgotten about, This *could* be a problem if we request and close 4 - * billion or so channels in too rapid succession for the remote end to - * respond, but the worst case scenario is that some data meant for - * another channel Gets picked up by the new one.... Pretty unlikely all - * told... - */ - session->next_channel = id + 1; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Allocated new channel ID#%lu", - id); - return id; -} - -/* - * _libssh2_channel_locate - * - * Locate a channel pointer by number - */ -LIBSSH2_CHANNEL * -_libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id) -{ - LIBSSH2_CHANNEL *channel; - LIBSSH2_LISTENER *l; - - for(channel = _libssh2_list_first(&session->channels); - channel; - channel = _libssh2_list_next(&channel->node)) { - if (channel->local.id == channel_id) - return channel; - } - - /* We didn't find the channel in the session, let's then check its - listeners since each listener may have its own set of pending channels - */ - for(l = _libssh2_list_first(&session->listeners); l; - l = _libssh2_list_next(&l->node)) { - for(channel = _libssh2_list_first(&l->queue); - channel; - channel = _libssh2_list_next(&channel->node)) { - if (channel->local.id == channel_id) - return channel; - } - } - - return NULL; -} - -/* - * _libssh2_channel_open - * - * Establish a generic session channel - */ -LIBSSH2_CHANNEL * -_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, - uint32_t channel_type_len, - uint32_t window_size, - uint32_t packet_size, - const unsigned char *message, - size_t message_len) -{ - static const unsigned char reply_codes[3] = { - SSH_MSG_CHANNEL_OPEN_CONFIRMATION, - SSH_MSG_CHANNEL_OPEN_FAILURE, - 0 - }; - unsigned char *s; - int rc; - - if (session->open_state == libssh2_NB_state_idle) { - session->open_channel = NULL; - session->open_packet = NULL; - session->open_data = NULL; - /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) + - * window_size(4) + packet_size(4) */ - session->open_packet_len = channel_type_len + 17; - session->open_local_channel = _libssh2_channel_nextid(session); - - /* Zero the whole thing out */ - memset(&session->open_packet_requirev_state, 0, - sizeof(session->open_packet_requirev_state)); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Opening Channel - win %d pack %d", window_size, - packet_size); - session->open_channel = - LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL)); - if (!session->open_channel) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate space for channel data"); - return NULL; - } - memset(session->open_channel, 0, sizeof(LIBSSH2_CHANNEL)); - - session->open_channel->channel_type_len = channel_type_len; - session->open_channel->channel_type = - LIBSSH2_ALLOC(session, channel_type_len); - if (!session->open_channel->channel_type) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Failed allocating memory for channel type name"); - LIBSSH2_FREE(session, session->open_channel); - session->open_channel = NULL; - return NULL; - } - memcpy(session->open_channel->channel_type, channel_type, - channel_type_len); - - /* REMEMBER: local as in locally sourced */ - session->open_channel->local.id = session->open_local_channel; - session->open_channel->remote.window_size = window_size; - session->open_channel->remote.window_size_initial = window_size; - session->open_channel->remote.packet_size = packet_size; - session->open_channel->session = session; - - _libssh2_list_add(&session->channels, - &session->open_channel->node); - - s = session->open_packet = - LIBSSH2_ALLOC(session, session->open_packet_len); - if (!session->open_packet) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate temporary space for packet"); - goto channel_error; - } - *(s++) = SSH_MSG_CHANNEL_OPEN; - _libssh2_store_str(&s, channel_type, channel_type_len); - _libssh2_store_u32(&s, session->open_local_channel); - _libssh2_store_u32(&s, window_size); - _libssh2_store_u32(&s, packet_size); - - /* Do not copy the message */ - - session->open_state = libssh2_NB_state_created; - } - - if (session->open_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - session->open_packet, - session->open_packet_len, - message, message_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending channel-open request"); - return NULL; - } - else if (rc) { - _libssh2_error(session, rc, - "Unable to send channel-open request"); - goto channel_error; - } - - session->open_state = libssh2_NB_state_sent; - } - - if (session->open_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, - &session->open_data, - &session->open_data_len, 1, - session->open_packet + 5 + - channel_type_len, 4, - &session->open_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - return NULL; - } else if (rc) { - goto channel_error; - } - - if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { - session->open_channel->remote.id = - _libssh2_ntohu32(session->open_data + 5); - session->open_channel->local.window_size = - _libssh2_ntohu32(session->open_data + 9); - session->open_channel->local.window_size_initial = - _libssh2_ntohu32(session->open_data + 9); - session->open_channel->local.packet_size = - _libssh2_ntohu32(session->open_data + 13); - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Connection Established - ID: %lu/%lu win: %lu/%lu" - " pack: %lu/%lu", - session->open_channel->local.id, - session->open_channel->remote.id, - session->open_channel->local.window_size, - session->open_channel->remote.window_size, - session->open_channel->local.packet_size, - session->open_channel->remote.packet_size); - LIBSSH2_FREE(session, session->open_packet); - session->open_packet = NULL; - LIBSSH2_FREE(session, session->open_data); - session->open_data = NULL; - - session->open_state = libssh2_NB_state_idle; - return session->open_channel; - } - - if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Channel open failure"); - } - } - - channel_error: - - if (session->open_data) { - LIBSSH2_FREE(session, session->open_data); - session->open_data = NULL; - } - if (session->open_packet) { - LIBSSH2_FREE(session, session->open_packet); - session->open_packet = NULL; - } - if (session->open_channel) { - unsigned char channel_id[4]; - LIBSSH2_FREE(session, session->open_channel->channel_type); - - _libssh2_list_remove(&session->open_channel->node); - - /* Clear out packets meant for this channel */ - _libssh2_htonu32(channel_id, session->open_channel->local.id); - while ((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, - &session->open_data, - &session->open_data_len, 1, - channel_id, 4) >= 0) - || - (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, - &session->open_data, - &session->open_data_len, 1, - channel_id, 4) >= 0)) { - LIBSSH2_FREE(session, session->open_data); - session->open_data = NULL; - } - - LIBSSH2_FREE(session, session->open_channel); - session->open_channel = NULL; - } - - session->open_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_channel_open_ex - * - * Establish a generic session channel - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type, - unsigned int type_len, - unsigned int window_size, unsigned int packet_size, - const char *msg, unsigned int msg_len) -{ - LIBSSH2_CHANNEL *ptr; - - if(!session) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, session, - _libssh2_channel_open(session, type, type_len, - window_size, packet_size, - (unsigned char *)msg, - msg_len)); - return ptr; -} - -/* - * libssh2_channel_direct_tcpip_ex - * - * Tunnel TCP/IP connect through the SSH session to direct host/port - */ -static LIBSSH2_CHANNEL * -channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host, - int port, const char *shost, int sport) -{ - LIBSSH2_CHANNEL *channel; - unsigned char *s; - - if (session->direct_state == libssh2_NB_state_idle) { - session->direct_host_len = strlen(host); - session->direct_shost_len = strlen(shost); - /* host_len(4) + port(4) + shost_len(4) + sport(4) */ - session->direct_message_len = - session->direct_host_len + session->direct_shost_len + 16; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Requesting direct-tcpip session to from %s:%d to %s:%d", - shost, sport, host, port); - - s = session->direct_message = - LIBSSH2_ALLOC(session, session->direct_message_len); - if (!session->direct_message) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for direct-tcpip connection"); - return NULL; - } - _libssh2_store_str(&s, host, session->direct_host_len); - _libssh2_store_u32(&s, port); - _libssh2_store_str(&s, shost, session->direct_shost_len); - _libssh2_store_u32(&s, sport); - } - - channel = - _libssh2_channel_open(session, "direct-tcpip", - sizeof("direct-tcpip") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, - session->direct_message, - session->direct_message_len); - - if (!channel && - libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { - /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state - to created to avoid re-creating the package on next invoke */ - session->direct_state = libssh2_NB_state_created; - return NULL; - } - /* by default we set (keep?) idle state... */ - session->direct_state = libssh2_NB_state_idle; - - LIBSSH2_FREE(session, session->direct_message); - session->direct_message = NULL; - - return channel; -} - -/* - * libssh2_channel_direct_tcpip_ex - * - * Tunnel TCP/IP connect through the SSH session to direct host/port - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host, - int port, const char *shost, int sport) -{ - LIBSSH2_CHANNEL *ptr; - - if(!session) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, session, - channel_direct_tcpip(session, host, port, shost, sport)); - return ptr; -} - -/* - * channel_forward_listen - * - * Bind a port on the remote host and listen for connections - */ -static LIBSSH2_LISTENER * -channel_forward_listen(LIBSSH2_SESSION * session, const char *host, - int port, int *bound_port, int queue_maxsize) -{ - unsigned char *s; - static const unsigned char reply_codes[3] = - { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 }; - int rc; - - if(!host) - host = "0.0.0.0"; - - if (session->fwdLstn_state == libssh2_NB_state_idle) { - session->fwdLstn_host_len = strlen(host); - /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) - + port(4) */ - session->fwdLstn_packet_len = - session->fwdLstn_host_len + (sizeof("tcpip-forward") - 1) + 14; - - /* Zero the whole thing out */ - memset(&session->fwdLstn_packet_requirev_state, 0, - sizeof(session->fwdLstn_packet_requirev_state)); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Requesting tcpip-forward session for %s:%d", host, - port); - - s = session->fwdLstn_packet = - LIBSSH2_ALLOC(session, session->fwdLstn_packet_len); - if (!session->fwdLstn_packet) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memeory for setenv packet"); - return NULL; - } - - *(s++) = SSH_MSG_GLOBAL_REQUEST; - _libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1); - *(s++) = 0x01; /* want_reply */ - - _libssh2_store_str(&s, host, session->fwdLstn_host_len); - _libssh2_store_u32(&s, port); - - session->fwdLstn_state = libssh2_NB_state_created; - } - - if (session->fwdLstn_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - session->fwdLstn_packet, - session->fwdLstn_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending global-request packet for " - "forward listen request"); - return NULL; - } - else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send global-request packet for forward " - "listen request"); - LIBSSH2_FREE(session, session->fwdLstn_packet); - session->fwdLstn_packet = NULL; - session->fwdLstn_state = libssh2_NB_state_idle; - return NULL; - } - LIBSSH2_FREE(session, session->fwdLstn_packet); - session->fwdLstn_packet = NULL; - - session->fwdLstn_state = libssh2_NB_state_sent; - } - - if (session->fwdLstn_state == libssh2_NB_state_sent) { - unsigned char *data; - size_t data_len; - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 0, NULL, 0, - &session->fwdLstn_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - return NULL; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown"); - session->fwdLstn_state = libssh2_NB_state_idle; - return NULL; - } - - if (data[0] == SSH_MSG_REQUEST_SUCCESS) { - LIBSSH2_LISTENER *listener; - - listener = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_LISTENER)); - if (!listener) - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for listener queue"); - else { - memset(listener, 0, sizeof(LIBSSH2_LISTENER)); - listener->host = - LIBSSH2_ALLOC(session, session->fwdLstn_host_len + 1); - if (!listener->host) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for listener queue"); - LIBSSH2_FREE(session, listener); - listener = NULL; - } - else { - listener->session = session; - memcpy(listener->host, host ? host : "0.0.0.0", - session->fwdLstn_host_len); - listener->host[session->fwdLstn_host_len] = 0; - if (data_len >= 5 && !port) { - listener->port = _libssh2_ntohu32(data + 1); - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Dynamic tcpip-forward port allocated: %d", - listener->port); - } - else - listener->port = port; - - listener->queue_size = 0; - listener->queue_maxsize = queue_maxsize; - - /* append this to the parent's list of listeners */ - _libssh2_list_add(&session->listeners, &listener->node); - - if (bound_port) { - *bound_port = listener->port; - } - } - } - - LIBSSH2_FREE(session, data); - session->fwdLstn_state = libssh2_NB_state_idle; - return listener; - } - else if (data[0] == SSH_MSG_REQUEST_FAILURE) { - LIBSSH2_FREE(session, data); - _libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED, - "Unable to complete request for forward-listen"); - session->fwdLstn_state = libssh2_NB_state_idle; - return NULL; - } - } - - session->fwdLstn_state = libssh2_NB_state_idle; - - return NULL; -} - -/* - * libssh2_channel_forward_listen_ex - * - * Bind a port on the remote host and listen for connections - */ -LIBSSH2_API LIBSSH2_LISTENER * -libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host, - int port, int *bound_port, int queue_maxsize) -{ - LIBSSH2_LISTENER *ptr; - - if(!session) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, session, - channel_forward_listen(session, host, port, bound_port, - queue_maxsize)); - return ptr; -} - -/* - * _libssh2_channel_forward_cancel - * - * Stop listening on a remote port and free the listener - * Toss out any pending (un-accept()ed) connections - * - * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error - */ -int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) -{ - LIBSSH2_SESSION *session = listener->session; - LIBSSH2_CHANNEL *queued; - unsigned char *packet, *s; - size_t host_len = strlen(listener->host); - /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + - port(4) */ - size_t packet_len = - host_len + 14 + sizeof("cancel-tcpip-forward") - 1; - int rc; - - if (listener->chanFwdCncl_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Cancelling tcpip-forward session for %s:%d", - listener->host, listener->port); - - s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memeory for setenv packet"); - return LIBSSH2_ERROR_ALLOC; - } - - *(s++) = SSH_MSG_GLOBAL_REQUEST; - _libssh2_store_str(&s, "cancel-tcpip-forward", - sizeof("cancel-tcpip-forward") - 1); - *(s++) = 0x00; /* want_reply */ - - _libssh2_store_str(&s, listener->host, host_len); - _libssh2_store_u32(&s, listener->port); - - listener->chanFwdCncl_state = libssh2_NB_state_created; - } else { - packet = listener->chanFwdCncl_data; - } - - if (listener->chanFwdCncl_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending forward request"); - listener->chanFwdCncl_data = packet; - return rc; - } - else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send global-request packet for forward " - "listen request"); - LIBSSH2_FREE(session, packet); - listener->chanFwdCncl_state = libssh2_NB_state_idle; - return LIBSSH2_ERROR_SOCKET_SEND; - } - LIBSSH2_FREE(session, packet); - - listener->chanFwdCncl_state = libssh2_NB_state_sent; - } - - queued = _libssh2_list_first(&listener->queue); - while (queued) { - LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node); - - rc = _libssh2_channel_free(queued); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - queued = next; - } - LIBSSH2_FREE(session, listener->host); - - /* remove this entry from the parent's list of listeners */ - _libssh2_list_remove(&listener->node); - - LIBSSH2_FREE(session, listener); - - listener->chanFwdCncl_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * libssh2_channel_forward_cancel - * - * Stop listening on a remote port and free the listener - * Toss out any pending (un-accept()ed) connections - * - * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error - */ -LIBSSH2_API int -libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) -{ - int rc; - - if(!listener) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, listener->session, - _libssh2_channel_forward_cancel(listener)); - return rc; -} - -/* - * channel_forward_accept - * - * Accept a connection - */ -static LIBSSH2_CHANNEL * -channel_forward_accept(LIBSSH2_LISTENER *listener) -{ - int rc; - - do { - rc = _libssh2_transport_read(listener->session); - } while (rc > 0); - - if (_libssh2_list_first(&listener->queue)) { - LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue); - - /* detach channel from listener's queue */ - _libssh2_list_remove(&channel->node); - - listener->queue_size--; - - /* add channel to session's channel list */ - _libssh2_list_add(&channel->session->channels, &channel->node); - - return channel; - } - - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for packet"); - } - else - _libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, - "Channel not found"); - return NULL; -} - -/* - * libssh2_channel_forward_accept - * - * Accept a connection - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener) -{ - LIBSSH2_CHANNEL *ptr; - - if(!listener) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, listener->session, - channel_forward_accept(listener)); - return ptr; - -} - -/* - * channel_setenv - * - * Set an environment variable prior to requesting a shell/program/subsystem - */ -static int channel_setenv(LIBSSH2_CHANNEL *channel, - const char *varname, unsigned int varname_len, - const char *value, unsigned int value_len) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char *s, *data; - static const unsigned char reply_codes[3] = - { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; - size_t data_len; - int rc; - - if (channel->setenv_state == libssh2_NB_state_idle) { - /* 21 = packet_type(1) + channel_id(4) + request_len(4) + - * request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */ - channel->setenv_packet_len = varname_len + value_len + 21; - - /* Zero the whole thing out */ - memset(&channel->setenv_packet_requirev_state, 0, - sizeof(channel->setenv_packet_requirev_state)); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Setting remote environment variable: %s=%s on " - "channel %lu/%lu", - varname, value, channel->local.id, channel->remote.id); - - s = channel->setenv_packet = - LIBSSH2_ALLOC(session, channel->setenv_packet_len); - if (!channel->setenv_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memeory " - "for setenv packet"); - } - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, "env", sizeof("env") - 1); - *(s++) = 0x01; - _libssh2_store_str(&s, varname, varname_len); - _libssh2_store_str(&s, value, value_len); - - channel->setenv_state = libssh2_NB_state_created; - } - - if (channel->setenv_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - channel->setenv_packet, - channel->setenv_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending setenv request"); - return rc; - } else if (rc) { - LIBSSH2_FREE(session, channel->setenv_packet); - channel->setenv_packet = NULL; - channel->setenv_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send channel-request packet for " - "setenv request"); - } - LIBSSH2_FREE(session, channel->setenv_packet); - channel->setenv_packet = NULL; - - _libssh2_htonu32(channel->setenv_local_channel, channel->local.id); - - channel->setenv_state = libssh2_NB_state_sent; - } - - if (channel->setenv_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 1, channel->setenv_local_channel, 4, - &channel-> - setenv_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - if (rc) { - channel->setenv_state = libssh2_NB_state_idle; - return rc; - } - - if (data[0] == SSH_MSG_CHANNEL_SUCCESS) { - LIBSSH2_FREE(session, data); - channel->setenv_state = libssh2_NB_state_idle; - return 0; - } - - LIBSSH2_FREE(session, data); - } - - channel->setenv_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for channel-setenv"); -} - -/* - * libssh2_channel_setenv_ex - * - * Set an environment variable prior to requesting a shell/program/subsystem - */ -LIBSSH2_API int -libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, - const char *varname, unsigned int varname_len, - const char *value, unsigned int value_len) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_setenv(channel, varname, varname_len, - value, value_len)); - return rc; -} - -/* - * channel_request_pty - * Duh... Request a PTY - */ -static int channel_request_pty(LIBSSH2_CHANNEL *channel, - const char *term, unsigned int term_len, - const char *modes, unsigned int modes_len, - int width, int height, - int width_px, int height_px) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char *s; - static const unsigned char reply_codes[3] = - { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; - int rc; - - if (channel->reqPTY_state == libssh2_NB_state_idle) { - /* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) + - * want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) + - * height_px(4) + modes_len(4) */ - if(term_len + modes_len > 256) { - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "term + mode lengths too large"); - } - - channel->reqPTY_packet_len = term_len + modes_len + 41; - - /* Zero the whole thing out */ - memset(&channel->reqPTY_packet_requirev_state, 0, - sizeof(channel->reqPTY_packet_requirev_state)); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Allocating tty on channel %lu/%lu", channel->local.id, - channel->remote.id); - - s = channel->reqPTY_packet; - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, (char *)"pty-req", sizeof("pty-req") - 1); - - *(s++) = 0x01; - - _libssh2_store_str(&s, term, term_len); - _libssh2_store_u32(&s, width); - _libssh2_store_u32(&s, height); - _libssh2_store_u32(&s, width_px); - _libssh2_store_u32(&s, height_px); - _libssh2_store_str(&s, modes, modes_len); - - channel->reqPTY_state = libssh2_NB_state_created; - } - - if (channel->reqPTY_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, channel->reqPTY_packet, - channel->reqPTY_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending pty request"); - return rc; - } else if (rc) { - channel->reqPTY_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send pty-request packet"); - } - _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id); - - channel->reqPTY_state = libssh2_NB_state_sent; - } - - if (channel->reqPTY_state == libssh2_NB_state_sent) { - unsigned char *data; - size_t data_len; - unsigned char code; - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 1, channel->reqPTY_local_channel, 4, - &channel->reqPTY_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - channel->reqPTY_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PROTO, - "Failed to require the PTY package"); - } - - code = data[0]; - - LIBSSH2_FREE(session, data); - channel->reqPTY_state = libssh2_NB_state_idle; - - if (code == SSH_MSG_CHANNEL_SUCCESS) - return 0; - } - - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for channel request-pty"); -} - -/* - * libssh2_channel_request_pty_ex - * Duh... Request a PTY - */ -LIBSSH2_API int -libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term, - unsigned int term_len, const char *modes, - unsigned int modes_len, int width, int height, - int width_px, int height_px) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_request_pty(channel, term, term_len, modes, - modes_len, width, height, - width_px, height_px)); - return rc; -} - -static int -channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, - int height, int width_px, int height_px) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char *s; - int rc; - int retcode = LIBSSH2_ERROR_PROTO; - - if (channel->reqPTY_state == libssh2_NB_state_idle) { - channel->reqPTY_packet_len = 39; - - /* Zero the whole thing out */ - memset(&channel->reqPTY_packet_requirev_state, 0, - sizeof(channel->reqPTY_packet_requirev_state)); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "changing tty size on channel %lu/%lu", - channel->local.id, - channel->remote.id); - - s = channel->reqPTY_packet; - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, (char *)"window-change", - sizeof("window-change") - 1); - *(s++) = 0x00; /* Don't reply */ - _libssh2_store_u32(&s, width); - _libssh2_store_u32(&s, height); - _libssh2_store_u32(&s, width_px); - _libssh2_store_u32(&s, height_px); - - channel->reqPTY_state = libssh2_NB_state_created; - } - - if (channel->reqPTY_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, channel->reqPTY_packet, - channel->reqPTY_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending window-change request"); - return rc; - } else if (rc) { - channel->reqPTY_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send window-change packet"); - } - _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id); - retcode = LIBSSH2_ERROR_NONE; - } - - channel->reqPTY_state = libssh2_NB_state_idle; - return retcode; -} - -LIBSSH2_API int -libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width, - int height, int width_px, int height_px) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_request_pty_size(channel, width, height, width_px, - height_px)); - return rc; -} - -/* Keep this an even number */ -#define LIBSSH2_X11_RANDOM_COOKIE_LEN 32 - -/* - * channel_x11_req - * Request X11 forwarding - */ -static int -channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, - const char *auth_proto, const char *auth_cookie, - int screen_number) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char *s; - static const unsigned char reply_codes[3] = - { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; - size_t proto_len = - auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1); - size_t cookie_len = - auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN; - int rc; - - if (channel->reqX11_state == libssh2_NB_state_idle) { - /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) + - * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) + - * screen_num(4) */ - channel->reqX11_packet_len = proto_len + cookie_len + 30; - - /* Zero the whole thing out */ - memset(&channel->reqX11_packet_requirev_state, 0, - sizeof(channel->reqX11_packet_requirev_state)); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Requesting x11-req for channel %lu/%lu: single=%d " - "proto=%s cookie=%s screen=%d", - channel->local.id, channel->remote.id, - single_connection, - auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1", - auth_cookie ? auth_cookie : "", screen_number); - - s = channel->reqX11_packet = - LIBSSH2_ALLOC(session, channel->reqX11_packet_len); - if (!channel->reqX11_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for pty-request"); - } - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, "x11-req", sizeof("x11-req") - 1); - - *(s++) = 0x01; /* want_reply */ - *(s++) = single_connection ? 0x01 : 0x00; - - _libssh2_store_str(&s, auth_proto?auth_proto:"MIT-MAGIC-COOKIE-1", - proto_len); - - _libssh2_store_u32(&s, cookie_len); - if (auth_cookie) { - memcpy(s, auth_cookie, cookie_len); - } else { - int i; - /* note: the extra +1 below is necessary since the sprintf() - loop will always write 3 bytes so the last one will write - the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2 - border */ - unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) +1]; - - _libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); - for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) { - sprintf((char *)&s[i*2], "%02X", buffer[i]); - } - } - s += cookie_len; - - _libssh2_store_u32(&s, screen_number); - channel->reqX11_state = libssh2_NB_state_created; - } - - if (channel->reqX11_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, channel->reqX11_packet, - channel->reqX11_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending X11-req packet"); - return rc; - } - if (rc) { - LIBSSH2_FREE(session, channel->reqX11_packet); - channel->reqX11_packet = NULL; - channel->reqX11_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send x11-req packet"); - } - LIBSSH2_FREE(session, channel->reqX11_packet); - channel->reqX11_packet = NULL; - - _libssh2_htonu32(channel->reqX11_local_channel, channel->local.id); - - channel->reqX11_state = libssh2_NB_state_sent; - } - - if (channel->reqX11_state == libssh2_NB_state_sent) { - size_t data_len; - unsigned char *data; - unsigned char code; - - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 1, channel->reqX11_local_channel, 4, - &channel->reqX11_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - channel->reqX11_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "waiting for x11-req response packet"); - } - - code = data[0]; - LIBSSH2_FREE(session, data); - channel->reqX11_state = libssh2_NB_state_idle; - - if (code == SSH_MSG_CHANNEL_SUCCESS) - return 0; - } - - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for channel x11-req"); -} - -/* - * libssh2_channel_x11_req_ex - * Request X11 forwarding - */ -LIBSSH2_API int -libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, - const char *auth_proto, const char *auth_cookie, - int screen_number) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_x11_req(channel, single_connection, auth_proto, - auth_cookie, screen_number)); - return rc; -} - - -/* - * _libssh2_channel_process_startup - * - * Primitive for libssh2_channel_(shell|exec|subsystem) - */ -int -_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, - const char *request, size_t request_len, - const char *message, size_t message_len) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char *s; - static const unsigned char reply_codes[3] = - { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; - int rc; - - if (channel->process_state == libssh2_NB_state_idle) { - /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */ - channel->process_packet_len = request_len + 10; - - /* Zero the whole thing out */ - memset(&channel->process_packet_requirev_state, 0, - sizeof(channel->process_packet_requirev_state)); - - if (message) - channel->process_packet_len += + 4; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "starting request(%s) on channel %lu/%lu, message=%s", - request, channel->local.id, channel->remote.id, - message?message:""); - s = channel->process_packet = - LIBSSH2_ALLOC(session, channel->process_packet_len); - if (!channel->process_packet) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory " - "for channel-process request"); - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, request, request_len); - *(s++) = 0x01; - - if (message) - _libssh2_store_u32(&s, message_len); - - channel->process_state = libssh2_NB_state_created; - } - - if (channel->process_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - channel->process_packet, - channel->process_packet_len, - (unsigned char *)message, message_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending channel request"); - return rc; - } - else if (rc) { - LIBSSH2_FREE(session, channel->process_packet); - channel->process_packet = NULL; - channel->process_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send channel request"); - } - LIBSSH2_FREE(session, channel->process_packet); - channel->process_packet = NULL; - - _libssh2_htonu32(channel->process_local_channel, channel->local.id); - - channel->process_state = libssh2_NB_state_sent; - } - - if (channel->process_state == libssh2_NB_state_sent) { - unsigned char *data; - size_t data_len; - unsigned char code; - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 1, channel->process_local_channel, 4, - &channel->process_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - channel->process_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Failed waiting for channel success"); - } - - code = data[0]; - LIBSSH2_FREE(session, data); - channel->process_state = libssh2_NB_state_idle; - - if (code == SSH_MSG_CHANNEL_SUCCESS) - return 0; - } - - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for " - "channel-process-startup"); -} - -/* - * libssh2_channel_process_startup - * - * Primitive for libssh2_channel_(shell|exec|subsystem) - */ -LIBSSH2_API int -libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, - const char *req, unsigned int req_len, - const char *msg, unsigned int msg_len) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_process_startup(channel, req, req_len, - msg, msg_len)); - return rc; -} - - -/* - * libssh2_channel_set_blocking - * - * Set a channel's BEHAVIOR blocking on or off. The socket will remain non- - * blocking. - */ -LIBSSH2_API void -libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking) -{ - if(channel) - (void) _libssh2_session_set_blocking(channel->session, blocking); -} - -/* - * _libssh2_channel_flush - * - * Flush data from one (or all) stream - * Returns number of bytes flushed, or negative on failure - */ -int -_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid) -{ - if (channel->flush_state == libssh2_NB_state_idle) { - LIBSSH2_PACKET *packet = - _libssh2_list_first(&channel->session->packets); - channel->flush_refund_bytes = 0; - channel->flush_flush_bytes = 0; - - while (packet) { - LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node); - unsigned char packet_type = packet->data[0]; - - if (((packet_type == SSH_MSG_CHANNEL_DATA) - || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) - && (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) { - /* It's our channel at least */ - long packet_stream_id = - (packet_type == SSH_MSG_CHANNEL_DATA) ? 0 : - _libssh2_ntohu32(packet->data + 5); - if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL) - || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA) - && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) - || (streamid == packet_stream_id))) - || ((packet_type == SSH_MSG_CHANNEL_DATA) - && (streamid == 0))) { - int bytes_to_flush = packet->data_len - packet->data_head; - - _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, - "Flushing %d bytes of data from stream " - "%lu on channel %lu/%lu", - bytes_to_flush, packet_stream_id, - channel->local.id, channel->remote.id); - - /* It's one of the streams we wanted to flush */ - channel->flush_refund_bytes += packet->data_len - 13; - channel->flush_flush_bytes += bytes_to_flush; - - LIBSSH2_FREE(channel->session, packet->data); - - /* remove this packet from the parent's list */ - _libssh2_list_remove(&packet->node); - LIBSSH2_FREE(channel->session, packet); - } - } - packet = next; - } - - channel->flush_state = libssh2_NB_state_created; - } - - if (channel->flush_refund_bytes) { - int rc; - - rc = _libssh2_channel_receive_window_adjust(channel, - channel->flush_refund_bytes, - 1, NULL); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - channel->flush_state = libssh2_NB_state_idle; - - return channel->flush_flush_bytes; -} - -/* - * libssh2_channel_flush_ex - * - * Flush data from one (or all) stream - * Returns number of bytes flushed, or negative on failure - */ -LIBSSH2_API int -libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_flush(channel, stream)); - return rc; -} - -/* - * libssh2_channel_get_exit_status - * - * Return the channel's program exit status. Note that the actual protocol - * provides the full 32bit this function returns. We cannot abuse it to - * return error values in case of errors so we return a zero if channel is - * NULL. - */ -LIBSSH2_API int -libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel) -{ - if(!channel) - return 0; - - return channel->exit_status; -} - -/* - * libssh2_channel_get_exit_signal - * - * Get exit signal (without leading "SIG"), error message, and language - * tag into newly allocated buffers of indicated length. Caller can - * use NULL pointers to indicate that the value should not be set. The - * *_len variables are set if they are non-NULL even if the - * corresponding string parameter is NULL. Returns LIBSSH2_ERROR_NONE - * on success, or an API error code. - */ -LIBSSH2_API int -libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel, - char **exitsignal, - size_t *exitsignal_len, - char **errmsg, - size_t *errmsg_len, - char **langtag, - size_t *langtag_len) -{ - LIBSSH2_SESSION *session = channel->session; - size_t namelen = 0; - - if (channel) { - if (channel->exit_signal) { - namelen = strlen(channel->exit_signal); - if (exitsignal) { - *exitsignal = LIBSSH2_ALLOC(session, namelen + 1); - if (!*exitsignal) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for signal name"); - } - memcpy(*exitsignal, channel->exit_signal, namelen); - (*exitsignal)[namelen] = '\0'; - } - if (exitsignal_len) - *exitsignal_len = namelen; - } else { - if (exitsignal) - *exitsignal = NULL; - if (exitsignal_len) - *exitsignal_len = 0; - } - - /* TODO: set error message and language tag */ - - if (errmsg) - *errmsg = NULL; - - if (errmsg_len) - *errmsg_len = 0; - - if (langtag) - *langtag = NULL; - - if (langtag_len) - *langtag_len = 0; - } - - return LIBSSH2_ERROR_NONE; -} - -/* - * _libssh2_channel_receive_window_adjust - * - * Adjust the receive window for a channel by adjustment bytes. If the amount - * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the - * adjustment amount will be queued for a later packet. - * - * Calls _libssh2_error() ! - */ -int -_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, - uint32_t adjustment, - unsigned char force, - unsigned int *store) -{ - int rc; - - if (channel->adjust_state == libssh2_NB_state_idle) { - if (!force - && (adjustment + channel->adjust_queue < - LIBSSH2_CHANNEL_MINADJUST)) { - _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, - "Queueing %lu bytes for receive window adjustment " - "for channel %lu/%lu", - adjustment, channel->local.id, channel->remote.id); - channel->adjust_queue += adjustment; - if(store) - *store = channel->remote.window_size; - return 0; - } - - if (!adjustment && !channel->adjust_queue) { - if(store) - *store = channel->remote.window_size; - return 0; - } - - adjustment += channel->adjust_queue; - channel->adjust_queue = 0; - - /* Adjust the window based on the block we just freed */ - channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST; - _libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id); - _libssh2_htonu32(&channel->adjust_adjust[5], adjustment); - _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, - "Adjusting window %lu bytes for data on " - "channel %lu/%lu", - adjustment, channel->local.id, channel->remote.id); - - channel->adjust_state = libssh2_NB_state_created; - } - - rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(channel->session, rc, - "Would block sending window adjust"); - return rc; - } - else if (rc) { - channel->adjust_queue = adjustment; - return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send transfer-window adjustment " - "packet, deferring"); - } - else { - channel->remote.window_size += adjustment; - } - - channel->adjust_state = libssh2_NB_state_idle; - - if(store) - *store = channel->remote.window_size; - return 0; -} - -/* - * libssh2_channel_receive_window_adjust - * - * DEPRECATED - * - * Adjust the receive window for a channel by adjustment bytes. If the amount - * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the - * adjustment amount will be queued for a later packet. - * - * Returns the new size of the receive window (as understood by remote end). - * Note that it might return EAGAIN too which is highly stupid. - * - */ -LIBSSH2_API unsigned long -libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, - unsigned long adj, - unsigned char force) -{ - unsigned int window; - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_receive_window_adjust(channel, adj, - force, &window)); - - /* stupid - but this is how it was made to work before and this is just - kept for backwards compatibility */ - return rc?(unsigned long)rc:window; -} - -/* - * libssh2_channel_receive_window_adjust2 - * - * Adjust the receive window for a channel by adjustment bytes. If the amount - * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the - * adjustment amount will be queued for a later packet. - * - * Stores the new size of the receive window in the data 'window' points to. - * - * Returns the "normal" error code: 0 for success, negative for failure. - */ -LIBSSH2_API int -libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel, - unsigned long adj, - unsigned char force, - unsigned int *window) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_receive_window_adjust(channel, adj, force, - window)); - return rc; -} - -int -_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode) -{ - if (channel->extData2_state == libssh2_NB_state_idle) { - _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, - "Setting channel %lu/%lu handle_extended_data" - " mode to %d", - channel->local.id, channel->remote.id, ignore_mode); - channel->remote.extended_data_ignore_mode = ignore_mode; - - channel->extData2_state = libssh2_NB_state_created; - } - - if (channel->extData2_state == libssh2_NB_state_idle) { - if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) { - int rc = - _libssh2_channel_flush(channel, - LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA); - if(LIBSSH2_ERROR_EAGAIN == rc) - return rc; - } - } - - channel->extData2_state = libssh2_NB_state_idle; - return 0; -} - -/* - * libssh2_channel_handle_extended_data2() - * - */ -LIBSSH2_API int -libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, - int mode) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel, - mode)); - return rc; -} - -/* - * libssh2_channel_handle_extended_data - * - * DEPRECATED DO NOTE USE! - * - * How should extended data look to the calling app? Keep it in separate - * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the - * standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss - * out packets as they come in]? (IGNORE) - */ -LIBSSH2_API void -libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, - int ignore_mode) -{ - (void)libssh2_channel_handle_extended_data2(channel, ignore_mode); -} - - - -/* - * _libssh2_channel_read - * - * Read data from a channel - * - * It is important to not return 0 until the currently read channel is - * complete. If we read stuff from the wire but it was no payload data to fill - * in the buffer with, we MUST make sure to return LIBSSH2_ERROR_EAGAIN. - * - * The receive window must be maintained (enlarged) by the user of this - * function. - */ -ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, - char *buf, size_t buflen) -{ - LIBSSH2_SESSION *session = channel->session; - int rc; - int bytes_read = 0; - int bytes_want; - int unlink_packet; - LIBSSH2_PACKET *read_packet; - LIBSSH2_PACKET *read_next; - - if (channel->read_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "channel_read() wants %d bytes from channel %lu/%lu " - "stream #%d", - (int) buflen, channel->local.id, channel->remote.id, - stream_id); - channel->read_state = libssh2_NB_state_created; - } - - rc = 1; /* set to >0 to let the while loop start */ - - /* Process all pending incoming packets in all states in order to "even - out" the network readings. Tests prove that this way produces faster - transfers. */ - while (rc > 0) - rc = _libssh2_transport_read(session); - - if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) - return _libssh2_error(session, rc, "transport read"); - - read_packet = _libssh2_list_first(&session->packets); - while (read_packet && (bytes_read < (int) buflen)) { - /* previously this loop condition also checked for - !channel->remote.close but we cannot let it do this: - - We may have a series of packets to read that are still pending even - if a close has been received. Acknowledging the close too early - makes us flush buffers prematurely and loose data. - */ - - LIBSSH2_PACKET *readpkt = read_packet; - - /* In case packet gets destroyed during this iteration */ - read_next = _libssh2_list_next(&readpkt->node); - - channel->read_local_id = - _libssh2_ntohu32(readpkt->data + 1); - - /* - * Either we asked for a specific extended data stream - * (and data was available), - * or the standard stream (and data was available), - * or the standard stream with extended_data_merge - * enabled and data was available - */ - if ((stream_id - && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) - && (channel->local.id == channel->read_local_id) - && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5))) - || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA) - && (channel->local.id == channel->read_local_id)) - || (!stream_id - && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) - && (channel->local.id == channel->read_local_id) - && (channel->remote.extended_data_ignore_mode == - LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) { - - /* figure out much more data we want to read */ - bytes_want = buflen - bytes_read; - unlink_packet = FALSE; - - if (bytes_want >= (int) (readpkt->data_len - readpkt->data_head)) { - /* we want more than this node keeps, so adjust the number and - delete this node after the copy */ - bytes_want = readpkt->data_len - readpkt->data_head; - unlink_packet = TRUE; - } - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "channel_read() got %d of data from %lu/%lu/%d%s", - bytes_want, channel->local.id, - channel->remote.id, stream_id, - unlink_packet?" [ul]":""); - - /* copy data from this struct to the target buffer */ - memcpy(&buf[bytes_read], - &readpkt->data[readpkt->data_head], bytes_want); - - /* advance pointer and counter */ - readpkt->data_head += bytes_want; - bytes_read += bytes_want; - - /* if drained, remove from list */ - if (unlink_packet) { - /* detach readpkt from session->packets list */ - _libssh2_list_remove(&readpkt->node); - - LIBSSH2_FREE(session, readpkt->data); - LIBSSH2_FREE(session, readpkt); - } - } - - /* check the next struct in the chain */ - read_packet = read_next; - } - - if (!bytes_read) { - channel->read_state = libssh2_NB_state_idle; - - /* If the channel is already at EOF or even closed, we need to signal - that back. We may have gotten that info while draining the incoming - transport layer until EAGAIN so we must not be fooled by that - return code. */ - if(channel->remote.eof || channel->remote.close) - return 0; - else if(rc != LIBSSH2_ERROR_EAGAIN) - return 0; - - /* if the transport layer said EAGAIN then we say so as well */ - return _libssh2_error(session, rc, "would block"); - } - else - /* make sure we remain in the created state to focus on emptying the - data we already have in the packet brigade before we try to read - more off the network again */ - channel->read_state = libssh2_NB_state_created; - - return bytes_read; -} - -/* - * libssh2_channel_read_ex - * - * Read data from a channel (blocking or non-blocking depending on set state) - * - * When this is done non-blocking, it is important to not return 0 until the - * currently read channel is complete. If we read stuff from the wire but it - * was no payload data to fill in the buffer with, we MUST make sure to return - * LIBSSH2_ERROR_EAGAIN. - * - * This function will first make sure there's a receive window enough to - * receive a full buffer's wort of contents. An application may choose to - * adjust the receive window more to increase transfer performance. - */ -LIBSSH2_API ssize_t -libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, - size_t buflen) -{ - int rc; - unsigned long recv_window; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL); - - if(buflen > recv_window) { - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_receive_window_adjust(channel, buflen, - 1, NULL)); - } - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_read(channel, stream_id, buf, buflen)); - return rc; -} - -/* - * _libssh2_channel_packet_data_len - * - * Return the size of the data block of the current packet, or 0 if there - * isn't a packet. - */ -size_t -_libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id) -{ - LIBSSH2_SESSION *session = channel->session; - LIBSSH2_PACKET *read_packet; - uint32_t read_local_id; - - read_packet = _libssh2_list_first(&session->packets); - if (read_packet == NULL) - return 0; - - while (read_packet) { - read_local_id = _libssh2_ntohu32(read_packet->data + 1); - - /* - * Either we asked for a specific extended data stream - * (and data was available), - * or the standard stream (and data was available), - * or the standard stream with extended_data_merge - * enabled and data was available - */ - if ((stream_id - && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) - && (channel->local.id == read_local_id) - && (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5))) - || - (!stream_id - && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA) - && (channel->local.id == read_local_id)) - || - (!stream_id - && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) - && (channel->local.id == read_local_id) - && (channel->remote.extended_data_ignore_mode - == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) - { - return (read_packet->data_len - read_packet->data_head); - } - read_packet = _libssh2_list_next(&read_packet->node); - } - - return 0; -} - -/* - * _libssh2_channel_write - * - * Send data to a channel. Note that if this returns EAGAIN, the caller must - * call this function again with the SAME input arguments. - * - * Returns: number of bytes sent, or if it returns a negative number, that is - * the error code! - */ -ssize_t -_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, - const unsigned char *buf, size_t buflen) -{ - int rc = 0; - LIBSSH2_SESSION *session = channel->session; - ssize_t wrote = 0; /* counter for this specific this call */ - - /* In theory we could split larger buffers into several smaller packets - * but it turns out to be really hard and nasty to do while still offering - * the API/prototype. - * - * Instead we only deal with the first 32K in this call and for the parent - * function to call it again with the remainder! 32K is a conservative - * limit based on the text in RFC4253 section 6.1. - */ - if(buflen > 32700) - buflen = 32700; - - if (channel->write_state == libssh2_NB_state_idle) { - unsigned char *s = channel->write_packet; - - _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, - "Writing %d bytes on channel %lu/%lu, stream #%d", - (int) buflen, channel->local.id, channel->remote.id, - stream_id); - - if (channel->local.close) - return _libssh2_error(channel->session, - LIBSSH2_ERROR_CHANNEL_CLOSED, - "We've already closed this channel"); - else if (channel->local.eof) - return _libssh2_error(channel->session, - LIBSSH2_ERROR_CHANNEL_EOF_SENT, - "EOF has already been received, " - "data might be ignored"); - - /* drain the incoming flow first, mostly to make sure we get all - * pending window adjust packets */ - do - rc = _libssh2_transport_read(session); - while (rc > 0); - - if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) - return rc; - - if(channel->local.window_size <= 0) - /* there's no room for data so we stop */ - return (rc==LIBSSH2_ERROR_EAGAIN?rc:0); - - channel->write_bufwrite = buflen; - - *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA : - SSH_MSG_CHANNEL_DATA; - _libssh2_store_u32(&s, channel->remote.id); - if (stream_id) - _libssh2_store_u32(&s, stream_id); - - /* Don't exceed the remote end's limits */ - /* REMEMBER local means local as the SOURCE of the data */ - if (channel->write_bufwrite > channel->local.window_size) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Splitting write block due to %lu byte " - "window_size on %lu/%lu/%d", - channel->local.window_size, channel->local.id, - channel->remote.id, stream_id); - channel->write_bufwrite = channel->local.window_size; - } - if (channel->write_bufwrite > channel->local.packet_size) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Splitting write block due to %lu byte " - "packet_size on %lu/%lu/%d", - channel->local.packet_size, channel->local.id, - channel->remote.id, stream_id); - channel->write_bufwrite = channel->local.packet_size; - } - /* store the size here only, the buffer is passed in as-is to - _libssh2_transport_send() */ - _libssh2_store_u32(&s, channel->write_bufwrite); - channel->write_packet_len = s - channel->write_packet; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Sending %d bytes on channel %lu/%lu, stream_id=%d", - (int) channel->write_bufwrite, channel->local.id, - channel->remote.id, stream_id); - - channel->write_state = libssh2_NB_state_created; - } - - if (channel->write_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, channel->write_packet, - channel->write_packet_len, - buf, channel->write_bufwrite); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, rc, - "Unable to send channel data"); - } - else if (rc) { - channel->write_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send channel data"); - } - /* Shrink local window size */ - channel->local.window_size -= channel->write_bufwrite; - - wrote += channel->write_bufwrite; - - /* Since _libssh2_transport_write() succeeded, we must return - now to allow the caller to provide the next chunk of data. - - We cannot move on to send the next piece of data that may - already have been provided in this same function call, as we - risk getting EAGAIN for that and we can't return information - both about sent data as well as EAGAIN. So, by returning short - now, the caller will call this function again with new data to - send */ - - channel->write_state = libssh2_NB_state_idle; - - return wrote; - } - - return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */ -} - -/* - * libssh2_channel_write_ex - * - * Send data to a channel - */ -LIBSSH2_API ssize_t -libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, - const char *buf, size_t buflen) -{ - ssize_t rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_write(channel, stream_id, - (unsigned char *)buf, buflen)); - return rc; -} - -/* - * channel_send_eof - * - * Send EOF on channel - */ -static int channel_send_eof(LIBSSH2_CHANNEL *channel) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char packet[5]; /* packet_type(1) + channelno(4) */ - int rc; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Sending EOF on channel %lu/%lu", - channel->local.id, channel->remote.id); - packet[0] = SSH_MSG_CHANNEL_EOF; - _libssh2_htonu32(packet + 1, channel->remote.id); - rc = _libssh2_transport_send(session, packet, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending EOF"); - return rc; - } - else if (rc) { - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send EOF on channel"); - } - channel->local.eof = 1; - - return 0; -} - -/* - * libssh2_channel_send_eof - * - * Send EOF on channel - */ -LIBSSH2_API int -libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel)); - return rc; -} - -/* - * libssh2_channel_eof - * - * Read channel's eof status - */ -LIBSSH2_API int -libssh2_channel_eof(LIBSSH2_CHANNEL * channel) -{ - LIBSSH2_SESSION *session; - LIBSSH2_PACKET *packet; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - session = channel->session; - packet = _libssh2_list_first(&session->packets); - - while (packet) { - if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) - || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) - && (channel->local.id == _libssh2_ntohu32(packet->data + 1))) { - /* There's data waiting to be read yet, mask the EOF status */ - return 0; - } - packet = _libssh2_list_next(&packet->node); - } - - return channel->remote.eof; -} - -/* - * channel_wait_eof - * - * Awaiting channel EOF - */ -static int channel_wait_eof(LIBSSH2_CHANNEL *channel) -{ - LIBSSH2_SESSION *session = channel->session; - int rc; - - if (channel->wait_eof_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Awaiting close of channel %lu/%lu", channel->local.id, - channel->remote.id); - - channel->wait_eof_state = libssh2_NB_state_created; - } - - /* - * While channel is not eof, read more packets from the network. - * Either the EOF will be set or network timeout will occur. - */ - do { - if (channel->remote.eof) { - break; - } - rc = _libssh2_transport_read(session); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - else if (rc < 0) { - channel->wait_eof_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "_libssh2_transport_read() bailed out!"); - } - } while (1); - - channel->wait_eof_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * libssh2_channel_wait_eof - * - * Awaiting channel EOF - */ -LIBSSH2_API int -libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel)); - return rc; -} - -int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) -{ - LIBSSH2_SESSION *session = channel->session; - int rc = 0; - int retcode; - - if (channel->local.close) { - /* Already closed, act like we sent another close, - * even though we didn't... shhhhhh */ - channel->close_state = libssh2_NB_state_idle; - return 0; - } - - if (!channel->local.eof) - if ((retcode = channel_send_eof(channel))) - return retcode; - - /* ignore if we have received a remote eof or not, as it is now too - late for us to wait for it. Continue closing! */ - - if (channel->close_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu", - channel->local.id, channel->remote.id); - - channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE; - _libssh2_htonu32(channel->close_packet + 1, channel->remote.id); - - channel->close_state = libssh2_NB_state_created; - } - - if (channel->close_state == libssh2_NB_state_created) { - retcode = _libssh2_transport_send(session, channel->close_packet, 5, - NULL, 0); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending close-channel"); - return retcode; - } else if (retcode) { - channel->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, retcode, - "Unable to send close-channel request"); - } - - channel->close_state = libssh2_NB_state_sent; - } - - if (channel->close_state == libssh2_NB_state_sent) { - /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */ - - while (!channel->remote.close && !rc && - (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED)) - rc = _libssh2_transport_read(session); - } - - if(rc != LIBSSH2_ERROR_EAGAIN) { - /* set the local close state first when we're perfectly confirmed to not - do any more EAGAINs */ - channel->local.close = 1; - - /* We call the callback last in this function to make it keep the local - data as long as EAGAIN is returned. */ - if (channel->close_cb) { - LIBSSH2_CHANNEL_CLOSE(session, channel); - } - - channel->close_state = libssh2_NB_state_idle; - } - - /* return 0 or an error */ - return rc>=0?0:rc; -} - -/* - * libssh2_channel_close - * - * Close a channel - */ -LIBSSH2_API int -libssh2_channel_close(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel) ); - return rc; -} - -/* - * channel_wait_closed - * - * Awaiting channel close after EOF - */ -static int channel_wait_closed(LIBSSH2_CHANNEL *channel) -{ - LIBSSH2_SESSION *session = channel->session; - int rc; - - if (!libssh2_channel_eof(channel)) { - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "libssh2_channel_wait_closed() invoked when " - "channel is not in EOF state"); - } - - if (channel->wait_closed_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Awaiting close of channel %lu/%lu", channel->local.id, - channel->remote.id); - - channel->wait_closed_state = libssh2_NB_state_created; - } - - /* - * While channel is not closed, read more packets from the network. - * Either the channel will be closed or network timeout will occur. - */ - if (!channel->remote.close) { - do { - rc = _libssh2_transport_read(session); - if (channel->remote.close) - /* it is now closed, move on! */ - break; - } while (rc > 0); - if(rc < 0) - return rc; - } - - channel->wait_closed_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * libssh2_channel_wait_closed - * - * Awaiting channel close after EOF - */ -LIBSSH2_API int -libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel)); - return rc; -} - -/* - * _libssh2_channel_free - * - * Make sure a channel is closed, then remove the channel from the session - * and free its resource(s) - * - * Returns 0 on success, negative on failure - */ -int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char channel_id[4]; - unsigned char *data; - size_t data_len; - int rc; - - assert(session); - - if (channel->free_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Freeing channel %lu/%lu resources", channel->local.id, - channel->remote.id); - - channel->free_state = libssh2_NB_state_created; - } - - /* Allow channel freeing even when the socket has lost its connection */ - if (!channel->local.close - && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) { - rc = _libssh2_channel_close(channel); - - if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - /* ignore all other errors as they otherwise risk blocking the channel - free from happening */ - } - - channel->free_state = libssh2_NB_state_idle; - - if (channel->exit_signal) { - LIBSSH2_FREE(session, channel->exit_signal); - } - - /* - * channel->remote.close *might* not be set yet, Well... - * We've sent the close packet, what more do you want? - * Just let packet_add ignore it when it finally arrives - */ - - /* Clear out packets meant for this channel */ - _libssh2_htonu32(channel_id, channel->local.id); - while ((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data, - &data_len, 1, channel_id, 4) >= 0) - || - (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data, - &data_len, 1, channel_id, 4) >= 0)) { - LIBSSH2_FREE(session, data); - } - - /* free "channel_type" */ - if (channel->channel_type) { - LIBSSH2_FREE(session, channel->channel_type); - } - - /* Unlink from channel list */ - _libssh2_list_remove(&channel->node); - - /* - * Make sure all memory used in the state variables are free - */ - if (channel->setenv_packet) { - LIBSSH2_FREE(session, channel->setenv_packet); - } - if (channel->reqX11_packet) { - LIBSSH2_FREE(session, channel->reqX11_packet); - } - if (channel->process_packet) { - LIBSSH2_FREE(session, channel->process_packet); - } - - LIBSSH2_FREE(session, channel); - - return 0; -} - -/* - * libssh2_channel_free - * - * Make sure a channel is closed, then remove the channel from the session - * and free its resource(s) - * - * Returns 0 on success, negative on failure - */ -LIBSSH2_API int -libssh2_channel_free(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel)); - return rc; -} -/* - * libssh2_channel_window_read_ex - * - * Check the status of the read window. Returns the number of bytes which the - * remote end may send without overflowing the window limit read_avail (if - * passed) will be populated with the number of bytes actually available to be - * read window_size_initial (if passed) will be populated with the - * window_size_initial as defined by the channel_open request - */ -LIBSSH2_API unsigned long -libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, - unsigned long *read_avail, - unsigned long *window_size_initial) -{ - if(!channel) - return 0; /* no channel, no window! */ - - if (window_size_initial) { - *window_size_initial = channel->remote.window_size_initial; - } - - if (read_avail) { - size_t bytes_queued = 0; - LIBSSH2_PACKET *packet = - _libssh2_list_first(&channel->session->packets); - - while (packet) { - unsigned char packet_type = packet->data[0]; - - if (((packet_type == SSH_MSG_CHANNEL_DATA) - || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) - && (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) { - bytes_queued += packet->data_len - packet->data_head; - } - - packet = _libssh2_list_next(&packet->node); - } - - *read_avail = bytes_queued; - } - - return channel->remote.window_size; -} - -/* - * libssh2_channel_window_write_ex - * - * Check the status of the write window Returns the number of bytes which may - * be safely writen on the channel without blocking window_size_initial (if - * passed) will be populated with the size of the initial window as defined by - * the channel_open request - */ -LIBSSH2_API unsigned long -libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, - unsigned long *window_size_initial) -{ - if(!channel) - return 0; /* no channel, no window! */ - - if (window_size_initial) { - /* For locally initiated channels this is very often 0, so it's not - * *that* useful as information goes */ - *window_size_initial = channel->local.window_size_initial; - } - - return channel->local.window_size; -} diff --git a/vendor/libssh2-1.4.2/src/channel.h b/vendor/libssh2-1.4.2/src/channel.h deleted file mode 100644 index dc0ee37..0000000 --- a/vendor/libssh2-1.4.2/src/channel.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef __LIBSSH2_CHANNEL_H -#define __LIBSSH2_CHANNEL_H -/* Copyright (c) 2008-2010 by Daniel Stenberg - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - */ - -/* - * _libssh2_channel_receive_window_adjust - * - * Adjust the receive window for a channel by adjustment bytes. If the amount - * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the - * adjustment amount will be queued for a later packet. - * - * Always non-blocking. - */ -int _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, - uint32_t adjustment, - unsigned char force, - unsigned int *store); - -/* - * _libssh2_channel_flush - * - * Flush data from one (or all) stream - * Returns number of bytes flushed, or negative on failure - */ -int _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid); - -/* - * _libssh2_channel_free - * - * Make sure a channel is closed, then remove the channel from the session - * and free its resource(s) - * - * Returns 0 on success, negative on failure - */ -int _libssh2_channel_free(LIBSSH2_CHANNEL *channel); - -int -_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode); - -/* - * _libssh2_channel_write - * - * Send data to a channel - */ -ssize_t -_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, - const unsigned char *buf, size_t buflen); - -/* - * _libssh2_channel_open - * - * Establish a generic session channel - */ -LIBSSH2_CHANNEL * -_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, - uint32_t channel_type_len, - uint32_t window_size, - uint32_t packet_size, - const unsigned char *message, size_t message_len); - - -/* - * _libssh2_channel_process_startup - * - * Primitive for libssh2_channel_(shell|exec|subsystem) - */ -int -_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, - const char *request, size_t request_len, - const char *message, size_t message_len); - -/* - * _libssh2_channel_read - * - * Read data from a channel - * - * It is important to not return 0 until the currently read channel is - * complete. If we read stuff from the wire but it was no payload data to fill - * in the buffer with, we MUST make sure to return PACKET_EAGAIN. - */ -ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, - char *buf, size_t buflen); - -uint32_t _libssh2_channel_nextid(LIBSSH2_SESSION * session); - -LIBSSH2_CHANNEL *_libssh2_channel_locate(LIBSSH2_SESSION * session, - uint32_t channel_id); - -size_t _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, - int stream_id); - -int _libssh2_channel_close(LIBSSH2_CHANNEL * channel); - -/* - * _libssh2_channel_forward_cancel - * - * Stop listening on a remote port and free the listener - * Toss out any pending (un-accept()ed) connections - * - * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error - */ -int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener); - -#endif /* __LIBSSH2_CHANNEL_H */ - diff --git a/vendor/libssh2-1.4.2/src/comp.c b/vendor/libssh2-1.4.2/src/comp.c deleted file mode 100644 index 0296f62..0000000 --- a/vendor/libssh2-1.4.2/src/comp.c +++ /dev/null @@ -1,390 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010, Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#ifdef LIBSSH2_HAVE_ZLIB -# include -#endif - -#include "comp.h" - -/* ******** - * none * - ******** */ - -/* - * comp_method_none_comp - * - * Minimalist compression: Absolutely none - */ -static int -comp_method_none_comp(LIBSSH2_SESSION *session, - unsigned char *dest, - size_t *dest_len, - const unsigned char *src, - size_t src_len, - void **abstract) -{ - (void) session; - (void) abstract; - (void) dest; - (void) dest_len; - (void) src; - (void) src_len; - - return 0; -} - -/* - * comp_method_none_decomp - * - * Minimalist decompression: Absolutely none - */ -static int -comp_method_none_decomp(LIBSSH2_SESSION * session, - unsigned char **dest, - size_t *dest_len, - size_t payload_limit, - const unsigned char *src, - size_t src_len, void **abstract) -{ - (void) session; - (void) payload_limit; - (void) abstract; - *dest = (unsigned char *) src; - *dest_len = src_len; - return 0; -} - - - -static const LIBSSH2_COMP_METHOD comp_method_none = { - "none", - 0, /* not really compressing */ - NULL, - comp_method_none_comp, - comp_method_none_decomp, - NULL -}; - -#ifdef LIBSSH2_HAVE_ZLIB -/* ******** - * zlib * - ******** */ - -/* Memory management wrappers - * Yes, I realize we're doing a callback to a callback, - * Deal... - */ - -static voidpf -comp_method_zlib_alloc(voidpf opaque, uInt items, uInt size) -{ - LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque; - - return (voidpf) LIBSSH2_ALLOC(session, items * size); -} - -static void -comp_method_zlib_free(voidpf opaque, voidpf address) -{ - LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque; - - LIBSSH2_FREE(session, address); -} - - - -/* libssh2_comp_method_zlib_init - * All your bandwidth are belong to us (so save some) - */ -static int -comp_method_zlib_init(LIBSSH2_SESSION * session, int compr, - void **abstract) -{ - z_stream *strm; - int status; - - strm = LIBSSH2_ALLOC(session, sizeof(z_stream)); - if (!strm) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "zlib compression/decompression"); - } - memset(strm, 0, sizeof(z_stream)); - - strm->opaque = (voidpf) session; - strm->zalloc = (alloc_func) comp_method_zlib_alloc; - strm->zfree = (free_func) comp_method_zlib_free; - if (compr) { - /* deflate */ - status = deflateInit(strm, Z_DEFAULT_COMPRESSION); - } else { - /* inflate */ - status = inflateInit(strm); - } - - if (status != Z_OK) { - LIBSSH2_FREE(session, strm); - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib error %d", status); - return LIBSSH2_ERROR_COMPRESS; - } - *abstract = strm; - - return LIBSSH2_ERROR_NONE; -} - -/* - * libssh2_comp_method_zlib_comp - * - * Compresses source to destination. Without allocation. - */ -static int -comp_method_zlib_comp(LIBSSH2_SESSION *session, - unsigned char *dest, - - /* dest_len is a pointer to allow this function to - update it with the final actual size used */ - size_t *dest_len, - const unsigned char *src, - size_t src_len, - void **abstract) -{ - z_stream *strm = *abstract; - int out_maxlen = *dest_len; - int status; - - strm->next_in = (unsigned char *) src; - strm->avail_in = src_len; - strm->next_out = dest; - strm->avail_out = out_maxlen; - - status = deflate(strm, Z_PARTIAL_FLUSH); - - if (status != Z_OK) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib compression error %d", status); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "compression failure"); - } - - *dest_len = out_maxlen - strm->avail_out; - return 0; -} - -/* - * libssh2_comp_method_zlib_decomp - * - * Decompresses source to destination. Allocates the output memory. - */ -static int -comp_method_zlib_decomp(LIBSSH2_SESSION * session, - unsigned char **dest, - size_t *dest_len, - size_t payload_limit, - const unsigned char *src, - size_t src_len, void **abstract) -{ - z_stream *strm = *abstract; - /* A short-term alloc of a full data chunk is better than a series of - reallocs */ - char *out; - int out_maxlen = 8 * src_len; - int limiter = 0; - - /* If strm is null, then we have not yet been initialized. */ - if (strm == NULL) - return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS, - "decompression unitilized");; - - /* In practice they never come smaller than this */ - if (out_maxlen < 25) - out_maxlen = 25; - - if (out_maxlen > (int) payload_limit) - out_maxlen = payload_limit; - - strm->next_in = (unsigned char *) src; - strm->avail_in = src_len; - strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen); - out = (char *) strm->next_out; - strm->avail_out = out_maxlen; - if (!strm->next_out) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate decompression buffer"); - while (strm->avail_in) { - int status; - - status = inflate(strm, Z_PARTIAL_FLUSH); - - if (status != Z_OK) { - LIBSSH2_FREE(session, out); - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib error %d", status); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "decompression failure"); - } - if (strm->avail_in) { - size_t out_ofs = out_maxlen - strm->avail_out; - char *newout; - - out_maxlen += 8 * strm->avail_in; - - if ((out_maxlen > (int) payload_limit) && limiter++) { - LIBSSH2_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "Excessive growth in decompression phase"); - } - - newout = LIBSSH2_REALLOC(session, out, out_maxlen); - if (!newout) { - LIBSSH2_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to expand decompression buffer"); - } - out = newout; - strm->next_out = (unsigned char *) out + out_ofs; - strm->avail_out += 8 * strm->avail_in; - } else - while (!strm->avail_out) { - /* Done with input, might be a byte or two in internal buffer - * during compress. Or potentially many bytes if it's a - * decompress - */ - int grow_size = 2048; - char *newout; - - if (out_maxlen >= (int) payload_limit) { - LIBSSH2_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "Excessive growth in decompression " - "phase"); - } - - if (grow_size > (int) (payload_limit - out_maxlen)) { - grow_size = payload_limit - out_maxlen; - } - - out_maxlen += grow_size; - strm->avail_out = grow_size; - - newout = LIBSSH2_REALLOC(session, out, out_maxlen); - if (!newout) { - LIBSSH2_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to expand final " - "decompress buffer"); - } - out = newout; - strm->next_out = (unsigned char *) out + out_maxlen - - grow_size; - - status = inflate(strm, Z_PARTIAL_FLUSH); - - if (status != Z_OK) { - LIBSSH2_FREE(session, out); - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib error %d", status); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "decompression failure"); - } - } - } - - *dest = (unsigned char *) out; - *dest_len = out_maxlen - strm->avail_out; - - return 0; -} - - -/* libssh2_comp_method_zlib_dtor - * All done, no more compression for you - */ -static int -comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract) -{ - z_stream *strm = *abstract; - - if (strm) { - if (compr) - deflateEnd(strm); - else - inflateEnd(strm); - LIBSSH2_FREE(session, strm); - } - - *abstract = NULL; - return 0; -} - -static const LIBSSH2_COMP_METHOD comp_method_zlib = { - "zlib", - 1, /* yes, this compresses */ - comp_method_zlib_init, - comp_method_zlib_comp, - comp_method_zlib_decomp, - comp_method_zlib_dtor, -}; -#endif /* LIBSSH2_HAVE_ZLIB */ - -/* If compression is enabled by the API, then this array is used which then - may allow compression if zlib is available at build time */ -static const LIBSSH2_COMP_METHOD *comp_methods[] = { -#ifdef LIBSSH2_HAVE_ZLIB - &comp_method_zlib, -#endif /* LIBSSH2_HAVE_ZLIB */ - &comp_method_none, - NULL -}; - -/* If compression is disabled by the API, then this array is used */ -static const LIBSSH2_COMP_METHOD *no_comp_methods[] = { - &comp_method_none, - NULL -}; - -const LIBSSH2_COMP_METHOD ** -_libssh2_comp_methods(LIBSSH2_SESSION *session) -{ - if(session->flag.compress) - return comp_methods; - else - return no_comp_methods; -} diff --git a/vendor/libssh2-1.4.2/src/comp.h b/vendor/libssh2-1.4.2/src/comp.h deleted file mode 100644 index 8edc150..0000000 --- a/vendor/libssh2-1.4.2/src/comp.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __LIBSSH2_COMP_H -#define __LIBSSH2_COMP_H - -/* Copyright (C) 2009-2010 by Daniel Stenberg - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session); - -#endif /* __LIBSSH2_COMP_H */ diff --git a/vendor/libssh2-1.4.2/src/crypt.c b/vendor/libssh2-1.4.2/src/crypt.c deleted file mode 100644 index 93d99c4..0000000 --- a/vendor/libssh2-1.4.2/src/crypt.c +++ /dev/null @@ -1,334 +0,0 @@ -/* Copyright (c) 2009, 2010 Simon Josefsson - * Copyright (c) 2004-2007, Sara Golemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -#ifdef LIBSSH2_CRYPT_NONE - -/* crypt_none_crypt - * Minimalist cipher: VERY secure *wink* - */ -static int -crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf, - void **abstract) -{ - /* Do nothing to the data! */ - return 0; -} - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = { - "none", - 8, /* blocksize (SSH2 defines minimum blocksize as 8) */ - 0, /* iv_len */ - 0, /* secret_len */ - 0, /* flags */ - NULL, - crypt_none_crypt, - NULL -}; -#endif /* LIBSSH2_CRYPT_NONE */ - -struct crypt_ctx -{ - int encrypt; - _libssh2_cipher_type(algo); - _libssh2_cipher_ctx h; -}; - -static int -crypt_init(LIBSSH2_SESSION * session, - const LIBSSH2_CRYPT_METHOD * method, - unsigned char *iv, int *free_iv, - unsigned char *secret, int *free_secret, - int encrypt, void **abstract) -{ - struct crypt_ctx *ctx = LIBSSH2_ALLOC(session, - sizeof(struct crypt_ctx)); - if (!ctx) - return LIBSSH2_ERROR_ALLOC; - - ctx->encrypt = encrypt; - ctx->algo = method->algo; - if (_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) { - LIBSSH2_FREE(session, ctx); - return -1; - } - *abstract = ctx; - *free_iv = 1; - *free_secret = 1; - return 0; -} - -static int -crypt_encrypt(LIBSSH2_SESSION * session, unsigned char *block, - void **abstract) -{ - struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract; - (void) session; - return _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block); -} - -static int -crypt_dtor(LIBSSH2_SESSION * session, void **abstract) -{ - struct crypt_ctx **cctx = (struct crypt_ctx **) abstract; - if (cctx && *cctx) { - _libssh2_cipher_dtor(&(*cctx)->h); - LIBSSH2_FREE(session, *cctx); - *abstract = NULL; - } - return 0; -} - -#if LIBSSH2_AES_CTR -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = { - "aes128-ctr", - 16, /* blocksize */ - 16, /* initial value length */ - 16, /* secret length -- 16*8 == 128bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes128ctr -}; - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = { - "aes192-ctr", - 16, /* blocksize */ - 16, /* initial value length */ - 24, /* secret length -- 24*8 == 192bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes192ctr -}; - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = { - "aes256-ctr", - 16, /* blocksize */ - 16, /* initial value length */ - 32, /* secret length -- 32*8 == 256bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes256ctr -}; -#endif - -#if LIBSSH2_AES -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = { - "aes128-cbc", - 16, /* blocksize */ - 16, /* initial value length */ - 16, /* secret length -- 16*8 == 128bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes128 -}; - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = { - "aes192-cbc", - 16, /* blocksize */ - 16, /* initial value length */ - 24, /* secret length -- 24*8 == 192bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes192 -}; - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = { - "aes256-cbc", - 16, /* blocksize */ - 16, /* initial value length */ - 32, /* secret length -- 32*8 == 256bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes256 -}; - -/* rijndael-cbc@lysator.liu.se == aes256-cbc */ -static const LIBSSH2_CRYPT_METHOD - libssh2_crypt_method_rijndael_cbc_lysator_liu_se = { - "rijndael-cbc@lysator.liu.se", - 16, /* blocksize */ - 16, /* initial value length */ - 32, /* secret length -- 32*8 == 256bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes256 -}; -#endif /* LIBSSH2_AES */ - -#if LIBSSH2_BLOWFISH -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = { - "blowfish-cbc", - 8, /* blocksize */ - 8, /* initial value length */ - 16, /* secret length */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_blowfish -}; -#endif /* LIBSSH2_BLOWFISH */ - -#if LIBSSH2_RC4 -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = { - "arcfour", - 8, /* blocksize */ - 8, /* initial value length */ - 16, /* secret length */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_arcfour -}; - -static int -crypt_init_arcfour128(LIBSSH2_SESSION * session, - const LIBSSH2_CRYPT_METHOD * method, - unsigned char *iv, int *free_iv, - unsigned char *secret, int *free_secret, - int encrypt, void **abstract) -{ - int rc; - - rc = crypt_init (session, method, iv, free_iv, secret, free_secret, - encrypt, abstract); - if (rc == 0) { - struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract; - unsigned char block[8]; - size_t discard = 1536; - for (; discard; discard -= 8) - _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block); - } - - return rc; -} - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = { - "arcfour128", - 8, /* blocksize */ - 8, /* initial value length */ - 16, /* secret length */ - 0, /* flags */ - &crypt_init_arcfour128, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_arcfour -}; -#endif /* LIBSSH2_RC4 */ - -#if LIBSSH2_CAST -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = { - "cast128-cbc", - 8, /* blocksize */ - 8, /* initial value length */ - 16, /* secret length */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_cast5 -}; -#endif /* LIBSSH2_CAST */ - -#if LIBSSH2_3DES -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = { - "3des-cbc", - 8, /* blocksize */ - 8, /* initial value length */ - 24, /* secret length */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_3des -}; -#endif - -static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = { -#if LIBSSH2_AES_CTR - &libssh2_crypt_method_aes128_ctr, - &libssh2_crypt_method_aes192_ctr, - &libssh2_crypt_method_aes256_ctr, -#endif /* LIBSSH2_AES */ -#if LIBSSH2_AES - &libssh2_crypt_method_aes256_cbc, - &libssh2_crypt_method_rijndael_cbc_lysator_liu_se, /* == aes256-cbc */ - &libssh2_crypt_method_aes192_cbc, - &libssh2_crypt_method_aes128_cbc, -#endif /* LIBSSH2_AES */ -#if LIBSSH2_BLOWFISH - &libssh2_crypt_method_blowfish_cbc, -#endif /* LIBSSH2_BLOWFISH */ -#if LIBSSH2_RC4 - &libssh2_crypt_method_arcfour128, - &libssh2_crypt_method_arcfour, -#endif /* LIBSSH2_RC4 */ -#if LIBSSH2_CAST - &libssh2_crypt_method_cast128_cbc, -#endif /* LIBSSH2_CAST */ -#if LIBSSH2_3DES - &libssh2_crypt_method_3des_cbc, -#endif /* LIBSSH2_DES */ -#ifdef LIBSSH2_CRYPT_NONE - &libssh2_crypt_method_none, -#endif - NULL -}; - -/* Expose to kex.c */ -const LIBSSH2_CRYPT_METHOD ** -libssh2_crypt_methods(void) -{ - return _libssh2_crypt_methods; -} diff --git a/vendor/libssh2-1.4.2/src/crypto.h b/vendor/libssh2-1.4.2/src/crypto.h deleted file mode 100644 index 8cf34f5..0000000 --- a/vendor/libssh2-1.4.2/src/crypto.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2010 Daniel Stenberg - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 LIBSSH2_CRYPTO_H -#define LIBSSH2_CRYPTO_H - -#ifdef LIBSSH2_LIBGCRYPT -#include "libgcrypt.h" -#else -#include "openssl.h" -#endif - -int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, - const unsigned char *edata, - unsigned long elen, - const unsigned char *ndata, - unsigned long nlen, - const unsigned char *ddata, - unsigned long dlen, - const unsigned char *pdata, - unsigned long plen, - const unsigned char *qdata, - unsigned long qlen, - const unsigned char *e1data, - unsigned long e1len, - const unsigned char *e2data, - unsigned long e2len, - const unsigned char *coeffdata, unsigned long coefflen); -int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, - LIBSSH2_SESSION * session, - const char *filename, - unsigned const char *passphrase); -int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, - const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, unsigned long m_len); -int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, - libssh2_rsa_ctx * rsactx, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, - size_t *signature_len); - -int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa, - const unsigned char *pdata, - unsigned long plen, - const unsigned char *qdata, - unsigned long qlen, - const unsigned char *gdata, - unsigned long glen, - const unsigned char *ydata, - unsigned long ylen, - const unsigned char *x, unsigned long x_len); -int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, - LIBSSH2_SESSION * session, - const char *filename, - unsigned const char *passphrase); -int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, - const unsigned char *sig, - const unsigned char *m, unsigned long m_len); -int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, - const unsigned char *hash, - unsigned long hash_len, unsigned char *sig); - -int _libssh2_cipher_init(_libssh2_cipher_ctx * h, - _libssh2_cipher_type(algo), - unsigned char *iv, - unsigned char *secret, int encrypt); - -int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, - _libssh2_cipher_type(algo), - int encrypt, unsigned char *block); - -int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase); - -void _libssh2_init_aes_ctr(void); - -#endif diff --git a/vendor/libssh2-1.4.2/src/global.c b/vendor/libssh2-1.4.2/src/global.c deleted file mode 100644 index dc45e70..0000000 --- a/vendor/libssh2-1.4.2/src/global.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2010 Lars Nordin - * Copyright (C) 2010 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -static int _libssh2_initialized = 0; -static int _libssh2_init_flags = 0; - -LIBSSH2_API int -libssh2_init(int flags) -{ - if (_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) { - libssh2_crypto_init(); - _libssh2_init_aes_ctr(); - } - - _libssh2_initialized++; - _libssh2_init_flags |= flags; - - return 0; -} - -LIBSSH2_API void -libssh2_exit(void) -{ - if (_libssh2_initialized == 0) - return; - - _libssh2_initialized--; - - if (!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) { - libssh2_crypto_exit(); - } - - return; -} - -void -_libssh2_init_if_needed(void) -{ - if (_libssh2_initialized == 0) - (void)libssh2_init (0); -} diff --git a/vendor/libssh2-1.4.2/src/hostkey.c b/vendor/libssh2-1.4.2/src/hostkey.c deleted file mode 100644 index 53f7479..0000000 --- a/vendor/libssh2-1.4.2/src/hostkey.c +++ /dev/null @@ -1,485 +0,0 @@ -/* Copyright (c) 2004-2006, Sara Golemon - * Copyright (c) 2009 by Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include "misc.h" - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#if LIBSSH2_RSA -/* *********** - * ssh-rsa * - *********** */ - -static int hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session, - void **abstract); - -/* - * hostkey_method_ssh_rsa_init - * - * Initialize the server hostkey working area with e/n pair - */ -static int -hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, - const unsigned char *hostkey_data, - size_t hostkey_data_len, - void **abstract) -{ - libssh2_rsa_ctx *rsactx; - const unsigned char *s, *e, *n; - unsigned long len, e_len, n_len; - - (void) hostkey_data_len; - - if (*abstract) { - hostkey_method_ssh_rsa_dtor(session, abstract); - *abstract = NULL; - } - - s = hostkey_data; - len = _libssh2_ntohu32(s); - s += 4; - - if (len != 7 || strncmp((char *) s, "ssh-rsa", 7) != 0) { - return -1; - } - s += 7; - - e_len = _libssh2_ntohu32(s); - s += 4; - - e = s; - s += e_len; - n_len = _libssh2_ntohu32(s); - s += 4; - n = s; - - if (_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) - return -1; - - *abstract = rsactx; - - return 0; -} - -/* - * hostkey_method_ssh_rsa_initPEM - * - * Load a Private Key from a PEM file - */ -static int -hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session, - const char *privkeyfile, - unsigned const char *passphrase, - void **abstract) -{ - libssh2_rsa_ctx *rsactx; - int ret; - - if (*abstract) { - hostkey_method_ssh_rsa_dtor(session, abstract); - *abstract = NULL; - } - - ret = _libssh2_rsa_new_private(&rsactx, session, privkeyfile, passphrase); - if (ret) { - return -1; - } - - *abstract = rsactx; - - return 0; -} - -/* - * hostkey_method_ssh_rsa_sign - * - * Verify signature created by remote - */ -static int -hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session, - const unsigned char *sig, - size_t sig_len, - const unsigned char *m, - size_t m_len, void **abstract) -{ - libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); - (void) session; - - /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */ - sig += 15; - sig_len -= 15; - return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len); -} - -/* - * hostkey_method_ssh_rsa_signv - * - * Construct a signature from an array of vectors - */ -static int -hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session, - unsigned char **signature, - size_t *signature_len, - int veccount, - const struct iovec datavec[], - void **abstract) -{ - libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); - int ret; - int i; - unsigned char hash[SHA_DIGEST_LENGTH]; - libssh2_sha1_ctx ctx; - - libssh2_sha1_init(&ctx); - for(i = 0; i < veccount; i++) { - libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len); - } - libssh2_sha1_final(ctx, hash); - - ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH, - signature, signature_len); - if (ret) { - return -1; - } - - return 0; -} - -/* - * hostkey_method_ssh_rsa_dtor - * - * Shutdown the hostkey - */ -static int -hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session, void **abstract) -{ - libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); - (void) session; - - _libssh2_rsa_free(rsactx); - - *abstract = NULL; - - return 0; -} - -static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa = { - "ssh-rsa", - MD5_DIGEST_LENGTH, - hostkey_method_ssh_rsa_init, - hostkey_method_ssh_rsa_initPEM, - hostkey_method_ssh_rsa_sig_verify, - hostkey_method_ssh_rsa_signv, - NULL, /* encrypt */ - hostkey_method_ssh_rsa_dtor, -}; -#endif /* LIBSSH2_RSA */ - -#if LIBSSH2_DSA -/* *********** - * ssh-dss * - *********** */ - -static int hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session, - void **abstract); - -/* - * hostkey_method_ssh_dss_init - * - * Initialize the server hostkey working area with p/q/g/y set - */ -static int -hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session, - const unsigned char *hostkey_data, - size_t hostkey_data_len, - void **abstract) -{ - libssh2_dsa_ctx *dsactx; - const unsigned char *p, *q, *g, *y, *s; - unsigned long p_len, q_len, g_len, y_len, len; - (void) hostkey_data_len; - - if (*abstract) { - hostkey_method_ssh_dss_dtor(session, abstract); - *abstract = NULL; - } - - s = hostkey_data; - len = _libssh2_ntohu32(s); - s += 4; - if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) { - return -1; - } - s += 7; - - p_len = _libssh2_ntohu32(s); - s += 4; - p = s; - s += p_len; - q_len = _libssh2_ntohu32(s); - s += 4; - q = s; - s += q_len; - g_len = _libssh2_ntohu32(s); - s += 4; - g = s; - s += g_len; - y_len = _libssh2_ntohu32(s); - s += 4; - y = s; - /* s += y_len; */ - - _libssh2_dsa_new(&dsactx, p, p_len, q, q_len, g, g_len, y, y_len, NULL, 0); - - *abstract = dsactx; - - return 0; -} - -/* - * hostkey_method_ssh_dss_initPEM - * - * Load a Private Key from a PEM file - */ -static int -hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session, - const char *privkeyfile, - unsigned const char *passphrase, - void **abstract) -{ - libssh2_dsa_ctx *dsactx; - int ret; - - if (*abstract) { - hostkey_method_ssh_dss_dtor(session, abstract); - *abstract = NULL; - } - - ret = _libssh2_dsa_new_private(&dsactx, session, privkeyfile, passphrase); - if (ret) { - return -1; - } - - *abstract = dsactx; - - return 0; -} - -/* - * libssh2_hostkey_method_ssh_dss_sign - * - * Verify signature created by remote - */ -static int -hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session, - const unsigned char *sig, - size_t sig_len, - const unsigned char *m, - size_t m_len, void **abstract) -{ - libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); - - /* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */ - sig += 15; - sig_len -= 15; - if (sig_len != 40) { - return _libssh2_error(session, LIBSSH2_ERROR_PROTO, - "Invalid DSS signature length"); - } - return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len); -} - -/* - * hostkey_method_ssh_dss_signv - * - * Construct a signature from an array of vectors - */ -static int -hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, - unsigned char **signature, - size_t *signature_len, - int veccount, - const struct iovec datavec[], - void **abstract) -{ - libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); - unsigned char hash[SHA_DIGEST_LENGTH]; - libssh2_sha1_ctx ctx; - int i; - - *signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH); - if (!*signature) { - return -1; - } - - *signature_len = 2 * SHA_DIGEST_LENGTH; - memset(*signature, 0, 2 * SHA_DIGEST_LENGTH); - - libssh2_sha1_init(&ctx); - for(i = 0; i < veccount; i++) { - libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len); - } - libssh2_sha1_final(ctx, hash); - - if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { - LIBSSH2_FREE(session, *signature); - return -1; - } - - return 0; -} - -/* - * libssh2_hostkey_method_ssh_dss_dtor - * - * Shutdown the hostkey method - */ -static int -hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session, void **abstract) -{ - libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); - (void) session; - - _libssh2_dsa_free(dsactx); - - *abstract = NULL; - - return 0; -} - -static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_dss = { - "ssh-dss", - MD5_DIGEST_LENGTH, - hostkey_method_ssh_dss_init, - hostkey_method_ssh_dss_initPEM, - hostkey_method_ssh_dss_sig_verify, - hostkey_method_ssh_dss_signv, - NULL, /* encrypt */ - hostkey_method_ssh_dss_dtor, -}; -#endif /* LIBSSH2_DSA */ - -static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = { -#if LIBSSH2_RSA - &hostkey_method_ssh_rsa, -#endif /* LIBSSH2_RSA */ -#if LIBSSH2_DSA - &hostkey_method_ssh_dss, -#endif /* LIBSSH2_DSA */ - NULL -}; - -const LIBSSH2_HOSTKEY_METHOD ** -libssh2_hostkey_methods(void) -{ - return hostkey_methods; -} - -/* - * libssh2_hostkey_hash - * - * Returns hash signature - * Returned buffer should NOT be freed - * Length of buffer is determined by hash type - * i.e. MD5 == 16, SHA1 == 20 - */ -LIBSSH2_API const char * -libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) -{ - switch (hash_type) { -#if LIBSSH2_MD5 - case LIBSSH2_HOSTKEY_HASH_MD5: - return (char *) session->server_hostkey_md5; - break; -#endif /* LIBSSH2_MD5 */ - case LIBSSH2_HOSTKEY_HASH_SHA1: - return (char *) session->server_hostkey_sha1; - break; - default: - return NULL; - } -} - -static int hostkey_type(const unsigned char *hostkey, size_t len) -{ - const unsigned char rsa[] = { - 0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a' - }; - const unsigned char dss[] = { - 0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's' - }; - - if (len < 11) - return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; - - if (!memcmp(rsa, hostkey, 11)) - return LIBSSH2_HOSTKEY_TYPE_RSA; - - if (!memcmp(dss, hostkey, 11)) - return LIBSSH2_HOSTKEY_TYPE_DSS; - - return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; -} - -/* - * libssh2_session_hostkey() - * - * Returns the server key and length. - * - */ -LIBSSH2_API const char * -libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type) -{ - if(session->server_hostkey_len) { - if(len) - *len = session->server_hostkey_len; - if (type) - *type = hostkey_type(session->server_hostkey, - session->server_hostkey_len); - return (char *) session->server_hostkey; - } - if(len) - *len = 0; - return NULL; -} - diff --git a/vendor/libssh2-1.4.2/src/keepalive.c b/vendor/libssh2-1.4.2/src/keepalive.c deleted file mode 100644 index 260206a..0000000 --- a/vendor/libssh2-1.4.2/src/keepalive.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2010 Simon Josefsson - * Author: Simon Josefsson - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include "transport.h" /* _libssh2_transport_write */ - -/* Keep-alive stuff. */ - -LIBSSH2_API void -libssh2_keepalive_config (LIBSSH2_SESSION *session, - int want_reply, - unsigned interval) -{ - if (interval == 1) - session->keepalive_interval = 2; - else - session->keepalive_interval = interval; - session->keepalive_want_reply = want_reply ? 1 : 0; -} - -LIBSSH2_API int -libssh2_keepalive_send (LIBSSH2_SESSION *session, - int *seconds_to_next) -{ - time_t now; - - if (!session->keepalive_interval) { - if (seconds_to_next) - *seconds_to_next = 0; - return 0; - } - - now = time (NULL); - - if (session->keepalive_last_sent + session->keepalive_interval <= now) { - /* Format is - "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */ - unsigned char keepalive_data[] - = "\x50\x00\x00\x00\x15keepalive@libssh2.orgW"; - size_t len = sizeof (keepalive_data) - 1; - int rc; - - keepalive_data[len - 1] = session->keepalive_want_reply; - - rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0); - /* Silently ignore PACKET_EAGAIN here: if the write buffer is - already full, sending another keepalive is not useful. */ - if (rc && rc != LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send keepalive message"); - return rc; - } - - session->keepalive_last_sent = now; - if (seconds_to_next) - *seconds_to_next = session->keepalive_interval; - } else if (seconds_to_next) { - *seconds_to_next = (int) session->keepalive_last_sent - + session->keepalive_interval - now; - } - - return 0; -} diff --git a/vendor/libssh2-1.4.2/src/kex.c b/vendor/libssh2-1.4.2/src/kex.c deleted file mode 100644 index 0a72cb7..0000000 --- a/vendor/libssh2-1.4.2/src/kex.c +++ /dev/null @@ -1,2008 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010, Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -#include "transport.h" -#include "comp.h" -#include "mac.h" - -/* TODO: Switch this to an inline and handle alloc() failures */ -/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */ -#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \ - { \ - libssh2_sha1_ctx hash; \ - unsigned long len = 0; \ - if (!(value)) { \ - value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \ - } \ - if (value) \ - while (len < (unsigned long)reqlen) { \ - libssh2_sha1_init(&hash); \ - libssh2_sha1_update(hash, exchange_state->k_value, \ - exchange_state->k_value_len); \ - libssh2_sha1_update(hash, exchange_state->h_sig_comp, \ - SHA_DIGEST_LENGTH); \ - if (len > 0) { \ - libssh2_sha1_update(hash, value, len); \ - } else { \ - libssh2_sha1_update(hash, (version), 1); \ - libssh2_sha1_update(hash, session->session_id, \ - session->session_id_len); \ - } \ - libssh2_sha1_final(hash, (value) + len); \ - len += SHA_DIGEST_LENGTH; \ - } \ - } - -/* - * diffie_hellman_sha1 - * - * Diffie Hellman Key Exchange, Group Agnostic - */ -static int diffie_hellman_sha1(LIBSSH2_SESSION *session, - _libssh2_bn *g, - _libssh2_bn *p, - int group_order, - unsigned char packet_type_init, - unsigned char packet_type_reply, - unsigned char *midhash, - unsigned long midhash_len, - kmdhgGPsha1kex_state_t *exchange_state) -{ - int ret = 0; - int rc; - - if (exchange_state->state == libssh2_NB_state_idle) { - /* Setup initial values */ - exchange_state->e_packet = NULL; - exchange_state->s_packet = NULL; - exchange_state->k_value = NULL; - exchange_state->ctx = _libssh2_bn_ctx_new(); - exchange_state->x = _libssh2_bn_init(); /* Random from client */ - exchange_state->e = _libssh2_bn_init(); /* g^x mod p */ - exchange_state->f = _libssh2_bn_init(); /* g^(Random from server) mod p */ - exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */ - - /* Zero the whole thing out */ - memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t)); - - /* Generate x and e */ - _libssh2_bn_rand(exchange_state->x, group_order, 0, -1); - _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p, - exchange_state->ctx); - - /* Send KEX init */ - /* packet_type(1) + String Length(4) + leading 0(1) */ - exchange_state->e_packet_len = - _libssh2_bn_bytes(exchange_state->e) + 6; - if (_libssh2_bn_bits(exchange_state->e) % 8) { - /* Leading 00 not needed */ - exchange_state->e_packet_len--; - } - - exchange_state->e_packet = - LIBSSH2_ALLOC(session, exchange_state->e_packet_len); - if (!exchange_state->e_packet) { - ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Out of memory error"); - goto clean_exit; - } - exchange_state->e_packet[0] = packet_type_init; - _libssh2_htonu32(exchange_state->e_packet + 1, - exchange_state->e_packet_len - 5); - if (_libssh2_bn_bits(exchange_state->e) % 8) { - _libssh2_bn_to_bin(exchange_state->e, - exchange_state->e_packet + 5); - } else { - exchange_state->e_packet[5] = 0; - _libssh2_bn_to_bin(exchange_state->e, - exchange_state->e_packet + 6); - } - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending KEX packet %d", - (int) packet_type_init); - exchange_state->state = libssh2_NB_state_created; - } - - if (exchange_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, exchange_state->e_packet, - exchange_state->e_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, - "Unable to send KEX init message"); - goto clean_exit; - } - exchange_state->state = libssh2_NB_state_sent; - } - - if (exchange_state->state == libssh2_NB_state_sent) { - if (session->burn_optimistic_kexinit) { - /* The first KEX packet to come along will be the guess initially - * sent by the server. That guess turned out to be wrong so we - * need to silently ignore it */ - int burn_type; - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Waiting for badly guessed KEX packet (to be ignored)"); - burn_type = - _libssh2_packet_burn(session, &exchange_state->burn_state); - if (burn_type == LIBSSH2_ERROR_EAGAIN) { - return burn_type; - } else if (burn_type <= 0) { - /* Failed to receive a packet */ - ret = burn_type; - goto clean_exit; - } - session->burn_optimistic_kexinit = 0; - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Burnt packet of type: %02x", - (unsigned int) burn_type); - } - - exchange_state->state = libssh2_NB_state_sent1; - } - - if (exchange_state->state == libssh2_NB_state_sent1) { - /* Wait for KEX reply */ - rc = _libssh2_packet_require(session, packet_type_reply, - &exchange_state->s_packet, - &exchange_state->s_packet_len, 0, NULL, - 0, &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - if (rc) { - ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, - "Timed out waiting for KEX reply"); - goto clean_exit; - } - - /* Parse KEXDH_REPLY */ - exchange_state->s = exchange_state->s_packet + 1; - - session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - session->server_hostkey = - LIBSSH2_ALLOC(session, session->server_hostkey_len); - if (!session->server_hostkey) { - ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for a copy " - "of the host key"); - goto clean_exit; - } - memcpy(session->server_hostkey, exchange_state->s, - session->server_hostkey_len); - exchange_state->s += session->server_hostkey_len; - -#if LIBSSH2_MD5 - { - libssh2_md5_ctx fingerprint_ctx; - - libssh2_md5_init(&fingerprint_ctx); - libssh2_md5_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_md5_final(fingerprint_ctx, session->server_hostkey_md5); - } -#ifdef LIBSSH2DEBUG - { - char fingerprint[50], *fprint = fingerprint; - int i; - for(i = 0; i < 16; i++, fprint += 3) { - snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]); - } - *(--fprint) = '\0'; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Server's MD5 Fingerprint: %s", fingerprint); - } -#endif /* LIBSSH2DEBUG */ -#endif /* ! LIBSSH2_MD5 */ - - { - libssh2_sha1_ctx fingerprint_ctx; - - libssh2_sha1_init(&fingerprint_ctx); - libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_sha1_final(fingerprint_ctx, session->server_hostkey_sha1); - } -#ifdef LIBSSH2DEBUG - { - char fingerprint[64], *fprint = fingerprint; - int i; - - for(i = 0; i < 20; i++, fprint += 3) { - snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]); - } - *(--fprint) = '\0'; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Server's SHA1 Fingerprint: %s", fingerprint); - } -#endif /* LIBSSH2DEBUG */ - - if (session->hostkey->init(session, session->server_hostkey, - session->server_hostkey_len, - &session->server_hostkey_abstract)) { - ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, - "Unable to initialize hostkey importer"); - goto clean_exit; - } - - exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->f_value = exchange_state->s; - exchange_state->s += exchange_state->f_value_len; - _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len, - exchange_state->f_value); - - exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->h_sig = exchange_state->s; - - /* Compute the shared secret */ - _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f, - exchange_state->x, p, exchange_state->ctx); - exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5; - if (_libssh2_bn_bits(exchange_state->k) % 8) { - /* don't need leading 00 */ - exchange_state->k_value_len--; - } - exchange_state->k_value = - LIBSSH2_ALLOC(session, exchange_state->k_value_len); - if (!exchange_state->k_value) { - ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate buffer for K"); - goto clean_exit; - } - _libssh2_htonu32(exchange_state->k_value, - exchange_state->k_value_len - 4); - if (_libssh2_bn_bits(exchange_state->k) % 8) { - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); - } else { - exchange_state->k_value[4] = 0; - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); - } - - libssh2_sha1_init(&exchange_state->exchange_hash); - if (session->local.banner) { - _libssh2_htonu32(exchange_state->h_sig_comp, - strlen((char *) session->local.banner) - 2); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); - libssh2_sha1_update(exchange_state->exchange_hash, - (char *) session->local.banner, - strlen((char *) session->local.banner) - 2); - } else { - _libssh2_htonu32(exchange_state->h_sig_comp, - sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); - libssh2_sha1_update(exchange_state->exchange_hash, - LIBSSH2_SSH_DEFAULT_BANNER, - sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); - } - - _libssh2_htonu32(exchange_state->h_sig_comp, - strlen((char *) session->remote.banner)); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); - libssh2_sha1_update(exchange_state->exchange_hash, - session->remote.banner, - strlen((char *) session->remote.banner)); - - _libssh2_htonu32(exchange_state->h_sig_comp, - session->local.kexinit_len); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); - libssh2_sha1_update(exchange_state->exchange_hash, - session->local.kexinit, - session->local.kexinit_len); - - _libssh2_htonu32(exchange_state->h_sig_comp, - session->remote.kexinit_len); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); - libssh2_sha1_update(exchange_state->exchange_hash, - session->remote.kexinit, - session->remote.kexinit_len); - - _libssh2_htonu32(exchange_state->h_sig_comp, - session->server_hostkey_len); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); - libssh2_sha1_update(exchange_state->exchange_hash, - session->server_hostkey, - session->server_hostkey_len); - - if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) { - /* diffie-hellman-group-exchange hashes additional fields */ -#ifdef LIBSSH2_DH_GEX_NEW - _libssh2_htonu32(exchange_state->h_sig_comp, - LIBSSH2_DH_GEX_MINGROUP); - _libssh2_htonu32(exchange_state->h_sig_comp + 4, - LIBSSH2_DH_GEX_OPTGROUP); - _libssh2_htonu32(exchange_state->h_sig_comp + 8, - LIBSSH2_DH_GEX_MAXGROUP); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 12); -#else - _libssh2_htonu32(exchange_state->h_sig_comp, - LIBSSH2_DH_GEX_OPTGROUP); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); -#endif - } - - if (midhash) { - libssh2_sha1_update(exchange_state->exchange_hash, midhash, - midhash_len); - } - - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->e_packet + 1, - exchange_state->e_packet_len - 1); - - _libssh2_htonu32(exchange_state->h_sig_comp, - exchange_state->f_value_len); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->h_sig_comp, 4); - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->f_value, - exchange_state->f_value_len); - - libssh2_sha1_update(exchange_state->exchange_hash, - exchange_state->k_value, - exchange_state->k_value_len); - - libssh2_sha1_final(exchange_state->exchange_hash, - exchange_state->h_sig_comp); - - if (session->hostkey-> - sig_verify(session, exchange_state->h_sig, - exchange_state->h_sig_len, exchange_state->h_sig_comp, - 20, &session->server_hostkey_abstract)) { - ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN, - "Unable to verify hostkey signature"); - goto clean_exit; - } - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending NEWKEYS message"); - exchange_state->c = SSH_MSG_NEWKEYS; - - exchange_state->state = libssh2_NB_state_sent2; - } - - if (exchange_state->state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message"); - goto clean_exit; - } - - exchange_state->state = libssh2_NB_state_sent3; - } - - if (exchange_state->state == libssh2_NB_state_sent3) { - rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS, - &exchange_state->tmp, - &exchange_state->tmp_len, 0, NULL, 0, - &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS"); - goto clean_exit; - } - /* The first key exchange has been performed, - switch to active crypt/comp/mac mode */ - session->state |= LIBSSH2_STATE_NEWKEYS; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message"); - - /* This will actually end up being just packet_type(1) - for this packet type anyway */ - LIBSSH2_FREE(session, exchange_state->tmp); - - if (!session->session_id) { - session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH); - if (!session->session_id) { - ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate buffer for SHA digest"); - goto clean_exit; - } - memcpy(session->session_id, exchange_state->h_sig_comp, - SHA_DIGEST_LENGTH); - session->session_id_len = SHA_DIGEST_LENGTH; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated"); - } - - /* Cleanup any existing cipher */ - if (session->local.crypt->dtor) { - session->local.crypt->dtor(session, - &session->local.crypt_abstract); - } - - /* Calculate IV/Secret/Key for each direction */ - if (session->local.crypt->init) { - unsigned char *iv = NULL, *secret = NULL; - int free_iv = 0, free_secret = 0; - - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, - session->local.crypt-> - iv_len, "A"); - if (!iv) { - ret = -1; - goto clean_exit; - } - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, - session->local.crypt-> - secret_len, "C"); - if (!secret) { - LIBSSH2_FREE(session, iv); - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - if (session->local.crypt-> - init(session, session->local.crypt, iv, &free_iv, secret, - &free_secret, 1, &session->local.crypt_abstract)) { - LIBSSH2_FREE(session, iv); - LIBSSH2_FREE(session, secret); - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - - if (free_iv) { - memset(iv, 0, session->local.crypt->iv_len); - LIBSSH2_FREE(session, iv); - } - - if (free_secret) { - memset(secret, 0, session->local.crypt->secret_len); - LIBSSH2_FREE(session, secret); - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Client to Server IV and Key calculated"); - - if (session->remote.crypt->dtor) { - /* Cleanup any existing cipher */ - session->remote.crypt->dtor(session, - &session->remote.crypt_abstract); - } - - if (session->remote.crypt->init) { - unsigned char *iv = NULL, *secret = NULL; - int free_iv = 0, free_secret = 0; - - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, - session->remote.crypt-> - iv_len, "B"); - if (!iv) { - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, - session->remote.crypt-> - secret_len, "D"); - if (!secret) { - LIBSSH2_FREE(session, iv); - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - if (session->remote.crypt-> - init(session, session->remote.crypt, iv, &free_iv, secret, - &free_secret, 0, &session->remote.crypt_abstract)) { - LIBSSH2_FREE(session, iv); - LIBSSH2_FREE(session, secret); - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - - if (free_iv) { - memset(iv, 0, session->remote.crypt->iv_len); - LIBSSH2_FREE(session, iv); - } - - if (free_secret) { - memset(secret, 0, session->remote.crypt->secret_len); - LIBSSH2_FREE(session, secret); - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Server to Client IV and Key calculated"); - - if (session->local.mac->dtor) { - session->local.mac->dtor(session, &session->local.mac_abstract); - } - - if (session->local.mac->init) { - unsigned char *key = NULL; - int free_key = 0; - - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, - session->local.mac-> - key_len, "E"); - if (!key) { - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - session->local.mac->init(session, key, &free_key, - &session->local.mac_abstract); - - if (free_key) { - memset(key, 0, session->local.mac->key_len); - LIBSSH2_FREE(session, key); - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Client to Server HMAC Key calculated"); - - if (session->remote.mac->dtor) { - session->remote.mac->dtor(session, &session->remote.mac_abstract); - } - - if (session->remote.mac->init) { - unsigned char *key = NULL; - int free_key = 0; - - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, - session->remote.mac-> - key_len, "F"); - if (!key) { - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - session->remote.mac->init(session, key, &free_key, - &session->remote.mac_abstract); - - if (free_key) { - memset(key, 0, session->remote.mac->key_len); - LIBSSH2_FREE(session, key); - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Server to Client HMAC Key calculated"); - - /* Initialize compression for each direction */ - - /* Cleanup any existing compression */ - if (session->local.comp && session->local.comp->dtor) { - session->local.comp->dtor(session, 1, - &session->local.comp_abstract); - } - - if (session->local.comp && session->local.comp->init) { - if (session->local.comp->init(session, 1, - &session->local.comp_abstract)) { - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Client to Server compression initialized"); - - if (session->remote.comp && session->remote.comp->dtor) { - session->remote.comp->dtor(session, 0, - &session->remote.comp_abstract); - } - - if (session->remote.comp && session->remote.comp->init) { - if (session->remote.comp->init(session, 0, - &session->remote.comp_abstract)) { - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Server to Client compression initialized"); - - } - - clean_exit: - _libssh2_bn_free(exchange_state->x); - exchange_state->x = NULL; - _libssh2_bn_free(exchange_state->e); - exchange_state->e = NULL; - _libssh2_bn_free(exchange_state->f); - exchange_state->f = NULL; - _libssh2_bn_free(exchange_state->k); - exchange_state->k = NULL; - _libssh2_bn_ctx_free(exchange_state->ctx); - exchange_state->ctx = NULL; - - if (exchange_state->e_packet) { - LIBSSH2_FREE(session, exchange_state->e_packet); - exchange_state->e_packet = NULL; - } - - if (exchange_state->s_packet) { - LIBSSH2_FREE(session, exchange_state->s_packet); - exchange_state->s_packet = NULL; - } - - if (exchange_state->k_value) { - LIBSSH2_FREE(session, exchange_state->k_value); - exchange_state->k_value = NULL; - } - - exchange_state->state = libssh2_NB_state_idle; - - return ret; -} - - - -/* kex_method_diffie_hellman_group1_sha1_key_exchange - * Diffie-Hellman Group1 (Actually Group2) Key Exchange using SHA1 - */ -static int -kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session, - key_exchange_state_low_t - * key_state) -{ - static const unsigned char p_value[128] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF - }; - - int ret; - - if (key_state->state == libssh2_NB_state_idle) { - /* g == 2 */ - key_state->p = _libssh2_bn_init(); /* SSH2 defined value (p_value) */ - key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */ - - /* Initialize P and G */ - _libssh2_bn_set_word(key_state->g, 2); - _libssh2_bn_from_bin(key_state->p, 128, p_value); - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group1 Key Exchange"); - - key_state->state = libssh2_NB_state_created; - } - ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128, - SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, - NULL, 0, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - - _libssh2_bn_free(key_state->p); - key_state->p = NULL; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; - key_state->state = libssh2_NB_state_idle; - - return ret; -} - - - -/* kex_method_diffie_hellman_group14_sha1_key_exchange - * Diffie-Hellman Group14 Key Exchange using SHA1 - */ -static int -kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session, - key_exchange_state_low_t - * key_state) -{ - static const unsigned char p_value[256] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF - }; - int ret; - - if (key_state->state == libssh2_NB_state_idle) { - key_state->p = _libssh2_bn_init(); /* SSH2 defined value (p_value) */ - key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */ - - /* g == 2 */ - /* Initialize P and G */ - _libssh2_bn_set_word(key_state->g, 2); - _libssh2_bn_from_bin(key_state->p, 256, p_value); - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group14 Key Exchange"); - - key_state->state = libssh2_NB_state_created; - } - ret = diffie_hellman_sha1(session, key_state->g, key_state->p, - 256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, - NULL, 0, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - - key_state->state = libssh2_NB_state_idle; - _libssh2_bn_free(key_state->p); - key_state->p = NULL; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; - - return ret; -} - - - -/* kex_method_diffie_hellman_group_exchange_sha1_key_exchange - * Diffie-Hellman Group Exchange Key Exchange using SHA1 - * Negotiates random(ish) group for secret derivation - */ -static int -kex_method_diffie_hellman_group_exchange_sha1_key_exchange -(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) -{ - unsigned long p_len, g_len; - int ret = 0; - int rc; - - if (key_state->state == libssh2_NB_state_idle) { - key_state->p = _libssh2_bn_init(); - key_state->g = _libssh2_bn_init(); - /* Ask for a P and G pair */ -#ifdef LIBSSH2_DH_GEX_NEW - key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST; - _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_MINGROUP); - _libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP); - _libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP); - key_state->request_len = 13; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group-Exchange (New Method)"); -#else - key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD; - _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP); - key_state->request_len = 5; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group-Exchange (Old Method)"); -#endif - - key_state->state = libssh2_NB_state_created; - } - - if (key_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, key_state->request, - key_state->request_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, - "Unable to send Group Exchange Request"); - goto dh_gex_clean_exit; - } - - key_state->state = libssh2_NB_state_sent; - } - - if (key_state->state == libssh2_NB_state_sent) { - rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP, - &key_state->data, &key_state->data_len, - 0, NULL, 0, &key_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, - "Timeout waiting for GEX_GROUP reply"); - goto dh_gex_clean_exit; - } - - key_state->state = libssh2_NB_state_sent1; - } - - if (key_state->state == libssh2_NB_state_sent1) { - unsigned char *s = key_state->data + 1; - p_len = _libssh2_ntohu32(s); - s += 4; - _libssh2_bn_from_bin(key_state->p, p_len, s); - s += p_len; - - g_len = _libssh2_ntohu32(s); - s += 4; - _libssh2_bn_from_bin(key_state->g, g_len, s); - - ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len, - SSH_MSG_KEX_DH_GEX_INIT, - SSH_MSG_KEX_DH_GEX_REPLY, - key_state->data + 1, - key_state->data_len - 1, - &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - - LIBSSH2_FREE(session, key_state->data); - } - - dh_gex_clean_exit: - key_state->state = libssh2_NB_state_idle; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; - _libssh2_bn_free(key_state->p); - key_state->p = NULL; - - return ret; -} - - - -#define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY 0x0001 -#define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY 0x0002 - -static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group1_sha1 = { - "diffie-hellman-group1-sha1", - kex_method_diffie_hellman_group1_sha1_key_exchange, - LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, -}; - -static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha1 = { - "diffie-hellman-group14-sha1", - kex_method_diffie_hellman_group14_sha1_key_exchange, - LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, -}; - -static const LIBSSH2_KEX_METHOD -kex_method_diffie_helman_group_exchange_sha1 = { - "diffie-hellman-group-exchange-sha1", - kex_method_diffie_hellman_group_exchange_sha1_key_exchange, - LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, -}; - -static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { - &kex_method_diffie_helman_group14_sha1, - &kex_method_diffie_helman_group_exchange_sha1, - &kex_method_diffie_helman_group1_sha1, - NULL -}; - -typedef struct _LIBSSH2_COMMON_METHOD -{ - const char *name; -} LIBSSH2_COMMON_METHOD; - -/* kex_method_strlen - * Calculate the length of a particular method list's resulting string - * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1 (because the last coma isn't used) - * Another sign of bad coding practices gone mad. Pretend you don't see this. - */ -static size_t -kex_method_strlen(LIBSSH2_COMMON_METHOD ** method) -{ - size_t len = 0; - - if (!method || !*method) { - return 0; - } - - while (*method && (*method)->name) { - len += strlen((*method)->name) + 1; - method++; - } - - return len - 1; -} - - - -/* kex_method_list - * Generate formatted preference list in buf - */ -static size_t -kex_method_list(unsigned char *buf, size_t list_strlen, - LIBSSH2_COMMON_METHOD ** method) -{ - _libssh2_htonu32(buf, list_strlen); - buf += 4; - - if (!method || !*method) { - return 4; - } - - while (*method && (*method)->name) { - int mlen = strlen((*method)->name); - memcpy(buf, (*method)->name, mlen); - buf += mlen; - *(buf++) = ','; - method++; - } - - return list_strlen + 4; -} - - - -#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar) \ - ((prefvar) ? strlen(prefvar) : \ - kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar))) - -#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \ - if (prefvar) { \ - _libssh2_htonu32((buf), (prefvarlen)); \ - buf += 4; \ - memcpy((buf), (prefvar), (prefvarlen)); \ - buf += (prefvarlen); \ - } else { \ - buf += kex_method_list((buf), (prefvarlen), \ - (LIBSSH2_COMMON_METHOD**)(defaultvar)); \ - } - -/* kexinit - * Send SSH_MSG_KEXINIT packet - */ -static int kexinit(LIBSSH2_SESSION * session) -{ - /* 62 = packet_type(1) + cookie(16) + first_packet_follows(1) + - reserved(4) + length longs(40) */ - size_t data_len = 62; - size_t kex_len, hostkey_len = 0; - size_t crypt_cs_len, crypt_sc_len; - size_t comp_cs_len, comp_sc_len; - size_t mac_cs_len, mac_sc_len; - size_t lang_cs_len, lang_sc_len; - unsigned char *data, *s; - int rc; - - if (session->kexinit_state == libssh2_NB_state_idle) { - kex_len = - LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods); - hostkey_len = - LIBSSH2_METHOD_PREFS_LEN(session->hostkey_prefs, - libssh2_hostkey_methods()); - crypt_cs_len = - LIBSSH2_METHOD_PREFS_LEN(session->local.crypt_prefs, - libssh2_crypt_methods()); - crypt_sc_len = - LIBSSH2_METHOD_PREFS_LEN(session->remote.crypt_prefs, - libssh2_crypt_methods()); - mac_cs_len = - LIBSSH2_METHOD_PREFS_LEN(session->local.mac_prefs, - _libssh2_mac_methods()); - mac_sc_len = - LIBSSH2_METHOD_PREFS_LEN(session->remote.mac_prefs, - _libssh2_mac_methods()); - comp_cs_len = - LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs, - _libssh2_comp_methods(session)); - comp_sc_len = - LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs, - _libssh2_comp_methods(session)); - lang_cs_len = - LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL); - lang_sc_len = - LIBSSH2_METHOD_PREFS_LEN(session->remote.lang_prefs, NULL); - - data_len += kex_len + hostkey_len + crypt_cs_len + crypt_sc_len + - comp_cs_len + comp_sc_len + mac_cs_len + mac_sc_len + - lang_cs_len + lang_sc_len; - - s = data = LIBSSH2_ALLOC(session, data_len); - if (!data) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory"); - } - - *(s++) = SSH_MSG_KEXINIT; - - _libssh2_random(s, 16); - s += 16; - - /* Ennumerating through these lists twice is probably (certainly?) - inefficient from a CPU standpoint, but it saves multiple - malloc/realloc calls */ - LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs, - libssh2_kex_methods); - LIBSSH2_METHOD_PREFS_STR(s, hostkey_len, session->hostkey_prefs, - libssh2_hostkey_methods()); - LIBSSH2_METHOD_PREFS_STR(s, crypt_cs_len, session->local.crypt_prefs, - libssh2_crypt_methods()); - LIBSSH2_METHOD_PREFS_STR(s, crypt_sc_len, session->remote.crypt_prefs, - libssh2_crypt_methods()); - LIBSSH2_METHOD_PREFS_STR(s, mac_cs_len, session->local.mac_prefs, - _libssh2_mac_methods()); - LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs, - _libssh2_mac_methods()); - LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs, - _libssh2_comp_methods(session)); - LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs, - _libssh2_comp_methods(session)); - LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs, - NULL); - LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs, - NULL); - - /* No optimistic KEX packet follows */ - /* Deal with optimistic packets - * session->flags |= KEXINIT_OPTIMISTIC - * session->flags |= KEXINIT_METHODSMATCH - */ - *(s++) = 0; - - /* Reserved == 0 */ - _libssh2_htonu32(s, 0); - -#ifdef LIBSSH2DEBUG - { - /* Funnily enough, they'll all "appear" to be '\0' terminated */ - unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */ - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent KEX: %s", p); - p += kex_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent HOSTKEY: %s", p); - p += hostkey_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_CS: %s", p); - p += crypt_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_SC: %s", p); - p += crypt_sc_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_CS: %s", p); - p += mac_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_SC: %s", p); - p += mac_sc_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_CS: %s", p); - p += comp_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_SC: %s", p); - p += comp_sc_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_CS: %s", p); - p += lang_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_SC: %s", p); - p += lang_sc_len + 4; - } -#endif /* LIBSSH2DEBUG */ - - session->kexinit_state = libssh2_NB_state_created; - } else { - data = session->kexinit_data; - data_len = session->kexinit_data_len; - /* zap the variables to ensure there is NOT a double free later */ - session->kexinit_data = NULL; - session->kexinit_data_len = 0; - } - - rc = _libssh2_transport_send(session, data, data_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - session->kexinit_data = data; - session->kexinit_data_len = data_len; - return rc; - } - else if (rc) { - LIBSSH2_FREE(session, data); - session->kexinit_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send KEXINIT packet to remote host"); - - } - - if (session->local.kexinit) { - LIBSSH2_FREE(session, session->local.kexinit); - } - - session->local.kexinit = data; - session->local.kexinit_len = data_len; - - session->kexinit_state = libssh2_NB_state_idle; - - return 0; -} - -/* kex_agree_instr - * Kex specific variant of strstr() - * Needle must be preceed by BOL or ',', and followed by ',' or EOL - */ -static unsigned char * -kex_agree_instr(unsigned char *haystack, unsigned long haystack_len, - const unsigned char *needle, unsigned long needle_len) -{ - unsigned char *s; - - /* Haystack too short to bother trying */ - if (haystack_len < needle_len) { - return NULL; - } - - /* Needle at start of haystack */ - if ((strncmp((char *) haystack, (char *) needle, needle_len) == 0) && - (needle_len == haystack_len || haystack[needle_len] == ',')) { - return haystack; - } - - s = haystack; - /* Search until we run out of comas or we run out of haystack, - whichever comes first */ - while ((s = (unsigned char *) strchr((char *) s, ',')) - && ((haystack_len - (s - haystack)) > needle_len)) { - s++; - /* Needle at X position */ - if ((strncmp((char *) s, (char *) needle, needle_len) == 0) && - (((s - haystack) + needle_len) == haystack_len - || s[needle_len] == ',')) { - return s; - } - } - - return NULL; -} - - - -/* kex_get_method_by_name - */ -static const LIBSSH2_COMMON_METHOD * -kex_get_method_by_name(const char *name, size_t name_len, - const LIBSSH2_COMMON_METHOD ** methodlist) -{ - while (*methodlist) { - if ((strlen((*methodlist)->name) == name_len) && - (strncmp((*methodlist)->name, name, name_len) == 0)) { - return *methodlist; - } - methodlist++; - } - return NULL; -} - - - -/* kex_agree_hostkey - * Agree on a Hostkey which works with this kex - */ -static int kex_agree_hostkey(LIBSSH2_SESSION * session, - unsigned long kex_flags, - unsigned char *hostkey, unsigned long hostkey_len) -{ - const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods(); - unsigned char *s; - - if (session->hostkey_prefs) { - s = (unsigned char *) session->hostkey_prefs; - - while (s && *s) { - unsigned char *p = (unsigned char *) strchr((char *) s, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if (kex_agree_instr(hostkey, hostkey_len, s, method_len)) { - const LIBSSH2_HOSTKEY_METHOD *method = - (const LIBSSH2_HOSTKEY_METHOD *) - kex_get_method_by_name((char *) s, method_len, - (const LIBSSH2_COMMON_METHOD **) - hostkeyp); - - if (!method) { - /* Invalid method -- Should never be reached */ - return -1; - } - - /* So far so good, but does it suit our purposes? (Encrypting - vs Signing) */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == - 0) || (method->encrypt)) { - /* Either this hostkey can do encryption or this kex just - doesn't require it */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) - == 0) || (method->sig_verify)) { - /* Either this hostkey can do signing or this kex just - doesn't require it */ - session->hostkey = method; - return 0; - } - } - } - - s = p ? p + 1 : NULL; - } - return -1; - } - - while (hostkeyp && (*hostkeyp) && (*hostkeyp)->name) { - s = kex_agree_instr(hostkey, hostkey_len, - (unsigned char *) (*hostkeyp)->name, - strlen((*hostkeyp)->name)); - if (s) { - /* So far so good, but does it suit our purposes? (Encrypting vs - Signing) */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) || - ((*hostkeyp)->encrypt)) { - /* Either this hostkey can do encryption or this kex just - doesn't require it */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) == - 0) || ((*hostkeyp)->sig_verify)) { - /* Either this hostkey can do signing or this kex just - doesn't require it */ - session->hostkey = *hostkeyp; - return 0; - } - } - } - hostkeyp++; - } - - return -1; -} - - - -/* kex_agree_kex_hostkey - * Agree on a Key Exchange method and a hostkey encoding type - */ -static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, - unsigned long kex_len, unsigned char *hostkey, - unsigned long hostkey_len) -{ - const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods; - unsigned char *s; - - if (session->kex_prefs) { - s = (unsigned char *) session->kex_prefs; - - while (s && *s) { - unsigned char *q, *p = (unsigned char *) strchr((char *) s, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if ((q = kex_agree_instr(kex, kex_len, s, method_len))) { - const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *) - kex_get_method_by_name((char *) s, method_len, - (const LIBSSH2_COMMON_METHOD **) - kexp); - - if (!method) { - /* Invalid method -- Should never be reached */ - return -1; - } - - /* We've agreed on a key exchange method, - * Can we agree on a hostkey that works with this kex? - */ - if (kex_agree_hostkey(session, method->flags, hostkey, - hostkey_len) == 0) { - session->kex = method; - if (session->burn_optimistic_kexinit && (kex == q)) { - /* Server sent an optimistic packet, - * and client agrees with preference - * cancel burning the first KEX_INIT packet that comes in */ - session->burn_optimistic_kexinit = 0; - } - return 0; - } - } - - s = p ? p + 1 : NULL; - } - return -1; - } - - while (*kexp && (*kexp)->name) { - s = kex_agree_instr(kex, kex_len, - (unsigned char *) (*kexp)->name, - strlen((*kexp)->name)); - if (s) { - /* We've agreed on a key exchange method, - * Can we agree on a hostkey that works with this kex? - */ - if (kex_agree_hostkey(session, (*kexp)->flags, hostkey, - hostkey_len) == 0) { - session->kex = *kexp; - if (session->burn_optimistic_kexinit && (kex == s)) { - /* Server sent an optimistic packet, - * and client agrees with preference - * cancel burning the first KEX_INIT packet that comes in */ - session->burn_optimistic_kexinit = 0; - } - return 0; - } - } - kexp++; - } - return -1; -} - - - -/* kex_agree_crypt - * Agree on a cipher algo - */ -static int kex_agree_crypt(LIBSSH2_SESSION * session, - libssh2_endpoint_data *endpoint, - unsigned char *crypt, - unsigned long crypt_len) -{ - const LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods(); - unsigned char *s; - - (void) session; - - if (endpoint->crypt_prefs) { - s = (unsigned char *) endpoint->crypt_prefs; - - while (s && *s) { - unsigned char *p = (unsigned char *) strchr((char *) s, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - - if (kex_agree_instr(crypt, crypt_len, s, method_len)) { - const LIBSSH2_CRYPT_METHOD *method = - (const LIBSSH2_CRYPT_METHOD *) - kex_get_method_by_name((char *) s, method_len, - (const LIBSSH2_COMMON_METHOD **) - cryptp); - - if (!method) { - /* Invalid method -- Should never be reached */ - return -1; - } - - endpoint->crypt = method; - return 0; - } - - s = p ? p + 1 : NULL; - } - return -1; - } - - while (*cryptp && (*cryptp)->name) { - s = kex_agree_instr(crypt, crypt_len, - (unsigned char *) (*cryptp)->name, - strlen((*cryptp)->name)); - if (s) { - endpoint->crypt = *cryptp; - return 0; - } - cryptp++; - } - - return -1; -} - - - -/* kex_agree_mac - * Agree on a message authentication hash - */ -static int kex_agree_mac(LIBSSH2_SESSION * session, - libssh2_endpoint_data * endpoint, unsigned char *mac, - unsigned long mac_len) -{ - const LIBSSH2_MAC_METHOD **macp = _libssh2_mac_methods(); - unsigned char *s; - (void) session; - - if (endpoint->mac_prefs) { - s = (unsigned char *) endpoint->mac_prefs; - - while (s && *s) { - unsigned char *p = (unsigned char *) strchr((char *) s, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - - if (kex_agree_instr(mac, mac_len, s, method_len)) { - const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *) - kex_get_method_by_name((char *) s, method_len, - (const LIBSSH2_COMMON_METHOD **) - macp); - - if (!method) { - /* Invalid method -- Should never be reached */ - return -1; - } - - endpoint->mac = method; - return 0; - } - - s = p ? p + 1 : NULL; - } - return -1; - } - - while (*macp && (*macp)->name) { - s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name, - strlen((*macp)->name)); - if (s) { - endpoint->mac = *macp; - return 0; - } - macp++; - } - - return -1; -} - - - -/* kex_agree_comp - * Agree on a compression scheme - */ -static int kex_agree_comp(LIBSSH2_SESSION *session, - libssh2_endpoint_data *endpoint, unsigned char *comp, - unsigned long comp_len) -{ - const LIBSSH2_COMP_METHOD **compp = _libssh2_comp_methods(session); - unsigned char *s; - (void) session; - - if (endpoint->comp_prefs) { - s = (unsigned char *) endpoint->comp_prefs; - - while (s && *s) { - unsigned char *p = (unsigned char *) strchr((char *) s, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - - if (kex_agree_instr(comp, comp_len, s, method_len)) { - const LIBSSH2_COMP_METHOD *method = - (const LIBSSH2_COMP_METHOD *) - kex_get_method_by_name((char *) s, method_len, - (const LIBSSH2_COMMON_METHOD **) - compp); - - if (!method) { - /* Invalid method -- Should never be reached */ - return -1; - } - - endpoint->comp = method; - return 0; - } - - s = p ? p + 1 : NULL; - } - return -1; - } - - while (*compp && (*compp)->name) { - s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name, - strlen((*compp)->name)); - if (s) { - endpoint->comp = *compp; - return 0; - } - compp++; - } - - return -1; -} - - - -/* TODO: When in server mode we need to turn this logic on its head - * The Client gets to make the final call on "agreed methods" - */ - -/* kex_agree_methods - * Decide which specific method to use of the methods offered by each party - */ -static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data, - unsigned data_len) -{ - unsigned char *kex, *hostkey, *crypt_cs, *crypt_sc, *comp_cs, *comp_sc, - *mac_cs, *mac_sc; - size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len; - size_t comp_sc_len, mac_cs_len, mac_sc_len; - unsigned char *s = data; - - /* Skip packet_type, we know it already */ - s++; - - /* Skip cookie, don't worry, it's preserved in the kexinit field */ - s += 16; - - /* Locate each string */ - kex_len = _libssh2_ntohu32(s); - kex = s + 4; - s += 4 + kex_len; - hostkey_len = _libssh2_ntohu32(s); - hostkey = s + 4; - s += 4 + hostkey_len; - crypt_cs_len = _libssh2_ntohu32(s); - crypt_cs = s + 4; - s += 4 + crypt_cs_len; - crypt_sc_len = _libssh2_ntohu32(s); - crypt_sc = s + 4; - s += 4 + crypt_sc_len; - mac_cs_len = _libssh2_ntohu32(s); - mac_cs = s + 4; - s += 4 + mac_cs_len; - mac_sc_len = _libssh2_ntohu32(s); - mac_sc = s + 4; - s += 4 + mac_sc_len; - comp_cs_len = _libssh2_ntohu32(s); - comp_cs = s + 4; - s += 4 + comp_cs_len; - comp_sc_len = _libssh2_ntohu32(s); - comp_sc = s + 4; -#if 0 - s += 4 + comp_sc_len; - lang_cs_len = _libssh2_ntohu32(s); - lang_cs = s + 4; - s += 4 + lang_cs_len; - lang_sc_len = _libssh2_ntohu32(s); - lang_sc = s + 4; - s += 4 + lang_sc_len; -#endif - /* If the server sent an optimistic packet, assume that it guessed wrong. - * If the guess is determined to be right (by kex_agree_kex_hostkey) - * This flag will be reset to zero so that it's not ignored */ - session->burn_optimistic_kexinit = *(s++); - /* Next uint32 in packet is all zeros (reserved) */ - - if (data_len < (unsigned) (s - data)) - return -1; /* short packet */ - - if (kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) { - return -1; - } - - if (kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len) - || kex_agree_crypt(session, &session->remote, crypt_sc, crypt_sc_len)) { - return -1; - } - - if (kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) || - kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) { - return -1; - } - - if (kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) || - kex_agree_comp(session, &session->remote, comp_sc, comp_sc_len)) { - return -1; - } - -#if 0 - if (libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len) - || libssh2_kex_agree_lang(session, &session->remote, lang_sc, - lang_sc_len)) { - return -1; - } -#endif - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on KEX method: %s", - session->kex->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on HOSTKEY method: %s", - session->hostkey->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_CS method: %s", - session->local.crypt->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_SC method: %s", - session->remote.crypt->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_CS method: %s", - session->local.mac->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_SC method: %s", - session->remote.mac->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_CS method: %s", - session->local.comp->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_SC method: %s", - session->remote.comp->name); - - return 0; -} - - - -/* _libssh2_kex_exchange - * Exchange keys - * Returns 0 on success, non-zero on failure - * - * Returns some errors without _libssh2_error() - */ -int -_libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, - key_exchange_state_t * key_state) -{ - int rc = 0; - int retcode; - - session->state |= LIBSSH2_STATE_KEX_ACTIVE; - - if (key_state->state == libssh2_NB_state_idle) { - /* Prevent loop in packet_add() */ - session->state |= LIBSSH2_STATE_EXCHANGING_KEYS; - - if (reexchange) { - session->kex = NULL; - - if (session->hostkey && session->hostkey->dtor) { - session->hostkey->dtor(session, - &session->server_hostkey_abstract); - } - session->hostkey = NULL; - } - - key_state->state = libssh2_NB_state_created; - } - - if (!session->kex || !session->hostkey) { - if (key_state->state == libssh2_NB_state_created) { - /* Preserve in case of failure */ - key_state->oldlocal = session->local.kexinit; - key_state->oldlocal_len = session->local.kexinit_len; - - session->local.kexinit = NULL; - - key_state->state = libssh2_NB_state_sent; - } - - if (key_state->state == libssh2_NB_state_sent) { - retcode = kexinit(session); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - return retcode; - } else if (retcode) { - session->local.kexinit = key_state->oldlocal; - session->local.kexinit_len = key_state->oldlocal_len; - key_state->state = libssh2_NB_state_idle; - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; - return -1; - } - - key_state->state = libssh2_NB_state_sent1; - } - - if (key_state->state == libssh2_NB_state_sent1) { - retcode = - _libssh2_packet_require(session, SSH_MSG_KEXINIT, - &key_state->data, - &key_state->data_len, 0, NULL, 0, - &key_state->req_state); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - return retcode; - } - else if (retcode) { - if (session->local.kexinit) { - LIBSSH2_FREE(session, session->local.kexinit); - } - session->local.kexinit = key_state->oldlocal; - session->local.kexinit_len = key_state->oldlocal_len; - key_state->state = libssh2_NB_state_idle; - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; - return -1; - } - - if (session->remote.kexinit) { - LIBSSH2_FREE(session, session->remote.kexinit); - } - session->remote.kexinit = key_state->data; - session->remote.kexinit_len = key_state->data_len; - - if (kex_agree_methods(session, key_state->data, - key_state->data_len)) - rc = LIBSSH2_ERROR_KEX_FAILURE; - - key_state->state = libssh2_NB_state_sent2; - } - } else { - key_state->state = libssh2_NB_state_sent2; - } - - if (rc == 0) { - if (key_state->state == libssh2_NB_state_sent2) { - retcode = session->kex->exchange_keys(session, - &key_state->key_state_low); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - return retcode; - } else if (retcode) { - rc = _libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, - "Unrecoverable error exchanging keys"); - } - } - } - - /* Done with kexinit buffers */ - if (session->local.kexinit) { - LIBSSH2_FREE(session, session->local.kexinit); - session->local.kexinit = NULL; - } - if (session->remote.kexinit) { - LIBSSH2_FREE(session, session->remote.kexinit); - session->remote.kexinit = NULL; - } - - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; - - key_state->state = libssh2_NB_state_idle; - - return rc; -} - - - -/* libssh2_session_method_pref - * Set preferred method - */ -LIBSSH2_API int -libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, - const char *prefs) -{ - char **prefvar, *s, *newprefs; - int prefs_len = strlen(prefs); - const LIBSSH2_COMMON_METHOD **mlist; - - switch (method_type) { - case LIBSSH2_METHOD_KEX: - prefvar = &session->kex_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods; - break; - - case LIBSSH2_METHOD_HOSTKEY: - prefvar = &session->hostkey_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods(); - break; - - case LIBSSH2_METHOD_CRYPT_CS: - prefvar = &session->local.crypt_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods(); - break; - - case LIBSSH2_METHOD_CRYPT_SC: - prefvar = &session->remote.crypt_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods(); - break; - - case LIBSSH2_METHOD_MAC_CS: - prefvar = &session->local.mac_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods(); - break; - - case LIBSSH2_METHOD_MAC_SC: - prefvar = &session->remote.mac_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods(); - break; - - case LIBSSH2_METHOD_COMP_CS: - prefvar = &session->local.comp_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) - _libssh2_comp_methods(session); - break; - - case LIBSSH2_METHOD_COMP_SC: - prefvar = &session->remote.comp_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) - _libssh2_comp_methods(session); - break; - - case LIBSSH2_METHOD_LANG_CS: - prefvar = &session->local.lang_prefs; - mlist = NULL; - break; - - case LIBSSH2_METHOD_LANG_SC: - prefvar = &session->remote.lang_prefs; - mlist = NULL; - break; - - default: - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "Invalid parameter specified for method_type"); - } - - s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1); - if (!newprefs) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Error allocated space for method preferences"); - } - memcpy(s, prefs, prefs_len + 1); - - while (s && *s) { - char *p = strchr(s, ','); - int method_len = p ? (p - s) : (int) strlen(s); - - if (!kex_get_method_by_name(s, method_len, mlist)) { - /* Strip out unsupported method */ - if (p) { - memcpy(s, p + 1, strlen(s) - method_len); - } else { - if (s > newprefs) { - *(--s) = '\0'; - } else { - *s = '\0'; - } - } - } - - s = p ? (p + 1) : NULL; - } - - if (strlen(newprefs) == 0) { - LIBSSH2_FREE(session, newprefs); - return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "The requested method(s) are not currently " - "supported"); - } - - if (*prefvar) { - LIBSSH2_FREE(session, *prefvar); - } - *prefvar = newprefs; - - return 0; -} - -/* - * libssh2_session_supported_algs() - * returns a number of returned algorithms (a positive number) on success, - * a negative number on failure - */ - -LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, - int method_type, - const char*** algs) -{ - unsigned int i; - unsigned int j; - unsigned int ialg; - const LIBSSH2_COMMON_METHOD **mlist; - - /* to prevent coredumps due to dereferencing of NULL */ - if (NULL == algs) - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "algs must not be NULL"); - - switch (method_type) { - case LIBSSH2_METHOD_KEX: - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods; - break; - - case LIBSSH2_METHOD_HOSTKEY: - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods(); - break; - - case LIBSSH2_METHOD_CRYPT_CS: - case LIBSSH2_METHOD_CRYPT_SC: - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods(); - break; - - case LIBSSH2_METHOD_MAC_CS: - case LIBSSH2_METHOD_MAC_SC: - mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods(); - break; - - case LIBSSH2_METHOD_COMP_CS: - case LIBSSH2_METHOD_COMP_SC: - mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods(session); - break; - - default: - return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown method type"); - } /* switch */ - - /* weird situation */ - if (NULL==mlist) - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "No algorithm found"); - - /* - mlist is looped through twice. The first time to find the number od - supported algorithms (needed to allocate the proper size of array) and - the second time to actually copy the pointers. Typically this function - will not be called often (typically at the beginning of a session) and - the number of algorithms (i.e. niumber of iterations in one loop) will - not be high (typically it will not exceed 20) for quite a long time. - - So double looping really shouldn't be an issue and it is definitely a - better solution than reallocation several times. - */ - - /* count the number of supported algorithms */ - for ( i=0, ialg=0; NULL!=mlist[i]; i++) { - /* do not count fields with NULL name */ - if (mlist[i]->name) - ialg++; - } - - /* weird situation, no algorithm found */ - if (0==ialg) - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "No algorithm found"); - - /* allocate buffer */ - *algs = (const char**) LIBSSH2_ALLOC(session, ialg*sizeof(const char*)); - if ( NULL==*algs ) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Memory allocation failed"); - } - /* Past this point *algs must be deallocated in case of an error!! */ - - /* copy non-NULL pointers only */ - for ( i=0, j=0; NULL!=mlist[i] && jname ){ - /* maybe a weird situation but if it occurs, do not include NULL - pointers */ - continue; - } - - /* note that [] has higher priority than * (dereferencing) */ - (*algs)[j++] = mlist[i]->name; - } - - /* correct number of pointers copied? (test the code above) */ - if ( j!=ialg ) { - /* deallocate buffer */ - LIBSSH2_FREE(session, (void *)*algs); - *algs = NULL; - - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "Internal error"); - } - - return ialg; -} diff --git a/vendor/libssh2-1.4.2/src/knownhost.c b/vendor/libssh2-1.4.2/src/knownhost.c deleted file mode 100644 index c58dfbb..0000000 --- a/vendor/libssh2-1.4.2/src/knownhost.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * Copyright (c) 2009-2011 by Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include "misc.h" - -struct known_host { - struct list_node node; - char *name; /* points to the name or the hash (allocated) */ - size_t name_len; /* needed for hashed data */ - int port; /* if non-zero, a specific port this key is for on this - host */ - int typemask; /* plain, sha1, custom, ... */ - char *salt; /* points to binary salt (allocated) */ - size_t salt_len; /* size of salt */ - char *key; /* the (allocated) associated key. This is kept base64 - encoded in memory. */ - char *comment; /* the (allocated) optional comment text, may be NULL */ - - /* this is the struct we expose externally */ - struct libssh2_knownhost external; -}; - -struct _LIBSSH2_KNOWNHOSTS -{ - LIBSSH2_SESSION *session; /* the session this "belongs to" */ - struct list_head head; -}; - -static void free_host(LIBSSH2_SESSION *session, struct known_host *entry) -{ - if(entry) { - if(entry->comment) - LIBSSH2_FREE(session, entry->comment); - if(entry->key) - LIBSSH2_FREE(session, entry->key); - if(entry->salt) - LIBSSH2_FREE(session, entry->salt); - if(entry->name) - LIBSSH2_FREE(session, entry->name); - LIBSSH2_FREE(session, entry); - } -} - -/* - * libssh2_knownhost_init - * - * Init a collection of known hosts. Returns the pointer to a collection. - * - */ -LIBSSH2_API LIBSSH2_KNOWNHOSTS * -libssh2_knownhost_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_KNOWNHOSTS *knh = - LIBSSH2_ALLOC(session, sizeof(struct _LIBSSH2_KNOWNHOSTS)); - - if(!knh) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for known-hosts " - "collection"); - return NULL; - } - - knh->session = session; - - _libssh2_list_init(&knh->head); - - return knh; -} - -#define KNOWNHOST_MAGIC 0xdeadcafe -/* - * knownhost_to_external() - * - * Copies data from the internal to the external representation struct. - * - */ -static struct libssh2_knownhost *knownhost_to_external(struct known_host *node) -{ - struct libssh2_knownhost *ext = &node->external; - - ext->magic = KNOWNHOST_MAGIC; - ext->node = node; - ext->name = ((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) == - LIBSSH2_KNOWNHOST_TYPE_PLAIN)? node->name:NULL; - ext->key = node->key; - ext->typemask = node->typemask; - - return ext; -} - -static int -knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *salt, - const char *key, size_t keylen, - const char *comment, size_t commentlen, - int typemask, struct libssh2_knownhost **store) -{ - struct known_host *entry; - size_t hostlen = strlen(host); - int rc; - char *ptr; - unsigned int ptrlen; - - /* make sure we have a key type set */ - if(!(typemask & LIBSSH2_KNOWNHOST_KEY_MASK)) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL, - "No key type set"); - - if(!(entry = LIBSSH2_ALLOC(hosts->session, sizeof(struct known_host)))) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for known host " - "entry"); - - memset(entry, 0, sizeof(struct known_host)); - - entry->typemask = typemask; - - switch(entry->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) { - case LIBSSH2_KNOWNHOST_TYPE_PLAIN: - case LIBSSH2_KNOWNHOST_TYPE_CUSTOM: - entry->name = LIBSSH2_ALLOC(hosts->session, hostlen+1); - if(!entry->name) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for host name"); - goto error; - } - memcpy(entry->name, host, hostlen+1); - break; - case LIBSSH2_KNOWNHOST_TYPE_SHA1: - rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen, - host, hostlen); - if(rc) - goto error; - entry->name = ptr; - entry->name_len = ptrlen; - - rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen, - salt, strlen(salt)); - if(rc) - goto error; - entry->salt = ptr; - entry->salt_len = ptrlen; - break; - default: - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown host name type"); - goto error; - } - - if(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64) { - /* the provided key is base64 encoded already */ - if(!keylen) - keylen = strlen(key); - entry->key = LIBSSH2_ALLOC(hosts->session, keylen+1); - if(!entry->key) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for key"); - goto error; - } - memcpy(entry->key, key, keylen+1); - entry->key[keylen]=0; /* force a terminating zero trailer */ - } - else { - /* key is raw, we base64 encode it and store it as such */ - size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen, - &ptr); - if(!nlen) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "base64-encoded key"); - goto error; - } - - entry->key = ptr; - } - - if (comment) { - entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen+1); - if(!entry->comment) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for comment"); - goto error; - } - memcpy(entry->comment, comment, commentlen+1); - entry->comment[commentlen]=0; /* force a terminating zero trailer */ - } - else { - entry->comment = NULL; - } - - /* add this new host to the big list of known hosts */ - _libssh2_list_add(&hosts->head, &entry->node); - - if(store) - *store = knownhost_to_external(entry); - - return LIBSSH2_ERROR_NONE; - error: - free_host(hosts->session, entry); - return rc; -} - -/* - * libssh2_knownhost_add - * - * Add a host and its associated key to the collection of known hosts. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -LIBSSH2_API int -libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *salt, - const char *key, size_t keylen, - int typemask, struct libssh2_knownhost **store) -{ - return knownhost_add(hosts, host, salt, key, keylen, NULL, 0, typemask, - store); -} - - -/* - * libssh2_knownhost_addc - * - * Add a host and its associated key to the collection of known hosts. - * - * Takes a comment argument that may be NULL. A NULL comment indicates - * there is no comment and the entry will end directly after the key - * when written out to a file. An empty string "" comment will indicate an - * empty comment which will cause a single space to be written after the key. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -LIBSSH2_API int -libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *salt, - const char *key, size_t keylen, - const char *comment, size_t commentlen, - int typemask, struct libssh2_knownhost **store) -{ - return knownhost_add(hosts, host, salt, key, keylen, comment, commentlen, - typemask, store); -} - -/* - * knownhost_check - * - * Check a host and its associated key against the collection of known hosts. - * - * The typemask is the type/format of the given host name and key - * - * plain - ascii "hostname.domain.tld" - * sha1 - NOT SUPPORTED AS INPUT - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_FAILURE - * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - * LIBSSH2_KNOWNHOST_CHECK_MATCH - * LIBSSH2_KNOWNHOST_CHECK_MISMATCH - */ -static int -knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, - const char *hostp, int port, - const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **ext) -{ - struct known_host *node; - struct known_host *badkey = NULL; - int type = typemask & LIBSSH2_KNOWNHOST_TYPE_MASK; - char *keyalloc = NULL; - int rc = LIBSSH2_KNOWNHOST_CHECK_NOTFOUND; - char hostbuff[270]; /* most host names can't be longer than like 256 */ - const char *host; - int numcheck; /* number of host combos to check */ - int match = 0; - - if(type == LIBSSH2_KNOWNHOST_TYPE_SHA1) - /* we can't work with a sha1 as given input */ - return LIBSSH2_KNOWNHOST_CHECK_MISMATCH; - - if(!(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64)) { - /* we got a raw key input, convert it to base64 for the checks below */ - size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen, - &keyalloc); - if(!nlen) { - _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for base64-encoded " - "key"); - return LIBSSH2_KNOWNHOST_CHECK_FAILURE; - } - - /* make the key point to this */ - key = keyalloc; - } - - /* if a port number is given, check for a '[host]:port' first before the - plain 'host' */ - if(port >= 0) { - snprintf(hostbuff, sizeof(hostbuff), "[%s]:%d", hostp, port); - host = hostbuff; - numcheck = 2; /* check both combos, start with this */ - } - else { - host = hostp; - numcheck = 1; /* only check this host version */ - } - - do { - node = _libssh2_list_first(&hosts->head); - while (node) { - switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) { - case LIBSSH2_KNOWNHOST_TYPE_PLAIN: - if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) - match = !strcmp(host, node->name); - break; - case LIBSSH2_KNOWNHOST_TYPE_CUSTOM: - if(type == LIBSSH2_KNOWNHOST_TYPE_CUSTOM) - match = !strcmp(host, node->name); - break; - case LIBSSH2_KNOWNHOST_TYPE_SHA1: - if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) { - /* when we have the sha1 version stored, we can use a - plain input to produce a hash to compare with the - stored hash. - */ - libssh2_hmac_ctx ctx; - unsigned char hash[SHA_DIGEST_LENGTH]; - - if(SHA_DIGEST_LENGTH != node->name_len) { - /* the name hash length must be the sha1 size or - we can't match it */ - break; - } - libssh2_hmac_sha1_init(&ctx, node->salt, node->salt_len); - libssh2_hmac_update(ctx, (unsigned char *)host, - strlen(host)); - libssh2_hmac_final(ctx, hash); - libssh2_hmac_cleanup(&ctx); - - if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH)) - /* this is a node we're interested in */ - match = 1; - } - break; - default: /* unsupported type */ - break; - } - if(match) { - /* host name match, now compare the keys */ - if(!strcmp(key, node->key)) { - /* they match! */ - if (ext) - *ext = knownhost_to_external(node); - badkey = NULL; - rc = LIBSSH2_KNOWNHOST_CHECK_MATCH; - break; - } - else { - /* remember the first node that had a host match but a - failed key match since we continue our search from - here */ - if(!badkey) - badkey = node; - match = 0; /* don't count this as a match anymore */ - } - } - node= _libssh2_list_next(&node->node); - } - host = hostp; - } while(!match && --numcheck); - - if(badkey) { - /* key mismatch */ - if (ext) - *ext = knownhost_to_external(badkey); - rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH; - } - - if(keyalloc) - LIBSSH2_FREE(hosts->session, keyalloc); - - return rc; -} - -/* - * libssh2_knownhost_check - * - * Check a host and its associated key against the collection of known hosts. - * - * The typemask is the type/format of the given host name and key - * - * plain - ascii "hostname.domain.tld" - * sha1 - NOT SUPPORTED AS INPUT - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_FAILURE - * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - * LIBSSH2_KNOWNHOST_CHECK_MATCH - * LIBSSH2_KNOWNHOST_CHECK_MISMATCH - */ -LIBSSH2_API int -libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, - const char *hostp, const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **ext) -{ - return knownhost_check(hosts, hostp, -1, key, keylen, - typemask, ext); -} - -/* - * libssh2_knownhost_checkp - * - * Check a host+port and its associated key against the collection of known - * hosts. - * - * Note that if 'port' is specified as greater than zero, the check function - * will be able to check for a dedicated key for this particular host+port - * combo, and if 'port' is negative it only checks for the generic host key. - * - * The typemask is the type/format of the given host name and key - * - * plain - ascii "hostname.domain.tld" - * sha1 - NOT SUPPORTED AS INPUT - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_FAILURE - * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - * LIBSSH2_KNOWNHOST_CHECK_MATCH - * LIBSSH2_KNOWNHOST_CHECK_MISMATCH - */ -LIBSSH2_API int -libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts, - const char *hostp, int port, - const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **ext) -{ - return knownhost_check(hosts, hostp, port, key, keylen, - typemask, ext); -} - - -/* - * libssh2_knownhost_del - * - * Remove a host from the collection of known hosts. - * - */ -LIBSSH2_API int -libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *entry) -{ - struct known_host *node; - - /* check that this was retrieved the right way or get out */ - if(!entry || (entry->magic != KNOWNHOST_MAGIC)) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL, - "Invalid host information"); - - /* get the internal node pointer */ - node = entry->node; - - /* unlink from the list of all hosts */ - _libssh2_list_remove(&node->node); - - /* clear the struct now since the memory in which it is allocated is - about to be freed! */ - memset(entry, 0, sizeof(struct libssh2_knownhost)); - - /* free all resources */ - free_host(hosts->session, node); - - return 0; -} - -/* - * libssh2_knownhost_free - * - * Free an entire collection of known hosts. - * - */ -LIBSSH2_API void -libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts) -{ - struct known_host *node; - struct known_host *next; - - for(node = _libssh2_list_first(&hosts->head); node; node = next) { - next = _libssh2_list_next(&node->node); - free_host(hosts->session, node); - } - LIBSSH2_FREE(hosts->session, hosts); -} - - -/* old style plain text: [name]([,][name])* - - for the sake of simplicity, we add them as separate hosts with the same - key -*/ -static int oldstyle_hostline(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, size_t hostlen, - const char *key, size_t keylen, int key_type, - const char *comment, size_t commentlen) -{ - int rc = 0; - size_t namelen = 0; - const char *name = host + hostlen; - - if(hostlen < 1) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(no host names)"); - - while(name > host) { - --name; - ++namelen; - - /* when we get the the start or see a comma coming up, add the host - name to the collection */ - if((name == host) || (*(name-1) == ',')) { - - char hostbuf[256]; - - /* make sure we don't overflow the buffer */ - if(namelen >= sizeof(hostbuf)-1) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(unexpected length)"); - - /* copy host name to the temp buffer and zero terminate */ - memcpy(hostbuf, name, namelen); - hostbuf[namelen]=0; - - rc = knownhost_add(hosts, hostbuf, NULL, key, keylen, - comment, commentlen, - key_type | LIBSSH2_KNOWNHOST_TYPE_PLAIN | - LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL); - if(rc) - return rc; - - if(name > host) { - namelen = 0; - --name; /* skip comma */ - } - } - } - - return rc; -} - -/* |1|[salt]|[hash] */ -static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, size_t hostlen, - const char *key, size_t keylen, int key_type, - const char *comment, size_t commentlen) -{ - const char *p; - char saltbuf[32]; - char hostbuf[256]; - - const char *salt = &host[3]; /* skip the magic marker */ - hostlen -= 3; /* deduct the marker */ - - /* this is where the salt starts, find the end of it */ - for(p = salt; *p && (*p != '|'); p++) - ; - - if(*p=='|') { - const char *hash = NULL; - size_t saltlen = p - salt; - if(saltlen >= (sizeof(saltbuf)-1)) /* weird length */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(unexpectedly long salt)"); - - memcpy(saltbuf, salt, saltlen); - saltbuf[saltlen] = 0; /* zero terminate */ - salt = saltbuf; /* point to the stack based buffer */ - - hash = p+1; /* the host hash is after the separator */ - - /* now make the host point to the hash */ - host = hash; - hostlen -= saltlen+1; /* deduct the salt and separator */ - - /* check that the lengths seem sensible */ - if(hostlen >= sizeof(hostbuf)-1) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(unexpected length)"); - - memcpy(hostbuf, host, hostlen); - hostbuf[hostlen]=0; - - return knownhost_add(hosts, hostbuf, salt, key, keylen, comment, - commentlen, - key_type | LIBSSH2_KNOWNHOST_TYPE_SHA1 | - LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL); - } - else - return 0; /* XXX: This should be an error, shouldn't it? */ -} - -/* - * hostline() - * - * Parse a single known_host line pre-split into host and key. - * - * The key part may include an optional comment which will be parsed here - * for ssh-rsa and ssh-dsa keys. Comments in other key types aren't handled. - * - * The function assumes new-lines have already been removed from the arguments. - */ -static int hostline(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, size_t hostlen, - const char *key, size_t keylen) -{ - const char *comment = NULL; - size_t commentlen = 0; - int key_type; - - /* make some checks that the lengths seem sensible */ - if(keylen < 20) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(key too short)"); - - switch(key[0]) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - key_type = LIBSSH2_KNOWNHOST_KEY_RSA1; - - /* Note that the old-style keys (RSA1) aren't truly base64, but we - * claim it is for now since we can get away with strcmp()ing the - * entire anything anyway! We need to check and fix these to make them - * work properly. - */ - break; - - case 's': /* ssh-dss or ssh-rsa */ - if(!strncmp(key, "ssh-dss", 7)) - key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS; - else if(!strncmp(key, "ssh-rsa", 7)) - key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA; - else - /* unknown key type */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown key type"); - - key += 7; - keylen -= 7; - - /* skip whitespaces */ - while((*key ==' ') || (*key == '\t')) { - key++; - keylen--; - } - - comment = key; - commentlen = keylen; - - /* move over key */ - while(commentlen && *comment && - (*comment != ' ') && (*comment != '\t')) { - comment++; - commentlen--; - } - - /* reduce key by comment length */ - keylen -= commentlen; - - /* Distinguish empty comment (a space) from no comment (no space) */ - if (commentlen == 0) - comment = NULL; - - /* skip whitespaces */ - while(commentlen && *comment && - ((*comment ==' ') || (*comment == '\t'))) { - comment++; - commentlen--; - } - break; - - default: /* unknown key format */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown key format"); - } - - /* Figure out host format */ - if((hostlen >2) && memcmp(host, "|1|", 3)) { - /* old style plain text: [name]([,][name])* - - for the sake of simplicity, we add them as separate hosts with the - same key - */ - return oldstyle_hostline(hosts, host, hostlen, key, keylen, key_type, - comment, commentlen); - } - else { - /* |1|[salt]|[hash] */ - return hashed_hostline(hosts, host, hostlen, key, keylen, key_type, - comment, commentlen); - } -} - -/* - * libssh2_knownhost_readline() - * - * Pass in a line of a file of 'type'. - * - * LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type. - * - * OpenSSH line format: - * - * - * - * Where the two parts can be created like: - * - * can be either - * or - * - * consists of - * [name] optionally followed by [,name] one or more times - * - * consists of - * |1||hash - * - * can be one of: - * [RSA bits] [e] [n as a decimal number] - * 'ssh-dss' [base64-encoded-key] - * 'ssh-rsa' [base64-encoded-key] - * - */ -LIBSSH2_API int -libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts, - const char *line, size_t len, int type) -{ - const char *cp; - const char *hostp; - const char *keyp; - size_t hostlen; - size_t keylen; - int rc; - - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - cp = line; - - /* skip leading whitespaces */ - while(len && ((*cp==' ') || (*cp == '\t'))) { - cp++; - len--; - } - - if(!len || !*cp || (*cp == '#') || (*cp == '\n')) - /* comment or empty line */ - return LIBSSH2_ERROR_NONE; - - /* the host part starts here */ - hostp = cp; - - /* move over the host to the separator */ - while(len && *cp && (*cp!=' ') && (*cp != '\t')) { - cp++; - len--; - } - - hostlen = cp - hostp; - - /* the key starts after the whitespaces */ - while(len && *cp && ((*cp==' ') || (*cp == '\t'))) { - cp++; - len--; - } - - if(!*cp || !len) /* illegal line */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line"); - - keyp = cp; /* the key starts here */ - keylen = len; - - /* check if the line (key) ends with a newline and if so kill it */ - while(len && *cp && (*cp != '\n')) { - cp++; - len--; - } - - /* zero terminate where the newline is */ - if(*cp == '\n') - keylen--; /* don't include this in the count */ - - /* deal with this one host+key line */ - rc = hostline(hosts, hostp, hostlen, keyp, keylen); - if(rc) - return rc; /* failed */ - - return LIBSSH2_ERROR_NONE; /* success */ -} - -/* - * libssh2_knownhost_readfile - * - * Read hosts+key pairs from a given file. - * - * Returns a negative value for error or number of successfully added hosts. - * - */ - -LIBSSH2_API int -libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type) -{ - FILE *file; - int num = 0; - char buf[2048]; - - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - file = fopen(filename, "r"); - if(file) { - while(fgets(buf, sizeof(buf), file)) { - if(libssh2_knownhost_readline(hosts, buf, strlen(buf), type)) - break; - num++; - } - fclose(file); - } - else - return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE, - "Failed to open file"); - - return num; -} - -/* - * knownhost_writeline() - * - * Ask libssh2 to convert a known host to an output line for storage. - * - * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given - * output buffer is too small to hold the desired output. The 'outlen' field - * will then contain the size libssh2 wanted to store, which then is the - * smallest sufficient buffer it would require. - * - */ -static int -knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, - struct known_host *node, - char *buf, size_t buflen, - size_t *outlen, int type) -{ - int rc = LIBSSH2_ERROR_NONE; - int tindex; - const char *keytypes[4]={ - "", /* not used */ - "", /* this type has no name in the file */ - " ssh-rsa", - " ssh-dss" - }; - const char *keytype; - size_t nlen; - size_t commentlen = 0; - - /* we only support this single file type for now, bail out on all other - attempts */ - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - tindex = (node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) >> - LIBSSH2_KNOWNHOST_KEY_SHIFT; - - /* set the string used in the file */ - keytype = keytypes[tindex]; - - /* calculate extra space needed for comment */ - if(node->comment) - commentlen = strlen(node->comment) + 1; - - if((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) == - LIBSSH2_KNOWNHOST_TYPE_SHA1) { - char *namealloc; - char *saltalloc; - nlen = _libssh2_base64_encode(hosts->session, node->name, - node->name_len, &namealloc); - if(!nlen) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "base64-encoded host name"); - - nlen = _libssh2_base64_encode(hosts->session, - node->salt, node->salt_len, - &saltalloc); - if(!nlen) { - free(namealloc); - return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "base64-encoded salt"); - } - - nlen = strlen(saltalloc) + strlen(namealloc) + strlen(keytype) + - strlen(node->key) + commentlen + 7; - /* |1| + | + ' ' + \n + \0 = 7 */ - - if(nlen <= buflen) - if(node->comment) - snprintf(buf, buflen, "|1|%s|%s%s %s %s\n", saltalloc, namealloc, - keytype, node->key, node->comment); - else - snprintf(buf, buflen, "|1|%s|%s%s %s\n", saltalloc, namealloc, - keytype, node->key); - else - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, - "Known-host write buffer too small"); - - free(namealloc); - free(saltalloc); - } - else { - nlen = strlen(node->name) + strlen(keytype) + strlen(node->key) + - commentlen + 3; - /* ' ' + '\n' + \0 = 3 */ - if(nlen <= buflen) - /* these types have the plain name */ - if(node->comment) - snprintf(buf, buflen, "%s%s %s %s\n", node->name, keytype, node->key, - node->comment); - else - snprintf(buf, buflen, "%s%s %s\n", node->name, keytype, node->key); - else - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, - "Known-host write buffer too small"); - } - - /* we report the full length of the data with the trailing zero excluded */ - *outlen = nlen-1; - - return rc; -} - -/* - * libssh2_knownhost_writeline() - * - * Ask libssh2 to convert a known host to an output line for storage. - * - * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given - * output buffer is too small to hold the desired output. - */ -LIBSSH2_API int -libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *known, - char *buffer, size_t buflen, - size_t *outlen, /* the amount of written data */ - int type) -{ - struct known_host *node; - - if(known->magic != KNOWNHOST_MAGIC) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL, - "Invalid host information"); - - node = known->node; - - return knownhost_writeline(hosts, node, buffer, buflen, outlen, type); -} - -/* - * libssh2_knownhost_writefile() - * - * Write hosts+key pairs to the given file. - */ -LIBSSH2_API int -libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type) -{ - struct known_host *node; - FILE *file; - int rc = LIBSSH2_ERROR_NONE; - char buffer[2048]; - - /* we only support this single file type for now, bail out on all other - attempts */ - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - file = fopen(filename, "w"); - if(!file) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE, - "Failed to open file"); - - for(node = _libssh2_list_first(&hosts->head); - node; - node= _libssh2_list_next(&node->node) ) { - size_t wrote; - size_t nwrote; - rc = knownhost_writeline(hosts, node, buffer, sizeof(buffer), &wrote, - type); - if(rc) - break; - - nwrote = fwrite(buffer, 1, wrote, file); - if(nwrote != wrote) { - /* failed to write the whole thing, bail out */ - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE, - "Write failed"); - break; - } - } - fclose(file); - - return rc; -} - - -/* - * libssh2_knownhost_get() - * - * Traverse the internal list of known hosts. Pass NULL to 'prev' to get - * the first one. - * - * Returns: - * 0 if a fine host was stored in 'store' - * 1 if end of hosts - * [negative] on errors - */ -LIBSSH2_API int -libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost **ext, - struct libssh2_knownhost *oprev) -{ - struct known_host *node; - if(oprev && oprev->node) { - /* we have a starting point */ - struct known_host *prev = oprev->node; - - /* get the next node in the list */ - node = _libssh2_list_next(&prev->node); - - } - else - node = _libssh2_list_first(&hosts->head); - - if(!node) - /* no (more) node */ - return 1; - - *ext = knownhost_to_external(node); - - return 0; -} diff --git a/vendor/libssh2-1.4.2/src/libgcrypt.c b/vendor/libssh2-1.4.2/src/libgcrypt.c deleted file mode 100644 index 5c2787b..0000000 --- a/vendor/libssh2-1.4.2/src/libgcrypt.c +++ /dev/null @@ -1,593 +0,0 @@ -/* Copyright (C) 2008, 2009, Simon Josefsson - * Copyright (C) 2006, 2007, The Written Word, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -#ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */ - -#include - -int -_libssh2_rsa_new(libssh2_rsa_ctx ** rsa, - const unsigned char *edata, - unsigned long elen, - const unsigned char *ndata, - unsigned long nlen, - const unsigned char *ddata, - unsigned long dlen, - const unsigned char *pdata, - unsigned long plen, - const unsigned char *qdata, - unsigned long qlen, - const unsigned char *e1data, - unsigned long e1len, - const unsigned char *e2data, - unsigned long e2len, - const unsigned char *coeffdata, unsigned long coefflen) -{ - int rc; - (void) e1data; - (void) e1len; - (void) e2data; - (void) e2len; - - if (ddata) { - rc = gcry_sexp_build - (rsa, NULL, - "(private-key(rsa(n%b)(e%b)(d%b)(q%b)(p%b)(u%b)))", - nlen, ndata, elen, edata, dlen, ddata, plen, pdata, - qlen, qdata, coefflen, coeffdata); - } else { - rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))", - nlen, ndata, elen, edata); - } - if (rc) { - *rsa = NULL; - return -1; - } - - return 0; -} - -int -_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, - const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, unsigned long m_len) -{ - unsigned char hash[SHA_DIGEST_LENGTH]; - gcry_sexp_t s_sig, s_hash; - int rc = -1; - - libssh2_sha1(m, m_len, hash); - - rc = gcry_sexp_build(&s_hash, NULL, - "(data (flags pkcs1) (hash sha1 %b))", - SHA_DIGEST_LENGTH, hash); - if (rc != 0) { - return -1; - } - - rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig); - if (rc != 0) { - gcry_sexp_release(s_hash); - return -1; - } - - rc = gcry_pk_verify(s_sig, s_hash, rsa); - gcry_sexp_release(s_sig); - gcry_sexp_release(s_hash); - - return (rc == 0) ? 0 : -1; -} - -int -_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, - const unsigned char *p, - unsigned long p_len, - const unsigned char *q, - unsigned long q_len, - const unsigned char *g, - unsigned long g_len, - const unsigned char *y, - unsigned long y_len, - const unsigned char *x, unsigned long x_len) -{ - int rc; - - if (x_len) { - rc = gcry_sexp_build - (dsactx, NULL, - "(private-key(dsa(p%b)(q%b)(g%b)(y%b)(x%b)))", - p_len, p, q_len, q, g_len, g, y_len, y, x_len, x); - } else { - rc = gcry_sexp_build(dsactx, NULL, - "(public-key(dsa(p%b)(q%b)(g%b)(y%b)))", - p_len, p, q_len, q, g_len, g, y_len, y); - } - - if (rc) { - *dsactx = NULL; - return -1; - } - - return 0; -} - -int -_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - FILE *fp; - unsigned char *data, *save_data; - unsigned int datalen; - int ret; - unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff; - unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen; - - (void) passphrase; - - fp = fopen(filename, "r"); - if (!fp) { - return -1; - } - - ret = _libssh2_pem_parse(session, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - fp, &data, &datalen); - fclose(fp); - if (ret) { - return -1; - } - - save_data = data; - - if (_libssh2_pem_decode_sequence(&data, &datalen)) { - ret = -1; - goto fail; - } -/* First read Version field (should be 0). */ - ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen); - if (ret != 0 || (nlen != 1 && *n != '\0')) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &e, &elen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &d, &dlen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &e1, &e1len); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &e2, &e2len); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &coeff, &coefflen); - if (ret != 0) { - ret = -1; - goto fail; - } - - if (_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen, - q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) { - ret = -1; - goto fail; - } - - ret = 0; - - fail: - LIBSSH2_FREE(session, save_data); - return ret; -} - -int -_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - FILE *fp; - unsigned char *data, *save_data; - unsigned int datalen; - int ret; - unsigned char *p, *q, *g, *y, *x; - unsigned int plen, qlen, glen, ylen, xlen; - - (void) passphrase; - - fp = fopen(filename, "r"); - if (!fp) { - return -1; - } - - ret = _libssh2_pem_parse(session, - "-----BEGIN DSA PRIVATE KEY-----", - "-----END DSA PRIVATE KEY-----", - fp, &data, &datalen); - fclose(fp); - if (ret) { - return -1; - } - - save_data = data; - - if (_libssh2_pem_decode_sequence(&data, &datalen)) { - ret = -1; - goto fail; - } - -/* First read Version field (should be 0). */ - ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen); - if (ret != 0 || (plen != 1 && *p != '\0')) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &g, &glen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &y, &ylen); - if (ret != 0) { - ret = -1; - goto fail; - } - - ret = _libssh2_pem_decode_integer(&data, &datalen, &x, &xlen); - if (ret != 0) { - ret = -1; - goto fail; - } - - if (datalen != 0) { - ret = -1; - goto fail; - } - - if (_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) { - ret = -1; - goto fail; - } - - ret = 0; - - fail: - LIBSSH2_FREE(session, save_data); - return ret; -} - -int -_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, - libssh2_dsa_ctx * rsactx, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, size_t *signature_len) -{ - gcry_sexp_t sig_sexp; - gcry_sexp_t data; - int rc; - const char *tmp; - size_t size; - - if (hash_len != SHA_DIGEST_LENGTH) { - return -1; - } - - if (gcry_sexp_build(&data, NULL, - "(data (flags pkcs1) (hash sha1 %b))", - hash_len, hash)) { - return -1; - } - - rc = gcry_pk_sign(&sig_sexp, data, rsactx); - - gcry_sexp_release(data); - - if (rc != 0) { - return -1; - } - - data = gcry_sexp_find_token(sig_sexp, "s", 0); - if (!data) { - return -1; - } - - tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) { - return -1; - } - - if (tmp[0] == '\0') { - tmp++; - size--; - } - - *signature = LIBSSH2_ALLOC(session, size); - memcpy(*signature, tmp, size); - *signature_len = size; - - return rc; -} - -int -_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, - const unsigned char *hash, - unsigned long hash_len, unsigned char *sig) -{ - unsigned char zhash[SHA_DIGEST_LENGTH + 1]; - gcry_sexp_t sig_sexp; - gcry_sexp_t data; - int ret; - const char *tmp; - size_t size; - - if (hash_len != SHA_DIGEST_LENGTH) { - return -1; - } - - memcpy(zhash + 1, hash, hash_len); - zhash[0] = 0; - - if (gcry_sexp_build(&data, NULL, "(data (value %b))", hash_len + 1, zhash)) { - return -1; - } - - ret = gcry_pk_sign(&sig_sexp, data, dsactx); - - gcry_sexp_release(data); - - if (ret != 0) { - return -1; - } - - memset(sig, 0, 40); - -/* Extract R. */ - - data = gcry_sexp_find_token(sig_sexp, "r", 0); - if (!data) - goto err; - - tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) - goto err; - - if (tmp[0] == '\0') { - tmp++; - size--; - } - - if (size < 1 || size > 20) - goto err; - - memcpy(sig + (20 - size), tmp, size); - - gcry_sexp_release(data); - -/* Extract S. */ - - data = gcry_sexp_find_token(sig_sexp, "s", 0); - if (!data) - goto err; - - tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) - goto err; - - if (tmp[0] == '\0') { - tmp++; - size--; - } - - if (size < 1 || size > 20) - goto err; - - memcpy(sig + 20 + (20 - size), tmp, size); - goto out; - - err: - ret = -1; - - out: - if (sig_sexp) { - gcry_sexp_release(sig_sexp); - } - if (data) { - gcry_sexp_release(data); - } - return ret; -} - -int -_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, - const unsigned char *sig, - const unsigned char *m, unsigned long m_len) -{ - unsigned char hash[SHA_DIGEST_LENGTH + 1]; - gcry_sexp_t s_sig, s_hash; - int rc = -1; - - libssh2_sha1(m, m_len, hash + 1); - hash[0] = 0; - - if (gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))", - SHA_DIGEST_LENGTH + 1, hash)) { - return -1; - } - - if (gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))", - 20, sig, 20, sig + 20)) { - gcry_sexp_release(s_hash); - return -1; - } - - rc = gcry_pk_verify(s_sig, s_hash, dsactx); - gcry_sexp_release(s_sig); - gcry_sexp_release(s_hash); - - return (rc == 0) ? 0 : -1; -} - -int -_libssh2_cipher_init(_libssh2_cipher_ctx * h, - _libssh2_cipher_type(algo), - unsigned char *iv, unsigned char *secret, int encrypt) -{ - int ret; - int cipher = _libssh2_gcry_cipher (algo); - int mode = _libssh2_gcry_mode (algo); - int keylen = gcry_cipher_get_algo_keylen(cipher); - - (void) encrypt; - - ret = gcry_cipher_open(h, cipher, mode, 0); - if (ret) { - return -1; - } - - ret = gcry_cipher_setkey(*h, secret, keylen); - if (ret) { - gcry_cipher_close(*h); - return -1; - } - - if (mode != GCRY_CIPHER_MODE_STREAM) { - int blklen = gcry_cipher_get_algo_blklen(cipher); - if (mode == GCRY_CIPHER_MODE_CTR) - ret = gcry_cipher_setctr(*h, iv, blklen); - else - ret = gcry_cipher_setiv(*h, iv, blklen); - if (ret) { - gcry_cipher_close(*h); - return -1; - } - } - - return 0; -} - -int -_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, - _libssh2_cipher_type(algo), - int encrypt, unsigned char *block) -{ - int cipher = _libssh2_gcry_cipher (algo); - size_t blklen = gcry_cipher_get_algo_blklen(cipher); - int ret; - - if (blklen == 1) { -/* Hack for arcfour. */ - blklen = 8; - } - - if (encrypt) { - ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen); - } else { - ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen); - } - return ret; -} - -int -_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase) -{ - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to extract public key from private key file: " - "Method unimplemented in libgcrypt backend"); -} - -void _libssh2_init_aes_ctr(void) -{ - /* no implementation */ -} -#endif /* LIBSSH2_LIBGCRYPT */ diff --git a/vendor/libssh2-1.4.2/src/libgcrypt.h b/vendor/libssh2-1.4.2/src/libgcrypt.h deleted file mode 100644 index 04516e5..0000000 --- a/vendor/libssh2-1.4.2/src/libgcrypt.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007, The Written Word, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 - -#define LIBSSH2_MD5 1 - -#define LIBSSH2_HMAC_RIPEMD 1 - -#define LIBSSH2_AES 1 -#define LIBSSH2_AES_CTR 1 -#define LIBSSH2_BLOWFISH 1 -#define LIBSSH2_RC4 1 -#define LIBSSH2_CAST 1 -#define LIBSSH2_3DES 1 - -#define LIBSSH2_RSA 1 -#define LIBSSH2_DSA 1 - -#define MD5_DIGEST_LENGTH 16 -#define SHA_DIGEST_LENGTH 20 - -#define _libssh2_random(buf, len) \ - (gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1) - -#define libssh2_sha1_ctx gcry_md_hd_t -#define libssh2_sha1_init(ctx) gcry_md_open (ctx, GCRY_MD_SHA1, 0); -#define libssh2_sha1_update(ctx, data, len) gcry_md_write (ctx, data, len) -#define libssh2_sha1_final(ctx, out) \ - memcpy (out, gcry_md_read (ctx, 0), SHA_DIGEST_LENGTH), gcry_md_close (ctx) -#define libssh2_sha1(message, len, out) \ - gcry_md_hash_buffer (GCRY_MD_SHA1, out, message, len) - -#define libssh2_md5_ctx gcry_md_hd_t -#define libssh2_md5_init(ctx) gcry_md_open (ctx, GCRY_MD_MD5, 0); -#define libssh2_md5_update(ctx, data, len) gcry_md_write (ctx, data, len) -#define libssh2_md5_final(ctx, out) \ - memcpy (out, gcry_md_read (ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close (ctx) -#define libssh2_md5(message, len, out) \ - gcry_md_hash_buffer (GCRY_MD_MD5, out, message, len) - -#define libssh2_hmac_ctx gcry_md_hd_t -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) -#define libssh2_hmac_update(ctx, data, datalen) \ - gcry_md_write (ctx, data, datalen) -#define libssh2_hmac_final(ctx, data) \ - memcpy (data, gcry_md_read (ctx, 0), \ - gcry_md_get_algo_dlen (gcry_md_get_algo (ctx))) -#define libssh2_hmac_cleanup(ctx) gcry_md_close (*ctx); - -#define libssh2_crypto_init() gcry_control (GCRYCTL_DISABLE_SECMEM) -#define libssh2_crypto_exit() - -#define libssh2_rsa_ctx struct gcry_sexp - -#define _libssh2_rsa_free(rsactx) gcry_sexp_release (rsactx) - -#define libssh2_dsa_ctx struct gcry_sexp - -#define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx) - -#define _libssh2_cipher_type(name) int name -#define _libssh2_cipher_ctx gcry_cipher_hd_t - -#define _libssh2_gcry_ciphermode(c,m) ((c << 8) | m) -#define _libssh2_gcry_cipher(c) (c >> 8) -#define _libssh2_gcry_mode(m) (m & 0xFF) - -#define _libssh2_cipher_aes256ctr \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR) -#define _libssh2_cipher_aes192ctr \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR) -#define _libssh2_cipher_aes128ctr \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR) -#define _libssh2_cipher_aes256 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_aes192 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_aes128 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_blowfish \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_arcfour \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM) -#define _libssh2_cipher_cast5 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_3des \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC) - - -#define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx)) - -#define _libssh2_bn struct gcry_mpi -#define _libssh2_bn_ctx int -#define _libssh2_bn_ctx_new() 0 -#define _libssh2_bn_ctx_free(bnctx) ((void)0) -#define _libssh2_bn_init() gcry_mpi_new(0) -#define _libssh2_bn_rand(bn, bits, top, bottom) gcry_mpi_randomize (bn, bits, GCRY_WEAK_RANDOM) -#define _libssh2_bn_mod_exp(r, a, p, m, ctx) gcry_mpi_powm (r, a, p, m) -#define _libssh2_bn_set_word(bn, val) gcry_mpi_set_ui(bn, val) -#define _libssh2_bn_from_bin(bn, len, val) gcry_mpi_scan(&((bn)), GCRYMPI_FMT_USG, val, len, NULL) -#define _libssh2_bn_to_bin(bn, val) gcry_mpi_print (GCRYMPI_FMT_USG, val, _libssh2_bn_bytes(bn), NULL, bn) -#define _libssh2_bn_bytes(bn) (gcry_mpi_get_nbits (bn) / 8 + ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1)) -#define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn) -#define _libssh2_bn_free(bn) gcry_mpi_release(bn) - diff --git a/vendor/libssh2-1.4.2/src/libssh2_config.h b/vendor/libssh2-1.4.2/src/libssh2_config.h deleted file mode 100644 index 4591f5f..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_config.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef WIN32 - #include "libssh2_config_win.h" -#else - #include "libssh2_config_osx.h" -#endif diff --git a/vendor/libssh2-1.4.2/src/libssh2_config_osx.h b/vendor/libssh2-1.4.2/src/libssh2_config_osx.h deleted file mode 100644 index d8917c2..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_config_osx.h +++ /dev/null @@ -1,224 +0,0 @@ -/* src/libssh2_config.h. Generated from libssh2_config.h.in by configure. */ -/* src/libssh2_config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#define HAVE_ALLOCA_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* disabled non-blocking sockets */ -/* #undef HAVE_DISABLED_NONBLOCKING */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the `EVP_aes_128_ctr' function. */ -/* #undef HAVE_EVP_AES_128_CTR */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* use FIONBIO for non-blocking sockets */ -/* #undef HAVE_FIONBIO */ - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* use ioctlsocket() for non-blocking sockets */ -/* #undef HAVE_IOCTLSOCKET */ - -/* use Ioctlsocket() for non-blocking sockets */ -/* #undef HAVE_IOCTLSOCKET_CASE */ - -/* Define if you have the gcrypt library. */ -/* #undef HAVE_LIBGCRYPT */ - -/* Define if you have the ssl library. */ -#define HAVE_LIBSSL 1 - -/* Define if you have the z library. */ -#define HAVE_LIBZ 1 - -/* Define to 1 if the compiler supports the 'long long' data type. */ -#define HAVE_LONGLONG 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* use O_NONBLOCK for non-blocking sockets */ -#define HAVE_O_NONBLOCK 1 - -/* Define to 1 if you have the `poll' function. */ -/* #undef HAVE_POLL */ - -/* Define to 1 if you have the select function. */ -#define HAVE_SELECT 1 - -/* use SO_NONBLOCK for non-blocking sockets */ -/* #undef HAVE_SO_NONBLOCK */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_UIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_UN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WINDOWS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WINSOCK2_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WS2TCPIP_H */ - -/* to make a symbol visible */ -/* #undef LIBSSH2_API */ - -/* Enable "none" cipher -- NOT RECOMMENDED */ -/* #undef LIBSSH2_CRYPT_NONE */ - -/* Enable newer diffie-hellman-group-exchange-sha1 syntax */ -#define LIBSSH2_DH_GEX_NEW 1 - -/* Compile in zlib support */ -#define LIBSSH2_HAVE_ZLIB 1 - -/* Use libgcrypt */ -/* #undef LIBSSH2_LIBGCRYPT */ - -/* Enable "none" MAC -- NOT RECOMMENDED */ -/* #undef LIBSSH2_MAC_NONE */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" - -/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ -/* #undef NEED_REENTRANT */ - -/* Name of package */ -#define PACKAGE "libssh2" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "libssh2-devel@cool.haxx.se" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libssh2" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libssh2 -" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libssh2" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "-" - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "-" - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif diff --git a/vendor/libssh2-1.4.2/src/libssh2_config_win.h b/vendor/libssh2-1.4.2/src/libssh2_config_win.h deleted file mode 100644 index 39e438f..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_config_win.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef LIBSSH2_CONFIG_H -#define LIBSSH2_CONFIG_H - -#ifndef WIN32 -#define WIN32 -#endif -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif /* _CRT_SECURE_NO_DEPRECATE */ -#include -#include -#include - -#ifdef __MINGW32__ -#define HAVE_UNISTD_H -#define HAVE_INTTYPES_H -#define HAVE_SYS_TIME_H -#endif - -#define HAVE_WINSOCK2_H -#define HAVE_IOCTLSOCKET -#define HAVE_SELECT - -#ifdef _MSC_VER -#define snprintf _snprintf -#if _MSC_VER < 1500 -#define vsnprintf _vsnprintf -#endif -#define strdup _strdup -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#define strncasecmp strnicmp -#define strcasecmp stricmp -#endif /* _MSC_VER */ - -/* Enable newer diffie-hellman-group-exchange-sha1 syntax */ -#define LIBSSH2_DH_GEX_NEW 1 - -#endif /* LIBSSH2_CONFIG_H */ - diff --git a/vendor/libssh2-1.4.2/src/libssh2_priv.h b/vendor/libssh2-1.4.2/src/libssh2_priv.h deleted file mode 100644 index c670a16..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_priv.h +++ /dev/null @@ -1,1038 +0,0 @@ -/* Copyright (c) 2004-2008, 2010, Sara Golemon - * Copyright (c) 2009-2011 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 LIBSSH2_PRIV_H -#define LIBSSH2_PRIV_H 1 - -#define LIBSSH2_LIBRARY -#include "libssh2_config.h" - -#ifdef HAVE_WINDOWS_H -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#undef WIN32_LEAN_AND_MEAN -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#include -#include - -/* The following CPP block should really only be in session.c and - packet.c. However, AIX have #define's for 'events' and 'revents' - and we are using those names in libssh2.h, so we need to include - the AIX headers first, to make sure all code is compiled with - consistent names of these fields. While arguable the best would to - change libssh2.h to use other names, that would break backwards - compatibility. For more information, see: - http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00003.html - http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00224.html -*/ -#ifdef HAVE_POLL -# include -#else -# if defined(HAVE_SELECT) && !defined(WIN32) -# ifdef HAVE_SYS_SELECT_H -# include -# else -# include -# include -# endif -# endif -#endif - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_INTTYPES_H -#include -#endif - -#include "libssh2.h" -#include "libssh2_publickey.h" -#include "libssh2_sftp.h" -#include "misc.h" /* for the linked list stuff */ - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -/* Provide iovec / writev on WIN32 platform. */ -#ifdef WIN32 - -struct iovec { - size_t iov_len; - void * iov_base; -}; - -#define inline __inline - -static inline int writev(int sock, struct iovec *iov, int nvecs) -{ - DWORD ret; - if (WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) { - return ret; - } - return -1; -} - -#endif /* WIN32 */ - -#include "crypto.h" - -#ifdef HAVE_WINSOCK2_H - -#include -#include -#include - -#ifdef _MSC_VER -/* "inline" keyword is valid only with C++ engine! */ -#define inline __inline -#endif - -#endif - -/* RFC4253 section 6.1 Maximum Packet Length says: - * - * "All implementations MUST be able to process packets with - * uncompressed payload length of 32768 bytes or less and - * total packet size of 35000 bytes or less (including length, - * padding length, payload, padding, and MAC.)." - */ -#define MAX_SSH_PACKET_LEN 35000 - -#define LIBSSH2_ALLOC(session, count) \ - session->alloc((count), &(session)->abstract) -#define LIBSSH2_REALLOC(session, ptr, count) \ - ((ptr) ? session->realloc((ptr), (count), &(session)->abstract) : \ - session->alloc((count), &(session)->abstract)) -#define LIBSSH2_FREE(session, ptr) \ - session->free((ptr), &(session)->abstract) -#define LIBSSH2_IGNORE(session, data, datalen) \ - session->ssh_msg_ignore((session), (data), (datalen), &(session)->abstract) -#define LIBSSH2_DEBUG(session, always_display, message, message_len, \ - language, language_len) \ - session->ssh_msg_debug((session), (always_display), (message), \ - (message_len), (language), (language_len), \ - &(session)->abstract) -#define LIBSSH2_DISCONNECT(session, reason, message, message_len, \ - language, language_len) \ - session->ssh_msg_disconnect((session), (reason), (message), \ - (message_len), (language), (language_len), \ - &(session)->abstract) - -#define LIBSSH2_MACERROR(session, data, datalen) \ - session->macerror((session), (data), (datalen), &(session)->abstract) -#define LIBSSH2_X11_OPEN(channel, shost, sport) \ - channel->session->x11(((channel)->session), (channel), \ - (shost), (sport), (&(channel)->session->abstract)) - -#define LIBSSH2_CHANNEL_CLOSE(session, channel) \ - channel->close_cb((session), &(session)->abstract, \ - (channel), &(channel)->abstract) - -#define LIBSSH2_SEND_FD(session, fd, buffer, length, flags) \ - session->send(fd, buffer, length, flags, &session->abstract) -#define LIBSSH2_RECV_FD(session, fd, buffer, length, flags) \ - session->recv(fd, buffer, length, flags, &session->abstract) - -#define LIBSSH2_SEND(session, buffer, length, flags) \ - LIBSSH2_SEND_FD(session, session->socket_fd, buffer, length, flags) -#define LIBSSH2_RECV(session, buffer, length, flags) \ - LIBSSH2_RECV_FD(session, session->socket_fd, buffer, length, flags) - -typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD; -typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD; -typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD; -typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD; - -typedef struct _LIBSSH2_PACKET LIBSSH2_PACKET; - -typedef enum -{ - libssh2_NB_state_idle = 0, - libssh2_NB_state_allocated, - libssh2_NB_state_created, - libssh2_NB_state_sent, - libssh2_NB_state_sent1, - libssh2_NB_state_sent2, - libssh2_NB_state_sent3, - libssh2_NB_state_sent4, - libssh2_NB_state_sent5, - libssh2_NB_state_sent6, - libssh2_NB_state_sent7, - libssh2_NB_state_jump1, - libssh2_NB_state_jump2, - libssh2_NB_state_jump3, - libssh2_NB_state_jump4, - libssh2_NB_state_jump5 -} libssh2_nonblocking_states; - -typedef struct packet_require_state_t -{ - libssh2_nonblocking_states state; - time_t start; -} packet_require_state_t; - -typedef struct packet_requirev_state_t -{ - time_t start; -} packet_requirev_state_t; - -typedef struct kmdhgGPsha1kex_state_t -{ - libssh2_nonblocking_states state; - unsigned char *e_packet; - unsigned char *s_packet; - unsigned char *tmp; - unsigned char h_sig_comp[SHA_DIGEST_LENGTH]; - unsigned char c; - size_t e_packet_len; - size_t s_packet_len; - size_t tmp_len; - _libssh2_bn_ctx *ctx; - _libssh2_bn *x; - _libssh2_bn *e; - _libssh2_bn *f; - _libssh2_bn *k; - unsigned char *s; - unsigned char *f_value; - unsigned char *k_value; - unsigned char *h_sig; - size_t f_value_len; - size_t k_value_len; - size_t h_sig_len; - libssh2_sha1_ctx exchange_hash; - packet_require_state_t req_state; - libssh2_nonblocking_states burn_state; -} kmdhgGPsha1kex_state_t; - -typedef struct key_exchange_state_low_t -{ - libssh2_nonblocking_states state; - packet_require_state_t req_state; - kmdhgGPsha1kex_state_t exchange_state; - _libssh2_bn *p; /* SSH2 defined value (p_value) */ - _libssh2_bn *g; /* SSH2 defined value (2) */ - unsigned char request[13]; - unsigned char *data; - size_t request_len; - size_t data_len; -} key_exchange_state_low_t; - -typedef struct key_exchange_state_t -{ - libssh2_nonblocking_states state; - packet_require_state_t req_state; - key_exchange_state_low_t key_state_low; - unsigned char *data; - size_t data_len; - unsigned char *oldlocal; - size_t oldlocal_len; -} key_exchange_state_t; - -#define FwdNotReq "Forward not requested" - -typedef struct packet_queue_listener_state_t -{ - libssh2_nonblocking_states state; - unsigned char packet[17 + (sizeof(FwdNotReq) - 1)]; - unsigned char *host; - unsigned char *shost; - uint32_t sender_channel; - uint32_t initial_window_size; - uint32_t packet_size; - uint32_t port; - uint32_t sport; - uint32_t host_len; - uint32_t shost_len; - LIBSSH2_CHANNEL *channel; -} packet_queue_listener_state_t; - -#define X11FwdUnAvil "X11 Forward Unavailable" - -typedef struct packet_x11_open_state_t -{ - libssh2_nonblocking_states state; - unsigned char packet[17 + (sizeof(X11FwdUnAvil) - 1)]; - unsigned char *shost; - uint32_t sender_channel; - uint32_t initial_window_size; - uint32_t packet_size; - uint32_t sport; - uint32_t shost_len; - LIBSSH2_CHANNEL *channel; -} packet_x11_open_state_t; - -struct _LIBSSH2_PACKET -{ - struct list_node node; /* linked list header */ - - /* the raw unencrypted payload */ - unsigned char *data; - size_t data_len; - - /* Where to start reading data from, - * used for channel data that's been partially consumed */ - size_t data_head; -}; - -typedef struct _libssh2_channel_data -{ - /* Identifier */ - uint32_t id; - - /* Limits and restrictions */ - uint32_t window_size_initial, window_size, packet_size; - - /* Set to 1 when CHANNEL_CLOSE / CHANNEL_EOF sent/received */ - char close, eof, extended_data_ignore_mode; -} libssh2_channel_data; - -struct _LIBSSH2_CHANNEL -{ - struct list_node node; - - unsigned char *channel_type; - unsigned channel_type_len; - - /* channel's program exit status */ - int exit_status; - - /* channel's program exit signal (without the SIG prefix) */ - char *exit_signal; - - libssh2_channel_data local, remote; - /* Amount of bytes to be refunded to receive window (but not yet sent) */ - uint32_t adjust_queue; - - LIBSSH2_SESSION *session; - - void *abstract; - LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb)); - - /* State variables used in libssh2_channel_setenv_ex() */ - libssh2_nonblocking_states setenv_state; - unsigned char *setenv_packet; - size_t setenv_packet_len; - unsigned char setenv_local_channel[4]; - packet_requirev_state_t setenv_packet_requirev_state; - - /* State variables used in libssh2_channel_request_pty_ex() - libssh2_channel_request_pty_size_ex() */ - libssh2_nonblocking_states reqPTY_state; - unsigned char reqPTY_packet[41 + 256]; - size_t reqPTY_packet_len; - unsigned char reqPTY_local_channel[4]; - packet_requirev_state_t reqPTY_packet_requirev_state; - - /* State variables used in libssh2_channel_x11_req_ex() */ - libssh2_nonblocking_states reqX11_state; - unsigned char *reqX11_packet; - size_t reqX11_packet_len; - unsigned char reqX11_local_channel[4]; - packet_requirev_state_t reqX11_packet_requirev_state; - - /* State variables used in libssh2_channel_process_startup() */ - libssh2_nonblocking_states process_state; - unsigned char *process_packet; - size_t process_packet_len; - unsigned char process_local_channel[4]; - packet_requirev_state_t process_packet_requirev_state; - - /* State variables used in libssh2_channel_flush_ex() */ - libssh2_nonblocking_states flush_state; - size_t flush_refund_bytes; - size_t flush_flush_bytes; - - /* State variables used in libssh2_channel_receive_window_adjust() */ - libssh2_nonblocking_states adjust_state; - unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */ - - /* State variables used in libssh2_channel_read_ex() */ - libssh2_nonblocking_states read_state; - - uint32_t read_local_id; - - /* State variables used in libssh2_channel_write_ex() */ - libssh2_nonblocking_states write_state; - unsigned char write_packet[13]; - size_t write_packet_len; - size_t write_bufwrite; - - /* State variables used in libssh2_channel_close() */ - libssh2_nonblocking_states close_state; - unsigned char close_packet[5]; - - /* State variables used in libssh2_channel_wait_closedeof() */ - libssh2_nonblocking_states wait_eof_state; - - /* State variables used in libssh2_channel_wait_closed() */ - libssh2_nonblocking_states wait_closed_state; - - /* State variables used in libssh2_channel_free() */ - libssh2_nonblocking_states free_state; - - /* State variables used in libssh2_channel_handle_extended_data2() */ - libssh2_nonblocking_states extData2_state; - -}; - -struct _LIBSSH2_LISTENER -{ - struct list_node node; /* linked list header */ - - LIBSSH2_SESSION *session; - - char *host; - int port; - - /* a list of CHANNELs for this listener */ - struct list_head queue; - - int queue_size; - int queue_maxsize; - - /* State variables used in libssh2_channel_forward_cancel() */ - libssh2_nonblocking_states chanFwdCncl_state; - unsigned char *chanFwdCncl_data; - size_t chanFwdCncl_data_len; -}; - -typedef struct _libssh2_endpoint_data -{ - unsigned char *banner; - - unsigned char *kexinit; - size_t kexinit_len; - - const LIBSSH2_CRYPT_METHOD *crypt; - void *crypt_abstract; - - const struct _LIBSSH2_MAC_METHOD *mac; - uint32_t seqno; - void *mac_abstract; - - const LIBSSH2_COMP_METHOD *comp; - void *comp_abstract; - - /* Method Preferences -- NULL yields "load order" */ - char *crypt_prefs; - char *mac_prefs; - char *comp_prefs; - char *lang_prefs; -} libssh2_endpoint_data; - -#define PACKETBUFSIZE (1024*16) - -struct transportpacket -{ - /* ------------- for incoming data --------------- */ - unsigned char buf[PACKETBUFSIZE]; - unsigned char init[5]; /* first 5 bytes of the incoming data stream, - still encrypted */ - size_t writeidx; /* at what array index we do the next write into - the buffer */ - size_t readidx; /* at what array index we do the next read from - the buffer */ - uint32_t packet_length; /* the most recent packet_length as read from the - network data */ - uint8_t padding_length; /* the most recent padding_length as read from the - network data */ - size_t data_num; /* How much of the total package that has been read - so far. */ - size_t total_num; /* How much a total package is supposed to be, in - number of bytes. A full package is - packet_length + padding_length + 4 + - mac_length. */ - unsigned char *payload; /* this is a pointer to a LIBSSH2_ALLOC() - area to which we write decrypted data */ - unsigned char *wptr; /* write pointer into the payload to where we - are currently writing decrypted data */ - - /* ------------- for outgoing data --------------- */ - unsigned char outbuf[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */ - - int ototal_num; /* size of outbuf in number of bytes */ - const unsigned char *odata; /* original pointer to the data */ - size_t olen; /* original size of the data we stored in - outbuf */ - size_t osent; /* number of bytes already sent */ -}; - -struct _LIBSSH2_PUBLICKEY -{ - LIBSSH2_CHANNEL *channel; - uint32_t version; - - /* State variables used in libssh2_publickey_packet_receive() */ - libssh2_nonblocking_states receive_state; - unsigned char *receive_packet; - size_t receive_packet_len; - - /* State variables used in libssh2_publickey_add_ex() */ - libssh2_nonblocking_states add_state; - unsigned char *add_packet; - unsigned char *add_s; - - /* State variables used in libssh2_publickey_remove_ex() */ - libssh2_nonblocking_states remove_state; - unsigned char *remove_packet; - unsigned char *remove_s; - - /* State variables used in libssh2_publickey_list_fetch() */ - libssh2_nonblocking_states listFetch_state; - unsigned char *listFetch_s; - unsigned char listFetch_buffer[12]; - unsigned char *listFetch_data; - size_t listFetch_data_len; -}; - -#define LIBSSH2_SCP_RESPONSE_BUFLEN 256 - -struct flags { - int sigpipe; /* LIBSSH2_FLAG_SIGPIPE */ - int compress; /* LIBSSH2_FLAG_COMPRESS */ -}; - -struct _LIBSSH2_SESSION -{ - /* Memory management callbacks */ - void *abstract; - LIBSSH2_ALLOC_FUNC((*alloc)); - LIBSSH2_REALLOC_FUNC((*realloc)); - LIBSSH2_FREE_FUNC((*free)); - - /* Other callbacks */ - LIBSSH2_IGNORE_FUNC((*ssh_msg_ignore)); - LIBSSH2_DEBUG_FUNC((*ssh_msg_debug)); - LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect)); - LIBSSH2_MACERROR_FUNC((*macerror)); - LIBSSH2_X11_OPEN_FUNC((*x11)); - LIBSSH2_SEND_FUNC((*send)); - LIBSSH2_RECV_FUNC((*recv)); - - /* Method preferences -- NULL yields "load order" */ - char *kex_prefs; - char *hostkey_prefs; - - int state; - - /* Flag options */ - struct flags flag; - - /* Agreed Key Exchange Method */ - const LIBSSH2_KEX_METHOD *kex; - int burn_optimistic_kexinit:1; - - unsigned char *session_id; - uint32_t session_id_len; - - /* this is set to TRUE if a blocking API behavior is requested */ - int api_block_mode; - - /* Timeout used when blocking API behavior is active */ - long api_timeout; - - /* Server's public key */ - const LIBSSH2_HOSTKEY_METHOD *hostkey; - void *server_hostkey_abstract; - - /* Either set with libssh2_session_hostkey() (for server mode) - * Or read from server in (eg) KEXDH_INIT (for client mode) - */ - unsigned char *server_hostkey; - uint32_t server_hostkey_len; -#if LIBSSH2_MD5 - unsigned char server_hostkey_md5[MD5_DIGEST_LENGTH]; -#endif /* ! LIBSSH2_MD5 */ - unsigned char server_hostkey_sha1[SHA_DIGEST_LENGTH]; - - /* (remote as source of data -- packet_read ) */ - libssh2_endpoint_data remote; - - /* (local as source of data -- packet_write ) */ - libssh2_endpoint_data local; - - /* Inbound Data linked list -- Sometimes the packet that comes in isn't the - packet we're ready for */ - struct list_head packets; - - /* Active connection channels */ - struct list_head channels; - - uint32_t next_channel; - - struct list_head listeners; /* list of LIBSSH2_LISTENER structs */ - - /* Actual I/O socket */ - libssh2_socket_t socket_fd; - int socket_state; - int socket_block_directions; - int socket_prev_blockstate; /* stores the state of the socket blockiness - when libssh2_session_startup() is called */ - - /* Error tracking */ - const char *err_msg; - int err_code; - - /* struct members for packet-level reading */ - struct transportpacket packet; -#ifdef LIBSSH2DEBUG - int showmask; /* what debug/trace messages to display */ - libssh2_trace_handler_func tracehandler; /* callback to display trace messages */ - void* tracehandler_context; /* context for the trace handler */ -#endif - - /* State variables used in libssh2_banner_send() */ - libssh2_nonblocking_states banner_TxRx_state; - char banner_TxRx_banner[256]; - ssize_t banner_TxRx_total_send; - - /* State variables used in libssh2_kexinit() */ - libssh2_nonblocking_states kexinit_state; - unsigned char *kexinit_data; - size_t kexinit_data_len; - - /* State variables used in libssh2_session_startup() */ - libssh2_nonblocking_states startup_state; - unsigned char *startup_data; - size_t startup_data_len; - unsigned char startup_service[sizeof("ssh-userauth") + 5 - 1]; - size_t startup_service_length; - packet_require_state_t startup_req_state; - key_exchange_state_t startup_key_state; - - /* State variables used in libssh2_session_free() */ - libssh2_nonblocking_states free_state; - - /* State variables used in libssh2_session_disconnect_ex() */ - libssh2_nonblocking_states disconnect_state; - unsigned char disconnect_data[256 + 13]; - size_t disconnect_data_len; - - /* State variables used in libssh2_packet_read() */ - libssh2_nonblocking_states readPack_state; - int readPack_encrypted; - - /* State variables used in libssh2_userauth_list() */ - libssh2_nonblocking_states userauth_list_state; - unsigned char *userauth_list_data; - size_t userauth_list_data_len; - packet_requirev_state_t userauth_list_packet_requirev_state; - - /* State variables used in libssh2_userauth_password_ex() */ - libssh2_nonblocking_states userauth_pswd_state; - unsigned char *userauth_pswd_data; - unsigned char userauth_pswd_data0; - size_t userauth_pswd_data_len; - char *userauth_pswd_newpw; - int userauth_pswd_newpw_len; - packet_requirev_state_t userauth_pswd_packet_requirev_state; - - /* State variables used in libssh2_userauth_hostbased_fromfile_ex() */ - libssh2_nonblocking_states userauth_host_state; - unsigned char *userauth_host_data; - size_t userauth_host_data_len; - unsigned char *userauth_host_packet; - size_t userauth_host_packet_len; - unsigned char *userauth_host_method; - size_t userauth_host_method_len; - unsigned char *userauth_host_s; - packet_requirev_state_t userauth_host_packet_requirev_state; - - /* State variables used in libssh2_userauth_publickey_fromfile_ex() */ - libssh2_nonblocking_states userauth_pblc_state; - unsigned char *userauth_pblc_data; - size_t userauth_pblc_data_len; - unsigned char *userauth_pblc_packet; - size_t userauth_pblc_packet_len; - unsigned char *userauth_pblc_method; - size_t userauth_pblc_method_len; - unsigned char *userauth_pblc_s; - unsigned char *userauth_pblc_b; - packet_requirev_state_t userauth_pblc_packet_requirev_state; - - /* State variables used in libssh2_userauth_keyboard_interactive_ex() */ - libssh2_nonblocking_states userauth_kybd_state; - unsigned char *userauth_kybd_data; - size_t userauth_kybd_data_len; - unsigned char *userauth_kybd_packet; - size_t userauth_kybd_packet_len; - unsigned int userauth_kybd_auth_name_len; - char *userauth_kybd_auth_name; - unsigned userauth_kybd_auth_instruction_len; - char *userauth_kybd_auth_instruction; - unsigned int userauth_kybd_num_prompts; - int userauth_kybd_auth_failure; - LIBSSH2_USERAUTH_KBDINT_PROMPT *userauth_kybd_prompts; - LIBSSH2_USERAUTH_KBDINT_RESPONSE *userauth_kybd_responses; - packet_requirev_state_t userauth_kybd_packet_requirev_state; - - /* State variables used in libssh2_channel_open_ex() */ - libssh2_nonblocking_states open_state; - packet_requirev_state_t open_packet_requirev_state; - LIBSSH2_CHANNEL *open_channel; - unsigned char *open_packet; - size_t open_packet_len; - unsigned char *open_data; - size_t open_data_len; - uint32_t open_local_channel; - - /* State variables used in libssh2_channel_direct_tcpip_ex() */ - libssh2_nonblocking_states direct_state; - unsigned char *direct_message; - size_t direct_host_len; - size_t direct_shost_len; - size_t direct_message_len; - - /* State variables used in libssh2_channel_forward_listen_ex() */ - libssh2_nonblocking_states fwdLstn_state; - unsigned char *fwdLstn_packet; - uint32_t fwdLstn_host_len; - uint32_t fwdLstn_packet_len; - packet_requirev_state_t fwdLstn_packet_requirev_state; - - /* State variables used in libssh2_publickey_init() */ - libssh2_nonblocking_states pkeyInit_state; - LIBSSH2_PUBLICKEY *pkeyInit_pkey; - LIBSSH2_CHANNEL *pkeyInit_channel; - unsigned char *pkeyInit_data; - size_t pkeyInit_data_len; - /* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */ - unsigned char pkeyInit_buffer[19]; - size_t pkeyInit_buffer_sent; /* how much of buffer that has been sent */ - - /* State variables used in libssh2_packet_add() */ - libssh2_nonblocking_states packAdd_state; - LIBSSH2_CHANNEL *packAdd_channelp; /* keeper of the channel during EAGAIN - states */ - packet_queue_listener_state_t packAdd_Qlstn_state; - packet_x11_open_state_t packAdd_x11open_state; - - /* State variables used in fullpacket() */ - libssh2_nonblocking_states fullpacket_state; - int fullpacket_macstate; - size_t fullpacket_payload_len; - int fullpacket_packet_type; - - /* State variables used in libssh2_sftp_init() */ - libssh2_nonblocking_states sftpInit_state; - LIBSSH2_SFTP *sftpInit_sftp; - LIBSSH2_CHANNEL *sftpInit_channel; - unsigned char sftpInit_buffer[9]; /* sftp_header(5){excludes request_id} - + version_id(4) */ - int sftpInit_sent; /* number of bytes from the buffer that have been - sent */ - - /* State variables used in libssh2_scp_recv() */ - libssh2_nonblocking_states scpRecv_state; - unsigned char *scpRecv_command; - size_t scpRecv_command_len; - unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN]; - size_t scpRecv_response_len; - long scpRecv_mode; -#if defined(HAVE_LONGLONG) && defined(HAVE_STRTOLL) - /* we have the type and we can parse such numbers */ - long long scpRecv_size; -#define scpsize_strtol strtoll -#else - long scpRecv_size; -#define scpsize_strtol strtol -#endif - long scpRecv_mtime; - long scpRecv_atime; - LIBSSH2_CHANNEL *scpRecv_channel; - - /* State variables used in libssh2_scp_send_ex() */ - libssh2_nonblocking_states scpSend_state; - unsigned char *scpSend_command; - size_t scpSend_command_len; - unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN]; - size_t scpSend_response_len; - LIBSSH2_CHANNEL *scpSend_channel; - - /* Keepalive variables used by keepalive.c. */ - int keepalive_interval; - int keepalive_want_reply; - time_t keepalive_last_sent; -}; - -/* session.state bits */ -#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001 -#define LIBSSH2_STATE_NEWKEYS 0x00000002 -#define LIBSSH2_STATE_AUTHENTICATED 0x00000004 -#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008 - -/* session.flag helpers */ -#ifdef MSG_NOSIGNAL -#define LIBSSH2_SOCKET_SEND_FLAGS(session) \ - (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL) -#define LIBSSH2_SOCKET_RECV_FLAGS(session) \ - (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL) -#else -/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */ -#define LIBSSH2_SOCKET_SEND_FLAGS(session) 0 -#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0 -#endif - -/* --------- */ - -/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional - methods via .so/.dll */ - -struct _LIBSSH2_KEX_METHOD -{ - const char *name; - - /* Key exchange, populates session->* and returns 0 on success, non-0 on error */ - int (*exchange_keys) (LIBSSH2_SESSION * session, - key_exchange_state_low_t * key_state); - - long flags; -}; - -struct _LIBSSH2_HOSTKEY_METHOD -{ - const char *name; - unsigned long hash_len; - - int (*init) (LIBSSH2_SESSION * session, const unsigned char *hostkey_data, - size_t hostkey_data_len, void **abstract); - int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile, - unsigned const char *passphrase, void **abstract); - int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig, - size_t sig_len, const unsigned char *m, - size_t m_len, void **abstract); - int (*signv) (LIBSSH2_SESSION * session, unsigned char **signature, - size_t *signature_len, int veccount, - const struct iovec datavec[], void **abstract); - int (*encrypt) (LIBSSH2_SESSION * session, unsigned char **dst, - size_t *dst_len, const unsigned char *src, - size_t src_len, void **abstract); - int (*dtor) (LIBSSH2_SESSION * session, void **abstract); -}; - -struct _LIBSSH2_CRYPT_METHOD -{ - const char *name; - - int blocksize; - - /* iv and key sizes (-1 for variable length) */ - int iv_len; - int secret_len; - - long flags; - - int (*init) (LIBSSH2_SESSION * session, - const LIBSSH2_CRYPT_METHOD * method, unsigned char *iv, - int *free_iv, unsigned char *secret, int *free_secret, - int encrypt, void **abstract); - int (*crypt) (LIBSSH2_SESSION * session, unsigned char *block, - void **abstract); - int (*dtor) (LIBSSH2_SESSION * session, void **abstract); - - _libssh2_cipher_type(algo); -}; - -struct _LIBSSH2_COMP_METHOD -{ - const char *name; - int compress; /* 1 if it does compress, 0 if it doesn't */ - int (*init) (LIBSSH2_SESSION *session, int compress, void **abstract); - int (*comp) (LIBSSH2_SESSION *session, - unsigned char *dest, - size_t *dest_len, - const unsigned char *src, - size_t src_len, - void **abstract); - int (*decomp) (LIBSSH2_SESSION *session, - unsigned char **dest, - size_t *dest_len, - size_t payload_limit, - const unsigned char *src, - size_t src_len, - void **abstract); - int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract); -}; - -#ifdef LIBSSH2DEBUG -void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, - ...); -#else -#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__) -/* C99 supported and also by older GCC */ -#define _libssh2_debug(x,y,z,...) do {} while (0) -#else -/* no gcc and not C99, do static and hopefully inline */ -static inline void -_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) -{ -} -#endif -#endif - -#define LIBSSH2_SOCKET_UNKNOWN 1 -#define LIBSSH2_SOCKET_CONNECTED 0 -#define LIBSSH2_SOCKET_DISCONNECTED -1 - -/* Initial packet state, prior to MAC check */ -#define LIBSSH2_MAC_UNCONFIRMED 1 -/* When MAC type is "none" (proto initiation phase) all packets are deemed "confirmed" */ -#define LIBSSH2_MAC_CONFIRMED 0 -/* Something very bad is going on */ -#define LIBSSH2_MAC_INVALID -1 - -/* SSH Packet Types -- Defined by internet draft */ -/* Transport Layer */ -#define SSH_MSG_DISCONNECT 1 -#define SSH_MSG_IGNORE 2 -#define SSH_MSG_UNIMPLEMENTED 3 -#define SSH_MSG_DEBUG 4 -#define SSH_MSG_SERVICE_REQUEST 5 -#define SSH_MSG_SERVICE_ACCEPT 6 - -#define SSH_MSG_KEXINIT 20 -#define SSH_MSG_NEWKEYS 21 - -/* diffie-hellman-group1-sha1 */ -#define SSH_MSG_KEXDH_INIT 30 -#define SSH_MSG_KEXDH_REPLY 31 - -/* diffie-hellman-group-exchange-sha1 */ -#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30 -#define SSH_MSG_KEX_DH_GEX_REQUEST 34 -#define SSH_MSG_KEX_DH_GEX_GROUP 31 -#define SSH_MSG_KEX_DH_GEX_INIT 32 -#define SSH_MSG_KEX_DH_GEX_REPLY 33 - -/* User Authentication */ -#define SSH_MSG_USERAUTH_REQUEST 50 -#define SSH_MSG_USERAUTH_FAILURE 51 -#define SSH_MSG_USERAUTH_SUCCESS 52 -#define SSH_MSG_USERAUTH_BANNER 53 - -/* "public key" method */ -#define SSH_MSG_USERAUTH_PK_OK 60 -/* "password" method */ -#define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60 -/* "keyboard-interactive" method */ -#define SSH_MSG_USERAUTH_INFO_REQUEST 60 -#define SSH_MSG_USERAUTH_INFO_RESPONSE 61 - -/* Channels */ -#define SSH_MSG_GLOBAL_REQUEST 80 -#define SSH_MSG_REQUEST_SUCCESS 81 -#define SSH_MSG_REQUEST_FAILURE 82 - -#define SSH_MSG_CHANNEL_OPEN 90 -#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91 -#define SSH_MSG_CHANNEL_OPEN_FAILURE 92 -#define SSH_MSG_CHANNEL_WINDOW_ADJUST 93 -#define SSH_MSG_CHANNEL_DATA 94 -#define SSH_MSG_CHANNEL_EXTENDED_DATA 95 -#define SSH_MSG_CHANNEL_EOF 96 -#define SSH_MSG_CHANNEL_CLOSE 97 -#define SSH_MSG_CHANNEL_REQUEST 98 -#define SSH_MSG_CHANNEL_SUCCESS 99 -#define SSH_MSG_CHANNEL_FAILURE 100 - -/* Error codes returned in SSH_MSG_CHANNEL_OPEN_FAILURE message - (see RFC4254) */ -#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1 -#define SSH_OPEN_CONNECT_FAILED 2 -#define SSH_OPEN_UNKNOWN_CHANNELTYPE 3 -#define SSH_OPEN_RESOURCE_SHORTAGE 4 - -ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer, - size_t length, int flags, void **abstract); -ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer, - size_t length, int flags, void **abstract); - -#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when - waiting for more data to arrive */ - - -int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, - key_exchange_state_t * state); - -/* Let crypt.c/hostkey.c expose their method structs */ -const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void); -const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void); - -/* pem.c */ -int _libssh2_pem_parse(LIBSSH2_SESSION * session, - const char *headerbegin, - const char *headerend, - FILE * fp, unsigned char **data, unsigned int *datalen); -int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen); -int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, - unsigned char **i, unsigned int *ilen); - -/* global.c */ -void _libssh2_init_if_needed (void); - - -#define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0])) - -/* define to output the libssh2_int64_t type in a *printf() */ -#if defined( __BORLANDC__ ) || defined( _MSC_VER ) || defined( __MINGW32__ ) -#define LIBSSH2_INT64_T_FORMAT "I64" -#else -#define LIBSSH2_INT64_T_FORMAT "ll" -#endif - -#endif /* LIBSSH2_H */ diff --git a/vendor/libssh2-1.4.2/src/mac.c b/vendor/libssh2-1.4.2/src/mac.c deleted file mode 100644 index 76894fc..0000000 --- a/vendor/libssh2-1.4.2/src/mac.c +++ /dev/null @@ -1,314 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include "mac.h" - -#ifdef LIBSSH2_MAC_NONE -/* mac_none_MAC - * Minimalist MAC: No MAC - */ -static int -mac_none_MAC(LIBSSH2_SESSION * session, unsigned char *buf, - uint32_t seqno, const unsigned char *packet, - uint32_t packet_len, const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - return 0; -} - - - - -static LIBSSH2_MAC_METHOD mac_method_none = { - "none", - 0, - 0, - NULL, - mac_none_MAC, - NULL -}; -#endif /* LIBSSH2_MAC_NONE */ - -/* mac_method_common_init - * Initialize simple mac methods - */ -static int -mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key, - int *free_key, void **abstract) -{ - *abstract = key; - *free_key = 0; - (void) session; - - return 0; -} - - - -/* mac_method_common_dtor - * Cleanup simple mac methods - */ -static int -mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract) -{ - if (*abstract) { - LIBSSH2_FREE(session, *abstract); - } - *abstract = NULL; - - return 0; -} - - - -/* mac_method_hmac_sha1_hash - * Calculate hash using full sha1 value - */ -static int -mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - libssh2_hmac_ctx ctx; - unsigned char seqno_buf[4]; - (void) session; - - _libssh2_htonu32(seqno_buf, seqno); - - libssh2_hmac_sha1_init(&ctx, *abstract, 20); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); - - return 0; -} - - - -static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1 = { - "hmac-sha1", - 20, - 20, - mac_method_common_init, - mac_method_hmac_sha1_hash, - mac_method_common_dtor, -}; - -/* mac_method_hmac_sha1_96_hash - * Calculate hash using first 96 bits of sha1 value - */ -static int -mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - unsigned char temp[SHA_DIGEST_LENGTH]; - - mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len, - addtl, addtl_len, abstract); - memcpy(buf, (char *) temp, 96 / 8); - - return 0; -} - - - -static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1_96 = { - "hmac-sha1-96", - 12, - 20, - mac_method_common_init, - mac_method_hmac_sha1_96_hash, - mac_method_common_dtor, -}; - -#if LIBSSH2_MD5 -/* mac_method_hmac_md5_hash - * Calculate hash using full md5 value - */ -static int -mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf, - uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - libssh2_hmac_ctx ctx; - unsigned char seqno_buf[4]; - (void) session; - - _libssh2_htonu32(seqno_buf, seqno); - - libssh2_hmac_md5_init(&ctx, *abstract, 16); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); - - return 0; -} - - - -static const LIBSSH2_MAC_METHOD mac_method_hmac_md5 = { - "hmac-md5", - 16, - 16, - mac_method_common_init, - mac_method_hmac_md5_hash, - mac_method_common_dtor, -}; - -/* mac_method_hmac_md5_96_hash - * Calculate hash using first 96 bits of md5 value - */ -static int -mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - unsigned char temp[MD5_DIGEST_LENGTH]; - mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len, - addtl, addtl_len, abstract); - memcpy(buf, (char *) temp, 96 / 8); - return 0; -} - - - -static const LIBSSH2_MAC_METHOD mac_method_hmac_md5_96 = { - "hmac-md5-96", - 12, - 16, - mac_method_common_init, - mac_method_hmac_md5_96_hash, - mac_method_common_dtor, -}; -#endif /* LIBSSH2_MD5 */ - -#if LIBSSH2_HMAC_RIPEMD -/* mac_method_hmac_ripemd160_hash - * Calculate hash using ripemd160 value - */ -static int -mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t addtl_len, - void **abstract) -{ - libssh2_hmac_ctx ctx; - unsigned char seqno_buf[4]; - (void) session; - - _libssh2_htonu32(seqno_buf, seqno); - - libssh2_hmac_ripemd160_init(&ctx, *abstract, 20); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); - - return 0; -} - - - -static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160 = { - "hmac-ripemd160", - 20, - 20, - mac_method_common_init, - mac_method_hmac_ripemd160_hash, - mac_method_common_dtor, -}; - -static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160_openssh_com = { - "hmac-ripemd160@openssh.com", - 20, - 20, - mac_method_common_init, - mac_method_hmac_ripemd160_hash, - mac_method_common_dtor, -}; -#endif /* LIBSSH2_HMAC_RIPEMD */ - -static const LIBSSH2_MAC_METHOD *mac_methods[] = { - &mac_method_hmac_sha1, - &mac_method_hmac_sha1_96, -#if LIBSSH2_MD5 - &mac_method_hmac_md5, - &mac_method_hmac_md5_96, -#endif -#if LIBSSH2_HMAC_RIPEMD - &mac_method_hmac_ripemd160, - &mac_method_hmac_ripemd160_openssh_com, -#endif /* LIBSSH2_HMAC_RIPEMD */ -#ifdef LIBSSH2_MAC_NONE - &mac_method_none, -#endif /* LIBSSH2_MAC_NONE */ - NULL -}; - -const LIBSSH2_MAC_METHOD ** -_libssh2_mac_methods(void) -{ - return mac_methods; -} diff --git a/vendor/libssh2-1.4.2/src/mac.h b/vendor/libssh2-1.4.2/src/mac.h deleted file mode 100644 index 66d3e61..0000000 --- a/vendor/libssh2-1.4.2/src/mac.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef __LIBSSH2_MAC_H -#define __LIBSSH2_MAC_H - -/* Copyright (C) 2009-2010 by Daniel Stenberg - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -struct _LIBSSH2_MAC_METHOD -{ - const char *name; - - /* The length of a given MAC packet */ - int mac_len; - - /* integrity key length */ - int key_len; - - /* Message Authentication Code Hashing algo */ - int (*init) (LIBSSH2_SESSION * session, unsigned char *key, int *free_key, - void **abstract); - int (*hash) (LIBSSH2_SESSION * session, unsigned char *buf, - uint32_t seqno, const unsigned char *packet, - uint32_t packet_len, const unsigned char *addtl, - uint32_t addtl_len, void **abstract); - int (*dtor) (LIBSSH2_SESSION * session, void **abstract); -}; - -typedef struct _LIBSSH2_MAC_METHOD LIBSSH2_MAC_METHOD; - -const LIBSSH2_MAC_METHOD **_libssh2_mac_methods(void); - -#endif /* __LIBSSH2_MAC_H */ diff --git a/vendor/libssh2-1.4.2/src/misc.c b/vendor/libssh2-1.4.2/src/misc.c deleted file mode 100644 index a9f423a..0000000 --- a/vendor/libssh2-1.4.2/src/misc.c +++ /dev/null @@ -1,612 +0,0 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include "misc.h" - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#include -#include - -int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg) -{ - session->err_msg = errmsg; - session->err_code = errcode; -#ifdef LIBSSH2DEBUG - if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode) - /* if this is EAGAIN and we're in non-blocking mode, don't generate - a debug output for this */ - return errcode; - _libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code, - session->err_msg); -#endif - - return errcode; -} - -#ifdef WIN32 -static int wsa2errno(void) -{ - switch (WSAGetLastError()) { - case WSAEWOULDBLOCK: - return EAGAIN; - - case WSAENOTSOCK: - return EBADF; - - case WSAEINTR: - return EINTR; - - default: - /* It is most important to ensure errno does not stay at EAGAIN - * when a different error occurs so just set errno to a generic - * error */ - return EIO; - } -} -#endif - -/* _libssh2_recv - * - * Replacement for the standard recv, return -errno on failure. - */ -ssize_t -_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags, void **abstract) -{ - ssize_t rc = recv(sock, buffer, length, flags); -#ifdef WIN32 - if (rc < 0 ) - return -wsa2errno(); -#elif defined(__VMS) - if (rc < 0 ){ - if ( errno == EWOULDBLOCK ) - return -EAGAIN; - else - return -errno; - } -#else - if (rc < 0 ){ - /* Sometimes the first recv() function call sets errno to ENOENT on - Solaris and HP-UX */ - if ( errno == ENOENT ) - return -EAGAIN; - else - return -errno; - } -#endif - return rc; -} - -/* _libssh2_send - * - * Replacement for the standard send, return -errno on failure. - */ -ssize_t -_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length, - int flags, void **abstract) -{ - ssize_t rc = send(sock, buffer, length, flags); -#ifdef WIN32 - if (rc < 0 ) - return -wsa2errno(); -#elif defined(__VMS) - if (rc < 0 ) { - if ( errno == EWOULDBLOCK ) - return -EAGAIN; - else - return -errno; - } -#else - if (rc < 0 ) - return -errno; -#endif - return rc; -} - -/* libssh2_ntohu32 - */ -unsigned int -_libssh2_ntohu32(const unsigned char *buf) -{ - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -} - - -/* _libssh2_ntohu64 - */ -libssh2_uint64_t -_libssh2_ntohu64(const unsigned char *buf) -{ - unsigned long msl, lsl; - - msl = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16) - | ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3]; - lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16) - | ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7]; - - return ((libssh2_uint64_t)msl <<32) | lsl; -} - -/* _libssh2_htonu32 - */ -void -_libssh2_htonu32(unsigned char *buf, uint32_t value) -{ - buf[0] = (value >> 24) & 0xFF; - buf[1] = (value >> 16) & 0xFF; - buf[2] = (value >> 8) & 0xFF; - buf[3] = value & 0xFF; -} - -/* _libssh2_store_u32 - */ -void _libssh2_store_u32(unsigned char **buf, uint32_t value) -{ - _libssh2_htonu32(*buf, value); - *buf += sizeof(uint32_t); -} - -/* _libssh2_store_str - */ -void _libssh2_store_str(unsigned char **buf, const char *str, size_t len) -{ - _libssh2_store_u32(buf, (uint32_t)len); - if(len) { - memcpy(*buf, str, len); - *buf += len; - } -} - -/* Base64 Conversion */ - -static const char base64_table[] = -{ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0' -}; - -static const char base64_pad = '='; - -static const short base64_reverse_table[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -/* libssh2_base64_decode - * - * Decode a base64 chunk and store it into a newly alloc'd buffer - */ -LIBSSH2_API int -libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, - unsigned int *datalen, const char *src, - unsigned int src_len) -{ - unsigned char *s, *d; - short v; - int i = 0, len = 0; - - *data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1); - d = (unsigned char *) *data; - if (!d) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for base64 decoding"); - } - - for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) { - if ((v = base64_reverse_table[*s]) < 0) - continue; - switch (i % 4) { - case 0: - d[len] = v << 2; - break; - case 1: - d[len++] |= v >> 4; - d[len] = v << 4; - break; - case 2: - d[len++] |= v >> 2; - d[len] = v << 6; - break; - case 3: - d[len++] |= v; - break; - } - i++; - } - if ((i % 4) == 1) { - /* Invalid -- We have a byte which belongs exclusively to a partial - octet */ - LIBSSH2_FREE(session, *data); - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64"); - } - - *datalen = len; - return 0; -} - -/* ---- Base64 Encoding/Decoding Table --- */ -static const char table64[]= - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* - * _libssh2_base64_encode() - * - * Returns the length of the newly created base64 string. The third argument - * is a pointer to an allocated area holding the base64 data. If something - * went wrong, 0 is returned. - * - */ -size_t _libssh2_base64_encode(LIBSSH2_SESSION *session, - const char *inp, size_t insize, char **outptr) -{ - unsigned char ibuf[3]; - unsigned char obuf[4]; - int i; - int inputparts; - char *output; - char *base64data; - const char *indata = inp; - - *outptr = NULL; /* set to NULL in case of failure before we reach the end */ - - if(0 == insize) - insize = strlen(indata); - - base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4); - if(NULL == output) - return 0; - - while(insize > 0) { - for (i = inputparts = 0; i < 3; i++) { - if(insize > 0) { - inputparts++; - ibuf[i] = *indata; - indata++; - insize--; - } - else - ibuf[i] = 0; - } - - obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); - obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ - ((ibuf[1] & 0xF0) >> 4)); - obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ - ((ibuf[2] & 0xC0) >> 6)); - obuf[3] = (unsigned char) (ibuf[2] & 0x3F); - - switch(inputparts) { - case 1: /* only one byte read */ - snprintf(output, 5, "%c%c==", - table64[obuf[0]], - table64[obuf[1]]); - break; - case 2: /* two bytes read */ - snprintf(output, 5, "%c%c%c=", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]]); - break; - default: - snprintf(output, 5, "%c%c%c%c", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]], - table64[obuf[3]] ); - break; - } - output += 4; - } - *output=0; - *outptr = base64data; /* make it return the actual data memory */ - - return strlen(base64data); /* return the length of the new data */ -} -/* ---- End of Base64 Encoding ---- */ - -LIBSSH2_API void -libssh2_free(LIBSSH2_SESSION *session, void *ptr) -{ - LIBSSH2_FREE(session, ptr); -} - -#ifdef LIBSSH2DEBUG -LIBSSH2_API int -libssh2_trace(LIBSSH2_SESSION * session, int bitmask) -{ - session->showmask = bitmask; - return 0; -} - -LIBSSH2_API int -libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, - libssh2_trace_handler_func callback) -{ - session->tracehandler = callback; - session->tracehandler_context = handler_context; - return 0; -} - -void -_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) -{ - char buffer[1536]; - int len, msglen, buflen = sizeof(buffer); - va_list vargs; - struct timeval now; - static int firstsec; - static const char *const contexts[] = { - "Unknown", - "Transport", - "Key Ex", - "Userauth", - "Conn", - "SCP", - "SFTP", - "Failure Event", - "Publickey", - "Socket", - }; - const char* contexttext = contexts[0]; - unsigned int contextindex; - - if (!(session->showmask & context)) { - /* no such output asked for */ - return; - } - - /* Find the first matching context string for this message */ - for (contextindex = 0; contextindex < ARRAY_SIZE(contexts); - contextindex++) { - if ((context & (1 << contextindex)) != 0) { - contexttext = contexts[contextindex]; - break; - } - } - - _libssh2_gettimeofday(&now, NULL); - if(!firstsec) { - firstsec = now.tv_sec; - } - now.tv_sec -= firstsec; - - len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ", - (int)now.tv_sec, (int)now.tv_usec, contexttext); - - if (len >= buflen) - msglen = buflen - 1; - else { - buflen -= len; - msglen = len; - va_start(vargs, format); - len = vsnprintf(buffer + msglen, buflen, format, vargs); - va_end(vargs); - msglen += len < buflen ? len : buflen - 1; - } - - if (session->tracehandler) - (session->tracehandler)(session, session->tracehandler_context, buffer, - msglen); - else - fprintf(stderr, "%s\n", buffer); -} - -#else -LIBSSH2_API int -libssh2_trace(LIBSSH2_SESSION * session, int bitmask) -{ - (void) session; - (void) bitmask; - return 0; -} - -LIBSSH2_API int -libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, - libssh2_trace_handler_func callback) -{ - (void) session; - (void) handler_context; - (void) callback; - return 0; -} -#endif - -/* init the list head */ -void _libssh2_list_init(struct list_head *head) -{ - head->first = head->last = NULL; -} - -/* add a node to the list */ -void _libssh2_list_add(struct list_head *head, - struct list_node *entry) -{ - /* store a pointer to the head */ - entry->head = head; - - /* we add this entry at the "top" so it has no next */ - entry->next = NULL; - - /* make our prev point to what the head thinks is last */ - entry->prev = head->last; - - /* and make head's last be us now */ - head->last = entry; - - /* make sure our 'prev' node points to us next */ - if(entry->prev) - entry->prev->next = entry; - else - head->first = entry; -} - -/* return the "first" node in the list this head points to */ -void *_libssh2_list_first(struct list_head *head) -{ - return head->first; -} - -/* return the next node in the list */ -void *_libssh2_list_next(struct list_node *node) -{ - return node->next; -} - -/* return the prev node in the list */ -void *_libssh2_list_prev(struct list_node *node) -{ - return node->prev; -} - -/* remove this node from the list */ -void _libssh2_list_remove(struct list_node *entry) -{ - if(entry->prev) - entry->prev->next = entry->next; - else - entry->head->first = entry->next; - - if(entry->next) - entry->next->prev = entry->prev; - else - entry->head->last = entry->prev; -} - -#if 0 -/* insert a node before the given 'after' entry */ -void _libssh2_list_insert(struct list_node *after, /* insert before this */ - struct list_node *entry) -{ - /* 'after' is next to 'entry' */ - bentry->next = after; - - /* entry's prev is then made to be the prev after current has */ - entry->prev = after->prev; - - /* the node that is now before 'entry' was previously before 'after' - and must be made to point to 'entry' correctly */ - if(entry->prev) - entry->prev->next = entry; - else - /* there was no node before this, so we make sure we point the head - pointer to this node */ - after->head->first = entry; - - /* after's prev entry points back to entry */ - after->prev = entry; - - /* after's next entry is still the same as before */ - - /* entry's head is the same as after's */ - entry->head = after->head; -} - -#endif - -/* this define is defined in misc.h for the correct platforms */ -#ifdef LIBSSH2_GETTIMEOFDAY_WIN32 -/* - * gettimeofday - * Implementation according to: - * The Open Group Base Specifications Issue 6 - * IEEE Std 1003.1, 2004 Edition - */ - -/* - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Contributed by: - * Danny Smith - */ - -/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ -#define _W32_FT_OFFSET (116444736000000000) - -int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp) - { - union { - unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */ - FILETIME ft; - } _now; - - if(tp) - { - GetSystemTimeAsFileTime (&_now.ft); - tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 ); - tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000); - } - /* Always return 0 as per Open Group Base Specifications Issue 6. - Do not set errno on error. */ - return 0; -} - - -#endif diff --git a/vendor/libssh2-1.4.2/src/misc.h b/vendor/libssh2-1.4.2/src/misc.h deleted file mode 100644 index 8a8294a..0000000 --- a/vendor/libssh2-1.4.2/src/misc.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef __LIBSSH2_MISC_H -#define __LIBSSH2_MISC_H -/* Copyright (c) 2009-2011 by Daniel Stenberg - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - */ - -struct list_head { - struct list_node *last; - struct list_node *first; -}; - -struct list_node { - struct list_node *next; - struct list_node *prev; - struct list_head *head; -}; - -int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg); - -void _libssh2_list_init(struct list_head *head); - -/* add a node last in the list */ -void _libssh2_list_add(struct list_head *head, - struct list_node *entry); - -/* return the "first" node in the list this head points to */ -void *_libssh2_list_first(struct list_head *head); - -/* return the next node in the list */ -void *_libssh2_list_next(struct list_node *node); - -/* return the prev node in the list */ -void *_libssh2_list_prev(struct list_node *node); - -/* remove this node from the list */ -void _libssh2_list_remove(struct list_node *entry); - -size_t _libssh2_base64_encode(struct _LIBSSH2_SESSION *session, - const char *inp, size_t insize, char **outptr); - -unsigned int _libssh2_ntohu32(const unsigned char *buf); -libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf); -void _libssh2_htonu32(unsigned char *buf, uint32_t val); -void _libssh2_store_u32(unsigned char **buf, uint32_t value); -void _libssh2_store_str(unsigned char **buf, const char *str, size_t len); - -#if defined(WIN32) || defined(LIBSSH2_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) -/* provide a private one */ -#undef HAVE_GETTIMEOFDAY -int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp); -#define HAVE_LIBSSH2_GETTIMEOFDAY -#define LIBSSH2_GETTIMEOFDAY_WIN32 /* enable the win32 implementation */ -#else -#ifdef HAVE_GETTIMEOFDAY -#define _libssh2_gettimeofday(x,y) gettimeofday(x,y) -#define HAVE_LIBSSH2_GETTIMEOFDAY -#endif -#endif - -#endif /* _LIBSSH2_MISC_H */ diff --git a/vendor/libssh2-1.4.2/src/openssl.c b/vendor/libssh2-1.4.2/src/openssl.c deleted file mode 100644 index 481982c..0000000 --- a/vendor/libssh2-1.4.2/src/openssl.c +++ /dev/null @@ -1,804 +0,0 @@ -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * Copyright (c) 2004-2006, Sara Golemon - * - * Author: Simon Josefsson - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -#ifndef LIBSSH2_LIBGCRYPT /* compile only if we build with OpenSSL */ - -#include - -#ifndef EVP_MAX_BLOCK_LENGTH -#define EVP_MAX_BLOCK_LENGTH 32 -#endif - -int -_libssh2_rsa_new(libssh2_rsa_ctx ** rsa, - const unsigned char *edata, - unsigned long elen, - const unsigned char *ndata, - unsigned long nlen, - const unsigned char *ddata, - unsigned long dlen, - const unsigned char *pdata, - unsigned long plen, - const unsigned char *qdata, - unsigned long qlen, - const unsigned char *e1data, - unsigned long e1len, - const unsigned char *e2data, - unsigned long e2len, - const unsigned char *coeffdata, unsigned long coefflen) -{ - *rsa = RSA_new(); - - (*rsa)->e = BN_new(); - BN_bin2bn(edata, elen, (*rsa)->e); - - (*rsa)->n = BN_new(); - BN_bin2bn(ndata, nlen, (*rsa)->n); - - if (ddata) { - (*rsa)->d = BN_new(); - BN_bin2bn(ddata, dlen, (*rsa)->d); - - (*rsa)->p = BN_new(); - BN_bin2bn(pdata, plen, (*rsa)->p); - - (*rsa)->q = BN_new(); - BN_bin2bn(qdata, qlen, (*rsa)->q); - - (*rsa)->dmp1 = BN_new(); - BN_bin2bn(e1data, e1len, (*rsa)->dmp1); - - (*rsa)->dmq1 = BN_new(); - BN_bin2bn(e2data, e2len, (*rsa)->dmq1); - - (*rsa)->iqmp = BN_new(); - BN_bin2bn(coeffdata, coefflen, (*rsa)->iqmp); - } - return 0; -} - -int -_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx, - const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, unsigned long m_len) -{ - unsigned char hash[SHA_DIGEST_LENGTH]; - int ret; - - libssh2_sha1(m, m_len, hash); - ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH, - (unsigned char *) sig, sig_len, rsactx); - return (ret == 1) ? 0 : -1; -} - -#if LIBSSH2_DSA -int -_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, - const unsigned char *p, - unsigned long p_len, - const unsigned char *q, - unsigned long q_len, - const unsigned char *g, - unsigned long g_len, - const unsigned char *y, - unsigned long y_len, - const unsigned char *x, unsigned long x_len) -{ - *dsactx = DSA_new(); - - (*dsactx)->p = BN_new(); - BN_bin2bn(p, p_len, (*dsactx)->p); - - (*dsactx)->q = BN_new(); - BN_bin2bn(q, q_len, (*dsactx)->q); - - (*dsactx)->g = BN_new(); - BN_bin2bn(g, g_len, (*dsactx)->g); - - (*dsactx)->pub_key = BN_new(); - BN_bin2bn(y, y_len, (*dsactx)->pub_key); - - if (x_len) { - (*dsactx)->priv_key = BN_new(); - BN_bin2bn(x, x_len, (*dsactx)->priv_key); - } - - return 0; -} - -int -_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, - const unsigned char *sig, - const unsigned char *m, unsigned long m_len) -{ - unsigned char hash[SHA_DIGEST_LENGTH]; - DSA_SIG dsasig; - int ret; - - dsasig.r = BN_new(); - BN_bin2bn(sig, 20, dsasig.r); - dsasig.s = BN_new(); - BN_bin2bn(sig + 20, 20, dsasig.s); - - libssh2_sha1(m, m_len, hash); - ret = DSA_do_verify(hash, SHA_DIGEST_LENGTH, &dsasig, dsactx); - BN_clear_free(dsasig.s); - BN_clear_free(dsasig.r); - - return (ret == 1) ? 0 : -1; -} -#endif /* LIBSSH_DSA */ - -int -_libssh2_cipher_init(_libssh2_cipher_ctx * h, - _libssh2_cipher_type(algo), - unsigned char *iv, unsigned char *secret, int encrypt) -{ - EVP_CIPHER_CTX_init(h); - EVP_CipherInit(h, algo(), secret, iv, encrypt); - return 0; -} - -int -_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, - _libssh2_cipher_type(algo), - int encrypt, unsigned char *block) -{ - int blocksize = ctx->cipher->block_size; - unsigned char buf[EVP_MAX_BLOCK_LENGTH]; - int ret; - (void) algo; - (void) encrypt; - - if (blocksize == 1) { -/* Hack for arcfour. */ - blocksize = 8; - } - ret = EVP_Cipher(ctx, buf, block, blocksize); - if (ret == 1) { - memcpy(block, buf, blocksize); - } - return ret == 1 ? 0 : 1; -} - -#if LIBSSH2_AES_CTR - -#include -#include - -typedef struct -{ - AES_KEY key; - EVP_CIPHER_CTX *aes_ctx; - unsigned char ctr[AES_BLOCK_SIZE]; -} aes_ctr_ctx; - -static int -aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) /* init key */ -{ - /* - * variable "c" is leaked from this scope, but is later freed - * in aes_ctr_cleanup - */ - aes_ctr_ctx *c = malloc(sizeof(*c)); - const EVP_CIPHER *aes_cipher; - (void) enc; - - if (c == NULL) - return 0; - - switch (ctx->key_len) { - case 16: - aes_cipher = EVP_aes_128_ecb(); - break; - case 24: - aes_cipher = EVP_aes_192_ecb(); - break; - case 32: - aes_cipher = EVP_aes_256_ecb(); - break; - default: - return 0; - } - c->aes_ctx = malloc(sizeof(EVP_CIPHER_CTX)); - if (c->aes_ctx == NULL) - return 0; - - if (EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) { - return 0; - } - - EVP_CIPHER_CTX_set_padding(c->aes_ctx, 0); - - memcpy(c->ctr, iv, AES_BLOCK_SIZE); - - EVP_CIPHER_CTX_set_app_data(ctx, c); - - return 1; -} - -static int -aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, - size_t inl) /* encrypt/decrypt data */ -{ - aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx); - unsigned char b1[AES_BLOCK_SIZE]; - size_t i = 0; - int outlen = 0; - - if (inl != 16) /* libssh2 only ever encrypt one block */ - return 0; - - if (c == NULL) { - return 0; - } - -/* - To encrypt a packet P=P1||P2||...||Pn (where P1, P2, ..., Pn are each - blocks of length L), the encryptor first encrypts with - to obtain a block B1. The block B1 is then XORed with P1 to generate - the ciphertext block C1. The counter X is then incremented -*/ - - if (EVP_EncryptUpdate(c->aes_ctx, b1, &outlen, c->ctr, AES_BLOCK_SIZE) != 1) { - return 0; - } - - for (i = 0; i < 16; i++) - *out++ = *in++ ^ b1[i]; - - i = 15; - while (c->ctr[i]++ == 0xFF) { - if (i == 0) - break; - i--; - } - - return 1; -} - -static int -aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */ -{ - aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx); - - if (c == NULL) { - return 1; - } - - if (c->aes_ctx != NULL) { - _libssh2_cipher_dtor(c->aes_ctx); - free(c->aes_ctx); - } - - free(c); - - return 1; -} - -static const EVP_CIPHER * -make_ctr_evp (size_t keylen, EVP_CIPHER *aes_ctr_cipher) -{ - aes_ctr_cipher->block_size = 16; - aes_ctr_cipher->key_len = keylen; - aes_ctr_cipher->iv_len = 16; - aes_ctr_cipher->init = aes_ctr_init; - aes_ctr_cipher->do_cipher = aes_ctr_do_cipher; - aes_ctr_cipher->cleanup = aes_ctr_cleanup; - - return aes_ctr_cipher; -} - -const EVP_CIPHER * -_libssh2_EVP_aes_128_ctr(void) -{ - static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (16, &aes_ctr_cipher) : &aes_ctr_cipher; -} - -const EVP_CIPHER * -_libssh2_EVP_aes_192_ctr(void) -{ - static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (24, &aes_ctr_cipher) : &aes_ctr_cipher; -} - -const EVP_CIPHER * -_libssh2_EVP_aes_256_ctr(void) -{ - static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (32, &aes_ctr_cipher) : &aes_ctr_cipher; -} - -void _libssh2_init_aes_ctr(void) -{ - _libssh2_EVP_aes_128_ctr(); - _libssh2_EVP_aes_192_ctr(); - _libssh2_EVP_aes_256_ctr(); -} - -#else -void _libssh2_init_aes_ctr(void) {} -#endif /* LIBSSH2_AES_CTR */ - -/* TODO: Optionally call a passphrase callback specified by the - * calling program - */ -static int -passphrase_cb(char *buf, int size, int rwflag, char *passphrase) -{ - int passphrase_len = strlen(passphrase); - (void) rwflag; - - if (passphrase_len > (size - 1)) { - passphrase_len = size - 1; - } - memcpy(buf, passphrase, passphrase_len); - buf[passphrase_len] = '\0'; - - return passphrase_len; -} - -typedef void * (*pem_read_bio_func)(BIO *, void **, pem_password_cb *, - void * u); - -static int -read_private_key_from_file(void ** key_ctx, - pem_read_bio_func read_private_key, - const char * filename, - unsigned const char *passphrase) -{ - BIO * bp; - - *key_ctx = NULL; - - bp = BIO_new_file(filename, "r"); - if (!bp) { - return -1; - } - - *key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb, - (void *) passphrase); - - BIO_free(bp); - return (*key_ctx) ? 0 : -1; -} - -int -_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - pem_read_bio_func read_rsa = - (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; - (void) session; - - _libssh2_init_if_needed (); - - return read_private_key_from_file((void **) rsa, read_rsa, - filename, passphrase); -} - -#if LIBSSH2_DSA -int -_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - pem_read_bio_func read_dsa = - (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; - (void) session; - - _libssh2_init_if_needed (); - - return read_private_key_from_file((void **) dsa, read_dsa, - filename, passphrase); -} -#endif /* LIBSSH_DSA */ - -int -_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, - libssh2_rsa_ctx * rsactx, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, size_t *signature_len) -{ - int ret; - unsigned char *sig; - unsigned int sig_len; - - sig_len = RSA_size(rsactx); - sig = LIBSSH2_ALLOC(session, sig_len); - - if (!sig) { - return -1; - } - - ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx); - - if (!ret) { - LIBSSH2_FREE(session, sig); - return -1; - } - - *signature = sig; - *signature_len = sig_len; - - return 0; -} - -#if LIBSSH2_DSA -int -_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, - const unsigned char *hash, - unsigned long hash_len, unsigned char *signature) -{ - DSA_SIG *sig; - int r_len, s_len; - (void) hash_len; - - sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); - if (!sig) { - return -1; - } - - r_len = BN_num_bytes(sig->r); - if (r_len < 1 || r_len > 20) { - DSA_SIG_free(sig); - return -1; - } - s_len = BN_num_bytes(sig->s); - if (s_len < 1 || s_len > 20) { - DSA_SIG_free(sig); - return -1; - } - - memset(signature, 0, 40); - - BN_bn2bin(sig->r, signature + (20 - r_len)); - BN_bn2bin(sig->s, signature + 20 + (20 - s_len)); - - DSA_SIG_free(sig); - - return 0; -} -#endif /* LIBSSH_DSA */ - -void -libssh2_sha1(const unsigned char *message, unsigned long len, - unsigned char *out) -{ - EVP_MD_CTX ctx; - - EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1")); - EVP_DigestUpdate(&ctx, message, len); - EVP_DigestFinal(&ctx, out, NULL); -} - -void -libssh2_md5(const unsigned char *message, unsigned long len, - unsigned char *out) -{ - EVP_MD_CTX ctx; - - EVP_DigestInit(&ctx, EVP_get_digestbyname("md5")); - EVP_DigestUpdate(&ctx, message, len); - EVP_DigestFinal(&ctx, out, NULL); -} - -static unsigned char * -write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) -{ - unsigned char *p = buf; - - /* Left space for bn size which will be written below. */ - p += 4; - - *p = 0; - BN_bn2bin(bn, p + 1); - if (!(*(p + 1) & 0x80)) { - memmove(p, p + 1, --bn_bytes); - } - _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */ - - return p + bn_bytes; -} - -static unsigned char * -gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, - size_t *key_len) -{ - int e_bytes, n_bytes; - unsigned long len; - unsigned char* key; - unsigned char* p; - - e_bytes = BN_num_bytes(rsa->e) + 1; - n_bytes = BN_num_bytes(rsa->n) + 1; - - /* Key form is "ssh-rsa" + e + n. */ - len = 4 + 7 + 4 + e_bytes + 4 + n_bytes; - - key = LIBSSH2_ALLOC(session, len); - if (key == NULL) { - return NULL; - } - - /* Process key encoding. */ - p = key; - - _libssh2_htonu32(p, 7); /* Key type. */ - p += 4; - memcpy(p, "ssh-rsa", 7); - p += 7; - - p = write_bn(p, rsa->e, e_bytes); - p = write_bn(p, rsa->n, n_bytes); - - *key_len = (size_t)(p - key); - return key; -} - -static unsigned char * -gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, - size_t *key_len) -{ - int p_bytes, q_bytes, g_bytes, k_bytes; - unsigned long len; - unsigned char* key; - unsigned char* p; - - p_bytes = BN_num_bytes(dsa->p) + 1; - q_bytes = BN_num_bytes(dsa->q) + 1; - g_bytes = BN_num_bytes(dsa->g) + 1; - k_bytes = BN_num_bytes(dsa->pub_key) + 1; - - /* Key form is "ssh-dss" + p + q + g + pub_key. */ - len = 4 + 7 + 4 + p_bytes + 4 + q_bytes + 4 + g_bytes + 4 + k_bytes; - - key = LIBSSH2_ALLOC(session, len); - if (key == NULL) { - return NULL; - } - - /* Process key encoding. */ - p = key; - - _libssh2_htonu32(p, 7); /* Key type. */ - p += 4; - memcpy(p, "ssh-dss", 7); - p += 7; - - p = write_bn(p, dsa->p, p_bytes); - p = write_bn(p, dsa->q, q_bytes); - p = write_bn(p, dsa->g, g_bytes); - p = write_bn(p, dsa->pub_key, k_bytes); - - *key_len = (size_t)(p - key); - return key; -} - -static int -gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - EVP_PKEY *pk) -{ - RSA* rsa = NULL; - unsigned char* key; - unsigned char* method_buf = NULL; - size_t key_len; - - _libssh2_debug(session, - LIBSSH2_TRACE_AUTH, - "Computing public key from RSA private key envelop"); - - rsa = EVP_PKEY_get1_RSA(pk); - if (rsa == NULL) { - /* Assume memory allocation error... what else could it be ? */ - goto __alloc_error; - } - - method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-rsa. */ - if (method_buf == NULL) { - goto __alloc_error; - } - - key = gen_publickey_from_rsa(session, rsa, &key_len); - if (key == NULL) { - goto __alloc_error; - } - RSA_free(rsa); - - memcpy(method_buf, "ssh-rsa", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; - return 0; - - __alloc_error: - if (rsa != NULL) { - RSA_free(rsa); - } - if (method_buf != NULL) { - LIBSSH2_FREE(session, method_buf); - } - - return _libssh2_error(session, - LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for private key data"); -} - -static int -gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - EVP_PKEY *pk) -{ - DSA* dsa = NULL; - unsigned char* key; - unsigned char* method_buf = NULL; - size_t key_len; - - _libssh2_debug(session, - LIBSSH2_TRACE_AUTH, - "Computing public key from DSA private key envelop"); - - dsa = EVP_PKEY_get1_DSA(pk); - if (dsa == NULL) { - /* Assume memory allocation error... what else could it be ? */ - goto __alloc_error; - } - - method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-dss. */ - if (method_buf == NULL) { - goto __alloc_error; - } - - key = gen_publickey_from_dsa(session, dsa, &key_len); - if (key == NULL) { - goto __alloc_error; - } - DSA_free(dsa); - - memcpy(method_buf, "ssh-dss", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; - return 0; - - __alloc_error: - if (dsa != NULL) { - DSA_free(dsa); - } - if (method_buf != NULL) { - LIBSSH2_FREE(session, method_buf); - } - - return _libssh2_error(session, - LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for private key data"); -} - -int -_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase) -{ - int st; - BIO* bp; - EVP_PKEY* pk; - - _libssh2_debug(session, - LIBSSH2_TRACE_AUTH, - "Computing public key from private key file: %s", - privatekey); - - bp = BIO_new_file(privatekey, "r"); - if (bp == NULL) { - return _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key from private key " - "file: Unable to open private key file"); - } - if (!EVP_get_cipherbyname("des")) { - /* If this cipher isn't loaded it's a pretty good indication that none - * are. I have *NO DOUBT* that there's a better way to deal with this - * ($#&%#$(%$#( Someone buy me an OpenSSL manual and I'll read up on - * it. - */ - OpenSSL_add_all_ciphers(); - } - BIO_reset(bp); - pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase); - BIO_free(bp); - - if (pk == NULL) { - return _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key " - "from private key file: " - "Wrong passphrase or invalid/unrecognized " - "private key file format"); - } - - switch (pk->type) { - case EVP_PKEY_RSA : - st = gen_publickey_from_rsa_evp( - session, method, method_len, pubkeydata, pubkeydata_len, pk); - break; - - case EVP_PKEY_DSA : - st = gen_publickey_from_dsa_evp( - session, method, method_len, pubkeydata, pubkeydata_len, pk); - break; - - default : - st = _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key " - "from private key file: " - "Unsupported private key file format"); - break; - } - - EVP_PKEY_free(pk); - return st; -} - -#endif /* !LIBSSH2_LIBGCRYPT */ diff --git a/vendor/libssh2-1.4.2/src/openssl.h b/vendor/libssh2-1.4.2/src/openssl.h deleted file mode 100644 index 6d2aeed..0000000 --- a/vendor/libssh2-1.4.2/src/openssl.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * - * Author: Simon Josefsson - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 -#include -#ifndef OPENSSL_NO_MD5 -#include -#endif -#include -#include -#include -#include -#include - -#ifdef OPENSSL_NO_RSA -# define LIBSSH2_RSA 0 -#else -# define LIBSSH2_RSA 1 -#endif - -#ifdef OPENSSL_NO_DSA -# define LIBSSH2_DSA 0 -#else -# define LIBSSH2_DSA 1 -#endif - -#ifdef OPENSSL_NO_MD5 -# define LIBSSH2_MD5 0 -#else -# define LIBSSH2_MD5 1 -#endif - -#ifdef OPENSSL_NO_RIPEMD -# define LIBSSH2_HMAC_RIPEMD 0 -#else -# define LIBSSH2_HMAC_RIPEMD 1 -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES) -# define LIBSSH2_AES_CTR 1 -# define LIBSSH2_AES 1 -#else -# define LIBSSH2_AES_CTR 0 -# define LIBSSH2_AES 0 -#endif - -#ifdef OPENSSL_NO_BLOWFISH -# define LIBSSH2_BLOWFISH 0 -#else -# define LIBSSH2_BLOWFISH 1 -#endif - -#ifdef OPENSSL_NO_RC4 -# define LIBSSH2_RC4 0 -#else -# define LIBSSH2_RC4 1 -#endif - -#ifdef OPENSSL_NO_CAST -# define LIBSSH2_CAST 0 -#else -# define LIBSSH2_CAST 1 -#endif - -#ifdef OPENSSL_NO_DES -# define LIBSSH2_3DES 0 -#else -# define LIBSSH2_3DES 1 -#endif - -#define _libssh2_random(buf, len) RAND_bytes ((buf), (len)) - -#define libssh2_sha1_ctx EVP_MD_CTX -#define libssh2_sha1_init(ctx) EVP_DigestInit(ctx, EVP_get_digestbyname("sha1")) -#define libssh2_sha1_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_sha1_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -void libssh2_sha1(const unsigned char *message, unsigned long len, unsigned char *out); - -#define libssh2_md5_ctx EVP_MD_CTX -#define libssh2_md5_init(ctx) EVP_DigestInit(ctx, EVP_get_digestbyname("md5")) -#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_md5_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -void libssh2_md5(const unsigned char *message, unsigned long len, unsigned char *out); - -#define libssh2_hmac_ctx HMAC_CTX -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - HMAC_Init(ctx, key, keylen, EVP_sha1()) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - HMAC_Init(ctx, key, keylen, EVP_md5()) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - HMAC_Init(ctx, key, keylen, EVP_ripemd160()) -#define libssh2_hmac_update(ctx, data, datalen) \ - HMAC_Update(&(ctx), data, datalen) -#define libssh2_hmac_final(ctx, data) HMAC_Final(&(ctx), data, NULL) -#define libssh2_hmac_cleanup(ctx) HMAC_cleanup(ctx) - -#define libssh2_crypto_init() OpenSSL_add_all_algorithms() -#define libssh2_crypto_exit() - -#define libssh2_rsa_ctx RSA - -#define _libssh2_rsa_free(rsactx) RSA_free(rsactx) - -#define libssh2_dsa_ctx DSA - - -#define _libssh2_dsa_free(dsactx) DSA_free(dsactx) - -#define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void) -#define _libssh2_cipher_ctx EVP_CIPHER_CTX - -#define _libssh2_cipher_aes256 EVP_aes_256_cbc -#define _libssh2_cipher_aes192 EVP_aes_192_cbc -#define _libssh2_cipher_aes128 EVP_aes_128_cbc -#define _libssh2_cipher_aes128ctr _libssh2_EVP_aes_128_ctr -#define _libssh2_cipher_aes192ctr _libssh2_EVP_aes_192_ctr -#define _libssh2_cipher_aes256ctr _libssh2_EVP_aes_256_ctr -#define _libssh2_cipher_blowfish EVP_bf_cbc -#define _libssh2_cipher_arcfour EVP_rc4 -#define _libssh2_cipher_cast5 EVP_cast5_cbc -#define _libssh2_cipher_3des EVP_des_ede3_cbc - -#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx) - -#define _libssh2_bn BIGNUM -#define _libssh2_bn_ctx BN_CTX -#define _libssh2_bn_ctx_new() BN_CTX_new() -#define _libssh2_bn_ctx_free(bnctx) BN_CTX_free(bnctx) -#define _libssh2_bn_init() BN_new() -#define _libssh2_bn_rand(bn, bits, top, bottom) BN_rand(bn, bits, top, bottom) -#define _libssh2_bn_mod_exp(r, a, p, m, ctx) BN_mod_exp(r, a, p, m, ctx) -#define _libssh2_bn_set_word(bn, val) BN_set_word(bn, val) -#define _libssh2_bn_from_bin(bn, len, val) BN_bin2bn(val, len, bn) -#define _libssh2_bn_to_bin(bn, val) BN_bn2bin(bn, val) -#define _libssh2_bn_bytes(bn) BN_num_bytes(bn) -#define _libssh2_bn_bits(bn) BN_num_bits(bn) -#define _libssh2_bn_free(bn) BN_clear_free(bn) - -const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void); -const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void); -const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void); - diff --git a/vendor/libssh2-1.4.2/src/packet.c b/vendor/libssh2-1.4.2/src/packet.c deleted file mode 100644 index bfbd56a..0000000 --- a/vendor/libssh2-1.4.2/src/packet.c +++ /dev/null @@ -1,1243 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2005,2006 Mikhail Gusarov - * Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#ifdef HAVE_INTTYPES_H -#include -#endif - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#include - -#include "transport.h" -#include "channel.h" -#include "packet.h" - -/* - * libssh2_packet_queue_listener - * - * Queue a connection request for a listener - */ -static inline int -packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, - unsigned long datalen, - packet_queue_listener_state_t *listen_state) -{ - /* - * Look for a matching listener - */ - /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1); - unsigned char *p; - LIBSSH2_LISTENER *listn = _libssh2_list_first(&session->listeners); - char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; - int rc; - - (void) datalen; - - if (listen_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5; - listen_state->sender_channel = _libssh2_ntohu32(s); - s += 4; - - listen_state->initial_window_size = _libssh2_ntohu32(s); - s += 4; - listen_state->packet_size = _libssh2_ntohu32(s); - s += 4; - - listen_state->host_len = _libssh2_ntohu32(s); - s += 4; - listen_state->host = s; - s += listen_state->host_len; - listen_state->port = _libssh2_ntohu32(s); - s += 4; - - listen_state->shost_len = _libssh2_ntohu32(s); - s += 4; - listen_state->shost = s; - s += listen_state->shost_len; - listen_state->sport = _libssh2_ntohu32(s); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Remote received connection from %s:%ld to %s:%ld", - listen_state->shost, listen_state->sport, - listen_state->host, listen_state->port); - - listen_state->state = libssh2_NB_state_allocated; - } - - if (listen_state->state != libssh2_NB_state_sent) { - while (listn) { - if ((listn->port == (int) listen_state->port) && - (strlen(listn->host) == listen_state->host_len) && - (memcmp (listn->host, listen_state->host, - listen_state->host_len) == 0)) { - /* This is our listener */ - LIBSSH2_CHANNEL *channel = NULL; - listen_state->channel = NULL; - - if (listen_state->state == libssh2_NB_state_allocated) { - if (listn->queue_maxsize && - (listn->queue_maxsize <= listn->queue_size)) { - /* Queue is full */ - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Listener queue full, ignoring"); - listen_state->state = libssh2_NB_state_sent; - break; - } - - channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL)); - if (!channel) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate a channel for " - "new connection"); - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - listen_state->state = libssh2_NB_state_sent; - break; - } - listen_state->channel = channel; - - memset(channel, 0, sizeof(LIBSSH2_CHANNEL)); - - channel->session = session; - channel->channel_type_len = sizeof("forwarded-tcpip") - 1; - channel->channel_type = LIBSSH2_ALLOC(session, - channel-> - channel_type_len + - 1); - if (!channel->channel_type) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate a channel for new" - " connection"); - LIBSSH2_FREE(session, channel); - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - listen_state->state = libssh2_NB_state_sent; - break; - } - memcpy(channel->channel_type, "forwarded-tcpip", - channel->channel_type_len + 1); - - channel->remote.id = listen_state->sender_channel; - channel->remote.window_size_initial = - LIBSSH2_CHANNEL_WINDOW_DEFAULT; - channel->remote.window_size = - LIBSSH2_CHANNEL_WINDOW_DEFAULT; - channel->remote.packet_size = - LIBSSH2_CHANNEL_PACKET_DEFAULT; - - channel->local.id = _libssh2_channel_nextid(session); - channel->local.window_size_initial = - listen_state->initial_window_size; - channel->local.window_size = - listen_state->initial_window_size; - channel->local.packet_size = listen_state->packet_size; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Connection queued: channel %lu/%lu " - "win %lu/%lu packet %lu/%lu", - channel->local.id, channel->remote.id, - channel->local.window_size, - channel->remote.window_size, - channel->local.packet_size, - channel->remote.packet_size); - - p = listen_state->packet; - *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; - _libssh2_store_u32(&p, channel->remote.id); - _libssh2_store_u32(&p, channel->local.id); - _libssh2_store_u32(&p, - channel->remote.window_size_initial); - _libssh2_store_u32(&p, channel->remote.packet_size); - - listen_state->state = libssh2_NB_state_created; - } - - if (listen_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, listen_state->packet, - 17, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc) { - listen_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send channel " - "open confirmation"); - } - - /* Link the channel into the end of the queue list */ - _libssh2_list_add(&listn->queue, - &listen_state->channel->node); - listn->queue_size++; - - listen_state->state = libssh2_NB_state_idle; - return 0; - } - } - - listn = _libssh2_list_next(&listn->node); - } - - listen_state->state = libssh2_NB_state_sent; - } - - /* We're not listening to you */ - p = listen_state->packet; - *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; - _libssh2_store_u32(&p, listen_state->sender_channel); - _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, FwdNotReq, sizeof(FwdNotReq) - 1); - _libssh2_htonu32(p, 0); - - rc = _libssh2_transport_send(session, listen_state->packet, - packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - listen_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, "Unable to send open failure"); - - } - listen_state->state = libssh2_NB_state_idle; - return 0; -} - -/* - * packet_x11_open - * - * Accept a forwarded X11 connection - */ -static inline int -packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, - unsigned long datalen, - packet_x11_open_state_t *x11open_state) -{ - int failure_code = SSH_OPEN_CONNECT_FAILED; - /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); - unsigned char *p; - LIBSSH2_CHANNEL *channel = x11open_state->channel; - int rc; - - (void) datalen; - - if (x11open_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("x11") - 1) + 5; - x11open_state->sender_channel = _libssh2_ntohu32(s); - s += 4; - x11open_state->initial_window_size = _libssh2_ntohu32(s); - s += 4; - x11open_state->packet_size = _libssh2_ntohu32(s); - s += 4; - x11open_state->shost_len = _libssh2_ntohu32(s); - s += 4; - x11open_state->shost = s; - s += x11open_state->shost_len; - x11open_state->sport = _libssh2_ntohu32(s); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "X11 Connection Received from %s:%ld on channel %lu", - x11open_state->shost, x11open_state->sport, - x11open_state->sender_channel); - - x11open_state->state = libssh2_NB_state_allocated; - } - - if (session->x11) { - if (x11open_state->state == libssh2_NB_state_allocated) { - channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL)); - if (!channel) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "allocate a channel for new connection"); - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - goto x11_exit; - } - memset(channel, 0, sizeof(LIBSSH2_CHANNEL)); - - channel->session = session; - channel->channel_type_len = sizeof("x11") - 1; - channel->channel_type = LIBSSH2_ALLOC(session, - channel->channel_type_len + - 1); - if (!channel->channel_type) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "allocate a channel for new connection"); - LIBSSH2_FREE(session, channel); - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - goto x11_exit; - } - memcpy(channel->channel_type, "x11", - channel->channel_type_len + 1); - - channel->remote.id = x11open_state->sender_channel; - channel->remote.window_size_initial = - LIBSSH2_CHANNEL_WINDOW_DEFAULT; - channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT; - channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT; - - channel->local.id = _libssh2_channel_nextid(session); - channel->local.window_size_initial = - x11open_state->initial_window_size; - channel->local.window_size = x11open_state->initial_window_size; - channel->local.packet_size = x11open_state->packet_size; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "X11 Connection established: channel %lu/%lu " - "win %lu/%lu packet %lu/%lu", - channel->local.id, channel->remote.id, - channel->local.window_size, - channel->remote.window_size, - channel->local.packet_size, - channel->remote.packet_size); - p = x11open_state->packet; - *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; - _libssh2_store_u32(&p, channel->remote.id); - _libssh2_store_u32(&p, channel->local.id); - _libssh2_store_u32(&p, channel->remote.window_size_initial); - _libssh2_store_u32(&p, channel->remote.packet_size); - - x11open_state->state = libssh2_NB_state_created; - } - - if (x11open_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, x11open_state->packet, 17, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - x11open_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send channel open " - "confirmation"); - } - - /* Link the channel into the session */ - _libssh2_list_add(&session->channels, &channel->node); - - /* - * Pass control to the callback, they may turn right around and - * free the channel, or actually use it - */ - LIBSSH2_X11_OPEN(channel, (char *)x11open_state->shost, - x11open_state->sport); - - x11open_state->state = libssh2_NB_state_idle; - return 0; - } - } - else - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - /* fall-trough */ - x11_exit: - p = x11open_state->packet; - *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; - _libssh2_store_u32(&p, x11open_state->sender_channel); - _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1); - _libssh2_htonu32(p, 0); - - rc = _libssh2_transport_send(session, x11open_state->packet, packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - x11open_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, "Unable to send open failure"); - } - x11open_state->state = libssh2_NB_state_idle; - return 0; -} - -/* - * _libssh2_packet_add - * - * Create a new packet and attach it to the brigade. Called from the transport - * layer when it has received a packet. - * - * The input pointer 'data' is pointing to allocated data that this function - * is asked to deal with so on failure OR success, it must be freed fine. - * - * This function will always be called with 'datalen' greater than zero. - */ -int -_libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - size_t datalen, int macstate) -{ - int rc = 0; - char *message=NULL; - char *language=NULL; - size_t message_len=0; - size_t language_len=0; - LIBSSH2_CHANNEL *channelp = NULL; - size_t data_head = 0; - unsigned char msg = data[0]; - - switch(session->packAdd_state) { - case libssh2_NB_state_idle: - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Packet type %d received, length=%d", - (int) msg, (int) datalen); - - if ((macstate == LIBSSH2_MAC_INVALID) && - (!session->macerror || - LIBSSH2_MACERROR(session, (char *) data, datalen))) { - /* Bad MAC input, but no callback set or non-zero return from the - callback */ - - LIBSSH2_FREE(session, data); - return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC, - "Invalid MAC received"); - } - session->packAdd_state = libssh2_NB_state_allocated; - break; - case libssh2_NB_state_jump1: - goto libssh2_packet_add_jump_point1; - case libssh2_NB_state_jump2: - goto libssh2_packet_add_jump_point2; - case libssh2_NB_state_jump3: - goto libssh2_packet_add_jump_point3; - case libssh2_NB_state_jump4: - goto libssh2_packet_add_jump_point4; - case libssh2_NB_state_jump5: - goto libssh2_packet_add_jump_point5; - default: /* nothing to do */ - break; - } - - if (session->packAdd_state == libssh2_NB_state_allocated) { - /* A couple exceptions to the packet adding rule: */ - switch (msg) { - - /* - byte SSH_MSG_DISCONNECT - uint32 reason code - string description in ISO-10646 UTF-8 encoding [RFC3629] - string language tag [RFC3066] - */ - - case SSH_MSG_DISCONNECT: - if(datalen >= 5) { - size_t reason = _libssh2_ntohu32(data + 1); - - if(datalen >= 9) { - message_len = _libssh2_ntohu32(data + 5); - - if(message_len < datalen-13) { - /* 9 = packet_type(1) + reason(4) + message_len(4) */ - message = (char *) data + 9; - - language_len = _libssh2_ntohu32(data + 9 + message_len); - language = (char *) data + 9 + message_len + 4; - - if(language_len > (datalen-13-message_len)) { - /* bad input, clear info */ - language = message = NULL; - language_len = message_len = 0; - } - } - else - /* bad size, clear it */ - message_len=0; - } - if (session->ssh_msg_disconnect) { - LIBSSH2_DISCONNECT(session, reason, message, - message_len, language, language_len); - } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Disconnect(%d): %s(%s)", reason, - message, language); - } - - LIBSSH2_FREE(session, data); - session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; - session->packAdd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, - "socket disconnect"); - /* - byte SSH_MSG_IGNORE - string data - */ - - case SSH_MSG_IGNORE: - if (datalen >= 2) { - if (session->ssh_msg_ignore) { - LIBSSH2_IGNORE(session, (char *) data + 1, datalen - 1); - } - } else if (session->ssh_msg_ignore) { - LIBSSH2_IGNORE(session, "", 0); - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_DEBUG - boolean always_display - string message in ISO-10646 UTF-8 encoding [RFC3629] - string language tag [RFC3066] - */ - - case SSH_MSG_DEBUG: - if(datalen >= 2) { - int always_display= data[1]; - - if(datalen >= 6) { - message_len = _libssh2_ntohu32(data + 2); - - if(message_len <= (datalen - 10)) { - /* 6 = packet_type(1) + display(1) + message_len(4) */ - message = (char *) data + 6; - language_len = _libssh2_ntohu32(data + 6 + message_len); - - if(language_len <= (datalen - 10 - message_len)) - language = (char *) data + 10 + message_len; - } - } - - if (session->ssh_msg_debug) { - LIBSSH2_DEBUG(session, always_display, message, - message_len, language, language_len); - } - } - /* - * _libssh2_debug will actually truncate this for us so - * that it's not an inordinate about of data - */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Debug Packet: %s", message); - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_GLOBAL_REQUEST - string request name in US-ASCII only - boolean want reply - .... request-specific data follows - */ - - case SSH_MSG_GLOBAL_REQUEST: - if(datalen >= 5) { - uint32_t len =0; - unsigned char want_reply=0; - len = _libssh2_ntohu32(data + 1); - if(datalen >= (6 + len)) { - want_reply = data[5 + len]; - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "Received global request type %.*s (wr %X)", - len, data + 5, want_reply); - } - - - if (want_reply) { - unsigned char packet = SSH_MSG_REQUEST_FAILURE; - libssh2_packet_add_jump_point5: - session->packAdd_state = libssh2_NB_state_jump5; - rc = _libssh2_transport_send(session, &packet, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_CHANNEL_EXTENDED_DATA - uint32 recipient channel - uint32 data_type_code - string data - */ - - case SSH_MSG_CHANNEL_EXTENDED_DATA: - /* streamid(4) */ - data_head += 4; - - /* fall-through */ - - /* - byte SSH_MSG_CHANNEL_DATA - uint32 recipient channel - string data - */ - - case SSH_MSG_CHANNEL_DATA: - /* packet_type(1) + channelno(4) + datalen(4) */ - data_head += 9; - - if(datalen >= data_head) - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - - if (!channelp) { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, - "Packet received for unknown channel"); - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } -#ifdef LIBSSH2DEBUG - { - uint32_t stream_id = 0; - if (msg == SSH_MSG_CHANNEL_EXTENDED_DATA) - stream_id = _libssh2_ntohu32(data + 5); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "%d bytes packet_add() for %lu/%lu/%lu", - (int) (datalen - data_head), - channelp->local.id, - channelp->remote.id, - stream_id); - } -#endif - if ((channelp->remote.extended_data_ignore_mode == - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && - (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) { - /* Pretend we didn't receive this */ - LIBSSH2_FREE(session, data); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Ignoring extended data and refunding %d bytes", - (int) (datalen - 13)); - session->packAdd_channelp = channelp; - - /* Adjust the window based on the block we just freed */ - libssh2_packet_add_jump_point1: - session->packAdd_state = libssh2_NB_state_jump1; - rc = _libssh2_channel_receive_window_adjust(session-> - packAdd_channelp, - datalen - 13, - 1, NULL); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - - /* - * REMEMBER! remote means remote as source of data, - * NOT remote window! - */ - if (channelp->remote.packet_size < (datalen - data_head)) { - /* - * Spec says we MAY ignore bytes sent beyond - * packet_size - */ - _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, - "Packet contains more data than we offered" - " to receive, truncating"); - datalen = channelp->remote.packet_size + data_head; - } - if (channelp->remote.window_size <= 0) { - /* - * Spec says we MAY ignore bytes sent beyond - * window_size - */ - _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, - "The current receive window is full," - " data ignored"); - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - /* Reset EOF status */ - channelp->remote.eof = 0; - - if ((datalen - data_head) > channelp->remote.window_size) { - _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, - "Remote sent more data than current " - "window allows, truncating"); - datalen = channelp->remote.window_size + data_head; - channelp->remote.window_size = 0; - } - else - /* Now that we've received it, shrink our window */ - channelp->remote.window_size -= datalen - data_head; - - break; - - /* - byte SSH_MSG_CHANNEL_EOF - uint32 recipient channel - */ - - case SSH_MSG_CHANNEL_EOF: - if(datalen >= 5) - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - if (!channelp) - /* We may have freed already, just quietly ignore this... */ - ; - else { - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "EOF received for channel %lu/%lu", - channelp->local.id, - channelp->remote.id); - channelp->remote.eof = 1; - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string request type in US-ASCII characters only - boolean want reply - .... type-specific data follows - */ - - case SSH_MSG_CHANNEL_REQUEST: - if(datalen >= 9) { - uint32_t channel = _libssh2_ntohu32(data + 1); - uint32_t len = _libssh2_ntohu32(data + 5); - unsigned char want_reply = 1; - - if(len < (datalen - 10)) - want_reply = data[9 + len]; - - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "Channel %d received request type %.*s (wr %X)", - channel, len, data + 9, want_reply); - - if (len == sizeof("exit-status") - 1 - && !memcmp("exit-status", data + 9, - sizeof("exit-status") - 1)) { - - /* we've got "exit-status" packet. Set the session value */ - if(datalen >= 20) - channelp = - _libssh2_channel_locate(session, channel); - - if (channelp) { - channelp->exit_status = - _libssh2_ntohu32(data + 9 + sizeof("exit-status")); - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Exit status %lu received for " - "channel %lu/%lu", - channelp->exit_status, - channelp->local.id, - channelp->remote.id); - } - - } - else if (len == sizeof("exit-signal") - 1 - && !memcmp("exit-signal", data + 9, - sizeof("exit-signal") - 1)) { - /* command terminated due to signal */ - if(datalen >= 20) - channelp = _libssh2_channel_locate(session, channel); - - if (channelp) { - /* set signal name (without SIG prefix) */ - uint32_t namelen = - _libssh2_ntohu32(data + 9 + sizeof("exit-signal")); - channelp->exit_signal = - LIBSSH2_ALLOC(session, namelen + 1); - if (!channelp->exit_signal) - rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "memory for signal name"); - else { - memcpy(channelp->exit_signal, - data + 13 + sizeof("exit_signal"), namelen); - channelp->exit_signal[namelen] = '\0'; - /* TODO: save error message and language tag */ - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Exit signal %s received for " - "channel %lu/%lu", - channelp->exit_signal, - channelp->local.id, - channelp->remote.id); - } - } - } - - - if (want_reply) { - unsigned char packet[5]; - libssh2_packet_add_jump_point4: - session->packAdd_state = libssh2_NB_state_jump4; - packet[0] = SSH_MSG_CHANNEL_FAILURE; - memcpy(&packet[1], data+1, 4); - rc = _libssh2_transport_send(session, packet, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return rc; - - /* - byte SSH_MSG_CHANNEL_CLOSE - uint32 recipient channel - */ - - case SSH_MSG_CHANNEL_CLOSE: - if(datalen >= 5) - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - if (!channelp) { - /* We may have freed already, just quietly ignore this... */ - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Close received for channel %lu/%lu", - channelp->local.id, - channelp->remote.id); - - channelp->remote.close = 1; - channelp->remote.eof = 1; - - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_CHANNEL_OPEN - string "session" - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - */ - - case SSH_MSG_CHANNEL_OPEN: - if(datalen < 17) - ; - else if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && - ((sizeof("forwarded-tcpip") - 1) == - _libssh2_ntohu32(data + 1)) - && - (memcmp(data + 5, "forwarded-tcpip", - sizeof("forwarded-tcpip") - 1) == 0)) { - - /* init the state struct */ - memset(&session->packAdd_Qlstn_state, 0, - sizeof(session->packAdd_Qlstn_state)); - - libssh2_packet_add_jump_point2: - session->packAdd_state = libssh2_NB_state_jump2; - rc = packet_queue_listener(session, data, datalen, - &session->packAdd_Qlstn_state); - } - else if ((datalen >= (sizeof("x11") + 4)) && - ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) && - (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) { - - /* init the state struct */ - memset(&session->packAdd_x11open_state, 0, - sizeof(session->packAdd_x11open_state)); - - libssh2_packet_add_jump_point3: - session->packAdd_state = libssh2_NB_state_jump3; - rc = packet_x11_open(session, data, datalen, - &session->packAdd_x11open_state); - } - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return rc; - - /* - byte SSH_MSG_CHANNEL_WINDOW_ADJUST - uint32 recipient channel - uint32 bytes to add - */ - case SSH_MSG_CHANNEL_WINDOW_ADJUST: - if(datalen < 9) - ; - else { - uint32_t bytestoadd = _libssh2_ntohu32(data + 5); - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - if(channelp) { - channelp->local.window_size += bytestoadd; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Window adjust for channel %lu/%lu, " - "adding %lu bytes, new window_size=%lu", - channelp->local.id, - channelp->remote.id, - bytestoadd, - channelp->local.window_size); - } - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - default: - break; - } - - session->packAdd_state = libssh2_NB_state_sent; - } - - if (session->packAdd_state == libssh2_NB_state_sent) { - LIBSSH2_PACKET *packetp = - LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); - if (!packetp) { - _libssh2_debug(session, LIBSSH2_ERROR_ALLOC, - "memory for packet"); - session->packAdd_state = libssh2_NB_state_idle; - return LIBSSH2_ERROR_ALLOC; - } - packetp->data = data; - packetp->data_len = datalen; - packetp->data_head = data_head; - - _libssh2_list_add(&session->packets, &packetp->node); - - session->packAdd_state = libssh2_NB_state_sent1; - } - - if ((msg == SSH_MSG_KEXINIT && - !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) || - (session->packAdd_state == libssh2_NB_state_sent2)) { - if (session->packAdd_state == libssh2_NB_state_sent1) { - /* - * Remote wants new keys - * Well, it's already in the brigade, - * let's just call back into ourselves - */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Renegotiating Keys"); - - session->packAdd_state = libssh2_NB_state_sent2; - } - - /* - * The KEXINIT message has been added to the queue. The packAdd and - * readPack states need to be reset because _libssh2_kex_exchange - * (eventually) calls upon _libssh2_transport_read to read the rest of - * the key exchange conversation. - */ - session->readPack_state = libssh2_NB_state_idle; - session->packet.total_num = 0; - session->packAdd_state = libssh2_NB_state_idle; - session->fullpacket_state = libssh2_NB_state_idle; - - memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t)); - - /* - * If there was a key reexchange failure, let's just hope we didn't - * send NEWKEYS yet, otherwise remote will drop us like a rock - */ - rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - session->packAdd_state = libssh2_NB_state_idle; - return 0; -} - -/* - * _libssh2_packet_ask - * - * Scan the brigade for a matching packet type, optionally poll the socket for - * a packet first - */ -int -_libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, - unsigned char **data, size_t *data_len, - int match_ofs, const unsigned char *match_buf, - size_t match_len) -{ - LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets); - - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Looking for packet of type: %d", (int) packet_type); - - while (packet) { - if (packet->data[0] == packet_type - && (packet->data_len >= (match_ofs + match_len)) - && (!match_buf || - (memcmp(packet->data + match_ofs, match_buf, - match_len) == 0))) { - *data = packet->data; - *data_len = packet->data_len; - - /* unlink struct from session->packets */ - _libssh2_list_remove(&packet->node); - - LIBSSH2_FREE(session, packet); - - return 0; - } - packet = _libssh2_list_next(&packet->node); - } - return -1; -} - -/* - * libssh2_packet_askv - * - * Scan for any of a list of packet types in the brigade, optionally poll the - * socket for a packet first - */ -int -_libssh2_packet_askv(LIBSSH2_SESSION * session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len) -{ - int i, packet_types_len = strlen((char *) packet_types); - - for(i = 0; i < packet_types_len; i++) { - if (0 == _libssh2_packet_ask(session, packet_types[i], data, - data_len, match_ofs, - match_buf, match_len)) { - return 0; - } - } - - return -1; -} - -/* - * _libssh2_packet_require - * - * Loops _libssh2_transport_read() until the packet requested is available - * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout - * - * Returns negative on error - * Returns 0 when it has taken care of the requested packet. - */ -int -_libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len, - packet_require_state_t *state) -{ - if (state->start == 0) { - if (_libssh2_packet_ask(session, packet_type, data, data_len, - match_ofs, match_buf, - match_len) == 0) { - /* A packet was available in the packet brigade */ - return 0; - } - - state->start = time(NULL); - } - - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - int ret = _libssh2_transport_read(session); - if (ret == LIBSSH2_ERROR_EAGAIN) - return ret; - else if (ret < 0) { - state->start = 0; - /* an error which is not just because of blocking */ - return ret; - } else if (ret == packet_type) { - /* Be lazy, let packet_ask pull it out of the brigade */ - ret = _libssh2_packet_ask(session, packet_type, data, data_len, - match_ofs, match_buf, match_len); - state->start = 0; - return ret; - } else if (ret == 0) { - /* nothing available, wait until data arrives or we time out */ - long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - - state->start); - - if (left <= 0) { - state->start = 0; - return LIBSSH2_ERROR_TIMEOUT; - } - return -1; /* no packet available yet */ - } - } - - /* Only reached if the socket died */ - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* - * _libssh2_packet_burn - * - * Loops _libssh2_transport_read() until any packet is available and promptly - * discards it. - * Used during KEX exchange to discard badly guessed KEX_INIT packets - */ -int -_libssh2_packet_burn(LIBSSH2_SESSION * session, - libssh2_nonblocking_states * state) -{ - unsigned char *data; - size_t data_len; - unsigned char all_packets[255]; - int i; - int ret; - - if (*state == libssh2_NB_state_idle) { - for(i = 1; i < 256; i++) { - all_packets[i - 1] = i; - } - - if (_libssh2_packet_askv(session, all_packets, &data, &data_len, 0, - NULL, 0) == 0) { - i = data[0]; - /* A packet was available in the packet brigade, burn it */ - LIBSSH2_FREE(session, data); - return i; - } - - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Blocking until packet becomes available to burn"); - *state = libssh2_NB_state_created; - } - - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - ret = _libssh2_transport_read(session); - if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } else if (ret < 0) { - *state = libssh2_NB_state_idle; - return ret; - } else if (ret == 0) { - /* FIXME: this might busyloop */ - continue; - } - - /* Be lazy, let packet_ask pull it out of the brigade */ - if (0 == - _libssh2_packet_ask(session, ret, &data, &data_len, 0, NULL, 0)) { - /* Smoke 'em if you got 'em */ - LIBSSH2_FREE(session, data); - *state = libssh2_NB_state_idle; - return ret; - } - } - - /* Only reached if the socket died */ - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* - * _libssh2_packet_requirev - * - * Loops _libssh2_transport_read() until one of a list of packet types - * requested is available. SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause - * a bailout. packet_types is a null terminated list of packet_type numbers - */ - -int -_libssh2_packet_requirev(LIBSSH2_SESSION *session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, size_t match_len, - packet_requirev_state_t * state) -{ - if (_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs, - match_buf, match_len) == 0) { - /* One of the packets listed was available in the packet brigade */ - state->start = 0; - return 0; - } - - if (state->start == 0) { - state->start = time(NULL); - } - - while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) { - int ret = _libssh2_transport_read(session); - if ((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) { - state->start = 0; - return ret; - } - if (ret <= 0) { - long left = LIBSSH2_READ_TIMEOUT - - (long)(time(NULL) - state->start); - - if (left <= 0) { - state->start = 0; - return LIBSSH2_ERROR_TIMEOUT; - } - else if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - } - - if (strchr((char *) packet_types, ret)) { - /* Be lazy, let packet_ask pull it out of the brigade */ - return _libssh2_packet_askv(session, packet_types, data, - data_len, match_ofs, match_buf, - match_len); - } - } - - /* Only reached if the socket died */ - state->start = 0; - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - diff --git a/vendor/libssh2-1.4.2/src/packet.h b/vendor/libssh2-1.4.2/src/packet.h deleted file mode 100644 index d66b15b..0000000 --- a/vendor/libssh2-1.4.2/src/packet.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef LIBSSH2_PACKET_H -#define LIBSSH2_PACKET_H -/* - * Copyright (C) 2010 by Daniel Stenberg - * Author: Daniel Stenberg - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - * - */ - -int _libssh2_packet_read(LIBSSH2_SESSION * session); - -int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len); - -int _libssh2_packet_askv(LIBSSH2_SESSION * session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len); -int _libssh2_packet_require(LIBSSH2_SESSION * session, - unsigned char packet_type, unsigned char **data, - size_t *data_len, int match_ofs, - const unsigned char *match_buf, - size_t match_len, - packet_require_state_t * state); -int _libssh2_packet_requirev(LIBSSH2_SESSION *session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len, - packet_requirev_state_t * state); -int _libssh2_packet_burn(LIBSSH2_SESSION * session, - libssh2_nonblocking_states * state); -int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data, - unsigned long data_len); -int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - size_t datalen, int macstate); - -#endif /* LIBSSH2_PACKET_H */ diff --git a/vendor/libssh2-1.4.2/src/pem.c b/vendor/libssh2-1.4.2/src/pem.c deleted file mode 100644 index 5749bc8..0000000 --- a/vendor/libssh2-1.4.2/src/pem.c +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2007 The Written Word, Inc. - * Copyright (C) 2008, Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -#ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */ - -static int -readline(char *line, int line_size, FILE * fp) -{ - if (!fgets(line, line_size, fp)) { - return -1; - } - if (*line && line[strlen(line) - 1] == '\n') { - line[strlen(line) - 1] = '\0'; - } - if (*line && line[strlen(line) - 1] == '\r') { - line[strlen(line) - 1] = '\0'; - } - return 0; -} - -#define LINE_SIZE 128 - -int -_libssh2_pem_parse(LIBSSH2_SESSION * session, - const char *headerbegin, - const char *headerend, - FILE * fp, unsigned char **data, unsigned int *datalen) -{ - char line[LINE_SIZE]; - char *b64data = NULL; - unsigned int b64datalen = 0; - int ret; - - do { - if (readline(line, LINE_SIZE, fp)) { - return -1; - } - } - while (strcmp(line, headerbegin) != 0); - - *line = '\0'; - - do { - if (*line) { - char *tmp; - size_t linelen; - - linelen = strlen(line); - tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen); - if (!tmp) { - ret = -1; - goto out; - } - memcpy(tmp + b64datalen, line, linelen); - b64data = tmp; - b64datalen += linelen; - } - - if (readline(line, LINE_SIZE, fp)) { - ret = -1; - goto out; - } - } while (strcmp(line, headerend) != 0); - - if (libssh2_base64_decode(session, (char**) data, datalen, - b64data, b64datalen)) { - ret = -1; - goto out; - } - - ret = 0; - out: - if (b64data) { - LIBSSH2_FREE(session, b64data); - } - return ret; -} - -static int -read_asn1_length(const unsigned char *data, - unsigned int datalen, unsigned int *len) -{ - unsigned int lenlen; - int nextpos; - - if (datalen < 1) { - return -1; - } - *len = data[0]; - - if (*len >= 0x80) { - lenlen = *len & 0x7F; - *len = data[1]; - if (1 + lenlen > datalen) { - return -1; - } - if (lenlen > 1) { - *len <<= 8; - *len |= data[2]; - } - } else { - lenlen = 0; - } - - nextpos = 1 + lenlen; - if (lenlen > 2 || 1 + lenlen + *len > datalen) { - return -1; - } - - return nextpos; -} - -int -_libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen) -{ - unsigned int len; - int lenlen; - - if (*datalen < 1) { - return -1; - } - - if ((*data)[0] != '\x30') { - return -1; - } - - (*data)++; - (*datalen)--; - - lenlen = read_asn1_length(*data, *datalen, &len); - if (lenlen < 0 || lenlen + len != *datalen) { - return -1; - } - - *data += lenlen; - *datalen -= lenlen; - - return 0; -} - -int -_libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, - unsigned char **i, unsigned int *ilen) -{ - unsigned int len; - int lenlen; - - if (*datalen < 1) { - return -1; - } - - if ((*data)[0] != '\x02') { - return -1; - } - - (*data)++; - (*datalen)--; - - lenlen = read_asn1_length(*data, *datalen, &len); - if (lenlen < 0 || lenlen + len > *datalen) { - return -1; - } - - *data += lenlen; - *datalen -= lenlen; - - *i = *data; - *ilen = len; - - *data += len; - *datalen -= len; - - return 0; -} - -#endif /* LIBSSH2_LIBGCRYPT */ diff --git a/vendor/libssh2-1.4.2/src/publickey.c b/vendor/libssh2-1.4.2/src/publickey.c deleted file mode 100644 index ab76ab2..0000000 --- a/vendor/libssh2-1.4.2/src/publickey.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010 by Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include "libssh2_publickey.h" -#include "channel.h" -#include "session.h" - -#define LIBSSH2_PUBLICKEY_VERSION 2 - -/* Numericised response codes -- Not IETF, just local representation */ -#define LIBSSH2_PUBLICKEY_RESPONSE_STATUS 0 -#define LIBSSH2_PUBLICKEY_RESPONSE_VERSION 1 -#define LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY 2 - -typedef struct _LIBSSH2_PUBLICKEY_CODE_LIST -{ - int code; - const char *name; - int name_len; -} LIBSSH2_PUBLICKEY_CODE_LIST; - -static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_response_codes[] = -{ - {LIBSSH2_PUBLICKEY_RESPONSE_STATUS, "status", sizeof("status") - 1}, - {LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1}, - {LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey", - sizeof("publickey") - 1} , - {0, NULL, 0} -}; - -/* PUBLICKEY status codes -- IETF defined */ -#define LIBSSH2_PUBLICKEY_SUCCESS 0 -#define LIBSSH2_PUBLICKEY_ACCESS_DENIED 1 -#define LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED 2 -#define LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED 3 -#define LIBSSH2_PUBLICKEY_KEY_NOT_FOUND 4 -#define LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED 5 -#define LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT 6 -#define LIBSSH2_PUBLICKEY_GENERAL_FAILURE 7 -#define LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED 8 - -#define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX 8 - -static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_status_codes[] = { - {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1} , - {LIBSSH2_PUBLICKEY_ACCESS_DENIED, "access denied", - sizeof("access denied") - 1}, - {LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED, "storage exceeded", - sizeof("storage exceeded") - 1} , - {LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED, "version not supported", - sizeof("version not supported") - 1} , - {LIBSSH2_PUBLICKEY_KEY_NOT_FOUND, "key not found", - sizeof("key not found") - 1}, - {LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED, "key not supported", - sizeof("key not supported") - 1}, - {LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT, "key already present", - sizeof("key already present") - 1}, - {LIBSSH2_PUBLICKEY_GENERAL_FAILURE, "general failure", - sizeof("general failure") - 1}, - {LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED, "request not supported", - sizeof("request not supported") - 1}, - {0, NULL, 0} -}; - -/* - * publickey_status_error - * - * Format an error message from a status code - */ -static void -publickey_status_error(const LIBSSH2_PUBLICKEY *pkey, - LIBSSH2_SESSION *session, int status) -{ - const char *msg; - - /* GENERAL_FAILURE got remapped between version 1 and 2 */ - if (status == 6 && pkey && pkey->version == 1) { - status = 7; - } - - if (status < 0 || status > LIBSSH2_PUBLICKEY_STATUS_CODE_MAX) { - msg = "unknown"; - } else { - msg = publickey_status_codes[status].name; - } - - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, msg); -} - -/* - * publickey_packet_receive - * - * Read a packet from the subsystem - */ -static int -publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey, - unsigned char **data, size_t *data_len) -{ - LIBSSH2_CHANNEL *channel = pkey->channel; - LIBSSH2_SESSION *session = channel->session; - unsigned char buffer[4]; - int rc; - - if (pkey->receive_state == libssh2_NB_state_idle) { - rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc != 4) { - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid response from publickey subsystem"); - } - - pkey->receive_packet_len = _libssh2_ntohu32(buffer); - pkey->receive_packet = - LIBSSH2_ALLOC(session, pkey->receive_packet_len); - if (!pkey->receive_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate publickey response " - "buffer"); - } - - pkey->receive_state = libssh2_NB_state_sent; - } - - if (pkey->receive_state == libssh2_NB_state_sent) { - rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet, - pkey->receive_packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc != (int)pkey->receive_packet_len) { - LIBSSH2_FREE(session, pkey->receive_packet); - pkey->receive_packet = NULL; - pkey->receive_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for publickey subsystem " - "response packet"); - } - - *data = pkey->receive_packet; - *data_len = pkey->receive_packet_len; - } - - pkey->receive_state = libssh2_NB_state_idle; - - return 0; -} - -/* publickey_response_id - * - * Translate a string response name to a numeric code - * Data will be incremented by 4 + response_len on success only - */ -static int -publickey_response_id(unsigned char **pdata, size_t data_len) -{ - size_t response_len; - unsigned char *data = *pdata; - const LIBSSH2_PUBLICKEY_CODE_LIST *codes = publickey_response_codes; - - if (data_len < 4) { - /* Malformed response */ - return -1; - } - response_len = _libssh2_ntohu32(data); - data += 4; - data_len -= 4; - if (data_len < response_len) { - /* Malformed response */ - return -1; - } - - while (codes->name) { - if ((unsigned long)codes->name_len == response_len && - strncmp(codes->name, (char *) data, response_len) == 0) { - *pdata = data + response_len; - return codes->code; - } - codes++; - } - - return -1; -} - -/* publickey_response_success - * - * Generic helper routine to wait for success response and nothing else - */ -static int -publickey_response_success(LIBSSH2_PUBLICKEY * pkey) -{ - LIBSSH2_SESSION *session = pkey->channel->session; - unsigned char *data, *s; - size_t data_len; - int response; - - while (1) { - int rc = publickey_packet_receive(pkey, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for response from " - "publickey subsystem"); - } - - s = data; - response = publickey_response_id(&s, data_len); - - switch (response) { - case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: - /* Error, or processing complete */ - { - unsigned long status = _libssh2_ntohu32(s); - - LIBSSH2_FREE(session, data); - - if (status == LIBSSH2_PUBLICKEY_SUCCESS) - return 0; - - publickey_status_error(pkey, session, status); - return -1; - } - default: - LIBSSH2_FREE(session, data); - if (response < 0) { - return _libssh2_error(session, - LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid publickey subsystem response"); - } - /* Unknown/Unexpected */ - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Unexpected publickey subsystem response"); - data = NULL; - } - } - /* never reached, but include `return` to silence compiler warnings */ - return -1; -} - -/* ***************** - * Publickey API * - ***************** */ - -/* - * publickey_init - * - * Startup the publickey subsystem - */ -static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) -{ - int response; - int rc; - - if (session->pkeyInit_state == libssh2_NB_state_idle) { - session->pkeyInit_data = NULL; - session->pkeyInit_pkey = NULL; - session->pkeyInit_channel = NULL; - - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Initializing publickey subsystem"); - - session->pkeyInit_state = libssh2_NB_state_allocated; - } - - if (session->pkeyInit_state == libssh2_NB_state_allocated) { - - session->pkeyInit_channel = - _libssh2_channel_open(session, "session", - sizeof("session") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, - 0); - if (!session->pkeyInit_channel) { - if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) - /* The error state is already set, so leave it */ - return NULL; - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to startup channel"); - goto err_exit; - } - - session->pkeyInit_state = libssh2_NB_state_sent; - } - - if (session->pkeyInit_state == libssh2_NB_state_sent) { - rc = _libssh2_channel_process_startup(session->pkeyInit_channel, - "subsystem", - sizeof("subsystem") - 1, - "publickey", - sizeof("publickey") - 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting publickey subsystem"); - return NULL; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to request publickey subsystem"); - goto err_exit; - } - - session->pkeyInit_state = libssh2_NB_state_sent1; - } - - if (session->pkeyInit_state == libssh2_NB_state_sent1) { - unsigned char *s; - rc = _libssh2_channel_extended_data(session->pkeyInit_channel, - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting publickey subsystem"); - return NULL; - } - - session->pkeyInit_pkey = - LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PUBLICKEY)); - if (!session->pkeyInit_pkey) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate a new publickey structure"); - goto err_exit; - } - memset(session->pkeyInit_pkey, 0, sizeof(LIBSSH2_PUBLICKEY)); - session->pkeyInit_pkey->channel = session->pkeyInit_channel; - session->pkeyInit_pkey->version = 0; - - s = session->pkeyInit_buffer; - _libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4); - s += 4; - _libssh2_htonu32(s, sizeof("version") - 1); - s += 4; - memcpy(s, "version", sizeof("version") - 1); - s += sizeof("version") - 1; - _libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION); - - session->pkeyInit_buffer_sent = 0; - - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Sending publickey advertising version %d support", - (int) LIBSSH2_PUBLICKEY_VERSION); - - session->pkeyInit_state = libssh2_NB_state_sent2; - } - - if (session->pkeyInit_state == libssh2_NB_state_sent2) { - rc = _libssh2_channel_write(session->pkeyInit_channel, 0, - session->pkeyInit_buffer, - 19 - session->pkeyInit_buffer_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending publickey version packet"); - return NULL; - } else if (rc) { - _libssh2_error(session, rc, - "Unable to send publickey version packet"); - goto err_exit; - } - session->pkeyInit_buffer_sent += rc; - if(session->pkeyInit_buffer_sent < 19) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Need to be called again to complete this"); - return NULL; - } - - session->pkeyInit_state = libssh2_NB_state_sent3; - } - - if (session->pkeyInit_state == libssh2_NB_state_sent3) { - while (1) { - unsigned char *s; - rc = publickey_packet_receive(session->pkeyInit_pkey, - &session->pkeyInit_data, - &session->pkeyInit_data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response from " - "publickey subsystem"); - return NULL; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for response from " - "publickey subsystem"); - goto err_exit; - } - - s = session->pkeyInit_data; - if ((response = - publickey_response_id(&s, session->pkeyInit_data_len)) < 0) { - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid publickey subsystem response code"); - goto err_exit; - } - - switch (response) { - case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: - /* Error */ - { - unsigned long status, descr_len, lang_len; - - status = _libssh2_ntohu32(s); - s += 4; - descr_len = _libssh2_ntohu32(s); - s += 4; - /* description starts here */ - s += descr_len; - lang_len = _libssh2_ntohu32(s); - s += 4; - /* lang starts here */ - s += lang_len; - - if (s > - session->pkeyInit_data + session->pkeyInit_data_len) { - _libssh2_error(session, - LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Malformed publickey subsystem packet"); - goto err_exit; - } - - publickey_status_error(NULL, session, status); - - goto err_exit; - } - - case LIBSSH2_PUBLICKEY_RESPONSE_VERSION: - /* What we want */ - session->pkeyInit_pkey->version = _libssh2_ntohu32(s); - if (session->pkeyInit_pkey->version > - LIBSSH2_PUBLICKEY_VERSION) { - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Truncate remote publickey version from %lu", - session->pkeyInit_pkey->version); - session->pkeyInit_pkey->version = - LIBSSH2_PUBLICKEY_VERSION; - } - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Enabling publickey subsystem version %lu", - session->pkeyInit_pkey->version); - LIBSSH2_FREE(session, session->pkeyInit_data); - session->pkeyInit_data = NULL; - session->pkeyInit_state = libssh2_NB_state_idle; - return session->pkeyInit_pkey; - - default: - /* Unknown/Unexpected */ - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Unexpected publickey subsystem response, " - "ignoring"); - LIBSSH2_FREE(session, session->pkeyInit_data); - session->pkeyInit_data = NULL; - } - } - } - - /* Never reached except by direct goto */ - err_exit: - session->pkeyInit_state = libssh2_NB_state_sent4; - if (session->pkeyInit_channel) { - rc = _libssh2_channel_close(session->pkeyInit_channel); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block closing channel"); - return NULL; - } - } - if (session->pkeyInit_pkey) { - LIBSSH2_FREE(session, session->pkeyInit_pkey); - session->pkeyInit_pkey = NULL; - } - if (session->pkeyInit_data) { - LIBSSH2_FREE(session, session->pkeyInit_data); - session->pkeyInit_data = NULL; - } - session->pkeyInit_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_publickey_init - * - * Startup the publickey subsystem - */ -LIBSSH2_API LIBSSH2_PUBLICKEY * -libssh2_publickey_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_PUBLICKEY *ptr; - - BLOCK_ADJUST_ERRNO(ptr, session, - publickey_init(session)); - return ptr; -} - - - -/* - * libssh2_publickey_add_ex - * - * Add a new public key entry - */ -LIBSSH2_API int -libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, - unsigned long name_len, const unsigned char *blob, - unsigned long blob_len, char overwrite, - unsigned long num_attrs, - const libssh2_publickey_attribute attrs[]) -{ - LIBSSH2_CHANNEL *channel; - LIBSSH2_SESSION *session; - /* 19 = packet_len(4) + add_len(4) + "add"(3) + name_len(4) + {name} - blob_len(4) + {blob} */ - unsigned long i, packet_len = 19 + name_len + blob_len; - unsigned char *comment = NULL; - unsigned long comment_len = 0; - int rc; - - if(!pkey) - return LIBSSH2_ERROR_BAD_USE; - - channel = pkey->channel; - session = channel->session; - - if (pkey->add_state == libssh2_NB_state_idle) { - pkey->add_packet = NULL; - - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, "Adding %s publickey", - name); - - if (pkey->version == 1) { - for(i = 0; i < num_attrs; i++) { - /* Search for a comment attribute */ - if (attrs[i].name_len == (sizeof("comment") - 1) && - strncmp(attrs[i].name, "comment", - sizeof("comment") - 1) == 0) { - comment = (unsigned char *) attrs[i].value; - comment_len = attrs[i].value_len; - break; - } - } - packet_len += 4 + comment_len; - } else { - packet_len += 5; /* overwrite(1) + attribute_count(4) */ - for(i = 0; i < num_attrs; i++) { - packet_len += 9 + attrs[i].name_len + attrs[i].value_len; - /* name_len(4) + value_len(4) + mandatory(1) */ - } - } - - pkey->add_packet = LIBSSH2_ALLOC(session, packet_len); - if (!pkey->add_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "publickey \"add\" packet"); - } - - pkey->add_s = pkey->add_packet; - _libssh2_htonu32(pkey->add_s, packet_len - 4); - pkey->add_s += 4; - _libssh2_htonu32(pkey->add_s, sizeof("add") - 1); - pkey->add_s += 4; - memcpy(pkey->add_s, "add", sizeof("add") - 1); - pkey->add_s += sizeof("add") - 1; - if (pkey->version == 1) { - _libssh2_htonu32(pkey->add_s, comment_len); - pkey->add_s += 4; - if (comment) { - memcpy(pkey->add_s, comment, comment_len); - pkey->add_s += comment_len; - } - - _libssh2_htonu32(pkey->add_s, name_len); - pkey->add_s += 4; - memcpy(pkey->add_s, name, name_len); - pkey->add_s += name_len; - _libssh2_htonu32(pkey->add_s, blob_len); - pkey->add_s += 4; - memcpy(pkey->add_s, blob, blob_len); - pkey->add_s += blob_len; - } else { - /* Version == 2 */ - - _libssh2_htonu32(pkey->add_s, name_len); - pkey->add_s += 4; - memcpy(pkey->add_s, name, name_len); - pkey->add_s += name_len; - _libssh2_htonu32(pkey->add_s, blob_len); - pkey->add_s += 4; - memcpy(pkey->add_s, blob, blob_len); - pkey->add_s += blob_len; - *(pkey->add_s++) = overwrite ? 0x01 : 0; - _libssh2_htonu32(pkey->add_s, num_attrs); - pkey->add_s += 4; - for(i = 0; i < num_attrs; i++) { - _libssh2_htonu32(pkey->add_s, attrs[i].name_len); - pkey->add_s += 4; - memcpy(pkey->add_s, attrs[i].name, attrs[i].name_len); - pkey->add_s += attrs[i].name_len; - _libssh2_htonu32(pkey->add_s, attrs[i].value_len); - pkey->add_s += 4; - memcpy(pkey->add_s, attrs[i].value, attrs[i].value_len); - pkey->add_s += attrs[i].value_len; - *(pkey->add_s++) = attrs[i].mandatory ? 0x01 : 0; - } - } - - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Sending publickey \"add\" packet: " - "type=%s blob_len=%ld num_attrs=%ld", - name, blob_len, num_attrs); - - pkey->add_state = libssh2_NB_state_created; - } - - if (pkey->add_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, pkey->add_packet, - (pkey->add_s - pkey->add_packet)); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((pkey->add_s - pkey->add_packet) != rc) { - LIBSSH2_FREE(session, pkey->add_packet); - pkey->add_packet = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send publickey add packet"); - } - LIBSSH2_FREE(session, pkey->add_packet); - pkey->add_packet = NULL; - - pkey->add_state = libssh2_NB_state_sent; - } - - rc = publickey_response_success(pkey); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - - pkey->add_state = libssh2_NB_state_idle; - - return rc; -} - -/* libssh2_publickey_remove_ex - * Remove an existing publickey so that authentication can no longer be - * performed using it - */ -LIBSSH2_API int -libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey, - const unsigned char *name, unsigned long name_len, - const unsigned char *blob, unsigned long blob_len) -{ - LIBSSH2_CHANNEL *channel; - LIBSSH2_SESSION *session; - /* 22 = packet_len(4) + remove_len(4) + "remove"(6) + name_len(4) + {name} - + blob_len(4) + {blob} */ - unsigned long packet_len = 22 + name_len + blob_len; - int rc; - - if(!pkey) - return LIBSSH2_ERROR_BAD_USE; - - channel = pkey->channel; - session = channel->session; - - if (pkey->remove_state == libssh2_NB_state_idle) { - pkey->remove_packet = NULL; - - pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len); - if (!pkey->remove_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "publickey \"remove\" packet"); - } - - pkey->remove_s = pkey->remove_packet; - _libssh2_htonu32(pkey->remove_s, packet_len - 4); - pkey->remove_s += 4; - _libssh2_htonu32(pkey->remove_s, sizeof("remove") - 1); - pkey->remove_s += 4; - memcpy(pkey->remove_s, "remove", sizeof("remove") - 1); - pkey->remove_s += sizeof("remove") - 1; - _libssh2_htonu32(pkey->remove_s, name_len); - pkey->remove_s += 4; - memcpy(pkey->remove_s, name, name_len); - pkey->remove_s += name_len; - _libssh2_htonu32(pkey->remove_s, blob_len); - pkey->remove_s += 4; - memcpy(pkey->remove_s, blob, blob_len); - pkey->remove_s += blob_len; - - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Sending publickey \"remove\" packet: " - "type=%s blob_len=%ld", - name, blob_len); - - pkey->remove_state = libssh2_NB_state_created; - } - - if (pkey->remove_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, pkey->remove_packet, - (pkey->remove_s - pkey->remove_packet)); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((pkey->remove_s - pkey->remove_packet) != rc) { - LIBSSH2_FREE(session, pkey->remove_packet); - pkey->remove_packet = NULL; - pkey->remove_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send publickey remove packet"); - } - LIBSSH2_FREE(session, pkey->remove_packet); - pkey->remove_packet = NULL; - - pkey->remove_state = libssh2_NB_state_sent; - } - - rc = publickey_response_success(pkey); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - - pkey->remove_state = libssh2_NB_state_idle; - - return rc; -} - -/* libssh2_publickey_list_fetch - * Fetch a list of supported public key from a server - */ -LIBSSH2_API int -libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, - libssh2_publickey_list ** pkey_list) -{ - LIBSSH2_CHANNEL *channel; - LIBSSH2_SESSION *session; - libssh2_publickey_list *list = NULL; - unsigned long buffer_len = 12, keys = 0, max_keys = 0, i; - /* 12 = packet_len(4) + list_len(4) + "list"(4) */ - int response; - int rc; - - if(!pkey) - return LIBSSH2_ERROR_BAD_USE; - - channel = pkey->channel; - session = channel->session; - - if (pkey->listFetch_state == libssh2_NB_state_idle) { - pkey->listFetch_data = NULL; - - pkey->listFetch_s = pkey->listFetch_buffer; - _libssh2_htonu32(pkey->listFetch_s, buffer_len - 4); - pkey->listFetch_s += 4; - _libssh2_htonu32(pkey->listFetch_s, sizeof("list") - 1); - pkey->listFetch_s += 4; - memcpy(pkey->listFetch_s, "list", sizeof("list") - 1); - pkey->listFetch_s += sizeof("list") - 1; - - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Sending publickey \"list\" packet"); - - pkey->listFetch_state = libssh2_NB_state_created; - } - - if (pkey->listFetch_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, - pkey->listFetch_buffer, - (pkey->listFetch_s - - pkey->listFetch_buffer)); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) { - pkey->listFetch_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send publickey list packet"); - } - - pkey->listFetch_state = libssh2_NB_state_sent; - } - - while (1) { - rc = publickey_packet_receive(pkey, &pkey->listFetch_data, - &pkey->listFetch_data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for response from " - "publickey subsystem"); - goto err_exit; - } - - pkey->listFetch_s = pkey->listFetch_data; - if ((response = - publickey_response_id(&pkey->listFetch_s, - pkey->listFetch_data_len)) < 0) { - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid publickey subsystem response code"); - goto err_exit; - } - - switch (response) { - case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: - /* Error, or processing complete */ - { - unsigned long status, descr_len, lang_len; - - status = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - descr_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - /* description starts at pkey->listFetch_s */ - pkey->listFetch_s += descr_len; - lang_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - /* lang starts at pkey->listFetch_s */ - pkey->listFetch_s += lang_len; - - if (pkey->listFetch_s > - pkey->listFetch_data + pkey->listFetch_data_len) { - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Malformed publickey subsystem packet"); - goto err_exit; - } - - if (status == LIBSSH2_PUBLICKEY_SUCCESS) { - LIBSSH2_FREE(session, pkey->listFetch_data); - pkey->listFetch_data = NULL; - *pkey_list = list; - *num_keys = keys; - pkey->listFetch_state = libssh2_NB_state_idle; - return 0; - } - - publickey_status_error(pkey, session, status); - goto err_exit; - } - case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY: - /* What we want */ - if (keys >= max_keys) { - libssh2_publickey_list *newlist; - /* Grow the key list if necessary */ - max_keys += 8; - newlist = - LIBSSH2_REALLOC(session, list, - (max_keys + - 1) * sizeof(libssh2_publickey_list)); - if (!newlist) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "publickey list"); - goto err_exit; - } - list = newlist; - } - if (pkey->version == 1) { - unsigned long comment_len; - - comment_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - if (comment_len) { - list[keys].num_attrs = 1; - list[keys].attrs = - LIBSSH2_ALLOC(session, - sizeof(libssh2_publickey_attribute)); - if (!list[keys].attrs) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "publickey attributes"); - goto err_exit; - } - list[keys].attrs[0].name = "comment"; - list[keys].attrs[0].name_len = sizeof("comment") - 1; - list[keys].attrs[0].value = (char *) pkey->listFetch_s; - list[keys].attrs[0].value_len = comment_len; - list[keys].attrs[0].mandatory = 0; - - pkey->listFetch_s += comment_len; - } else { - list[keys].num_attrs = 0; - list[keys].attrs = NULL; - } - list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].name = pkey->listFetch_s; - pkey->listFetch_s += list[keys].name_len; - list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].blob = pkey->listFetch_s; - pkey->listFetch_s += list[keys].blob_len; - } else { - /* Version == 2 */ - list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].name = pkey->listFetch_s; - pkey->listFetch_s += list[keys].name_len; - list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].blob = pkey->listFetch_s; - pkey->listFetch_s += list[keys].blob_len; - list[keys].num_attrs = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - if (list[keys].num_attrs) { - list[keys].attrs = - LIBSSH2_ALLOC(session, - list[keys].num_attrs * - sizeof(libssh2_publickey_attribute)); - if (!list[keys].attrs) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "publickey attributes"); - goto err_exit; - } - for(i = 0; i < list[keys].num_attrs; i++) { - list[keys].attrs[i].name_len = - _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].attrs[i].name = (char *) pkey->listFetch_s; - pkey->listFetch_s += list[keys].attrs[i].name_len; - list[keys].attrs[i].value_len = - _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].attrs[i].value = (char *) pkey->listFetch_s; - pkey->listFetch_s += list[keys].attrs[i].value_len; - - /* actually an ignored value */ - list[keys].attrs[i].mandatory = 0; - } - } else { - list[keys].attrs = NULL; - } - } - /* To be FREEd in libssh2_publickey_list_free() */ - list[keys].packet = pkey->listFetch_data; - keys++; - - list[keys].packet = NULL; /* Terminate the list */ - pkey->listFetch_data = NULL; - break; - default: - /* Unknown/Unexpected */ - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Unexpected publickey subsystem response"); - LIBSSH2_FREE(session, pkey->listFetch_data); - pkey->listFetch_data = NULL; - } - } - - /* Only reached via explicit goto */ - err_exit: - if (pkey->listFetch_data) { - LIBSSH2_FREE(session, pkey->listFetch_data); - pkey->listFetch_data = NULL; - } - if (list) { - libssh2_publickey_list_free(pkey, list); - } - pkey->listFetch_state = libssh2_NB_state_idle; - return -1; -} - -/* libssh2_publickey_list_free - * Free a previously fetched list of public keys - */ -LIBSSH2_API void -libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey, - libssh2_publickey_list * pkey_list) -{ - LIBSSH2_SESSION *session; - libssh2_publickey_list *p = pkey_list; - - if(!pkey || !p) - return; - - session = pkey->channel->session; - - while (p->packet) { - if (p->attrs) { - LIBSSH2_FREE(session, p->attrs); - } - LIBSSH2_FREE(session, p->packet); - p++; - } - - LIBSSH2_FREE(session, pkey_list); -} - -/* libssh2_publickey_shutdown - * Shutdown the publickey subsystem - */ -LIBSSH2_API int -libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey) -{ - LIBSSH2_SESSION *session; - int rc; - - if(!pkey) - return LIBSSH2_ERROR_BAD_USE; - - session = pkey->channel->session; - - /* - * Make sure all memory used in the state variables are free - */ - if (pkey->receive_packet) { - LIBSSH2_FREE(session, pkey->receive_packet); - pkey->receive_packet = NULL; - } - if (pkey->add_packet) { - LIBSSH2_FREE(session, pkey->add_packet); - pkey->add_packet = NULL; - } - if (pkey->remove_packet) { - LIBSSH2_FREE(session, pkey->remove_packet); - pkey->remove_packet = NULL; - } - if (pkey->listFetch_data) { - LIBSSH2_FREE(session, pkey->listFetch_data); - pkey->listFetch_data = NULL; - } - - rc = _libssh2_channel_free(pkey->channel); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - LIBSSH2_FREE(session, pkey); - return 0; -} diff --git a/vendor/libssh2-1.4.2/src/scp.c b/vendor/libssh2-1.4.2/src/scp.c deleted file mode 100644 index 6401dac..0000000 --- a/vendor/libssh2-1.4.2/src/scp.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2004-2008, Sara Golemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include -#include - -#include "channel.h" -#include "session.h" - - -/* Max. length of a quoted string after libssh2_shell_quotearg() processing */ -#define _libssh2_shell_quotedsize(s) (3 * strlen(s) + 2) - -/* - This function quotes a string in a way suitable to be used with a - shell, e.g. the file name - one two - becomes - 'one two' - - The resulting output string is crafted in a way that makes it usable - with the two most common shell types: Bourne Shell derived shells - (sh, ksh, ksh93, bash, zsh) and C-Shell derivates (csh, tcsh). - - The following special cases are handled: - o If the string contains an apostrophy itself, the apostrophy - character is written in quotation marks, e.g. "'". - The shell cannot handle the syntax 'doesn\'t', so we close the - current argument word, add the apostrophe in quotation marks "", - and open a new argument word instead (_ indicate the input - string characters): - _____ _ _ - 'doesn' "'" 't' - - Sequences of apostrophes are combined in one pair of quotation marks: - a'''b - becomes - _ ___ _ - 'a'"'''"'b' - - o If the string contains an exclamation mark (!), the C-Shell - interprets it as an event number. Using \! (not within quotation - marks or single quotation marks) is a mechanism understood by - both Bourne Shell and C-Shell. - - If a quotation was already started, the argument word is closed - first: - a!b - - become - _ _ _ - 'a'\!'b' - - The result buffer must be large enough for the expanded result. A - bad case regarding expansion is alternating characters and - apostrophes: - - a'b'c'd' (length 8) gets converted to - 'a'"'"'b'"'"'c'"'"'d'"'" (length 24) - - This is the worst case. - - Maximum length of the result: - 1 + 6 * (length(input) + 1) / 2) + 1 - - => 3 * length(input) + 2 - - Explanation: - o leading apostrophe - o one character / apostrophe pair (two characters) can get - represented as 6 characters: a' -> a'"'"' - o String terminator (+1) - - A result buffer three times the size of the input buffer + 2 - characters should be safe. - - References: - o csh-compatible quotation (special handling for '!' etc.), see - http://www.grymoire.com/Unix/Csh.html#toc-uh-10 - - Return value: - Length of the resulting string (not counting the terminating '\0'), - or 0 in case of errors, e.g. result buffer too small - - Note: this function could possible be used elsewhere within libssh2, but - until then it is kept static and in this source file. -*/ - -static unsigned -shell_quotearg(const char *path, unsigned char *buf, - unsigned bufsize) -{ - const char *src; - unsigned char *dst, *endp; - - /* - * Processing States: - * UQSTRING: unquoted string: ... -- used for quoting exclamation - * marks. This is the initial state - * SQSTRING: single-qouted-string: '... -- any character may follow - * QSTRING: quoted string: "... -- only apostrophes may follow - */ - enum { UQSTRING, SQSTRING, QSTRING } state = UQSTRING; - - endp = &buf[bufsize]; - src = path; - dst = buf; - while (*src && dst < endp - 1) { - - switch (*src) { - /* - * Special handling for apostrophe. - * An apostrophe is always written in quotation marks, e.g. - * ' -> "'". - */ - - case '\'': - switch (state) { - case UQSTRING: /* Unquoted string */ - if (dst+1 >= endp) - return 0; - *dst++ = '"'; - break; - case QSTRING: /* Continue quoted string */ - break; - case SQSTRING: /* Close single quoted string */ - if (dst+2 >= endp) - return 0; - *dst++ = '\''; - *dst++ = '"'; - break; - default: - break; - } - state = QSTRING; - break; - - /* - * Special handling for exclamation marks. CSH interprets - * exclamation marks even when quoted with apostrophes. We convert - * it to the plain string \!, because both Bourne Shell and CSH - * interpret that as a verbatim exclamation mark. - */ - - case '!': - switch (state) { - case UQSTRING: - if (dst+1 >= endp) - return 0; - *dst++ = '\\'; - break; - case QSTRING: - if (dst+2 >= endp) - return 0; - *dst++ = '"'; /* Closing quotation mark */ - *dst++ = '\\'; - break; - case SQSTRING: /* Close single quoted string */ - if (dst+2 >= endp) - return 0; - *dst++ = '\''; - *dst++ = '\\'; - break; - default: - break; - } - state = UQSTRING; - break; - - /* - * Ordinary character: prefer single-quoted string - */ - - default: - switch (state) { - case UQSTRING: - if (dst+1 >= endp) - return 0; - *dst++ = '\''; - break; - case QSTRING: - if (dst+2 >= endp) - return 0; - *dst++ = '"'; /* Closing quotation mark */ - *dst++ = '\''; - break; - case SQSTRING: /* Continue single quoted string */ - break; - default: - break; - } - state = SQSTRING; /* Start single-quoted string */ - break; - } - - if (dst+1 >= endp) - return 0; - *dst++ = *src++; - } - - switch (state) { - case UQSTRING: - break; - case QSTRING: /* Close quoted string */ - if (dst+1 >= endp) - return 0; - *dst++ = '"'; - break; - case SQSTRING: /* Close single quoted string */ - if (dst+1 >= endp) - return 0; - *dst++ = '\''; - break; - default: - break; - } - - if (dst+1 >= endp) - return 0; - *dst = '\0'; - - /* The result cannot be larger than 3 * strlen(path) + 2 */ - /* assert((dst - buf) <= (3 * (src - path) + 2)); */ - - return dst - buf; -} - -/* - * scp_recv - * - * Open a channel and request a remote file via SCP - * - */ -static LIBSSH2_CHANNEL * -scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) -{ - int cmd_len; - int rc; - int tmp_err_code; - const char *tmp_err_msg; - - if (session->scpRecv_state == libssh2_NB_state_idle) { - session->scpRecv_mode = 0; - session->scpRecv_size = 0; - session->scpRecv_mtime = 0; - session->scpRecv_atime = 0; - - session->scpRecv_command_len = - _libssh2_shell_quotedsize(path) + sizeof("scp -f ") + (sb?1:0); - - session->scpRecv_command = - LIBSSH2_ALLOC(session, session->scpRecv_command_len); - - if (!session->scpRecv_command) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate a command buffer for " - "SCP session"); - return NULL; - } - - snprintf((char *)session->scpRecv_command, - session->scpRecv_command_len, "scp -%sf ", sb?"p":""); - - cmd_len = strlen((char *)session->scpRecv_command); - - (void) shell_quotearg(path, - &session->scpRecv_command[cmd_len], - session->scpRecv_command_len - cmd_len); - - - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "Opening channel for SCP receive"); - - session->scpRecv_state = libssh2_NB_state_created; - } - - if (session->scpRecv_state == libssh2_NB_state_created) { - /* Allocate a channel */ - session->scpRecv_channel = - _libssh2_channel_open(session, "session", - sizeof("session") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, - 0); - if (!session->scpRecv_channel) { - if (libssh2_session_last_errno(session) != - LIBSSH2_ERROR_EAGAIN) { - LIBSSH2_FREE(session, session->scpRecv_command); - session->scpRecv_command = NULL; - session->scpRecv_state = libssh2_NB_state_idle; - } - else { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting up channel"); - } - return NULL; - } - - session->scpRecv_state = libssh2_NB_state_sent; - } - - if (session->scpRecv_state == libssh2_NB_state_sent) { - /* Request SCP for the desired file */ - rc = _libssh2_channel_process_startup(session->scpRecv_channel, "exec", - sizeof("exec") - 1, - (char *) session->scpRecv_command, - session->scpRecv_command_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting SCP startup"); - return NULL; - } else if (rc) { - LIBSSH2_FREE(session, session->scpRecv_command); - session->scpRecv_command = NULL; - goto scp_recv_error; - } - LIBSSH2_FREE(session, session->scpRecv_command); - session->scpRecv_command = NULL; - - _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sending initial wakeup"); - /* SCP ACK */ - session->scpRecv_response[0] = '\0'; - - session->scpRecv_state = libssh2_NB_state_sent1; - } - - if (session->scpRecv_state == libssh2_NB_state_sent1) { - rc = _libssh2_channel_write(session->scpRecv_channel, 0, - session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending initial wakeup"); - return NULL; - } else if (rc != 1) { - goto scp_recv_error; - } - - /* Parse SCP response */ - session->scpRecv_response_len = 0; - - session->scpRecv_state = libssh2_NB_state_sent2; - } - - if ((session->scpRecv_state == libssh2_NB_state_sent2) - || (session->scpRecv_state == libssh2_NB_state_sent3)) { - while (sb && (session->scpRecv_response_len < - LIBSSH2_SCP_RESPONSE_BUFLEN)) { - unsigned char *s, *p; - - if (session->scpRecv_state == libssh2_NB_state_sent2) { - rc = _libssh2_channel_read(session->scpRecv_channel, 0, - (char *) session-> - scpRecv_response + - session->scpRecv_response_len, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for SCP response"); - return NULL; - } - else if (rc < 0) { - /* error, give up */ - _libssh2_error(session, rc, "Failed reading SCP response"); - goto scp_recv_error; - } - else if(rc == 0) - goto scp_recv_empty_channel; - - session->scpRecv_response_len++; - - if (session->scpRecv_response[0] != 'T') { - size_t err_len; - char *err_msg; - - /* there can be - 01 for warnings - 02 for errors - - The following string MUST be newline terminated - */ - err_len = - _libssh2_channel_packet_data_len(session-> - scpRecv_channel, 0); - err_msg = LIBSSH2_ALLOC(session, err_len + 1); - if (!err_msg) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Failed to get memory "); - goto scp_recv_error; - } - - /* Read the remote error message */ - (void)_libssh2_channel_read(session->scpRecv_channel, 0, - err_msg, err_len); - /* If it failed for any reason, we ignore it anyway. */ - - /* zero terminate the error */ - err_msg[err_len]=0; - - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "got %02x %s", session->scpRecv_response[0], - err_msg); - - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Failed to recv file"); - - LIBSSH2_FREE(session, err_msg); - goto scp_recv_error; - } - - if ((session->scpRecv_response_len > 1) && - ((session-> - scpRecv_response[session->scpRecv_response_len - 1] < - '0') - || (session-> - scpRecv_response[session->scpRecv_response_len - 1] > - '9')) - && (session-> - scpRecv_response[session->scpRecv_response_len - 1] != - ' ') - && (session-> - scpRecv_response[session->scpRecv_response_len - 1] != - '\r') - && (session-> - scpRecv_response[session->scpRecv_response_len - 1] != - '\n')) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid data in SCP response"); - goto scp_recv_error; - } - - if ((session->scpRecv_response_len < 9) - || (session-> - scpRecv_response[session->scpRecv_response_len - 1] != - '\n')) { - if (session->scpRecv_response_len == - LIBSSH2_SCP_RESPONSE_BUFLEN) { - /* You had your chance */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unterminated response from SCP server"); - goto scp_recv_error; - } - /* Way too short to be an SCP response, or not done yet, - short circuit */ - continue; - } - - /* We're guaranteed not to go under response_len == 0 by the - logic above */ - while ((session-> - scpRecv_response[session->scpRecv_response_len - 1] == - '\r') - || (session-> - scpRecv_response[session->scpRecv_response_len - - 1] == '\n')) - session->scpRecv_response_len--; - session->scpRecv_response[session->scpRecv_response_len] = - '\0'; - - if (session->scpRecv_response_len < 8) { - /* EOL came too soon */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, " - "too short" ); - goto scp_recv_error; - } - - s = session->scpRecv_response + 1; - - p = (unsigned char *) strchr((char *) s, ' '); - if (!p || ((p - s) <= 0)) { - /* No spaces or space in the wrong spot */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, " - "malformed mtime"); - goto scp_recv_error; - } - - *(p++) = '\0'; - /* Make sure we don't get fooled by leftover values */ - session->scpRecv_mtime = strtol((char *) s, NULL, 10); - - s = (unsigned char *) strchr((char *) p, ' '); - if (!s || ((s - p) <= 0)) { - /* No spaces or space in the wrong spot */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, malformed mtime.usec"); - goto scp_recv_error; - } - - /* Ignore mtime.usec */ - s++; - p = (unsigned char *) strchr((char *) s, ' '); - if (!p || ((p - s) <= 0)) { - /* No spaces or space in the wrong spot */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, too short or malformed"); - goto scp_recv_error; - } - - *p = '\0'; - /* Make sure we don't get fooled by leftover values */ - session->scpRecv_atime = strtol((char *) s, NULL, 10); - - /* SCP ACK */ - session->scpRecv_response[0] = '\0'; - - session->scpRecv_state = libssh2_NB_state_sent3; - } - - if (session->scpRecv_state == libssh2_NB_state_sent3) { - rc = _libssh2_channel_write(session->scpRecv_channel, 0, - session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting to send SCP ACK"); - return NULL; - } else if (rc != 1) { - goto scp_recv_error; - } - - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "mtime = %ld, atime = %ld", - session->scpRecv_mtime, session->scpRecv_atime); - - /* We *should* check that atime.usec is valid, but why let - that stop use? */ - break; - } - } - - session->scpRecv_state = libssh2_NB_state_sent4; - } - - if (session->scpRecv_state == libssh2_NB_state_sent4) { - session->scpRecv_response_len = 0; - - session->scpRecv_state = libssh2_NB_state_sent5; - } - - if ((session->scpRecv_state == libssh2_NB_state_sent5) - || (session->scpRecv_state == libssh2_NB_state_sent6)) { - while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) { - char *s, *p, *e = NULL; - - if (session->scpRecv_state == libssh2_NB_state_sent5) { - rc = _libssh2_channel_read(session->scpRecv_channel, 0, - (char *) session-> - scpRecv_response + - session->scpRecv_response_len, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for SCP response"); - return NULL; - } - else if (rc < 0) { - /* error, bail out*/ - _libssh2_error(session, rc, "Failed reading SCP response"); - goto scp_recv_error; - } - else if(rc == 0) - goto scp_recv_empty_channel; - - session->scpRecv_response_len++; - - if (session->scpRecv_response[0] != 'C') { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server"); - goto scp_recv_error; - } - - if ((session->scpRecv_response_len > 1) && - (session-> - scpRecv_response[session->scpRecv_response_len - 1] != - '\r') - && (session-> - scpRecv_response[session->scpRecv_response_len - 1] != - '\n') - && - (session-> - scpRecv_response[session->scpRecv_response_len - 1] - < 32)) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid data in SCP response"); - goto scp_recv_error; - } - - if ((session->scpRecv_response_len < 7) - || (session-> - scpRecv_response[session->scpRecv_response_len - 1] != - '\n')) { - if (session->scpRecv_response_len == - LIBSSH2_SCP_RESPONSE_BUFLEN) { - /* You had your chance */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unterminated response from SCP server"); - goto scp_recv_error; - } - /* Way too short to be an SCP response, or not done yet, - short circuit */ - continue; - } - - /* We're guaranteed not to go under response_len == 0 by the - logic above */ - while ((session-> - scpRecv_response[session->scpRecv_response_len - 1] == - '\r') - || (session-> - scpRecv_response[session->scpRecv_response_len - - 1] == '\n')) { - session->scpRecv_response_len--; - } - session->scpRecv_response[session->scpRecv_response_len] = - '\0'; - - if (session->scpRecv_response_len < 6) { - /* EOL came too soon */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, too short"); - goto scp_recv_error; - } - - s = (char *) session->scpRecv_response + 1; - - p = strchr(s, ' '); - if (!p || ((p - s) <= 0)) { - /* No spaces or space in the wrong spot */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, malformed mode"); - goto scp_recv_error; - } - - *(p++) = '\0'; - /* Make sure we don't get fooled by leftover values */ - - session->scpRecv_mode = strtol(s, &e, 8); - if (e && *e) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, invalid mode"); - goto scp_recv_error; - } - - s = strchr(p, ' '); - if (!s || ((s - p) <= 0)) { - /* No spaces or space in the wrong spot */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, too short or malformed"); - goto scp_recv_error; - } - - *s = '\0'; - /* Make sure we don't get fooled by leftover values */ - session->scpRecv_size = scpsize_strtol(p, &e, 10); - if (e && *e) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, invalid size"); - goto scp_recv_error; - } - - /* SCP ACK */ - session->scpRecv_response[0] = '\0'; - - session->scpRecv_state = libssh2_NB_state_sent6; - } - - if (session->scpRecv_state == libssh2_NB_state_sent6) { - rc = _libssh2_channel_write(session->scpRecv_channel, 0, - session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending SCP ACK"); - return NULL; - } else if (rc != 1) { - goto scp_recv_error; - } - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "mode = 0%lo size = %ld", session->scpRecv_mode, - session->scpRecv_size); - - /* We *should* check that basename is valid, but why let that - stop us? */ - break; - } - } - - session->scpRecv_state = libssh2_NB_state_sent7; - } - - if (sb) { - memset(sb, 0, sizeof(struct stat)); - - sb->st_mtime = session->scpRecv_mtime; - sb->st_atime = session->scpRecv_atime; - sb->st_size = session->scpRecv_size; - sb->st_mode = session->scpRecv_mode; - } - - session->scpRecv_state = libssh2_NB_state_idle; - return session->scpRecv_channel; - - scp_recv_empty_channel: - /* the code only jumps here as a result of a zero read from channel_read() - so we check EOF status to avoid getting stuck in a loop */ - if(libssh2_channel_eof(session->scpRecv_channel)) - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unexpected channel close"); - else - return session->scpRecv_channel; - /* fall-through */ - scp_recv_error: - tmp_err_code = session->err_code; - tmp_err_msg = session->err_msg; - while (libssh2_channel_free(session->scpRecv_channel) == - LIBSSH2_ERROR_EAGAIN); - session->err_code = tmp_err_code; - session->err_msg = tmp_err_msg; - session->scpRecv_channel = NULL; - session->scpRecv_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_scp_recv - * - * Open a channel and request a remote file via SCP - * - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb) -{ - LIBSSH2_CHANNEL *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb)); - return ptr; -} - -/* - * scp_send() - * - * Send a file using SCP - * - */ -static LIBSSH2_CHANNEL * -scp_send(LIBSSH2_SESSION * session, const char *path, int mode, - libssh2_int64_t size, time_t mtime, time_t atime) -{ - int cmd_len; - int rc; - int tmp_err_code; - const char *tmp_err_msg; - - if (session->scpSend_state == libssh2_NB_state_idle) { - session->scpSend_command_len = - _libssh2_shell_quotedsize(path) + sizeof("scp -t ") + - ((mtime || atime)?1:0); - - session->scpSend_command = - LIBSSH2_ALLOC(session, session->scpSend_command_len); - if (!session->scpSend_command) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate a command buffer for scp session"); - return NULL; - } - - snprintf((char *)session->scpSend_command, session->scpSend_command_len, - "scp -%st ", (mtime || atime)?"p":""); - - cmd_len = strlen((char *)session->scpSend_command); - - (void)shell_quotearg(path, - &session->scpSend_command[cmd_len], - session->scpSend_command_len - cmd_len); - - session->scpSend_command[session->scpSend_command_len - 1] = '\0'; - - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "Opening channel for SCP send"); - /* Allocate a channel */ - - session->scpSend_state = libssh2_NB_state_created; - } - - if (session->scpSend_state == libssh2_NB_state_created) { - session->scpSend_channel = - _libssh2_channel_open(session, "session", sizeof("session") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); - if (!session->scpSend_channel) { - if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { - /* previous call set libssh2_session_last_error(), pass it - through */ - LIBSSH2_FREE(session, session->scpSend_command); - session->scpSend_command = NULL; - session->scpSend_state = libssh2_NB_state_idle; - } - else { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting up channel"); - } - return NULL; - } - - session->scpSend_state = libssh2_NB_state_sent; - } - - if (session->scpSend_state == libssh2_NB_state_sent) { - /* Request SCP for the desired file */ - rc = _libssh2_channel_process_startup(session->scpSend_channel, "exec", - sizeof("exec") - 1, - (char *) session->scpSend_command, - session->scpSend_command_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting SCP startup"); - return NULL; - } - else if (rc) { - /* previous call set libssh2_session_last_error(), pass it - through */ - LIBSSH2_FREE(session, session->scpSend_command); - session->scpSend_command = NULL; - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unknown error while getting error string"); - goto scp_send_error; - } - LIBSSH2_FREE(session, session->scpSend_command); - session->scpSend_command = NULL; - - session->scpSend_state = libssh2_NB_state_sent1; - } - - if (session->scpSend_state == libssh2_NB_state_sent1) { - /* Wait for ACK */ - rc = _libssh2_channel_read(session->scpSend_channel, 0, - (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response from remote"); - return NULL; - } - else if (rc < 0) { - _libssh2_error(session, rc, "SCP failure"); - goto scp_send_error; - } - else if(!rc) - /* remain in the same state */ - goto scp_send_empty_channel; - else if (session->scpSend_response[0] != 0) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid ACK response from remote"); - goto scp_send_error; - } - if (mtime || atime) { - /* Send mtime and atime to be used for file */ - session->scpSend_response_len = - snprintf((char *) session->scpSend_response, - LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", - (long)mtime, (long)atime); - _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s", - session->scpSend_response); - } - - session->scpSend_state = libssh2_NB_state_sent2; - } - - /* Send mtime and atime to be used for file */ - if (mtime || atime) { - if (session->scpSend_state == libssh2_NB_state_sent2) { - rc = _libssh2_channel_write(session->scpSend_channel, 0, - session->scpSend_response, - session->scpSend_response_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending time data for SCP file"); - return NULL; - } else if (rc != (int)session->scpSend_response_len) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send time data for SCP file"); - goto scp_send_error; - } - - session->scpSend_state = libssh2_NB_state_sent3; - } - - if (session->scpSend_state == libssh2_NB_state_sent3) { - /* Wait for ACK */ - rc = _libssh2_channel_read(session->scpSend_channel, 0, - (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response"); - return NULL; - } - else if (rc < 0) { - _libssh2_error(session, rc, "SCP failure"); - goto scp_send_error; - } - else if(!rc) - /* remain in the same state */ - goto scp_send_empty_channel; - else if (session->scpSend_response[0] != 0) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid SCP ACK response"); - goto scp_send_error; - } - - session->scpSend_state = libssh2_NB_state_sent4; - } - } else { - if (session->scpSend_state == libssh2_NB_state_sent2) { - session->scpSend_state = libssh2_NB_state_sent4; - } - } - - if (session->scpSend_state == libssh2_NB_state_sent4) { - /* Send mode, size, and basename */ - const char *base = strrchr(path, '/'); - if (base) - base++; - else - base = path; - - session->scpSend_response_len = - snprintf((char *) session->scpSend_response, - LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %" - LIBSSH2_INT64_T_FORMAT "u %s\n", mode, - size, base); - _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s", - session->scpSend_response); - - session->scpSend_state = libssh2_NB_state_sent5; - } - - if (session->scpSend_state == libssh2_NB_state_sent5) { - rc = _libssh2_channel_write(session->scpSend_channel, 0, - session->scpSend_response, - session->scpSend_response_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block send core file data for SCP file"); - return NULL; - } else if (rc != (int)session->scpSend_response_len) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send core file data for SCP file"); - goto scp_send_error; - } - - session->scpSend_state = libssh2_NB_state_sent6; - } - - if (session->scpSend_state == libssh2_NB_state_sent6) { - /* Wait for ACK */ - rc = _libssh2_channel_read(session->scpSend_channel, 0, - (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response"); - return NULL; - } - else if (rc < 0) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid ACK response from remote"); - goto scp_send_error; - } - else if (rc == 0) - goto scp_send_empty_channel; - - else if (session->scpSend_response[0] != 0) { - size_t err_len; - char *err_msg; - - err_len = - _libssh2_channel_packet_data_len(session->scpSend_channel, 0); - err_msg = LIBSSH2_ALLOC(session, err_len + 1); - if (!err_msg) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "failed to get memory"); - goto scp_send_error; - } - - /* Read the remote error message */ - rc = _libssh2_channel_read(session->scpSend_channel, 0, - err_msg, err_len); - if (rc > 0) { - err_msg[err_len]=0; - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "got %02x %s", session->scpSend_response[0], - err_msg); - } - LIBSSH2_FREE(session, err_msg); - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "failed to send file"); - goto scp_send_error; - } - } - - session->scpSend_state = libssh2_NB_state_idle; - return session->scpSend_channel; - - scp_send_empty_channel: - /* the code only jumps here as a result of a zero read from channel_read() - so we check EOF status to avoid getting stuck in a loop */ - if(libssh2_channel_eof(session->scpSend_channel)) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unexpected channel close"); - } - else - return session->scpSend_channel; - /* fall-through */ - scp_send_error: - tmp_err_code = session->err_code; - tmp_err_msg = session->err_msg; - while (libssh2_channel_free(session->scpSend_channel) == - LIBSSH2_ERROR_EAGAIN); - session->err_code = tmp_err_code; - session->err_msg = tmp_err_msg; - session->scpSend_channel = NULL; - session->scpSend_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_scp_send_ex - * - * Send a file using SCP. Old API. - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, - size_t size, long mtime, long atime) -{ - LIBSSH2_CHANNEL *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, - scp_send(session, path, mode, size, - (time_t)mtime, (time_t)atime)); - return ptr; -} - -/* - * libssh2_scp_send64 - * - * Send a file using SCP - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode, - libssh2_int64_t size, time_t mtime, time_t atime) -{ - LIBSSH2_CHANNEL *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, - scp_send(session, path, mode, size, mtime, atime)); - return ptr; -} diff --git a/vendor/libssh2-1.4.2/src/session.c b/vendor/libssh2-1.4.2/src/session.c deleted file mode 100644 index 77ab9bc..0000000 --- a/vendor/libssh2-1.4.2/src/session.c +++ /dev/null @@ -1,1751 +0,0 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2011 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include - -#ifdef HAVE_GETTIMEOFDAY -#include -#endif -#ifdef HAVE_ALLOCA_H -#include -#endif - -#include "transport.h" -#include "session.h" -#include "channel.h" -#include "mac.h" -#include "misc.h" - -/* libssh2_default_alloc - */ -static -LIBSSH2_ALLOC_FUNC(libssh2_default_alloc) -{ - (void) abstract; - return malloc(count); -} - -/* libssh2_default_free - */ -static -LIBSSH2_FREE_FUNC(libssh2_default_free) -{ - (void) abstract; - free(ptr); -} - -/* libssh2_default_realloc - */ -static -LIBSSH2_REALLOC_FUNC(libssh2_default_realloc) -{ - (void) abstract; - return realloc(ptr, count); -} - -/* - * banner_receive - * - * Wait for a hello from the remote host - * Allocate a buffer and store the banner in session->remote.banner - * Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative - * on failure - */ -static int -banner_receive(LIBSSH2_SESSION * session) -{ - int ret; - int banner_len; - - if (session->banner_TxRx_state == libssh2_NB_state_idle) { - banner_len = 0; - - session->banner_TxRx_state = libssh2_NB_state_created; - } else { - banner_len = session->banner_TxRx_total_send; - } - - while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) && - ((banner_len == 0) - || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) { - char c = '\0'; - - /* no incoming block yet! */ - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; - - ret = LIBSSH2_RECV(session, &c, 1, - LIBSSH2_SOCKET_RECV_FLAGS(session)); - if (ret < 0) { - if(session->api_block_mode || (ret != -EAGAIN)) - /* ignore EAGAIN when non-blocking */ - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes: %d", 1, -ret); - } - else - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Recved %d bytes banner", ret); - - if (ret < 0) { - if (ret == -EAGAIN) { - session->socket_block_directions = - LIBSSH2_SESSION_BLOCK_INBOUND; - session->banner_TxRx_total_send = banner_len; - return LIBSSH2_ERROR_EAGAIN; - } - - /* Some kinda error */ - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - return LIBSSH2_ERROR_SOCKET_RECV; - } - - if (ret == 0) { - session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; - return LIBSSH2_ERROR_SOCKET_DISCONNECT; - } - - if (c == '\0') { - /* NULLs are not allowed in SSH banners */ - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - return LIBSSH2_ERROR_BANNER_RECV; - } - - session->banner_TxRx_banner[banner_len++] = c; - } - - while (banner_len && - ((session->banner_TxRx_banner[banner_len - 1] == '\n') || - (session->banner_TxRx_banner[banner_len - 1] == '\r'))) { - banner_len--; - } - - /* From this point on, we are done here */ - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - - if (!banner_len) - return LIBSSH2_ERROR_BANNER_RECV; - - session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1); - if (!session->remote.banner) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Error allocating space for remote banner"); - } - memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len); - session->remote.banner[banner_len] = '\0'; - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s", - session->remote.banner); - return LIBSSH2_ERROR_NONE; -} - -/* - * banner_send - * - * Send the default banner, or the one set via libssh2_setopt_string - * - * Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you - * should call this function again as soon as it is likely that more data can - * be sent, and this function should then be called with the same argument set - * (same data pointer and same data_len) until zero or failure is returned. - */ -static int -banner_send(LIBSSH2_SESSION * session) -{ - char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF; - int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1; - ssize_t ret; -#ifdef LIBSSH2DEBUG - char banner_dup[256]; -#endif - - if (session->banner_TxRx_state == libssh2_NB_state_idle) { - if (session->local.banner) { - /* setopt_string will have given us our \r\n characters */ - banner_len = strlen((char *) session->local.banner); - banner = (char *) session->local.banner; - } -#ifdef LIBSSH2DEBUG - /* Hack and slash to avoid sending CRLF in debug output */ - if (banner_len < 256) { - memcpy(banner_dup, banner, banner_len - 2); - banner_dup[banner_len - 2] = '\0'; - } else { - memcpy(banner_dup, banner, 255); - banner[255] = '\0'; - } - - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s", - banner_dup); -#endif - - session->banner_TxRx_state = libssh2_NB_state_created; - } - - /* no outgoing block yet! */ - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; - - ret = LIBSSH2_SEND(session, - banner + session->banner_TxRx_total_send, - banner_len - session->banner_TxRx_total_send, - LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (ret < 0) - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", - banner_len - session->banner_TxRx_total_send, -ret); - else - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p+%d", ret, - banner_len - session->banner_TxRx_total_send, - banner, session->banner_TxRx_total_send); - - if (ret != (banner_len - session->banner_TxRx_total_send)) { - if (ret >= 0 || ret == -EAGAIN) { - /* the whole packet could not be sent, save the what was */ - session->socket_block_directions = - LIBSSH2_SESSION_BLOCK_OUTBOUND; - if (ret > 0) - session->banner_TxRx_total_send += ret; - return LIBSSH2_ERROR_EAGAIN; - } - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - return LIBSSH2_ERROR_SOCKET_RECV; - } - - /* Set the state back to idle */ - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - - return 0; -} - -/* - * session_nonblock() sets the given socket to either blocking or - * non-blocking mode based on the 'nonblock' boolean argument. This function - * is copied from the libcurl sources with permission. - */ -static int -session_nonblock(libssh2_socket_t sockfd, /* operate on this */ - int nonblock /* TRUE or FALSE */ ) -{ -#undef SETBLOCK -#define SETBLOCK 0 -#ifdef HAVE_O_NONBLOCK - /* most recent unix versions */ - int flags; - - flags = fcntl(sockfd, F_GETFL, 0); - if (nonblock) - return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); - else - return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); -#undef SETBLOCK -#define SETBLOCK 1 -#endif - -#if defined(HAVE_FIONBIO) && (SETBLOCK == 0) - /* older unix versions and VMS*/ - int flags; - - flags = nonblock; - return ioctl(sockfd, FIONBIO, &flags); -#undef SETBLOCK -#define SETBLOCK 2 -#endif - -#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0) - /* Windows? */ - unsigned long flags; - flags = nonblock; - - return ioctlsocket(sockfd, FIONBIO, &flags); -#undef SETBLOCK -#define SETBLOCK 3 -#endif - -#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0) - /* presumably for Amiga */ - return IoctlSocket(sockfd, FIONBIO, (long) nonblock); -#undef SETBLOCK -#define SETBLOCK 4 -#endif - -#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0) - /* BeOS */ - long b = nonblock ? 1 : 0; - return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); -#undef SETBLOCK -#define SETBLOCK 5 -#endif - -#ifdef HAVE_DISABLED_NONBLOCKING - return 0; /* returns success */ -#undef SETBLOCK -#define SETBLOCK 6 -#endif - -#if (SETBLOCK == 0) -#error "no non-blocking method was found/used/set" -#endif -} - -/* - * get_socket_nonblocking() - * - * gets the given blocking or non-blocking state of the socket. - */ -static int -get_socket_nonblocking(int sockfd) -{ /* operate on this */ -#undef GETBLOCK -#define GETBLOCK 0 -#ifdef HAVE_O_NONBLOCK - /* most recent unix versions */ - int flags; - - if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) { - /* Assume blocking on error */ - return 1; - } - return (flags & O_NONBLOCK); -#undef GETBLOCK -#define GETBLOCK 1 -#endif - -#if defined(WSAEWOULDBLOCK) && (GETBLOCK == 0) - /* Windows? */ - unsigned int option_value; - socklen_t option_len = sizeof(option_value); - - if (getsockopt - (sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) { - /* Assume blocking on error */ - return 1; - } - return (int) option_value; -#undef GETBLOCK -#define GETBLOCK 2 -#endif - -#if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0) - /* BeOS */ - long b; - if (getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) { - /* Assume blocking on error */ - return 1; - } - return (int) b; -#undef GETBLOCK -#define GETBLOCK 5 -#endif - -#if defined(SO_STATE) && defined( __VMS ) && (GETBLOCK == 0) - - /* VMS TCP/IP Services */ - - size_t sockstat = 0; - int callstat = 0; - size_t size = sizeof( int ); - - callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE, - (char *)&sockstat, &size); - if ( callstat == -1 ) return(0); - if ( (sockstat&SS_NBIO) )return(1); - return(0); - -#undef GETBLOCK -#define GETBLOCK 6 -#endif - -#ifdef HAVE_DISABLED_NONBLOCKING - return 1; /* returns blocking */ -#undef GETBLOCK -#define GETBLOCK 7 -#endif - -#if (GETBLOCK == 0) -#error "no non-blocking method was found/used/get" -#endif -} - -/* libssh2_session_banner_set - * Set the local banner to use in the server handshake. - */ -LIBSSH2_API int -libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner) -{ - size_t banner_len = banner ? strlen(banner) : 0; - - if (session->local.banner) { - LIBSSH2_FREE(session, session->local.banner); - session->local.banner = NULL; - } - - if (!banner_len) - return 0; - - session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3); - if (!session->local.banner) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for local banner"); - } - - memcpy(session->local.banner, banner, banner_len); - - /* first zero terminate like this so that the debug output is nice */ - session->local.banner[banner_len] = '\0'; - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s", - session->local.banner); - session->local.banner[banner_len++] = '\r'; - session->local.banner[banner_len++] = '\n'; - session->local.banner[banner_len] = '\0'; - - return 0; -} - -/* libssh2_banner_set - * Set the local banner. DEPRECATED VERSION - */ -LIBSSH2_API int -libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner) -{ - return libssh2_session_banner_set(session, banner); -} - -/* - * libssh2_session_init_ex - * - * Allocate and initialize a libssh2 session structure. Allows for malloc - * callbacks in case the calling program has its own memory manager It's - * allowable (but unadvisable) to define some but not all of the malloc - * callbacks An additional pointer value may be optionally passed to be sent - * to the callbacks (so they know who's asking) - */ -LIBSSH2_API LIBSSH2_SESSION * -libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), - LIBSSH2_FREE_FUNC((*my_free)), - LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract) -{ - LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc; - LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free; - LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc; - LIBSSH2_SESSION *session; - - if (my_alloc) { - local_alloc = my_alloc; - } - if (my_free) { - local_free = my_free; - } - if (my_realloc) { - local_realloc = my_realloc; - } - - session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract); - if (session) { - memset(session, 0, sizeof(LIBSSH2_SESSION)); - session->alloc = local_alloc; - session->free = local_free; - session->realloc = local_realloc; - session->send = _libssh2_send; - session->recv = _libssh2_recv; - session->abstract = abstract; - session->api_timeout = 0; /* timeout-free API by default */ - session->api_block_mode = 1; /* blocking API by default */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "New session resource allocated"); - _libssh2_init_if_needed (); - } - return session; -} - -/* - * libssh2_session_callback_set - * - * Set (or reset) a callback function - * Returns the prior address - * - * FIXME: this function relies on that we can typecast function pointers - * to void pointers, which isn't allowed in ISO C! - */ -LIBSSH2_API void * -libssh2_session_callback_set(LIBSSH2_SESSION * session, - int cbtype, void *callback) -{ - void *oldcb; - - switch (cbtype) { - case LIBSSH2_CALLBACK_IGNORE: - oldcb = session->ssh_msg_ignore; - session->ssh_msg_ignore = callback; - return oldcb; - - case LIBSSH2_CALLBACK_DEBUG: - oldcb = session->ssh_msg_debug; - session->ssh_msg_debug = callback; - return oldcb; - - case LIBSSH2_CALLBACK_DISCONNECT: - oldcb = session->ssh_msg_disconnect; - session->ssh_msg_disconnect = callback; - return oldcb; - - case LIBSSH2_CALLBACK_MACERROR: - oldcb = session->macerror; - session->macerror = callback; - return oldcb; - - case LIBSSH2_CALLBACK_X11: - oldcb = session->x11; - session->x11 = callback; - return oldcb; - - case LIBSSH2_CALLBACK_SEND: - oldcb = session->send; - session->send = callback; - return oldcb; - - case LIBSSH2_CALLBACK_RECV: - oldcb = session->recv; - session->recv = callback; - return oldcb; - } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype); - - return NULL; -} - -/* - * _libssh2_wait_socket() - * - * Utility function that waits for action on the socket. Returns 0 when ready - * to run again or error on timeout. - */ -int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) -{ - int rc; - int seconds_to_next; - int dir; - int has_timeout; - long ms_to_next = 0; - long elapsed_ms; - - /* since libssh2 often sets EAGAIN internally before this function is - called, we can decrease some amount of confusion in user programs by - resetting the error code in this function to reduce the risk of EAGAIN - being stored as error when a blocking function has returned */ - session->err_code = LIBSSH2_ERROR_NONE; - - rc = libssh2_keepalive_send (session, &seconds_to_next); - if (rc < 0) - return rc; - - ms_to_next = seconds_to_next * 1000; - - /* figure out what to wait for */ - dir = libssh2_session_block_directions(session); - - if(!dir) { - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Nothing to wait for in wait_socket"); - /* To avoid that we hang below just because there's nothing set to - wait for, we timeout on 1 second to also avoid busy-looping - during this condition */ - ms_to_next = 1000; - } - - if (session->api_timeout > 0 && - (seconds_to_next == 0 || - seconds_to_next > session->api_timeout)) { - time_t now = time (NULL); - elapsed_ms = (long)(1000*difftime(start_time, now)); - if (elapsed_ms > session->api_timeout) { - session->err_code = LIBSSH2_ERROR_TIMEOUT; - return LIBSSH2_ERROR_TIMEOUT; - } - ms_to_next = (session->api_timeout - elapsed_ms); - has_timeout = 1; - } - else if (ms_to_next > 0) { - has_timeout = 1; - } - else - has_timeout = 0; - -#ifdef HAVE_POLL - { - struct pollfd sockets[1]; - - sockets[0].fd = session->socket_fd; - sockets[0].events = 0; - sockets[0].revents = 0; - - if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) - sockets[0].events |= POLLIN; - - if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) - sockets[0].events |= POLLOUT; - - rc = poll(sockets, 1, has_timeout?ms_to_next: -1); - } -#else - { - fd_set rfd; - fd_set wfd; - fd_set *writefd = NULL; - fd_set *readfd = NULL; - struct timeval tv; - - tv.tv_sec = ms_to_next / 1000; - tv.tv_usec = (ms_to_next - tv.tv_sec*1000) * 1000; - - if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) { - FD_ZERO(&rfd); - FD_SET(session->socket_fd, &rfd); - readfd = &rfd; - } - - if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) { - FD_ZERO(&wfd); - FD_SET(session->socket_fd, &wfd); - writefd = &wfd; - } - - rc = select(session->socket_fd + 1, readfd, writefd, NULL, - has_timeout ? &tv : NULL); - } -#endif - if(rc <= 0) { - /* timeout (or error), bail out with a timeout error */ - session->err_code = LIBSSH2_ERROR_TIMEOUT; - return LIBSSH2_ERROR_TIMEOUT; - } - - return 0; /* ready to try again */ -} - -static int -session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) -{ - int rc; - - if (session->startup_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "session_startup for socket %d", sock); - if (LIBSSH2_INVALID_SOCKET == sock) { - /* Did we forget something? */ - return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET, - "Bad socket provided"); - } - session->socket_fd = sock; - - session->socket_prev_blockstate = - !get_socket_nonblocking(session->socket_fd); - - if (session->socket_prev_blockstate) { - /* If in blocking state chang to non-blocking */ - session_nonblock(session->socket_fd, 1); - } - - session->startup_state = libssh2_NB_state_created; - } - - if (session->startup_state == libssh2_NB_state_created) { - rc = banner_send(session); - if (rc) { - return _libssh2_error(session, rc, - "Failed sending banner"); - } - session->startup_state = libssh2_NB_state_sent; - session->banner_TxRx_state = libssh2_NB_state_idle; - } - - if (session->startup_state == libssh2_NB_state_sent) { - do { - rc = banner_receive(session); - if (rc) - return _libssh2_error(session, rc, - "Failed getting banner"); - } while(strncmp("SSH-", (char *)session->remote.banner, 4)); - - session->startup_state = libssh2_NB_state_sent1; - } - - if (session->startup_state == libssh2_NB_state_sent1) { - rc = _libssh2_kex_exchange(session, 0, &session->startup_key_state); - if (rc) - return _libssh2_error(session, rc, - "Unable to exchange encryption keys"); - - session->startup_state = libssh2_NB_state_sent2; - } - - if (session->startup_state == libssh2_NB_state_sent2) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Requesting userauth service"); - - /* Request the userauth service */ - session->startup_service[0] = SSH_MSG_SERVICE_REQUEST; - _libssh2_htonu32(session->startup_service + 1, - sizeof("ssh-userauth") - 1); - memcpy(session->startup_service + 5, "ssh-userauth", - sizeof("ssh-userauth") - 1); - - session->startup_state = libssh2_NB_state_sent3; - } - - if (session->startup_state == libssh2_NB_state_sent3) { - rc = _libssh2_transport_send(session, session->startup_service, - sizeof("ssh-userauth") + 5 - 1, - NULL, 0); - if (rc) { - return _libssh2_error(session, rc, - "Unable to ask for ssh-userauth service"); - } - - session->startup_state = libssh2_NB_state_sent4; - } - - if (session->startup_state == libssh2_NB_state_sent4) { - rc = _libssh2_packet_require(session, SSH_MSG_SERVICE_ACCEPT, - &session->startup_data, - &session->startup_data_len, 0, NULL, 0, - &session->startup_req_state); - if (rc) - return rc; - - session->startup_service_length = - _libssh2_ntohu32(session->startup_data + 1); - - if ((session->startup_service_length != (sizeof("ssh-userauth") - 1)) - || strncmp("ssh-userauth", (char *) session->startup_data + 5, - session->startup_service_length)) { - LIBSSH2_FREE(session, session->startup_data); - session->startup_data = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_PROTO, - "Invalid response received from server"); - } - LIBSSH2_FREE(session, session->startup_data); - session->startup_data = NULL; - - session->startup_state = libssh2_NB_state_idle; - - return 0; - } - - /* just for safety return some error */ - return LIBSSH2_ERROR_INVAL; -} - -/* - * libssh2_session_handshake() - * - * session: LIBSSH2_SESSION struct allocated and owned by the calling program - * sock: *must* be populated with an opened and connected socket. - * - * Returns: 0 on success, or non-zero on failure - */ -LIBSSH2_API int -libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock) -{ - int rc; - - BLOCK_ADJUST(rc, session, session_startup(session, sock) ); - - return rc; -} - -/* - * libssh2_session_startup() - * - * DEPRECATED. Use libssh2_session_handshake() instead! This function is not - * portable enough. - * - * session: LIBSSH2_SESSION struct allocated and owned by the calling program - * sock: *must* be populated with an opened and connected socket. - * - * Returns: 0 on success, or non-zero on failure - */ -LIBSSH2_API int -libssh2_session_startup(LIBSSH2_SESSION *session, int sock) -{ - return libssh2_session_handshake(session, (libssh2_socket_t) sock); -} - -/* - * libssh2_session_free - * - * Frees the memory allocated to the session - * Also closes and frees any channels attached to this session - */ -static int -session_free(LIBSSH2_SESSION *session) -{ - int rc; - LIBSSH2_PACKET *pkg; - LIBSSH2_CHANNEL *ch; - LIBSSH2_LISTENER *l; - int packets_left = 0; - - if (session->free_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource", - session->remote.banner); - - session->state = libssh2_NB_state_created; - } - - if (session->free_state == libssh2_NB_state_created) { - while ((ch = _libssh2_list_first(&session->channels))) { - - rc = _libssh2_channel_free(ch); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - session->state = libssh2_NB_state_sent; - } - - if (session->state == libssh2_NB_state_sent) { - while ((l = _libssh2_list_first(&session->listeners))) { - rc = _libssh2_channel_forward_cancel(l); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - session->state = libssh2_NB_state_sent1; - } - - if (session->state & LIBSSH2_STATE_NEWKEYS) { - /* hostkey */ - if (session->hostkey && session->hostkey->dtor) { - session->hostkey->dtor(session, &session->server_hostkey_abstract); - } - - /* Client to Server */ - /* crypt */ - if (session->local.crypt && session->local.crypt->dtor) { - session->local.crypt->dtor(session, - &session->local.crypt_abstract); - } - /* comp */ - if (session->local.comp && session->local.comp->dtor) { - session->local.comp->dtor(session, 1, - &session->local.comp_abstract); - } - /* mac */ - if (session->local.mac && session->local.mac->dtor) { - session->local.mac->dtor(session, &session->local.mac_abstract); - } - - /* Server to Client */ - /* crypt */ - if (session->remote.crypt && session->remote.crypt->dtor) { - session->remote.crypt->dtor(session, - &session->remote.crypt_abstract); - } - /* comp */ - if (session->remote.comp && session->remote.comp->dtor) { - session->remote.comp->dtor(session, 0, - &session->remote.comp_abstract); - } - /* mac */ - if (session->remote.mac && session->remote.mac->dtor) { - session->remote.mac->dtor(session, &session->remote.mac_abstract); - } - - /* session_id */ - if (session->session_id) { - LIBSSH2_FREE(session, session->session_id); - } - } - - /* Free banner(s) */ - if (session->remote.banner) { - LIBSSH2_FREE(session, session->remote.banner); - } - if (session->local.banner) { - LIBSSH2_FREE(session, session->local.banner); - } - - /* Free preference(s) */ - if (session->kex_prefs) { - LIBSSH2_FREE(session, session->kex_prefs); - } - if (session->hostkey_prefs) { - LIBSSH2_FREE(session, session->hostkey_prefs); - } - - if (session->local.kexinit) { - LIBSSH2_FREE(session, session->local.kexinit); - } - if (session->local.crypt_prefs) { - LIBSSH2_FREE(session, session->local.crypt_prefs); - } - if (session->local.mac_prefs) { - LIBSSH2_FREE(session, session->local.mac_prefs); - } - if (session->local.comp_prefs) { - LIBSSH2_FREE(session, session->local.comp_prefs); - } - if (session->local.lang_prefs) { - LIBSSH2_FREE(session, session->local.lang_prefs); - } - - if (session->remote.kexinit) { - LIBSSH2_FREE(session, session->remote.kexinit); - } - if (session->remote.crypt_prefs) { - LIBSSH2_FREE(session, session->remote.crypt_prefs); - } - if (session->remote.mac_prefs) { - LIBSSH2_FREE(session, session->remote.mac_prefs); - } - if (session->remote.comp_prefs) { - LIBSSH2_FREE(session, session->remote.comp_prefs); - } - if (session->remote.lang_prefs) { - LIBSSH2_FREE(session, session->remote.lang_prefs); - } - - /* - * Make sure all memory used in the state variables are free - */ - if (session->kexinit_data) { - LIBSSH2_FREE(session, session->kexinit_data); - } - if (session->startup_data) { - LIBSSH2_FREE(session, session->startup_data); - } - if (session->userauth_list_data) { - LIBSSH2_FREE(session, session->userauth_list_data); - } - if (session->userauth_pswd_data) { - LIBSSH2_FREE(session, session->userauth_pswd_data); - } - if (session->userauth_pswd_newpw) { - LIBSSH2_FREE(session, session->userauth_pswd_newpw); - } - if (session->userauth_host_packet) { - LIBSSH2_FREE(session, session->userauth_host_packet); - } - if (session->userauth_host_method) { - LIBSSH2_FREE(session, session->userauth_host_method); - } - if (session->userauth_host_data) { - LIBSSH2_FREE(session, session->userauth_host_data); - } - if (session->userauth_pblc_data) { - LIBSSH2_FREE(session, session->userauth_pblc_data); - } - if (session->userauth_pblc_packet) { - LIBSSH2_FREE(session, session->userauth_pblc_packet); - } - if (session->userauth_pblc_method) { - LIBSSH2_FREE(session, session->userauth_pblc_method); - } - if (session->userauth_kybd_data) { - LIBSSH2_FREE(session, session->userauth_kybd_data); - } - if (session->userauth_kybd_packet) { - LIBSSH2_FREE(session, session->userauth_kybd_packet); - } - if (session->userauth_kybd_auth_instruction) { - LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction); - } - if (session->open_packet) { - LIBSSH2_FREE(session, session->open_packet); - } - if (session->open_data) { - LIBSSH2_FREE(session, session->open_data); - } - if (session->direct_message) { - LIBSSH2_FREE(session, session->direct_message); - } - if (session->fwdLstn_packet) { - LIBSSH2_FREE(session, session->fwdLstn_packet); - } - if (session->pkeyInit_data) { - LIBSSH2_FREE(session, session->pkeyInit_data); - } - if (session->scpRecv_command) { - LIBSSH2_FREE(session, session->scpRecv_command); - } - if (session->scpSend_command) { - LIBSSH2_FREE(session, session->scpSend_command); - } - - /* Cleanup all remaining packets */ - while ((pkg = _libssh2_list_first(&session->packets))) { - packets_left++; - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "packet left with id %d", pkg->data[0]); - /* unlink the node */ - _libssh2_list_remove(&pkg->node); - - /* free */ - LIBSSH2_FREE(session, pkg->data); - LIBSSH2_FREE(session, pkg); - } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Extra packets left %d", packets_left); - - if(session->socket_prev_blockstate) - /* if the socket was previously blocking, put it back so */ - session_nonblock(session->socket_fd, 0); - - if (session->server_hostkey) { - LIBSSH2_FREE(session, session->server_hostkey); - } - - LIBSSH2_FREE(session, session); - - return 0; -} - -/* - * libssh2_session_free - * - * Frees the memory allocated to the session - * Also closes and frees any channels attached to this session - */ -LIBSSH2_API int -libssh2_session_free(LIBSSH2_SESSION * session) -{ - int rc; - - BLOCK_ADJUST(rc, session, session_free(session) ); - - return rc; -} - -/* - * libssh2_session_disconnect_ex - */ -static int -session_disconnect(LIBSSH2_SESSION *session, int reason, - const char *description, - const char *lang) -{ - unsigned char *s; - unsigned long descr_len = 0, lang_len = 0; - int rc; - - if (session->disconnect_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Disconnecting: reason=%d, desc=%s, lang=%s", reason, - description, lang); - if (description) - descr_len = strlen(description); - - if (lang) - lang_len = strlen(lang); - - if(descr_len > 256) - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "too long description"); - - /* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */ - session->disconnect_data_len = descr_len + lang_len + 13; - - s = session->disconnect_data; - - *(s++) = SSH_MSG_DISCONNECT; - _libssh2_store_u32(&s, reason); - _libssh2_store_str(&s, description, descr_len); - /* store length only, lang is sent separately */ - _libssh2_store_u32(&s, lang_len); - - session->disconnect_state = libssh2_NB_state_created; - } - - rc = _libssh2_transport_send(session, session->disconnect_data, - session->disconnect_data_len, - (unsigned char *)lang, lang_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - session->disconnect_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * libssh2_session_disconnect_ex - */ -LIBSSH2_API int -libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, - const char *desc, const char *lang) -{ - int rc; - - BLOCK_ADJUST(rc, session, - session_disconnect(session, reason, desc, lang)); - - return rc; -} - -/* libssh2_session_methods - * - * Return the currently active methods for method_type - * - * NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string - * regardless of actual negotiation Strings should NOT be freed - */ -LIBSSH2_API const char * -libssh2_session_methods(LIBSSH2_SESSION * session, int method_type) -{ - /* All methods have char *name as their first element */ - const LIBSSH2_KEX_METHOD *method = NULL; - - switch (method_type) { - case LIBSSH2_METHOD_KEX: - method = session->kex; - break; - - case LIBSSH2_METHOD_HOSTKEY: - method = (LIBSSH2_KEX_METHOD *) session->hostkey; - break; - - case LIBSSH2_METHOD_CRYPT_CS: - method = (LIBSSH2_KEX_METHOD *) session->local.crypt; - break; - - case LIBSSH2_METHOD_CRYPT_SC: - method = (LIBSSH2_KEX_METHOD *) session->remote.crypt; - break; - - case LIBSSH2_METHOD_MAC_CS: - method = (LIBSSH2_KEX_METHOD *) session->local.mac; - break; - - case LIBSSH2_METHOD_MAC_SC: - method = (LIBSSH2_KEX_METHOD *) session->remote.mac; - break; - - case LIBSSH2_METHOD_COMP_CS: - method = (LIBSSH2_KEX_METHOD *) session->local.comp; - break; - - case LIBSSH2_METHOD_COMP_SC: - method = (LIBSSH2_KEX_METHOD *) session->remote.comp; - break; - - case LIBSSH2_METHOD_LANG_CS: - return ""; - - case LIBSSH2_METHOD_LANG_SC: - return ""; - - default: - _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "Invalid parameter specified for method_type"); - return NULL; - } - - if (!method) { - _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, - "No method negotiated"); - return NULL; - } - - return method->name; -} - -/* libssh2_session_abstract - * Retrieve a pointer to the abstract property - */ -LIBSSH2_API void ** -libssh2_session_abstract(LIBSSH2_SESSION * session) -{ - return &session->abstract; -} - -/* libssh2_session_last_error - * - * Returns error code and populates an error string into errmsg If want_buf is - * non-zero then the string placed into errmsg must be freed by the calling - * program. Otherwise it is assumed to be owned by libssh2 - */ -LIBSSH2_API int -libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg, - int *errmsg_len, int want_buf) -{ - size_t msglen = 0; - - /* No error to report */ - if (!session->err_code) { - if (errmsg) { - if (want_buf) { - *errmsg = LIBSSH2_ALLOC(session, 1); - if (*errmsg) { - **errmsg = 0; - } - } else { - *errmsg = (char *) ""; - } - } - if (errmsg_len) { - *errmsg_len = 0; - } - return 0; - } - - if (errmsg) { - const char *error = session->err_msg ? session->err_msg : ""; - - msglen = strlen(error); - - if (want_buf) { - /* Make a copy so the calling program can own it */ - *errmsg = LIBSSH2_ALLOC(session, msglen + 1); - if (*errmsg) { - memcpy(*errmsg, error, msglen); - (*errmsg)[msglen] = 0; - } - } - else - *errmsg = (char *)error; - } - - if (errmsg_len) { - *errmsg_len = msglen; - } - - return session->err_code; -} - -/* libssh2_session_last_errno - * - * Returns error code - */ -LIBSSH2_API int -libssh2_session_last_errno(LIBSSH2_SESSION * session) -{ - return session->err_code; -} - -/* libssh2_session_flag - * - * Set/Get session flags - * - * Return error code. - */ -LIBSSH2_API int -libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value) -{ - switch(flag) { - case LIBSSH2_FLAG_SIGPIPE: - session->flag.sigpipe = value; - break; - case LIBSSH2_FLAG_COMPRESS: - session->flag.compress = value; - break; - default: - /* unknown flag */ - return LIBSSH2_ERROR_INVAL; - } - - return LIBSSH2_ERROR_NONE; -} - -/* _libssh2_session_set_blocking - * - * Set a session's blocking mode on or off, return the previous status when - * this function is called. Note this function does not alter the state of the - * actual socket involved. - */ -int -_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking) -{ - int bl = session->api_block_mode; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Setting blocking mode %s", blocking?"ON":"OFF"); - session->api_block_mode = blocking; - - return bl; -} - -/* libssh2_session_set_blocking - * - * Set a channel's blocking mode on or off, similar to a socket's - * fcntl(fd, F_SETFL, O_NONBLOCK); type command - */ -LIBSSH2_API void -libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking) -{ - (void) _libssh2_session_set_blocking(session, blocking); -} - -/* libssh2_session_get_blocking - * - * Returns a session's blocking mode on or off - */ -LIBSSH2_API int -libssh2_session_get_blocking(LIBSSH2_SESSION * session) -{ - return session->api_block_mode; -} - - -/* libssh2_session_set_timeout - * - * Set a session's timeout (in msec) for blocking mode, - * or 0 to disable timeouts. - */ -LIBSSH2_API void -libssh2_session_set_timeout(LIBSSH2_SESSION * session, long timeout) -{ - session->api_timeout = timeout; -} - -/* libssh2_session_get_timeout - * - * Returns a session's timeout, or 0 if disabled - */ -LIBSSH2_API long -libssh2_session_get_timeout(LIBSSH2_SESSION * session) -{ - return session->api_timeout; -} - -/* - * libssh2_poll_channel_read - * - * Returns 0 if no data is waiting on channel, - * non-0 if data is available - */ -LIBSSH2_API int -libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended) -{ - LIBSSH2_SESSION *session; - LIBSSH2_PACKET *packet; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - session = channel->session; - packet = _libssh2_list_first(&session->packets); - - while (packet) { - if ( channel->local.id == _libssh2_ntohu32(packet->data + 1)) { - if ( extended == 1 && - (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA - || packet->data[0] == SSH_MSG_CHANNEL_DATA )) { - return 1; - } else if ( extended == 0 && - packet->data[0] == SSH_MSG_CHANNEL_DATA) { - return 1; - } - /* else - no data of any type is ready to be read */ - } - packet = _libssh2_list_next(&packet->node); - } - - return 0; -} - -/* - * poll_channel_write - * - * Returns 0 if writing to channel would block, - * non-0 if data can be written without blocking - */ -static inline int -poll_channel_write(LIBSSH2_CHANNEL * channel) -{ - return channel->local.window_size ? 1 : 0; -} - -/* poll_listener_queued - * - * Returns 0 if no connections are waiting to be accepted - * non-0 if one or more connections are available - */ -static inline int -poll_listener_queued(LIBSSH2_LISTENER * listener) -{ - return _libssh2_list_first(&listener->queue) ? 1 : 0; -} - -/* - * libssh2_poll - * - * Poll sockets, channels, and listeners for activity - */ -LIBSSH2_API int -libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) -{ - long timeout_remaining; - unsigned int i, active_fds; -#ifdef HAVE_POLL - LIBSSH2_SESSION *session = NULL; -#ifdef HAVE_ALLOCA - struct pollfd *sockets = alloca(sizeof(struct pollfd) * nfds); -#else - struct pollfd sockets[256]; - - if (nfds > 256) - /* systems without alloca use a fixed-size array, this can be fixed if - we really want to, at least if the compiler is a C99 capable one */ - return -1; -#endif - /* Setup sockets for polling */ - for(i = 0; i < nfds; i++) { - fds[i].revents = 0; - switch (fds[i].type) { - case LIBSSH2_POLLFD_SOCKET: - sockets[i].fd = fds[i].fd.socket; - sockets[i].events = fds[i].events; - sockets[i].revents = 0; - break; - - case LIBSSH2_POLLFD_CHANNEL: - sockets[i].fd = fds[i].fd.channel->session->socket_fd; - sockets[i].events = POLLIN; - sockets[i].revents = 0; - if (!session) - session = fds[i].fd.channel->session; - break; - - case LIBSSH2_POLLFD_LISTENER: - sockets[i].fd = fds[i].fd.listener->session->socket_fd; - sockets[i].events = POLLIN; - sockets[i].revents = 0; - if (!session) - session = fds[i].fd.listener->session; - break; - - default: - if (session) - _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, - "Invalid descriptor passed to libssh2_poll()"); - return -1; - } - } -#elif defined(HAVE_SELECT) - LIBSSH2_SESSION *session = NULL; - libssh2_socket_t maxfd = 0; - fd_set rfds, wfds; - struct timeval tv; - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - for(i = 0; i < nfds; i++) { - fds[i].revents = 0; - switch (fds[i].type) { - case LIBSSH2_POLLFD_SOCKET: - if (fds[i].events & LIBSSH2_POLLFD_POLLIN) { - FD_SET(fds[i].fd.socket, &rfds); - if (fds[i].fd.socket > maxfd) - maxfd = fds[i].fd.socket; - } - if (fds[i].events & LIBSSH2_POLLFD_POLLOUT) { - FD_SET(fds[i].fd.socket, &wfds); - if (fds[i].fd.socket > maxfd) - maxfd = fds[i].fd.socket; - } - break; - - case LIBSSH2_POLLFD_CHANNEL: - FD_SET(fds[i].fd.channel->session->socket_fd, &rfds); - if (fds[i].fd.channel->session->socket_fd > maxfd) - maxfd = fds[i].fd.channel->session->socket_fd; - if (!session) - session = fds[i].fd.channel->session; - break; - - case LIBSSH2_POLLFD_LISTENER: - FD_SET(fds[i].fd.listener->session->socket_fd, &rfds); - if (fds[i].fd.listener->session->socket_fd > maxfd) - maxfd = fds[i].fd.listener->session->socket_fd; - if (!session) - session = fds[i].fd.listener->session; - break; - - default: - if (session) - _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, - "Invalid descriptor passed to libssh2_poll()"); - return -1; - } - } -#else - /* No select() or poll() - * no sockets sturcture to setup - */ - - timeout = 0; -#endif /* HAVE_POLL or HAVE_SELECT */ - - timeout_remaining = timeout; - do { -#if defined(HAVE_POLL) || defined(HAVE_SELECT) - int sysret; -#endif - - active_fds = 0; - - for(i = 0; i < nfds; i++) { - if (fds[i].events != fds[i].revents) { - switch (fds[i].type) { - case LIBSSH2_POLLFD_CHANNEL: - if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && - /* Want to be ready for read */ - ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { - /* Not yet known to be ready for read */ - fds[i].revents |= - libssh2_poll_channel_read(fds[i].fd.channel, - 0) ? - LIBSSH2_POLLFD_POLLIN : 0; - } - if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && - /* Want to be ready for extended read */ - ((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) { - /* Not yet known to be ready for extended read */ - fds[i].revents |= - libssh2_poll_channel_read(fds[i].fd.channel, - 1) ? - LIBSSH2_POLLFD_POLLEXT : 0; - } - if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && - /* Want to be ready for write */ - ((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) { - /* Not yet known to be ready for write */ - fds[i].revents |= - poll_channel_write(fds[i].fd. channel) ? - LIBSSH2_POLLFD_POLLOUT : 0; - } - if (fds[i].fd.channel->remote.close - || fds[i].fd.channel->local.close) { - fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED; - } - if (fds[i].fd.channel->session->socket_state == - LIBSSH2_SOCKET_DISCONNECTED) { - fds[i].revents |= - LIBSSH2_POLLFD_CHANNEL_CLOSED | - LIBSSH2_POLLFD_SESSION_CLOSED; - } - break; - - case LIBSSH2_POLLFD_LISTENER: - if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && - /* Want a connection */ - ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { - /* No connections known of yet */ - fds[i].revents |= - poll_listener_queued(fds[i].fd. listener) ? - LIBSSH2_POLLFD_POLLIN : 0; - } - if (fds[i].fd.listener->session->socket_state == - LIBSSH2_SOCKET_DISCONNECTED) { - fds[i].revents |= - LIBSSH2_POLLFD_LISTENER_CLOSED | - LIBSSH2_POLLFD_SESSION_CLOSED; - } - break; - } - } - if (fds[i].revents) { - active_fds++; - } - } - - if (active_fds) { - /* Don't block on the sockets if we have channels/listeners which - are ready */ - timeout_remaining = 0; - } -#ifdef HAVE_POLL - -#ifdef HAVE_LIBSSH2_GETTIMEOFDAY - { - struct timeval tv_begin, tv_end; - - _libssh2_gettimeofday((struct timeval *) &tv_begin, NULL); - sysret = poll(sockets, nfds, timeout_remaining); - _libssh2_gettimeofday((struct timeval *) &tv_end, NULL); - timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000; - timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000; - } -#else - /* If the platform doesn't support gettimeofday, - * then just make the call non-blocking and walk away - */ - sysret = poll(sockets, nfds, timeout_remaining); - timeout_remaining = 0; -#endif /* HAVE_GETTIMEOFDAY */ - - if (sysret > 0) { - for(i = 0; i < nfds; i++) { - switch (fds[i].type) { - case LIBSSH2_POLLFD_SOCKET: - fds[i].revents = sockets[i].revents; - sockets[i].revents = 0; /* In case we loop again, be nice */ - if (fds[i].revents) { - active_fds++; - } - break; - case LIBSSH2_POLLFD_CHANNEL: - if (sockets[i].events & POLLIN) { - /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.channel->session) - > 0); - } - if (sockets[i].revents & POLLHUP) { - fds[i].revents |= - LIBSSH2_POLLFD_CHANNEL_CLOSED | - LIBSSH2_POLLFD_SESSION_CLOSED; - } - sockets[i].revents = 0; - break; - case LIBSSH2_POLLFD_LISTENER: - if (sockets[i].events & POLLIN) { - /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.listener->session) - > 0); - } - if (sockets[i].revents & POLLHUP) { - fds[i].revents |= - LIBSSH2_POLLFD_LISTENER_CLOSED | - LIBSSH2_POLLFD_SESSION_CLOSED; - } - sockets[i].revents = 0; - break; - } - } - } -#elif defined(HAVE_SELECT) - tv.tv_sec = timeout_remaining / 1000; - tv.tv_usec = (timeout_remaining % 1000) * 1000; -#ifdef HAVE_LIBSSH2_GETTIMEOFDAY - { - struct timeval tv_begin, tv_end; - - _libssh2_gettimeofday((struct timeval *) &tv_begin, NULL); - sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv); - _libssh2_gettimeofday((struct timeval *) &tv_end, NULL); - - timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000; - timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000; - } -#else - /* If the platform doesn't support gettimeofday, - * then just make the call non-blocking and walk away - */ - sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv); - timeout_remaining = 0; -#endif - - if (sysret > 0) { - for(i = 0; i < nfds; i++) { - switch (fds[i].type) { - case LIBSSH2_POLLFD_SOCKET: - if (FD_ISSET(fds[i].fd.socket, &rfds)) { - fds[i].revents |= LIBSSH2_POLLFD_POLLIN; - } - if (FD_ISSET(fds[i].fd.socket, &wfds)) { - fds[i].revents |= LIBSSH2_POLLFD_POLLOUT; - } - if (fds[i].revents) { - active_fds++; - } - break; - - case LIBSSH2_POLLFD_CHANNEL: - if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) { - /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.channel->session) - > 0); - } - break; - - case LIBSSH2_POLLFD_LISTENER: - if (FD_ISSET - (fds[i].fd.listener->session->socket_fd, &rfds)) { - /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.listener->session) - > 0); - } - break; - } - } - } -#endif /* else no select() or poll() -- timeout (and by extension - * timeout_remaining) will be equal to 0 */ - } while ((timeout_remaining > 0) && !active_fds); - - return active_fds; -} - -/* - * libssh2_session_block_directions - * - * Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN - * Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked - * or LIBSSH2_SOCKET_BLOCK_OUTBOUND if send() blocked - */ -LIBSSH2_API int -libssh2_session_block_directions(LIBSSH2_SESSION *session) -{ - return session->socket_block_directions; -} - -/* libssh2_session_banner_get - * Get the remote banner (server ID string) - */ - -LIBSSH2_API const char * -libssh2_session_banner_get(LIBSSH2_SESSION *session) -{ - /* to avoid a coredump when session is NULL */ - if (NULL == session) - return NULL; - - if (NULL==session->remote.banner) - return NULL; - - return (const char *) session->remote.banner; -} diff --git a/vendor/libssh2-1.4.2/src/session.h b/vendor/libssh2-1.4.2/src/session.h deleted file mode 100644 index aff4f2c..0000000 --- a/vendor/libssh2-1.4.2/src/session.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef LIBSSH2_SESSION_H -#define LIBSSH2_SESSION_H -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - */ - -/* Conveniance-macros to allow code like this; - - int rc = BLOCK_ADJUST(rc, session, session_startup(session, sock) ); - - int rc = BLOCK_ADJUST_ERRNO(ptr, session, session_startup(session, sock) ); - - The point of course being to make sure that while in non-blocking mode - these always return no matter what the return code is, but in blocking mode - it blocks if EAGAIN is the reason for the return from the underlying - function. - -*/ -#define BLOCK_ADJUST(rc,sess,x) \ - do { \ - time_t entry_time = time (NULL); \ - do { \ - rc = x; \ - /* the order of the check below is important to properly deal with \ - the case when the 'sess' is freed */ \ - if((rc != LIBSSH2_ERROR_EAGAIN) || !sess->api_block_mode) \ - break; \ - rc = _libssh2_wait_socket(sess, entry_time); \ - } while(!rc); \ - } while(0) - -/* - * For functions that returns a pointer, we need to check if the API is - * non-blocking and return immediately. If the pointer is non-NULL we return - * immediately. If the API is blocking and we get a NULL we check the errno - * and *only* if that is EAGAIN we loop and wait for socket action. - */ -#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \ - do { \ - time_t entry_time = time (NULL); \ - int rc; \ - do { \ - ptr = x; \ - if(!sess->api_block_mode || \ - (ptr != NULL) || \ - (libssh2_session_last_errno(sess) != LIBSSH2_ERROR_EAGAIN) ) \ - break; \ - rc = _libssh2_wait_socket(sess, entry_time); \ - } while(!rc); \ - } while(0) - - -int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time); - -/* this is the lib-internal set blocking function */ -int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking); - -#endif /* LIBSSH2_SESSION_H */ diff --git a/vendor/libssh2-1.4.2/src/sftp.c b/vendor/libssh2-1.4.2/src/sftp.c deleted file mode 100644 index ec9d033..0000000 --- a/vendor/libssh2-1.4.2/src/sftp.c +++ /dev/null @@ -1,3278 +0,0 @@ -/* Copyright (c) 2004-2008, Sara Golemon - * Copyright (c) 2007 Eli Fant - * Copyright (c) 2009-2012 by Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 - -#include "libssh2_priv.h" -#include "libssh2_sftp.h" -#include "channel.h" -#include "session.h" -#include "sftp.h" - -/* Note: Version 6 was documented at the time of writing - * However it was marked as "DO NOT IMPLEMENT" due to pending changes - * - * This release of libssh2 implements Version 5 with automatic downgrade - * based on server's declaration - */ - -/* SFTP packet types */ -#define SSH_FXP_INIT 1 -#define SSH_FXP_VERSION 2 -#define SSH_FXP_OPEN 3 -#define SSH_FXP_CLOSE 4 -#define SSH_FXP_READ 5 -#define SSH_FXP_WRITE 6 -#define SSH_FXP_LSTAT 7 -#define SSH_FXP_FSTAT 8 -#define SSH_FXP_SETSTAT 9 -#define SSH_FXP_FSETSTAT 10 -#define SSH_FXP_OPENDIR 11 -#define SSH_FXP_READDIR 12 -#define SSH_FXP_REMOVE 13 -#define SSH_FXP_MKDIR 14 -#define SSH_FXP_RMDIR 15 -#define SSH_FXP_REALPATH 16 -#define SSH_FXP_STAT 17 -#define SSH_FXP_RENAME 18 -#define SSH_FXP_READLINK 19 -#define SSH_FXP_SYMLINK 20 -#define SSH_FXP_STATUS 101 -#define SSH_FXP_HANDLE 102 -#define SSH_FXP_DATA 103 -#define SSH_FXP_NAME 104 -#define SSH_FXP_ATTRS 105 -#define SSH_FXP_EXTENDED 200 -#define SSH_FXP_EXTENDED_REPLY 201 - -/* S_IFREG */ -#define LIBSSH2_SFTP_ATTR_PFILETYPE_FILE 0100000 -/* S_IFDIR */ -#define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000 - -#define SSH_FXE_STATVFS_ST_RDONLY 0x00000001 -#define SSH_FXE_STATVFS_ST_NOSUID 0x00000002 - -/* This is the maximum packet length to accept, as larger than this indicate - some kind of server problem. */ -#define LIBSSH2_SFTP_PACKET_MAXLEN 80000 - -static int sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle); -static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type, - uint32_t request_id, unsigned char **data, - size_t *data_len); -static void sftp_packet_flush(LIBSSH2_SFTP *sftp); - -/* sftp_attrsize - * Size that attr with this flagset will occupy when turned into a bin struct - */ -static int sftp_attrsize(unsigned long flags) -{ - return (4 + /* flags(4) */ - ((flags & LIBSSH2_SFTP_ATTR_SIZE) ? 8 : 0) + - ((flags & LIBSSH2_SFTP_ATTR_UIDGID) ? 8 : 0) + - ((flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) ? 4 : 0) + - ((flags & LIBSSH2_SFTP_ATTR_ACMODTIME) ? 8 : 0)); - /* atime + mtime as u32 */ -} - -/* _libssh2_store_u64 - */ -static void _libssh2_store_u64(unsigned char **ptr, libssh2_uint64_t value) -{ - uint32_t msl = (uint32_t)(value >> 32); - unsigned char *buf = *ptr; - - buf[0] = (unsigned char)((msl >> 24) & 0xFF); - buf[1] = (unsigned char)((msl >> 16) & 0xFF); - buf[2] = (unsigned char)((msl >> 8) & 0xFF); - buf[3] = (unsigned char)( msl & 0xFF); - - buf[4] = (unsigned char)((value >> 24) & 0xFF); - buf[5] = (unsigned char)((value >> 16) & 0xFF); - buf[6] = (unsigned char)((value >> 8) & 0xFF); - buf[7] = (unsigned char)( value & 0xFF); - - *ptr += 8; -} - -/* - * Search list of zombied FXP_READ request IDs. - * - * Returns NULL if ID not in list. - */ -static struct sftp_zombie_requests * -find_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) -{ - struct sftp_zombie_requests *zombie = - _libssh2_list_first(&sftp->zombie_requests); - - while(zombie) { - if(zombie->request_id == request_id) - break; - else - zombie = _libssh2_list_next(&zombie->node); - } - - return zombie; -} - -static void -remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - - struct sftp_zombie_requests *zombie = find_zombie_request(sftp, - request_id); - if(zombie) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Removing request ID %ld from the list of zombie requests", - request_id); - - _libssh2_list_remove(&zombie->node); - LIBSSH2_FREE(session, zombie); - } -} - -static int -add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - - struct sftp_zombie_requests *zombie; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Marking request ID %ld as a zombie request", request_id); - - zombie = LIBSSH2_ALLOC(sftp->channel->session, - sizeof(struct sftp_zombie_requests)); - if (!zombie) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "malloc fail for zombie request ID"); - else { - zombie->request_id = request_id; - _libssh2_list_add(&sftp->zombie_requests, &zombie->node); - return LIBSSH2_ERROR_NONE; - } -} - -/* - * sftp_packet_add - * - * Add a packet to the SFTP packet brigade - */ -static int -sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data, - size_t data_len) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - LIBSSH2_SFTP_PACKET *packet; - uint32_t request_id; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet %d (len %d)", - (int) data[0], data_len); - - /* - * Experience shows that if we mess up EAGAIN handling somewhere or - * otherwise get out of sync with the channel, this is where we first get - * a wrong byte and if so we need to bail out at once to aid tracking the - * problem better. - */ - - switch(data[0]) { - case SSH_FXP_INIT: - case SSH_FXP_VERSION: - case SSH_FXP_OPEN: - case SSH_FXP_CLOSE: - case SSH_FXP_READ: - case SSH_FXP_WRITE: - case SSH_FXP_LSTAT: - case SSH_FXP_FSTAT: - case SSH_FXP_SETSTAT: - case SSH_FXP_FSETSTAT: - case SSH_FXP_OPENDIR: - case SSH_FXP_READDIR: - case SSH_FXP_REMOVE: - case SSH_FXP_MKDIR: - case SSH_FXP_RMDIR: - case SSH_FXP_REALPATH: - case SSH_FXP_STAT: - case SSH_FXP_RENAME: - case SSH_FXP_READLINK: - case SSH_FXP_SYMLINK: - case SSH_FXP_STATUS: - case SSH_FXP_HANDLE: - case SSH_FXP_DATA: - case SSH_FXP_NAME: - case SSH_FXP_ATTRS: - case SSH_FXP_EXTENDED: - case SSH_FXP_EXTENDED_REPLY: - break; - default: - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Out of sync with the world"); - } - - request_id = _libssh2_ntohu32(&data[1]); - - /* Don't add the packet if it answers a request we've given up on. */ - if((data[0] == SSH_FXP_STATUS || data[0] == SSH_FXP_DATA) - && find_zombie_request(sftp, request_id)) { - - /* If we get here, the file ended before the response arrived. We - are no longer interested in the request so we discard it */ - - LIBSSH2_FREE(session, data); - - remove_zombie_request(sftp, request_id); - return LIBSSH2_ERROR_NONE; - } - - packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_PACKET)); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate datablock for SFTP packet"); - } - - packet->data = data; - packet->data_len = data_len; - packet->request_id = request_id; - - _libssh2_list_add(&sftp->packets, &packet->node); - - return LIBSSH2_ERROR_NONE; -} - -/* - * sftp_packet_read - * - * Frame an SFTP packet off the channel - */ -static int -sftp_packet_read(LIBSSH2_SFTP *sftp) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - unsigned char *packet = NULL; - ssize_t rc; - unsigned long recv_window; - int packet_type; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "recv packet"); - - switch(sftp->packet_state) { - case libssh2_NB_state_sent: /* EAGAIN from window adjusting */ - sftp->packet_state = libssh2_NB_state_idle; - - packet = sftp->partial_packet; - goto window_adjust; - - case libssh2_NB_state_sent1: /* EAGAIN from channel read */ - sftp->packet_state = libssh2_NB_state_idle; - - packet = sftp->partial_packet; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "partial read cont, len: %lu", sftp->partial_len); - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "partial read cont, already recvd: %lu", - sftp->partial_received); - /* fall-through */ - default: - if(!packet) { - /* only do this if there's not already a packet buffer allocated - to use */ - - /* each packet starts with a 32 bit length field */ - rc = _libssh2_channel_read(channel, 0, - (char *)&sftp->partial_size[ - sftp->partial_size_len], - 4 - sftp->partial_size_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc < 0) - return _libssh2_error(session, rc, "channel read"); - - sftp->partial_size_len += rc; - - if(4 != sftp->partial_size_len) - /* we got a short read for the length part */ - return LIBSSH2_ERROR_EAGAIN; - - sftp->partial_len = _libssh2_ntohu32(sftp->partial_size); - /* make sure we don't proceed if the packet size is unreasonably - large */ - if (sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN) - return _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, - "SFTP packet too large"); - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Data begin - Packet Length: %lu", - sftp->partial_len); - packet = LIBSSH2_ALLOC(session, sftp->partial_len); - if (!packet) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate SFTP packet"); - sftp->partial_size_len = 0; - sftp->partial_received = 0; /* how much of the packet already - received */ - sftp->partial_packet = packet; - - window_adjust: - recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL); - - if(sftp->partial_len > recv_window) { - /* ask for twice the data amount we need at once */ - rc = _libssh2_channel_receive_window_adjust(channel, - sftp->partial_len*2, - 1, NULL); - /* store the state so that we continue with the correct - operation at next invoke */ - sftp->packet_state = (rc == LIBSSH2_ERROR_EAGAIN)? - libssh2_NB_state_sent: - libssh2_NB_state_idle; - - if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - } - - /* Read as much of the packet as we can */ - while (sftp->partial_len > sftp->partial_received) { - rc = _libssh2_channel_read(channel, 0, - (char *)&packet[sftp->partial_received], - sftp->partial_len - - sftp->partial_received); - - if (rc == LIBSSH2_ERROR_EAGAIN) { - /* - * We received EAGAIN, save what we have and return EAGAIN to - * the caller. Set 'partial_packet' so that this function - * knows how to continue on the next invoke. - */ - sftp->packet_state = libssh2_NB_state_sent1; - return rc; - } - else if (rc < 0) { - LIBSSH2_FREE(session, packet); - sftp->partial_packet = NULL; - return _libssh2_error(session, rc, - "Error waiting for SFTP packet"); - } - sftp->partial_received += rc; - } - - sftp->partial_packet = NULL; - - /* sftp_packet_add takes ownership of the packet and might free it - so we take a copy of the packet type before we call it. */ - packet_type = packet[0]; - rc = sftp_packet_add(sftp, packet, sftp->partial_len); - if (rc) { - LIBSSH2_FREE(session, packet); - return rc; - } - else { - return packet_type; - } - } - /* WON'T REACH */ -} -/* - * sftp_packetlist_flush - * - * Remove all pending packets in the packet_list and the corresponding one(s) - * in the SFTP packet brigade. - */ -static void sftp_packetlist_flush(LIBSSH2_SFTP_HANDLE *handle) -{ - struct sftp_pipeline_chunk *chunk; - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_SESSION *session = sftp->channel->session; - - /* remove pending packets, if any */ - chunk = _libssh2_list_first(&handle->packet_list); - while(chunk) { - unsigned char *data; - size_t data_len; - int rc; - struct sftp_pipeline_chunk *next = _libssh2_list_next(&chunk->node); - - rc = sftp_packet_ask(sftp, SSH_FXP_STATUS, - chunk->request_id, &data, &data_len); - if(rc) - rc = sftp_packet_ask(sftp, SSH_FXP_DATA, - chunk->request_id, &data, &data_len); - - if(!rc) - /* we found a packet, free it */ - LIBSSH2_FREE(session, data); - else if(chunk->sent) - /* there was no incoming packet for this request, mark this - request as a zombie if it ever sent the request */ - add_zombie_request(sftp, chunk->request_id); - - _libssh2_list_remove(&chunk->node); - LIBSSH2_FREE(session, chunk); - chunk = next; - } -} - - -/* - * sftp_packet_ask() - * - * Checks if there's a matching SFTP packet available. - */ -static int -sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type, - uint32_t request_id, unsigned char **data, - size_t *data_len) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets); - - if(!packet) - return -1; - - /* Special consideration when getting VERSION packet */ - - while (packet) { - if((packet->data[0] == packet_type) && - ((packet_type == SSH_FXP_VERSION) || - (packet->request_id == request_id))) { - - /* Match! Fetch the data */ - *data = packet->data; - *data_len = packet->data_len; - - /* unlink and free this struct */ - _libssh2_list_remove(&packet->node); - LIBSSH2_FREE(session, packet); - - return 0; - } - /* check next struct in the list */ - packet = _libssh2_list_next(&packet->node); - } - return -1; -} - -/* sftp_packet_require - * A la libssh2_packet_require - */ -static int -sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type, - uint32_t request_id, unsigned char **data, - size_t *data_len) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - int rc; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld", - (int) packet_type, request_id); - - if (sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) { - /* The right packet was available in the packet brigade */ - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d", - (int) packet_type); - return LIBSSH2_ERROR_NONE; - } - - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - rc = sftp_packet_read(sftp); - if (rc < 0) - return rc; - - /* data was read, check the queue again */ - if (!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) { - /* The right packet was available in the packet brigade */ - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d", - (int) packet_type); - return LIBSSH2_ERROR_NONE; - } - } - - /* Only reached if the socket died */ - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* sftp_packet_requirev - * Require one of N possible reponses - */ -static int -sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses, - const unsigned char *valid_responses, - uint32_t request_id, unsigned char **data, - size_t *data_len) -{ - int i; - int rc; - - /* If no timeout is active, start a new one */ - if (sftp->requirev_start == 0) - sftp->requirev_start = time(NULL); - - while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - for(i = 0; i < num_valid_responses; i++) { - if (sftp_packet_ask(sftp, valid_responses[i], request_id, - data, data_len) == 0) { - /* - * Set to zero before all returns to say - * the timeout is not active - */ - sftp->requirev_start = 0; - return LIBSSH2_ERROR_NONE; - } - } - - rc = sftp_packet_read(sftp); - if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) { - sftp->requirev_start = 0; - return rc; - } else if (rc <= 0) { - /* prevent busy-looping */ - long left = - LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - sftp->requirev_start); - - if (left <= 0) { - sftp->requirev_start = 0; - return LIBSSH2_ERROR_TIMEOUT; - } - else if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - } - } - - sftp->requirev_start = 0; - - /* Only reached if the socket died */ - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* sftp_attr2bin - * Populate attributes into an SFTP block - */ -static ssize_t -sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs) -{ - unsigned char *s = p; - uint32_t flag_mask = - LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID | - LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME; - - /* TODO: When we add SFTP4+ functionality flag_mask can get additional - bits */ - - if (!attrs) { - _libssh2_htonu32(s, 0); - return 4; - } - - _libssh2_store_u32(&s, attrs->flags & flag_mask); - - if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { - _libssh2_store_u64(&s, attrs->filesize); - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { - _libssh2_store_u32(&s, attrs->uid); - _libssh2_store_u32(&s, attrs->gid); - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { - _libssh2_store_u32(&s, attrs->permissions); - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { - _libssh2_store_u32(&s, attrs->atime); - _libssh2_store_u32(&s, attrs->mtime); - } - - return (s - p); -} - -/* sftp_bin2attr - */ -static int -sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p) -{ - const unsigned char *s = p; - - memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - attrs->flags = _libssh2_ntohu32(s); - s += 4; - - if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { - attrs->filesize = _libssh2_ntohu64(s); - s += 8; - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { - attrs->uid = _libssh2_ntohu32(s); - s += 4; - attrs->gid = _libssh2_ntohu32(s); - s += 4; - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { - attrs->permissions = _libssh2_ntohu32(s); - s += 4; - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { - attrs->atime = _libssh2_ntohu32(s); - s += 4; - attrs->mtime = _libssh2_ntohu32(s); - s += 4; - } - - return (s - p); -} - -/* ************ - * SFTP API * - ************ */ - -LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor); - -/* libssh2_sftp_dtor - * Shutdown an SFTP stream when the channel closes - */ -LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor) -{ - LIBSSH2_SFTP *sftp = (LIBSSH2_SFTP *) (*channel_abstract); - - (void) session_abstract; - (void) channel; - - /* Free the partial packet storage for sftp_packet_read */ - if (sftp->partial_packet) { - LIBSSH2_FREE(session, sftp->partial_packet); - } - - /* Free the packet storage for _libssh2_sftp_packet_readdir */ - if (sftp->readdir_packet) { - LIBSSH2_FREE(session, sftp->readdir_packet); - } - - LIBSSH2_FREE(session, sftp); -} - -/* - * sftp_init - * - * Startup an SFTP session - */ -static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) -{ - unsigned char *data, *s; - size_t data_len; - ssize_t rc; - LIBSSH2_SFTP *sftp_handle; - - if (session->sftpInit_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Initializing SFTP subsystem"); - - /* - * The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the - * session struct are only to be used during the setup phase. As soon - * as the SFTP session is created they are cleared and can thus be - * re-used again to allow any amount of SFTP handles per sessions. - * - * Note that you MUST NOT try to call libssh2_sftp_init() again to get - * another handle until the previous call has finished and either - * succesffully made a handle or failed and returned error (not - * including *EAGAIN). - */ - - assert(session->sftpInit_sftp == NULL); - session->sftpInit_sftp = NULL; - session->sftpInit_state = libssh2_NB_state_created; - } - - sftp_handle = session->sftpInit_sftp; - - if (session->sftpInit_state == libssh2_NB_state_created) { - session->sftpInit_channel = - _libssh2_channel_open(session, "session", sizeof("session") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); - if (!session->sftpInit_channel) { - if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting up channel"); - } - else { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to startup channel"); - session->sftpInit_state = libssh2_NB_state_idle; - } - return NULL; - } - - session->sftpInit_state = libssh2_NB_state_sent; - } - - if (session->sftpInit_state == libssh2_NB_state_sent) { - int ret = _libssh2_channel_process_startup(session->sftpInit_channel, - "subsystem", - sizeof("subsystem") - 1, "sftp", - strlen("sftp")); - if (ret == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block to request SFTP subsystem"); - return NULL; - } else if (ret) { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to request SFTP subsystem"); - goto sftp_init_error; - } - - session->sftpInit_state = libssh2_NB_state_sent1; - } - - if (session->sftpInit_state == libssh2_NB_state_sent1) { - rc = _libssh2_channel_extended_data(session->sftpInit_channel, - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting handle extended data"); - return NULL; - } - - sftp_handle = - session->sftpInit_sftp = - LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP)); - if (!sftp_handle) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate a new SFTP structure"); - goto sftp_init_error; - } - memset(sftp_handle, 0, sizeof(LIBSSH2_SFTP)); - sftp_handle->channel = session->sftpInit_channel; - sftp_handle->request_id = 0; - - _libssh2_htonu32(session->sftpInit_buffer, 5); - session->sftpInit_buffer[4] = SSH_FXP_INIT; - _libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION); - session->sftpInit_sent = 0; /* nothing's sent yet */ - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Sending FXP_INIT packet advertising version %d support", - (int) LIBSSH2_SFTP_VERSION); - - session->sftpInit_state = libssh2_NB_state_sent2; - } - - if (session->sftpInit_state == libssh2_NB_state_sent2) { - /* sent off what's left of the init buffer to send */ - rc = _libssh2_channel_write(session->sftpInit_channel, 0, - session->sftpInit_buffer + - session->sftpInit_sent, - 9 - session->sftpInit_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending SSH_FXP_INIT"); - return NULL; - } - else if(rc < 0) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send SSH_FXP_INIT"); - goto sftp_init_error; - } - else { - /* add up the number of bytes sent */ - session->sftpInit_sent += rc; - - if(session->sftpInit_sent == 9) - /* move on */ - session->sftpInit_state = libssh2_NB_state_sent3; - - /* if less than 9, we remain in this state to send more later on */ - } - } - - rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION, - 0, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return NULL; - else if (rc) { - _libssh2_error(session, rc, - "Timeout waiting for response from SFTP subsystem"); - goto sftp_init_error; - } - if (data_len < 5) { - _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Invalid SSH_FXP_VERSION response"); - goto sftp_init_error; - } - - s = data + 1; - sftp_handle->version = _libssh2_ntohu32(s); - s += 4; - if (sftp_handle->version > LIBSSH2_SFTP_VERSION) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Truncating remote SFTP version from %lu", - sftp_handle->version); - sftp_handle->version = LIBSSH2_SFTP_VERSION; - } - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Enabling SFTP version %lu compatability", - sftp_handle->version); - while (s < (data + data_len)) { - size_t extname_len, extdata_len; - - extname_len = _libssh2_ntohu32(s); - s += 4; - /* the extension name starts here */ - s += extname_len; - - extdata_len = _libssh2_ntohu32(s); - s += 4; - - /* TODO: Actually process extensions */ - s += extdata_len; - - } - LIBSSH2_FREE(session, data); - - /* Make sure that when the channel gets closed, the SFTP service is shut - down too */ - sftp_handle->channel->abstract = sftp_handle; - sftp_handle->channel->close_cb = libssh2_sftp_dtor; - - session->sftpInit_state = libssh2_NB_state_idle; - - /* clear the sftp and channel pointers in this session struct now */ - session->sftpInit_sftp = NULL; - session->sftpInit_channel = NULL; - - _libssh2_list_init(&sftp_handle->sftp_handles); - - return sftp_handle; - - sftp_init_error: - while (_libssh2_channel_free(session->sftpInit_channel) == - LIBSSH2_ERROR_EAGAIN); - session->sftpInit_channel = NULL; - if (session->sftpInit_sftp) { - LIBSSH2_FREE(session, session->sftpInit_sftp); - session->sftpInit_sftp = NULL; - } - session->sftpInit_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_sftp_init - * - * Startup an SFTP session - */ -LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_SFTP *ptr; - - if(!session) - return NULL; - - if(!(session->state & LIBSSH2_STATE_AUTHENTICATED)) { - _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "session not authenticated yet"); - return NULL; - } - - BLOCK_ADJUST_ERRNO(ptr, session, sftp_init(session)); - return ptr; -} - -/* - * sftp_shutdown - * - * Shutsdown the SFTP subsystem - */ -static int -sftp_shutdown(LIBSSH2_SFTP *sftp) -{ - int rc; - LIBSSH2_SESSION *session = sftp->channel->session; - /* - * Make sure all memory used in the state variables are free - */ - if (sftp->partial_packet) { - LIBSSH2_FREE(session, sftp->partial_packet); - sftp->partial_packet = NULL; - } - if (sftp->open_packet) { - LIBSSH2_FREE(session, sftp->open_packet); - sftp->open_packet = NULL; - } - if (sftp->readdir_packet) { - LIBSSH2_FREE(session, sftp->readdir_packet); - sftp->readdir_packet = NULL; - } - if (sftp->fstat_packet) { - LIBSSH2_FREE(session, sftp->fstat_packet); - sftp->fstat_packet = NULL; - } - if (sftp->unlink_packet) { - LIBSSH2_FREE(session, sftp->unlink_packet); - sftp->unlink_packet = NULL; - } - if (sftp->rename_packet) { - LIBSSH2_FREE(session, sftp->rename_packet); - sftp->rename_packet = NULL; - } - if (sftp->fstatvfs_packet) { - LIBSSH2_FREE(session, sftp->fstatvfs_packet); - sftp->fstatvfs_packet = NULL; - } - if (sftp->statvfs_packet) { - LIBSSH2_FREE(session, sftp->statvfs_packet); - sftp->statvfs_packet = NULL; - } - if (sftp->mkdir_packet) { - LIBSSH2_FREE(session, sftp->mkdir_packet); - sftp->mkdir_packet = NULL; - } - if (sftp->rmdir_packet) { - LIBSSH2_FREE(session, sftp->rmdir_packet); - sftp->rmdir_packet = NULL; - } - if (sftp->stat_packet) { - LIBSSH2_FREE(session, sftp->stat_packet); - sftp->stat_packet = NULL; - } - if (sftp->symlink_packet) { - LIBSSH2_FREE(session, sftp->symlink_packet); - sftp->symlink_packet = NULL; - } - - sftp_packet_flush(sftp); - - /* TODO: We should consider walking over the sftp_handles list and kill - * any remaining sftp handles ... */ - - rc = _libssh2_channel_free(sftp->channel); - - return rc; -} - -/* libssh2_sftp_shutdown - * Shutsdown the SFTP subsystem - */ -LIBSSH2_API int -libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp)); - return rc; -} - -/* ******************************* - * SFTP File and Directory Ops * - ******************************* */ - -/* sftp_open - */ -static LIBSSH2_SFTP_HANDLE * -sftp_open(LIBSSH2_SFTP *sftp, const char *filename, - size_t filename_len, uint32_t flags, long mode, - int open_type) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - LIBSSH2_SFTP_HANDLE *fp; - LIBSSH2_SFTP_ATTRIBUTES attrs = { - LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0 - }; - unsigned char *s; - ssize_t rc; - int open_file = (open_type == LIBSSH2_SFTP_OPENFILE)?1:0; - - if (sftp->open_state == libssh2_NB_state_idle) { - /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) + - flags(4) */ - sftp->open_packet_len = filename_len + 13 + - (open_file? (4 + sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0); - - /* surprise! this starts out with nothing sent */ - sftp->open_packet_sent = 0; - s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len); - if (!sftp->open_packet) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_OPEN or " - "FXP_OPENDIR packet"); - return NULL; - } - /* Filetype in SFTP 3 and earlier */ - attrs.permissions = mode | - (open_file ? LIBSSH2_SFTP_ATTR_PFILETYPE_FILE : - LIBSSH2_SFTP_ATTR_PFILETYPE_DIR); - - _libssh2_store_u32(&s, sftp->open_packet_len - 4); - *(s++) = open_file? SSH_FXP_OPEN : SSH_FXP_OPENDIR; - sftp->open_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->open_request_id); - _libssh2_store_str(&s, filename, filename_len); - - if (open_file) { - _libssh2_store_u32(&s, flags); - s += sftp_attr2bin(s, &attrs); - } - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Sending %s open request", - open_file? "file" : "directory"); - - sftp->open_state = libssh2_NB_state_created; - } - - if (sftp->open_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->open_packet+ - sftp->open_packet_sent, - sftp->open_packet_len - - sftp->open_packet_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending FXP_OPEN or FXP_OPENDIR command"); - return NULL; - } - else if(rc < 0) { - _libssh2_error(session, rc, "Unable to send FXP_OPEN*"); - LIBSSH2_FREE(session, sftp->open_packet); - sftp->open_packet = NULL; - sftp->open_state = libssh2_NB_state_idle; - return NULL; - } - - /* bump the sent counter and remain in this state until the whole - data is off */ - sftp->open_packet_sent += rc; - - if(sftp->open_packet_len == sftp->open_packet_sent) { - LIBSSH2_FREE(session, sftp->open_packet); - sftp->open_packet = NULL; - - sftp->open_state = libssh2_NB_state_sent; - } - } - - if (sftp->open_state == libssh2_NB_state_sent) { - size_t data_len; - unsigned char *data; - static const unsigned char fopen_responses[2] = - { SSH_FXP_HANDLE, SSH_FXP_STATUS }; - rc = sftp_packet_requirev(sftp, 2, fopen_responses, - sftp->open_request_id, &data, - &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for status message"); - return NULL; - } - sftp->open_state = libssh2_NB_state_idle; - if (rc) { - _libssh2_error(session, rc, "Timeout waiting for status message"); - return NULL; - } - - /* OPEN can basically get STATUS or HANDLE back, where HANDLE implies - a fine response while STATUS means error. It seems though that at - times we get an SSH_FX_OK back in a STATUS, followed the "real" - HANDLE so we need to properly deal with that. */ - if (data[0] == SSH_FXP_STATUS) { - int badness = 1; - - if(data_len < 9) { - _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Too small FXP_STATUS"); - LIBSSH2_FREE(session, data); - return NULL; - } - - sftp->last_errno = _libssh2_ntohu32(data + 5); - - if(LIBSSH2_FX_OK == sftp->last_errno) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got HANDLE FXOK!"); - - LIBSSH2_FREE(session, data); - - /* silly situation, but check for a HANDLE */ - rc = sftp_packet_require(sftp, SSH_FXP_HANDLE, - sftp->open_request_id, &data, - &data_len); - if(rc == LIBSSH2_ERROR_EAGAIN) { - /* go back to sent state and wait for something else */ - sftp->open_state = libssh2_NB_state_sent; - return NULL; - } - else if(!rc) - /* we got the handle so this is not a bad situation */ - badness = 0; - } - - if(badness) { - _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Failed opening remote file"); - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got FXP_STATUS %d", - sftp->last_errno); - LIBSSH2_FREE(session, data); - return NULL; - } - } - - if(data_len < 10) { - _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Too small FXP_HANDLE"); - LIBSSH2_FREE(session, data); - return NULL; - } - - fp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE)); - if (!fp) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate new SFTP handle structure"); - LIBSSH2_FREE(session, data); - return NULL; - } - memset(fp, 0, sizeof(LIBSSH2_SFTP_HANDLE)); - fp->handle_type = open_file ? LIBSSH2_SFTP_HANDLE_FILE : - LIBSSH2_SFTP_HANDLE_DIR; - - fp->handle_len = _libssh2_ntohu32(data + 5); - if (fp->handle_len > SFTP_HANDLE_MAXLEN) - /* SFTP doesn't allow handles longer than 256 characters */ - fp->handle_len = SFTP_HANDLE_MAXLEN; - - if(fp->handle_len > (data_len - 9)) - /* do not reach beyond the end of the data we got */ - fp->handle_len = data_len - 9; - - memcpy(fp->handle, data + 9, fp->handle_len); - - LIBSSH2_FREE(session, data); - - /* add this file handle to the list kept in the sftp session */ - _libssh2_list_add(&sftp->sftp_handles, &fp->node); - - fp->sftp = sftp; /* point to the parent struct */ - - fp->u.file.offset = 0; - fp->u.file.offset_sent = 0; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Open command successful"); - return fp; - } - return NULL; -} - -/* libssh2_sftp_open_ex - */ -LIBSSH2_API LIBSSH2_SFTP_HANDLE * -libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename, - unsigned int filename_len, unsigned long flags, long mode, - int open_type) -{ - LIBSSH2_SFTP_HANDLE *hnd; - - if(!sftp) - return NULL; - - BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session, - sftp_open(sftp, filename, filename_len, flags, mode, - open_type)); - return hnd; -} - -/* - * sftp_read - * - * Read from an SFTP file handle - * - */ -static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, - size_t buffer_size) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t count = 0; - struct sftp_pipeline_chunk *chunk; - struct sftp_pipeline_chunk *next; - ssize_t rc; - struct _libssh2_sftp_handle_file_data *filep = - &handle->u.file; - - /* This function can be interrupted in three different places where it - might need to wait for data from the network. It returns EAGAIN to - allow non-blocking clients to do other work but these client are - expected to call this function again (possibly many times) to finish - the operation. - - The tricky part is that if we previously aborted a sftp_read due to - EAGAIN, we must continue at the same spot to continue the previously - interrupted operation. This is done using a state machine to record - what phase of execution we were at. The state is stored in - sftp->read_state. - - libssh2_NB_state_idle: The first phase is where we prepare multiple - FXP_READ packets to do optimistic read-ahead. We send off as many as - possible in the second phase without waiting for a response to each - one; this is the key to fast reads. But we may have to adjust the - channel window size to do this which may interrupt this function while - waiting. The state machine saves the phase as libssh2_NB_state_idle so - it returns here on the next call. - - libssh2_NB_state_sent: The second phase is where we send the FXP_READ - packets. Writing them to the channel can be interrupted with EAGAIN - but the state machine ensures we skip the first phase on the next call - and resume sending. - - libssh2_NB_state_sent2: In the third phase (indicated by ) we read the - data from the responses that have arrived so far. Reading can be - interrupted with EAGAIN but the state machine ensures we skip the first - and second phases on the next call and resume sending. - */ - - switch (sftp->read_state) { - case libssh2_NB_state_idle: - - /* Some data may already have been read from the server in the - previous call but didn't fit in the buffer at the time. If so, we - return that now as we can't risk being interrupted later with data - partially written to the buffer. */ - if(filep->data_left) { - size_t copy = MIN(buffer_size, filep->data_left); - - memcpy(buffer, &filep->data[ filep->data_len - filep->data_left], - copy); - - filep->data_left -= copy; - filep->offset += copy; - - if(!filep->data_left) { - LIBSSH2_FREE(session, filep->data); - filep->data = NULL; - } - - return copy; - } - - /* We allow a number of bytes being requested at any given time - without having been acked - until we reach EOF. */ - if(!filep->eof) { - /* Number of bytes asked for that haven't been acked yet */ - size_t already = (filep->offset_sent - filep->offset); - - size_t max_read_ahead = buffer_size*4; - unsigned long recv_window; - - if(max_read_ahead > LIBSSH2_CHANNEL_WINDOW_DEFAULT*4) - max_read_ahead = LIBSSH2_CHANNEL_WINDOW_DEFAULT*4; - - /* if the buffer_size passed in now is smaller than what has - already been sent, we risk getting count become a very large - number */ - if(max_read_ahead > already) - count = max_read_ahead - already; - - /* 'count' is how much more data to ask for, and 'already' is how - much data that already has been asked for but not yet returned. - Specificly, 'count' means how much data that have or will be - asked for by the nodes that are already added to the linked - list. Some of those read requests may not actually have been - sent off successfully yet. - - If 'already' is very large it should be perfectly fine to have - count set to 0 as then we don't have to ask for more data - (right now). - - buffer_size*4 is just picked more or less out of the air. The - idea is that when reading SFTP from a remote server, we send - away multiple read requests guessing that the client will read - more than only this 'buffer_size' amount of memory. So we ask - for maximum buffer_size*4 amount of data so that we can return - them very fast in subsequent calls. - */ - - recv_window = libssh2_channel_window_read_ex(sftp->channel, - NULL, NULL); - if(max_read_ahead > recv_window) { - /* more data will be asked for than what the window currently - allows, expand it! */ - - rc = _libssh2_channel_receive_window_adjust(sftp->channel, - max_read_ahead*8, - 1, NULL); - /* if this returns EAGAIN, we will get back to this function - at next call */ - assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->data_left); - assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->eof); - if (rc) - return rc; - } - } - - while(count > 0) { - unsigned char *s; - uint32_t size = MIN(MAX_SFTP_READ_SIZE, count); - - /* 25 = packet_len(4) + packet_type(1) + request_id(4) + - handle_len(4) + offset(8) + count(4) */ - uint32_t packet_len = (uint32_t)handle->handle_len + 25; - uint32_t request_id; - - chunk = LIBSSH2_ALLOC(session, packet_len + - sizeof(struct sftp_pipeline_chunk)); - if (!chunk) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "malloc fail for FXP_WRITE"); - - chunk->len = size; - chunk->lefttosend = packet_len; - chunk->sent = 0; - - s = chunk->packet; - - _libssh2_store_u32(&s, packet_len - 4); - *s++ = SSH_FXP_READ; - request_id = sftp->request_id++; - chunk->request_id = request_id; - _libssh2_store_u32(&s, request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - _libssh2_store_u64(&s, filep->offset_sent); - filep->offset_sent += size; /* advance offset at once */ - _libssh2_store_u32(&s, size); - - /* add this new entry LAST in the list */ - _libssh2_list_add(&handle->packet_list, &chunk->node); - count -= size; /* deduct the size we used, as we might have - to create more packets */ - } - - case libssh2_NB_state_sent: - - sftp->read_state = libssh2_NB_state_idle; - - /* move through the READ packets that haven't been sent and send as - many as possible - remember that we don't block */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - if(chunk->lefttosend) { - - rc = _libssh2_channel_write(channel, 0, - &chunk->packet[chunk->sent], - chunk->lefttosend); - if(rc < 0) { - sftp->read_state = libssh2_NB_state_sent; - return rc; - } - - /* remember where to continue sending the next time */ - chunk->lefttosend -= rc; - chunk->sent += rc; - - if(chunk->lefttosend) - /* data left to send, get out of loop */ - break; - } - - /* move on to the next chunk with data to send */ - chunk = _libssh2_list_next(&chunk->node); - } - - case libssh2_NB_state_sent2: - - sftp->read_state = libssh2_NB_state_idle; - - /* - * Count all ACKed packets and act on the contents of them. - */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - unsigned char *data; - size_t data_len; - uint32_t rc32; - static const unsigned char read_responses[2] = { - SSH_FXP_DATA, SSH_FXP_STATUS - }; - - if(chunk->lefttosend) - /* if the chunk still has data left to send, we shouldn't wait - for an ACK for it just yet */ - break; - - rc = sftp_packet_requirev(sftp, 2, read_responses, - chunk->request_id, &data, &data_len); - if (rc < 0) { - sftp->read_state = libssh2_NB_state_sent2; - return rc; - } - - /* - * We get DATA or STATUS back. STATUS can be error, or it is - * FX_EOF when we reach the end of the file. - */ - - switch (data[0]) { - case SSH_FXP_STATUS: - /* remove the chunk we just processed keeping track of the - * next one in case we need it */ - next = _libssh2_list_next(&chunk->node); - _libssh2_list_remove(&chunk->node); - LIBSSH2_FREE(session, chunk); - - /* we must remove all outstanding READ requests, as either we - got an error or we're at end of file */ - sftp_packetlist_flush(handle); - - rc32 = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (rc32 == LIBSSH2_FX_EOF) { - filep->eof = TRUE; - return 0; - } - else { - sftp->last_errno = rc32; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP READ error"); - } - break; - - case SSH_FXP_DATA: - rc32 = _libssh2_ntohu32(data + 5); - if (rc32 > (data_len - 9)) - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol badness"); - - if(rc32 != chunk->len) { - /* a short read does not imply end of file, but we must - adjust the offset_sent since it was advanced with a - full chunk->len before */ - filep->offset_sent -= (chunk->len - rc32); - } - - if(rc32 > buffer_size) { - /* figure out the overlap amount */ - filep->data_left = rc32 - buffer_size; - - /* getting the full packet would overflow the buffer, so - only get the correct amount and keep the remainder */ - rc32 = (uint32_t)buffer_size; - - /* store data to keep for next call */ - filep->data = data; - filep->data_len = data_len; - } - else - filep->data_len = 0; - - /* copy the received data from the received FXP_DATA packet to - the buffer at the correct index */ - memcpy(buffer, data + 9, rc32); - filep->offset += rc32; - - if(filep->data_len == 0) - /* free the allocated data if not stored to keep */ - LIBSSH2_FREE(session, data); - - - /* remove the chunk we just processed keeping track of the - * next one in case we need it */ - next = _libssh2_list_next(&chunk->node); - _libssh2_list_remove(&chunk->node); - LIBSSH2_FREE(session, chunk); - chunk = NULL; - - if(rc32 > 0) { - /* we must return as we wrote some data to the buffer */ - return rc32; - } else { - /* A zero-byte read is not necessarily EOF so we must not - * return 0 (that would signal EOF to the caller) so - * instead we carry on to the next chunk */ - chunk = next; - } - - break; - default: - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol badness: unrecognised " - "read request response"); - } - } - - break; - - default: - assert(!"State machine error; unrecognised read state"); - } - - return 0; -} - -/* libssh2_sftp_read - * Read from an SFTP file handle - */ -LIBSSH2_API ssize_t -libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *hnd, char *buffer, - size_t buffer_maxlen) -{ - ssize_t rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_read(hnd, buffer, buffer_maxlen)); - return rc; -} - -/* sftp_readdir - * Read from an SFTP directory handle - */ -static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, - size_t buffer_maxlen, char *longentry, - size_t longentry_maxlen, - LIBSSH2_SFTP_ATTRIBUTES *attrs) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - uint32_t num_names; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */ - uint32_t packet_len = handle->handle_len + 13; - unsigned char *s, *data; - static const unsigned char read_responses[2] = { - SSH_FXP_NAME, SSH_FXP_STATUS }; - ssize_t retcode; - - if (sftp->readdir_state == libssh2_NB_state_idle) { - if (handle->u.dir.names_left) { - /* - * A prior request returned more than one directory entry, - * feed it back from the buffer - */ - LIBSSH2_SFTP_ATTRIBUTES attrs_dummy; - size_t real_longentry_len; - size_t real_filename_len; - size_t filename_len; - size_t longentry_len; - - s = (unsigned char *) handle->u.dir.next_name; - real_filename_len = _libssh2_ntohu32(s); - - s += 4; - - filename_len = real_filename_len; - if (filename_len >= buffer_maxlen) { - filename_len = LIBSSH2_ERROR_BUFFER_TOO_SMALL; - goto end; - } - - memcpy(buffer, s, filename_len); - buffer[filename_len] = '\0'; /* zero terminate */ - s += real_filename_len; - - real_longentry_len = _libssh2_ntohu32(s); - s += 4; - - if (longentry && (longentry_maxlen>1)) { - longentry_len = real_longentry_len; - - if (longentry_len >= longentry_maxlen) { - filename_len = LIBSSH2_ERROR_BUFFER_TOO_SMALL; - goto end; - } - - memcpy(longentry, s, longentry_len); - longentry[longentry_len] = '\0'; /* zero terminate */ - } - s += real_longentry_len; - - if (attrs) - memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - - s += sftp_bin2attr(attrs ? attrs : &attrs_dummy, s); - - handle->u.dir.next_name = (char *) s; - end: - - if ((--handle->u.dir.names_left) == 0) - LIBSSH2_FREE(session, handle->u.dir.names_packet); - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "libssh2_sftp_readdir_ex() return %d", - filename_len); - return (ssize_t)filename_len; - } - - /* Request another entry(entries?) */ - - s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->readdir_packet) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "FXP_READDIR packet"); - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_READDIR; - sftp->readdir_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->readdir_request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - - sftp->readdir_state = libssh2_NB_state_created; - } - - if (sftp->readdir_state == libssh2_NB_state_created) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Reading entries from directory handle"); - retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet, - packet_len); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - return retcode; - } - else if ((ssize_t)packet_len != retcode) { - LIBSSH2_FREE(session, sftp->readdir_packet); - sftp->readdir_packet = NULL; - sftp->readdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - - LIBSSH2_FREE(session, sftp->readdir_packet); - sftp->readdir_packet = NULL; - - sftp->readdir_state = libssh2_NB_state_sent; - } - - retcode = sftp_packet_requirev(sftp, 2, read_responses, - sftp->readdir_request_id, &data, - &data_len); - if (retcode == LIBSSH2_ERROR_EAGAIN) - return retcode; - else if (retcode) { - sftp->readdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, retcode, - "Timeout waiting for status message"); - } - - if (data[0] == SSH_FXP_STATUS) { - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_EOF) { - sftp->readdir_state = libssh2_NB_state_idle; - return 0; - } - else { - sftp->last_errno = retcode; - sftp->readdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - sftp->readdir_state = libssh2_NB_state_idle; - - num_names = _libssh2_ntohu32(data + 5); - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned", - num_names); - if (!num_names) { - LIBSSH2_FREE(session, data); - return 0; - } - - handle->u.dir.names_left = num_names; - handle->u.dir.names_packet = data; - handle->u.dir.next_name = (char *) data + 9; - - /* use the name popping mechanism from the start of the function */ - return sftp_readdir(handle, buffer, buffer_maxlen, longentry, - longentry_maxlen, attrs); -} - -/* libssh2_sftp_readdir_ex - * Read from an SFTP directory handle - */ -LIBSSH2_API int -libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer, - size_t buffer_maxlen, char *longentry, - size_t longentry_maxlen, - LIBSSH2_SFTP_ATTRIBUTES *attrs) -{ - int rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_readdir(hnd, buffer, buffer_maxlen, longentry, - longentry_maxlen, attrs)); - return rc; -} - -/* - * sftp_write - * - * Write data to an SFTP handle. Returns the number of bytes written, or - * a negative error code. - * - * We recommend sending very large data buffers to this function! - * - * Concept: - * - * - Detect how much of the given buffer that was already sent in a previous - * call by inspecting the linked list of outgoing chunks. Make sure to skip - * passed the data that has already been taken care of. - * - * - Split all (new) outgoing data in chunks no larger than N. - * - * - Each N bytes chunk gets created as a separate SFTP packet. - * - * - Add all created outgoing packets to the linked list. - * - * - Walk through the list and send the chunks that haven't been sent, - * as many as possible until EAGAIN. Some of the chunks may have been put - * in the list in a previous invoke. - * - * - For all the chunks in the list that have been completely sent off, check - * for ACKs. If a chunk has been ACKed, it is removed from the linked - * list and the "acked" counter gets increased with that data amount. - * - * - Return TOTAL bytes acked so far. - * - * Caveats: - * - be careful: we must not return a higher number than what was given! - * - * TODO: - * Introduce an option that disables this sort of "speculative" ahead writing - * as there's a risk that it will do harm to some app. - */ - -static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, - size_t count) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - uint32_t retcode; - uint32_t packet_len; - unsigned char *s, *data; - ssize_t rc; - struct sftp_pipeline_chunk *chunk; - struct sftp_pipeline_chunk *next; - size_t acked = 0; - size_t org_count = count; - size_t already; - - switch(sftp->write_state) { - default: - case libssh2_NB_state_idle: - - /* Number of bytes sent off that haven't been acked and therefor we - will get passed in here again. - - Also, add up the number of bytes that actually already have been - acked but we haven't been able to return as such yet, so we will - get that data as well passed in here again. - */ - already = (handle->u.file.offset_sent - handle->u.file.offset)+ - handle->u.file.acked; - - if(count >= already) { - /* skip the part already made into packets */ - buffer += already; - count -= already; - } - else - /* there is more data already fine than what we got in this call */ - count = 0; - - sftp->write_state = libssh2_NB_state_idle; - while(count) { - /* TODO: Possibly this should have some logic to prevent a very - very small fraction to be left but lets ignore that for now */ - uint32_t size = MIN(MAX_SFTP_OUTGOING_SIZE, count); - uint32_t request_id; - - /* 25 = packet_len(4) + packet_type(1) + request_id(4) + - handle_len(4) + offset(8) + count(4) */ - packet_len = handle->handle_len + size + 25; - - chunk = LIBSSH2_ALLOC(session, packet_len + - sizeof(struct sftp_pipeline_chunk)); - if (!chunk) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "malloc fail for FXP_WRITE"); - - chunk->len = size; - chunk->sent = 0; - chunk->lefttosend = packet_len; - - s = chunk->packet; - _libssh2_store_u32(&s, packet_len - 4); - - *(s++) = SSH_FXP_WRITE; - request_id = sftp->request_id++; - chunk->request_id = request_id; - _libssh2_store_u32(&s, request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - _libssh2_store_u64(&s, handle->u.file.offset_sent); - handle->u.file.offset_sent += size; /* advance offset at once */ - _libssh2_store_str(&s, buffer, size); - - /* add this new entry LAST in the list */ - _libssh2_list_add(&handle->packet_list, &chunk->node); - - buffer += size; - count -= size; /* deduct the size we used, as we might have - to create more packets */ - } - - /* move through the WRITE packets that haven't been sent and send as many - as possible - remember that we don't block */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - if(chunk->lefttosend) { - rc = _libssh2_channel_write(channel, 0, - &chunk->packet[chunk->sent], - chunk->lefttosend); - if(rc < 0) - /* remain in idle state */ - return rc; - - /* remember where to continue sending the next time */ - chunk->lefttosend -= rc; - chunk->sent += rc; - - if(chunk->lefttosend) - /* data left to send, get out of loop */ - break; - } - - /* move on to the next chunk with data to send */ - chunk = _libssh2_list_next(&chunk->node); - } - - /* fall-through */ - case libssh2_NB_state_sent: - - sftp->write_state = libssh2_NB_state_idle; - /* - * Count all ACKed packets - */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - if(chunk->lefttosend) - /* if the chunk still has data left to send, we shouldn't wait - for an ACK for it just yet */ - break; - - else if(acked) - /* if we have sent data that is acked, we must return that - info before we call a function that might return EAGAIN */ - break; - - /* we check the packets in order */ - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, - chunk->request_id, &data, &data_len); - if (rc < 0) { - if (rc == LIBSSH2_ERROR_EAGAIN) - sftp->write_state = libssh2_NB_state_sent; - return rc; - } - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - sftp->last_errno = retcode; - if (retcode == LIBSSH2_FX_OK) { - acked += chunk->len; /* number of payload data that was acked - here */ - - /* we increase the offset value for all acks */ - handle->u.file.offset += chunk->len; - - next = _libssh2_list_next(&chunk->node); - - _libssh2_list_remove(&chunk->node); /* remove from list */ - LIBSSH2_FREE(session, chunk); /* free memory */ - - chunk = next; - } - else { - /* flush all pending packets from the outgoing list */ - sftp_packetlist_flush(handle); - - /* since we return error now, the applicaton will not get any - outstanding data acked, so we need to rewind the offset to - where the application knows it has reached with acked data */ - handle->u.file.offset -= handle->u.file.acked; - - /* then reset the offset_sent to be the same as the offset */ - handle->u.file.offset_sent = handle->u.file.offset; - - /* clear the acked counter since we can have no pending data to - ack after an error */ - handle->u.file.acked = 0; - - /* the server returned an error for that written chunk, propagate - this back to our parent function */ - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "FXP write failed"); - } - } - break; - } - - /* if there were acked data in a previous call that wasn't returned then, - add that up and try to return it all now. This can happen if the app - first sends a huge buffer of data, and then in a second call it sends a - smaller one. */ - acked += handle->u.file.acked; - - if(acked) { - ssize_t ret = MIN(acked, org_count); - /* we got data acked so return that amount, but no more than what - was asked to get sent! */ - - /* store the remainder. 'ret' is always equal to or less than 'acked' - here */ - handle->u.file.acked = acked - ret; - - return ret; - } - - else - return 0; /* nothing was acked, and no EAGAIN was received! */ -} - -/* libssh2_sftp_write - * Write data to a file handle - */ -LIBSSH2_API ssize_t -libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer, - size_t count) -{ - ssize_t rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_write(hnd, buffer, count)); - return rc; - -} - -/* - * sftp_fstat - * - * Get or Set stat on a file - */ -static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle, - LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */ - uint32_t packet_len = - handle->handle_len + 13 + (setstat ? sftp_attrsize(attrs->flags) : 0); - unsigned char *s, *data; - static const unsigned char fstat_responses[2] = - { SSH_FXP_ATTRS, SSH_FXP_STATUS }; - ssize_t rc; - - if (sftp->fstat_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command", - setstat ? "set-stat" : "stat"); - s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->fstat_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "FSTAT/FSETSTAT packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = setstat ? SSH_FXP_FSETSTAT : SSH_FXP_FSTAT; - sftp->fstat_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->fstat_request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - - if (setstat) { - s += sftp_attr2bin(s, attrs); - } - - sftp->fstat_state = libssh2_NB_state_created; - } - - if (sftp->fstat_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, sftp->fstat_packet); - sftp->fstat_packet = NULL; - sftp->fstat_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - (setstat ? "Unable to send FXP_FSETSTAT" - : "Unable to send FXP_FSTAT command")); - } - LIBSSH2_FREE(session, sftp->fstat_packet); - sftp->fstat_packet = NULL; - - sftp->fstat_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_requirev(sftp, 2, fstat_responses, - sftp->fstat_request_id, &data, - &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc) { - sftp->fstat_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Timeout waiting for status message"); - } - - sftp->fstat_state = libssh2_NB_state_idle; - - if (data[0] == SSH_FXP_STATUS) { - uint32_t retcode; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { - return 0; - } else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - sftp_bin2attr(attrs, data + 5); - LIBSSH2_FREE(session, data); - - return 0; -} - -/* libssh2_sftp_fstat_ex - * Get or Set stat on a file - */ -LIBSSH2_API int -libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *hnd, - LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat) -{ - int rc; - if(!hnd || !attrs) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_fstat(hnd, attrs, setstat)); - return rc; -} - - -/* libssh2_sftp_seek64 - * Set the read/write pointer to an arbitrary position within the file - */ -LIBSSH2_API void -libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset) -{ - if(handle) { - handle->u.file.offset = handle->u.file.offset_sent = offset; - /* discard all pending requests and currently read data */ - sftp_packetlist_flush(handle); - - /* free the left received buffered data */ - if (handle->u.file.data_left) { - LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data); - handle->u.file.data_left = handle->u.file.data_len = 0; - handle->u.file.data = NULL; - } - - /* reset EOF to False */ - handle->u.file.eof = FALSE; - } -} - -/* libssh2_sftp_seek - * Set the read/write pointer to an arbitrary position within the file - */ -LIBSSH2_API void -libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset) -{ - libssh2_sftp_seek64(handle, (libssh2_uint64_t)offset); -} - -/* libssh2_sftp_tell - * Return the current read/write pointer's offset - */ -LIBSSH2_API size_t -libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle) -{ - if(!handle) - return 0; /* no handle, no size */ - - /* NOTE: this may very well truncate the size if it is larger than what - size_t can hold, so libssh2_sftp_tell64() is really the function you - should use */ - return (size_t)(handle->u.file.offset); -} - -/* libssh2_sftp_tell64 - * Return the current read/write pointer's offset - */ -LIBSSH2_API libssh2_uint64_t -libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle) -{ - if(!handle) - return 0; /* no handle, no size */ - - return handle->u.file.offset; -} - -/* - * Flush all remaining incoming SFTP packets and zombies. - */ -static void sftp_packet_flush(LIBSSH2_SFTP *sftp) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets); - struct sftp_zombie_requests *zombie = - _libssh2_list_first(&sftp->zombie_requests); - - while(packet) { - LIBSSH2_SFTP_PACKET *next; - - /* check next struct in the list */ - next = _libssh2_list_next(&packet->node); - _libssh2_list_remove(&packet->node); - LIBSSH2_FREE(session, packet->data); - LIBSSH2_FREE(session, packet); - - packet = next; - } - - while(zombie) { - /* figure out the next node */ - struct sftp_zombie_requests *next = _libssh2_list_next(&zombie->node); - /* unlink the current one */ - _libssh2_list_remove(&zombie->node); - /* free the memory */ - LIBSSH2_FREE(session, zombie); - zombie = next; - } - -} - -/* sftp_close_handle - * - * Close a file or directory handle - * Also frees handle resource and unlinks it from the SFTP structure - */ -static int -sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */ - uint32_t packet_len = handle->handle_len + 13; - unsigned char *s, *data = NULL; - int rc; - - if (handle->close_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle"); - s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len); - if (!handle->close_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_CLOSE " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_CLOSE; - handle->close_request_id = sftp->request_id++; - _libssh2_store_u32(&s, handle->close_request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - handle->close_state = libssh2_NB_state_created; - } - - if (handle->close_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, handle->close_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, handle->close_packet); - handle->close_packet = NULL; - handle->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_CLOSE command"); - } - LIBSSH2_FREE(session, handle->close_packet); - handle->close_packet = NULL; - - handle->close_state = libssh2_NB_state_sent; - } - - if (handle->close_state == libssh2_NB_state_sent) { - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, - handle->close_request_id, &data, - &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - handle->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for status message"); - } - - handle->close_state = libssh2_NB_state_sent1; - } - - if(!data) - /* if it reaches this point with data unset, something unwanted - happened (like this function is called again when in - libssh2_NB_state_sent1 state) and we just bail out */ - return LIBSSH2_ERROR_INVAL; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (retcode != LIBSSH2_FX_OK) { - sftp->last_errno = retcode; - handle->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - - /* remove this handle from the parent's list */ - _libssh2_list_remove(&handle->node); - - if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) - && handle->u.dir.names_left) { - LIBSSH2_FREE(session, handle->u.dir.names_packet); - } - else { - if(handle->u.file.data) - LIBSSH2_FREE(session, handle->u.file.data); - } - - sftp_packetlist_flush(handle); - sftp->read_state = libssh2_NB_state_idle; - - handle->close_state = libssh2_NB_state_idle; - - LIBSSH2_FREE(session, handle); - - return 0; -} - -/* libssh2_sftp_close_handle - * - * Close a file or directory handle - * Also frees handle resource and unlinks it from the SFTP structure - */ -LIBSSH2_API int -libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *hnd) -{ - int rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_close_handle(hnd)); - return rc; -} - -/* sftp_unlink - * Delete a file from the remote server - */ -static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename, - size_t filename_len) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */ - uint32_t packet_len = filename_len + 13; - unsigned char *s, *data; - int rc; - - if (sftp->unlink_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename); - s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->unlink_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_REMOVE " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_REMOVE; - sftp->unlink_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->unlink_request_id); - _libssh2_store_str(&s, filename, filename_len); - sftp->unlink_state = libssh2_NB_state_created; - } - - if (sftp->unlink_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, sftp->unlink_packet); - sftp->unlink_packet = NULL; - sftp->unlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_REMOVE command"); - } - LIBSSH2_FREE(session, sftp->unlink_packet); - sftp->unlink_packet = NULL; - - sftp->unlink_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, - sftp->unlink_request_id, &data, - &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - else if (rc) { - sftp->unlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - sftp->unlink_state = libssh2_NB_state_idle; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (retcode == LIBSSH2_FX_OK) { - return 0; - } else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } -} - -/* libssh2_sftp_unlink_ex - * Delete a file from the remote server - */ -LIBSSH2_API int -libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename, - unsigned int filename_len) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_unlink(sftp, filename, filename_len)); - return rc; -} - -/* - * sftp_rename - * - * Rename a file on the remote server - */ -static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename, - unsigned int source_filename_len, - const char *dest_filename, - unsigned int dest_filename_len, long flags) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - int retcode; - uint32_t packet_len = - source_filename_len + dest_filename_len + 17 + (sftp->version >= - 5 ? 4 : 0); - /* packet_len(4) + packet_type(1) + request_id(4) + - source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */ - unsigned char *data; - ssize_t rc; - - if (sftp->version < 2) { - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Server does not support RENAME"); - } - - if (sftp->rename_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s", - source_filename, dest_filename); - sftp->rename_s = sftp->rename_packet = - LIBSSH2_ALLOC(session, packet_len); - if (!sftp->rename_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_RENAME " - "packet"); - } - - _libssh2_store_u32(&sftp->rename_s, packet_len - 4); - *(sftp->rename_s++) = SSH_FXP_RENAME; - sftp->rename_request_id = sftp->request_id++; - _libssh2_store_u32(&sftp->rename_s, sftp->rename_request_id); - _libssh2_store_str(&sftp->rename_s, source_filename, - source_filename_len); - _libssh2_store_str(&sftp->rename_s, dest_filename, dest_filename_len); - - if (sftp->version >= 5) - _libssh2_store_u32(&sftp->rename_s, flags); - - sftp->rename_state = libssh2_NB_state_created; - } - - if (sftp->rename_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->rename_packet, - sftp->rename_s - sftp->rename_packet); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, sftp->rename_packet); - sftp->rename_packet = NULL; - sftp->rename_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_RENAME command"); - } - LIBSSH2_FREE(session, sftp->rename_packet); - sftp->rename_packet = NULL; - - sftp->rename_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, - sftp->rename_request_id, &data, - &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->rename_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - sftp->rename_state = libssh2_NB_state_idle; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - sftp->last_errno = retcode; - - /* now convert the SFTP error code to libssh2 return code or error - message */ - switch (retcode) { - case LIBSSH2_FX_OK: - retcode = LIBSSH2_ERROR_NONE; - break; - - case LIBSSH2_FX_FILE_ALREADY_EXISTS: - retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "File already exists and " - "SSH_FXP_RENAME_OVERWRITE not specified"); - break; - - case LIBSSH2_FX_OP_UNSUPPORTED: - retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Operation Not Supported"); - break; - - default: - retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - break; - } - - return retcode; -} - -/* libssh2_sftp_rename_ex - * Rename a file on the remote server - */ -LIBSSH2_API int -libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename, - unsigned int source_filename_len, - const char *dest_filename, - unsigned int dest_filename_len, long flags) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_rename(sftp, source_filename, source_filename_len, - dest_filename, dest_filename_len, flags)); - return rc; -} - -/* - * sftp_fstatvfs - * - * Get file system statistics - */ -static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4) - + handle_len (4) */ - /* 20 = strlen ("fstatvfs@openssh.com") */ - uint32_t packet_len = handle->handle_len + 20 + 17; - unsigned char *packet, *s, *data; - ssize_t rc; - unsigned int flag; - - if (sftp->fstatvfs_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Getting file system statistics"); - s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_EXTENDED " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_EXTENDED; - sftp->fstatvfs_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->fstatvfs_request_id); - _libssh2_store_str(&s, "fstatvfs@openssh.com", 20); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - - sftp->fstatvfs_state = libssh2_NB_state_created; - } - else { - packet = sftp->fstatvfs_packet; - } - - if (sftp->fstatvfs_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN || - (0 <= rc && rc < (ssize_t)packet_len)) { - sftp->fstatvfs_packet = packet; - return LIBSSH2_ERROR_EAGAIN; - } - - LIBSSH2_FREE(session, packet); - sftp->fstatvfs_packet = NULL; - - if (rc < 0) { - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - sftp->fstatvfs_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_require(sftp, SSH_FXP_EXTENDED_REPLY, - sftp->fstatvfs_request_id, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP EXTENDED REPLY"); - } else if (data_len < 93) { - LIBSSH2_FREE(session, data); - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error: short response"); - } - - sftp->fstatvfs_state = libssh2_NB_state_idle; - - st->f_bsize = _libssh2_ntohu64(data + 5); - st->f_frsize = _libssh2_ntohu64(data + 13); - st->f_blocks = _libssh2_ntohu64(data + 21); - st->f_bfree = _libssh2_ntohu64(data + 29); - st->f_bavail = _libssh2_ntohu64(data + 37); - st->f_files = _libssh2_ntohu64(data + 45); - st->f_ffree = _libssh2_ntohu64(data + 53); - st->f_favail = _libssh2_ntohu64(data + 61); - st->f_fsid = _libssh2_ntohu64(data + 69); - flag = _libssh2_ntohu64(data + 77); - st->f_namemax = _libssh2_ntohu64(data + 85); - - st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY) - ? LIBSSH2_SFTP_ST_RDONLY : 0; - st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID) - ? LIBSSH2_SFTP_ST_NOSUID : 0; - - LIBSSH2_FREE(session, data); - return 0; -} - -/* libssh2_sftp_fstatvfs - * Get filesystem space and inode utilization (requires fstatvfs@openssh.com - * support on the server) - */ -LIBSSH2_API int -libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) -{ - int rc; - if(!handle || !st) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, handle->sftp->channel->session, sftp_fstatvfs(handle, st)); - return rc; -} - -/* - * sftp_statvfs - * - * Get file system statistics - */ -static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, LIBSSH2_SFTP_STATVFS *st) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4) - + path_len (4) */ - /* 19 = strlen ("statvfs@openssh.com") */ - uint32_t packet_len = path_len + 19 + 17; - unsigned char *packet, *s, *data; - ssize_t rc; - unsigned int flag; - - if (sftp->statvfs_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Getting file system statistics of %s", path); - s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_EXTENDED " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_EXTENDED; - sftp->statvfs_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->statvfs_request_id); - _libssh2_store_str(&s, "statvfs@openssh.com", 19); - _libssh2_store_str(&s, path, path_len); - - sftp->statvfs_state = libssh2_NB_state_created; - } - else { - packet = sftp->statvfs_packet; - } - - if (sftp->statvfs_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN || - (0 <= rc && rc < (ssize_t)packet_len)) { - sftp->statvfs_packet = packet; - return LIBSSH2_ERROR_EAGAIN; - } - - LIBSSH2_FREE(session, packet); - sftp->statvfs_packet = NULL; - - if (rc < 0) { - sftp->statvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - sftp->statvfs_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_require(sftp, SSH_FXP_EXTENDED_REPLY, - sftp->statvfs_request_id, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->statvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP EXTENDED REPLY"); - } else if (data_len < 93) { - LIBSSH2_FREE(session, data); - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error: short response"); - } - - sftp->statvfs_state = libssh2_NB_state_idle; - - st->f_bsize = _libssh2_ntohu64(data + 5); - st->f_frsize = _libssh2_ntohu64(data + 13); - st->f_blocks = _libssh2_ntohu64(data + 21); - st->f_bfree = _libssh2_ntohu64(data + 29); - st->f_bavail = _libssh2_ntohu64(data + 37); - st->f_files = _libssh2_ntohu64(data + 45); - st->f_ffree = _libssh2_ntohu64(data + 53); - st->f_favail = _libssh2_ntohu64(data + 61); - st->f_fsid = _libssh2_ntohu64(data + 69); - flag = _libssh2_ntohu64(data + 77); - st->f_namemax = _libssh2_ntohu64(data + 85); - - st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY) - ? LIBSSH2_SFTP_ST_RDONLY : 0; - st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID) - ? LIBSSH2_SFTP_ST_NOSUID : 0; - - LIBSSH2_FREE(session, data); - return 0; -} - -/* libssh2_sftp_statvfs_ex - * Get filesystem space and inode utilization (requires statvfs@openssh.com - * support on the server) - */ -LIBSSH2_API int -libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, - size_t path_len, LIBSSH2_SFTP_STATVFS *st) -{ - int rc; - if(!sftp || !st) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, sftp_statvfs(sftp, path, path_len, - st)); - return rc; -} - - -/* - * sftp_mkdir - * - * Create an SFTP directory - */ -static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, long mode) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - LIBSSH2_SFTP_ATTRIBUTES attrs = { - LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0 - }; - size_t data_len; - int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ - ssize_t packet_len = path_len + 13 + - sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS); - unsigned char *packet, *s, *data; - int rc; - - if (sftp->mkdir_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Creating directory %s with mode 0%lo", path, mode); - s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_MKDIR " - "packet"); - } - /* Filetype in SFTP 3 and earlier */ - attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR; - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_MKDIR; - sftp->mkdir_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->mkdir_request_id); - _libssh2_store_str(&s, path, path_len); - - s += sftp_attr2bin(s, &attrs); - - sftp->mkdir_state = libssh2_NB_state_created; - } - else { - packet = sftp->mkdir_packet; - } - - if (sftp->mkdir_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - sftp->mkdir_packet = packet; - return rc; - } - if (packet_len != rc) { - LIBSSH2_FREE(session, packet); - sftp->mkdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - LIBSSH2_FREE(session, packet); - sftp->mkdir_state = libssh2_NB_state_sent; - sftp->mkdir_packet = NULL; - } - - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id, - &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->mkdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - sftp->mkdir_state = libssh2_NB_state_idle; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (retcode == LIBSSH2_FX_OK) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!"); - return 0; - } else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } -} - -/* - * libssh2_sftp_mkdir_ex - * - * Create an SFTP directory - */ -LIBSSH2_API int -libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, long mode) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_mkdir(sftp, path, path_len, mode)); - return rc; -} - -/* sftp_rmdir - * Remove a directory - */ -static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ - ssize_t packet_len = path_len + 13; - unsigned char *s, *data; - int rc; - - if (sftp->rmdir_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s", - path); - s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->rmdir_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_RMDIR " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_RMDIR; - sftp->rmdir_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->rmdir_request_id); - _libssh2_store_str(&s, path, path_len); - - sftp->rmdir_state = libssh2_NB_state_created; - } - - if (sftp->rmdir_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (packet_len != rc) { - LIBSSH2_FREE(session, sftp->rmdir_packet); - sftp->rmdir_packet = NULL; - sftp->rmdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_RMDIR command"); - } - LIBSSH2_FREE(session, sftp->rmdir_packet); - sftp->rmdir_packet = NULL; - - sftp->rmdir_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, - sftp->rmdir_request_id, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->rmdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - sftp->rmdir_state = libssh2_NB_state_idle; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (retcode == LIBSSH2_FX_OK) { - return 0; - } else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } -} - -/* libssh2_sftp_rmdir_ex - * Remove a directory - */ -LIBSSH2_API int -libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_rmdir(sftp, path, path_len)); - return rc; -} - -/* sftp_stat - * Stat a file or symbolic link - */ -static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, int stat_type, - LIBSSH2_SFTP_ATTRIBUTES * attrs) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ - ssize_t packet_len = - path_len + 13 + - ((stat_type == - LIBSSH2_SFTP_SETSTAT) ? sftp_attrsize(attrs->flags) : 0); - unsigned char *s, *data; - static const unsigned char stat_responses[2] = - { SSH_FXP_ATTRS, SSH_FXP_STATUS }; - int rc; - - if (sftp->stat_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s", - (stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" : - (stat_type == - LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path); - s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->stat_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_*STAT " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - - switch (stat_type) { - case LIBSSH2_SFTP_SETSTAT: - *(s++) = SSH_FXP_SETSTAT; - break; - - case LIBSSH2_SFTP_LSTAT: - *(s++) = SSH_FXP_LSTAT; - break; - - case LIBSSH2_SFTP_STAT: - default: - *(s++) = SSH_FXP_STAT; - } - sftp->stat_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->stat_request_id); - _libssh2_store_str(&s, path, path_len); - - if (stat_type == LIBSSH2_SFTP_SETSTAT) - s += sftp_attr2bin(s, attrs); - - sftp->stat_state = libssh2_NB_state_created; - } - - if (sftp->stat_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (packet_len != rc) { - LIBSSH2_FREE(session, sftp->stat_packet); - sftp->stat_packet = NULL; - sftp->stat_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send STAT/LSTAT/SETSTAT command"); - } - LIBSSH2_FREE(session, sftp->stat_packet); - sftp->stat_packet = NULL; - - sftp->stat_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_requirev(sftp, 2, stat_responses, - sftp->stat_request_id, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc) { - sftp->stat_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Timeout waiting for status message"); - } - - sftp->stat_state = libssh2_NB_state_idle; - - if (data[0] == SSH_FXP_STATUS) { - int retcode; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { - return 0; - } else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - sftp_bin2attr(attrs, data + 5); - LIBSSH2_FREE(session, data); - - return 0; -} - -/* libssh2_sftp_stat_ex - * Stat a file or symbolic link - */ -LIBSSH2_API int -libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, int stat_type, - LIBSSH2_SFTP_ATTRIBUTES *attrs) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_stat(sftp, path, path_len, stat_type, attrs)); - return rc; -} - -/* sftp_symlink - * Read or set a symlink - */ -static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, char *target, - unsigned int target_len, int link_type) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len, link_len; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ - ssize_t packet_len = - path_len + 13 + - ((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0); - unsigned char *s, *data; - static const unsigned char link_responses[2] = - { SSH_FXP_NAME, SSH_FXP_STATUS }; - int retcode; - - if ((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) { - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Server does not support SYMLINK or READLINK"); - } - - if (sftp->symlink_state == libssh2_NB_state_idle) { - s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->symlink_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "SYMLINK/READLINK/REALPATH packet"); - } - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s on %s", - (link_type == - LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading", - (link_type == - LIBSSH2_SFTP_REALPATH) ? "realpath" : "symlink", path); - - _libssh2_store_u32(&s, packet_len - 4); - - switch (link_type) { - case LIBSSH2_SFTP_REALPATH: - *(s++) = SSH_FXP_REALPATH; - break; - - case LIBSSH2_SFTP_SYMLINK: - *(s++) = SSH_FXP_SYMLINK; - break; - - case LIBSSH2_SFTP_READLINK: - default: - *(s++) = SSH_FXP_READLINK; - } - sftp->symlink_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->symlink_request_id); - _libssh2_store_str(&s, path, path_len); - - if (link_type == LIBSSH2_SFTP_SYMLINK) - _libssh2_store_str(&s, target, target_len); - - sftp->symlink_state = libssh2_NB_state_created; - } - - if (sftp->symlink_state == libssh2_NB_state_created) { - ssize_t rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (packet_len != rc) { - LIBSSH2_FREE(session, sftp->symlink_packet); - sftp->symlink_packet = NULL; - sftp->symlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send SYMLINK/READLINK command"); - } - LIBSSH2_FREE(session, sftp->symlink_packet); - sftp->symlink_packet = NULL; - - sftp->symlink_state = libssh2_NB_state_sent; - } - - retcode = sftp_packet_requirev(sftp, 2, link_responses, - sftp->symlink_request_id, &data, - &data_len); - if (retcode == LIBSSH2_ERROR_EAGAIN) - return retcode; - else if (retcode) { - sftp->symlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, retcode, - "Error waiting for status message"); - } - - sftp->symlink_state = libssh2_NB_state_idle; - - if (data[0] == SSH_FXP_STATUS) { - int retcode; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) - return LIBSSH2_ERROR_NONE; - else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - if (_libssh2_ntohu32(data + 5) < 1) { - LIBSSH2_FREE(session, data); - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Invalid READLINK/REALPATH response, " - "no name entries"); - } - - /* this reads a u32 and stores it into a signed 32bit value */ - link_len = _libssh2_ntohu32(data + 9); - if (link_len < target_len) { - memcpy(target, data + 13, link_len); - target[link_len] = 0; - retcode = (int)link_len; - } - else - retcode = LIBSSH2_ERROR_BUFFER_TOO_SMALL; - LIBSSH2_FREE(session, data); - - return retcode; -} - -/* libssh2_sftp_symlink_ex - * Read or set a symlink - */ -LIBSSH2_API int -libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, char *target, - unsigned int target_len, int link_type) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_symlink(sftp, path, path_len, target, target_len, - link_type)); - return rc; -} - -/* libssh2_sftp_last_error - * Returns the last error code reported by SFTP - */ -LIBSSH2_API unsigned long -libssh2_sftp_last_error(LIBSSH2_SFTP *sftp) -{ - if(!sftp) - return 0; - - return sftp->last_errno; -} - -/* libssh2_sftp_get_channel - * Return the channel of sftp, then caller can control the channel's behavior. - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp) -{ - if (!sftp) - return NULL; - - return sftp->channel; -} diff --git a/vendor/libssh2-1.4.2/src/sftp.h b/vendor/libssh2-1.4.2/src/sftp.h deleted file mode 100644 index 55bdb46..0000000 --- a/vendor/libssh2-1.4.2/src/sftp.h +++ /dev/null @@ -1,230 +0,0 @@ -#ifndef _LIBSSH2_SFTP_H -#define _LIBSSH2_SFTP_H -/* - * Copyright (C) 2010 - 2012 by Daniel Stenberg - * Author: Daniel Stenberg - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - * - */ - -/* - * MAX_SFTP_OUTGOING_SIZE MUST not be larger than 32500 or so. This is the - * amount of data sent in each FXP_WRITE packet - */ -#define MAX_SFTP_OUTGOING_SIZE 30000 - -/* MAX_SFTP_READ_SIZE is how much data is asked for at max in each FXP_READ - * packets. - */ -#define MAX_SFTP_READ_SIZE 2000 - -struct sftp_pipeline_chunk { - struct list_node node; - size_t len; /* WRITE: size of the data to write - READ: how many bytes that was asked for */ - size_t sent; - ssize_t lefttosend; /* if 0, the entire packet has been sent off */ - uint32_t request_id; - unsigned char packet[1]; /* data */ -}; - -struct sftp_zombie_requests { - struct list_node node; - uint32_t request_id; -}; - -#ifndef MIN -#define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -struct _LIBSSH2_SFTP_PACKET -{ - struct list_node node; /* linked list header */ - uint32_t request_id; - unsigned char *data; - size_t data_len; /* payload size */ -}; - -typedef struct _LIBSSH2_SFTP_PACKET LIBSSH2_SFTP_PACKET; - -#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */ - -struct _LIBSSH2_SFTP_HANDLE -{ - struct list_node node; - - LIBSSH2_SFTP *sftp; - - char handle[SFTP_HANDLE_MAXLEN]; - size_t handle_len; - - enum { - LIBSSH2_SFTP_HANDLE_FILE, - LIBSSH2_SFTP_HANDLE_DIR - } handle_type; - - union _libssh2_sftp_handle_data - { - struct _libssh2_sftp_handle_file_data - { - libssh2_uint64_t offset; - libssh2_uint64_t offset_sent; - size_t acked; /* container for acked data that hasn't been - returned to caller yet, used for sftp_write */ - - /* 'data' is used by sftp_read() and is allocated data that has - been received already from the server but wasn't returned to - the caller yet. It is of size 'data_len' and 'data_left is the - number of bytes not yet returned, counted from the end of the - buffer. */ - unsigned char *data; - size_t data_len; - size_t data_left; - - char eof; /* we have read to the end */ - } file; - struct _libssh2_sftp_handle_dir_data - { - uint32_t names_left; - void *names_packet; - char *next_name; - } dir; - } u; - - /* State variables used in libssh2_sftp_close_handle() */ - libssh2_nonblocking_states close_state; - uint32_t close_request_id; - unsigned char *close_packet; - - /* list of outstanding packets sent to server */ - struct list_head packet_list; - -}; - -struct _LIBSSH2_SFTP -{ - LIBSSH2_CHANNEL *channel; - - uint32_t request_id, version; - - struct list_head packets; - - /* List of FXP_READ responses to ignore because EOF already received. */ - struct list_head zombie_requests; - - /* a list of _LIBSSH2_SFTP_HANDLE structs */ - struct list_head sftp_handles; - - uint32_t last_errno; - - /* Holder for partial packet, use in libssh2_sftp_packet_read() */ - unsigned char partial_size[4]; /* buffer for size field */ - size_t partial_size_len; /* size field length */ - unsigned char *partial_packet; /* The data */ - uint32_t partial_len; /* Desired number of bytes */ - size_t partial_received; /* Bytes received so far */ - - /* Time that libssh2_sftp_packet_requirev() started reading */ - time_t requirev_start; - - /* State variables used in libssh2_sftp_open_ex() */ - libssh2_nonblocking_states open_state; - unsigned char *open_packet; - uint32_t open_packet_len; /* 32 bit on the wire */ - size_t open_packet_sent; - uint32_t open_request_id; - - /* State variable used in sftp_read() */ - libssh2_nonblocking_states read_state; - - /* State variable used in sftp_packet_read() */ - libssh2_nonblocking_states packet_state; - - /* State variable used in sftp_write() */ - libssh2_nonblocking_states write_state; - - /* State variables used in libssh2_sftp_readdir() */ - libssh2_nonblocking_states readdir_state; - unsigned char *readdir_packet; - uint32_t readdir_request_id; - - /* State variables used in libssh2_sftp_fstat_ex() */ - libssh2_nonblocking_states fstat_state; - unsigned char *fstat_packet; - uint32_t fstat_request_id; - - /* State variables used in libssh2_sftp_unlink_ex() */ - libssh2_nonblocking_states unlink_state; - unsigned char *unlink_packet; - uint32_t unlink_request_id; - - /* State variables used in libssh2_sftp_rename_ex() */ - libssh2_nonblocking_states rename_state; - unsigned char *rename_packet; - unsigned char *rename_s; - uint32_t rename_request_id; - - /* State variables used in libssh2_sftp_fstatvfs() */ - libssh2_nonblocking_states fstatvfs_state; - unsigned char *fstatvfs_packet; - uint32_t fstatvfs_request_id; - - /* State variables used in libssh2_sftp_statvfs() */ - libssh2_nonblocking_states statvfs_state; - unsigned char *statvfs_packet; - uint32_t statvfs_request_id; - - /* State variables used in libssh2_sftp_mkdir() */ - libssh2_nonblocking_states mkdir_state; - unsigned char *mkdir_packet; - uint32_t mkdir_request_id; - - /* State variables used in libssh2_sftp_rmdir() */ - libssh2_nonblocking_states rmdir_state; - unsigned char *rmdir_packet; - uint32_t rmdir_request_id; - - /* State variables used in libssh2_sftp_stat() */ - libssh2_nonblocking_states stat_state; - unsigned char *stat_packet; - uint32_t stat_request_id; - - /* State variables used in libssh2_sftp_symlink() */ - libssh2_nonblocking_states symlink_state; - unsigned char *symlink_packet; - uint32_t symlink_request_id; -}; - -#endif diff --git a/vendor/libssh2-1.4.2/src/transport.c b/vendor/libssh2-1.4.2/src/transport.c deleted file mode 100644 index 95b9a3a..0000000 --- a/vendor/libssh2-1.4.2/src/transport.c +++ /dev/null @@ -1,873 +0,0 @@ -/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2009-2010 by Daniel Stenberg - * Author: Daniel Stenberg - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 file handles reading and writing to the SECSH transport layer. RFC4253. - */ - -#include "libssh2_priv.h" -#include -#include -#include -#ifdef LIBSSH2DEBUG -#include -#endif - -#include - -#include "transport.h" -#include "mac.h" - -#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */ -#define MAX_MACSIZE 20 /* MUST fit biggest MAC length we support */ - -#ifdef LIBSSH2DEBUG -#define UNPRINTABLE_CHAR '.' -static void -debugdump(LIBSSH2_SESSION * session, - const char *desc, const unsigned char *ptr, size_t size) -{ - size_t i; - size_t c; - unsigned int width = 0x10; - char buffer[256]; /* Must be enough for width*4 + about 30 or so */ - size_t used; - static const char* hex_chars = "0123456789ABCDEF"; - - if (!(session->showmask & LIBSSH2_TRACE_TRANS)) { - /* not asked for, bail out */ - return; - } - - used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n", - desc, (int) size); - if (session->tracehandler) - (session->tracehandler)(session, session->tracehandler_context, - buffer, used); - else - fprintf(stderr, "%s", buffer); - - for(i = 0; i < size; i += width) { - - used = snprintf(buffer, sizeof(buffer), "%04lx: ", (long)i); - - /* hex not disabled, show it */ - for(c = 0; c < width; c++) { - if (i + c < size) { - buffer[used++] = hex_chars[(ptr[i+c] >> 4) & 0xF]; - buffer[used++] = hex_chars[ptr[i+c] & 0xF]; - } - else { - buffer[used++] = ' '; - buffer[used++] = ' '; - } - - buffer[used++] = ' '; - if ((width/2) - 1 == c) - buffer[used++] = ' '; - } - - buffer[used++] = ':'; - buffer[used++] = ' '; - - for(c = 0; (c < width) && (i + c < size); c++) { - buffer[used++] = isprint(ptr[i + c]) ? - ptr[i + c] : UNPRINTABLE_CHAR; - } - buffer[used++] = '\n'; - buffer[used] = 0; - - if (session->tracehandler) - (session->tracehandler)(session, session->tracehandler_context, - buffer, used); - else - fprintf(stderr, "%s", buffer); - } -} -#else -#define debugdump(a,x,y,z) -#endif - - -/* decrypt() decrypts 'len' bytes from 'source' to 'dest'. - * - * returns 0 on success and negative on failure - */ - -static int -decrypt(LIBSSH2_SESSION * session, unsigned char *source, - unsigned char *dest, int len) -{ - struct transportpacket *p = &session->packet; - int blocksize = session->remote.crypt->blocksize; - - /* if we get called with a len that isn't an even number of blocksizes - we risk losing those extra bytes */ - assert((len % blocksize) == 0); - - while (len >= blocksize) { - if (session->remote.crypt->crypt(session, source, - &session->remote.crypt_abstract)) { - LIBSSH2_FREE(session, p->payload); - return LIBSSH2_ERROR_DECRYPT; - } - - /* if the crypt() function would write to a given address it - wouldn't have to memcpy() and we could avoid this memcpy() - too */ - memcpy(dest, source, blocksize); - - len -= blocksize; /* less bytes left */ - dest += blocksize; /* advance write pointer */ - source += blocksize; /* advance read pointer */ - } - return LIBSSH2_ERROR_NONE; /* all is fine */ -} - -/* - * fullpacket() gets called when a full packet has been received and properly - * collected. - */ -static int -fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) -{ - unsigned char macbuf[MAX_MACSIZE]; - struct transportpacket *p = &session->packet; - int rc; - - if (session->fullpacket_state == libssh2_NB_state_idle) { - session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED; - session->fullpacket_payload_len = p->packet_length - 1; - - if (encrypted) { - - /* Calculate MAC hash */ - session->remote.mac->hash(session, macbuf, /* store hash here */ - session->remote.seqno, - p->init, 5, - p->payload, - session->fullpacket_payload_len, - &session->remote.mac_abstract); - - /* Compare the calculated hash with the MAC we just read from - * the network. The read one is at the very end of the payload - * buffer. Note that 'payload_len' here is the packet_length - * field which includes the padding but not the MAC. - */ - if (memcmp(macbuf, p->payload + session->fullpacket_payload_len, - session->remote.mac->mac_len)) { - session->fullpacket_macstate = LIBSSH2_MAC_INVALID; - } - } - - session->remote.seqno++; - - /* ignore the padding */ - session->fullpacket_payload_len -= p->padding_length; - - /* Check for and deal with decompression */ - if (session->remote.comp && - session->remote.comp->compress && - session->remote.comp_abstract) { - /* - * The buffer for the decompression (remote.comp_abstract) is - * initialised in time when it is needed so as long it is NULL we - * cannot decompress. - */ - - unsigned char *data; - size_t data_len; - rc = session->remote.comp->decomp(session, - &data, &data_len, - LIBSSH2_PACKET_MAXDECOMP, - p->payload, - session->fullpacket_payload_len, - &session->remote.comp_abstract); - LIBSSH2_FREE(session, p->payload); - if(rc) - return rc; - - p->payload = data; - session->fullpacket_payload_len = data_len; - } - - session->fullpacket_packet_type = p->payload[0]; - - debugdump(session, "libssh2_transport_read() plain", - p->payload, session->fullpacket_payload_len); - - session->fullpacket_state = libssh2_NB_state_created; - } - - if (session->fullpacket_state == libssh2_NB_state_created) { - rc = _libssh2_packet_add(session, p->payload, - session->fullpacket_payload_len, - session->fullpacket_macstate); - if (rc) - return rc; - } - - session->fullpacket_state = libssh2_NB_state_idle; - - return session->fullpacket_packet_type; -} - - -/* - * _libssh2_transport_read - * - * Collect a packet into the input queue. - * - * Returns packet type added to input queue (0 if nothing added), or a - * negative error number. - */ - -/* - * This function reads the binary stream as specified in chapter 6 of RFC4253 - * "The Secure Shell (SSH) Transport Layer Protocol" - * - * DOES NOT call _libssh2_error() for ANY error case. - */ -int _libssh2_transport_read(LIBSSH2_SESSION * session) -{ - int rc; - struct transportpacket *p = &session->packet; - int remainbuf; - int remainpack; - int numbytes; - int numdecrypt; - unsigned char block[MAX_BLOCKSIZE]; - int blocksize; - int encrypted = 1; - size_t total_num; - - /* default clear the bit */ - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; - - /* - * All channels, systems, subsystems, etc eventually make it down here - * when looking for more incoming data. If a key exchange is going on - * (LIBSSH2_STATE_EXCHANGING_KEYS bit is set) then the remote end will - * ONLY send key exchange related traffic. In non-blocking mode, there is - * a chance to break out of the kex_exchange function with an EAGAIN - * status, and never come back to it. If LIBSSH2_STATE_EXCHANGING_KEYS is - * active, then we must redirect to the key exchange. However, if - * kex_exchange is active (as in it is the one that calls this execution - * of packet_read, then don't redirect, as that would be an infinite loop! - */ - - if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS && - !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) { - - /* Whoever wants a packet won't get anything until the key re-exchange - * is done! - */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the" - " key re-exchange from _libssh2_transport_read"); - rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc) - return rc; - } - - /* - * =============================== NOTE =============================== - * I know this is very ugly and not a really good use of "goto", but - * this case statement would be even uglier to do it any other way - */ - if (session->readPack_state == libssh2_NB_state_jump1) { - session->readPack_state = libssh2_NB_state_idle; - encrypted = session->readPack_encrypted; - goto libssh2_transport_read_point1; - } - - do { - if (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { - return LIBSSH2_ERROR_NONE; - } - - if (session->state & LIBSSH2_STATE_NEWKEYS) { - blocksize = session->remote.crypt->blocksize; - } else { - encrypted = 0; /* not encrypted */ - blocksize = 5; /* not strictly true, but we can use 5 here to - make the checks below work fine still */ - } - - /* read/use a whole big chunk into a temporary area stored in - the LIBSSH2_SESSION struct. We will decrypt data from that - buffer into the packet buffer so this temp one doesn't have - to be able to keep a whole SSH packet, just be large enough - so that we can read big chunks from the network layer. */ - - /* how much data there is remaining in the buffer to deal with - before we should read more from the network */ - remainbuf = p->writeidx - p->readidx; - - /* if remainbuf turns negative we have a bad internal error */ - assert(remainbuf >= 0); - - if (remainbuf < blocksize) { - /* If we have less than a blocksize left, it is too - little data to deal with, read more */ - ssize_t nread; - - /* move any remainder to the start of the buffer so - that we can do a full refill */ - if (remainbuf) { - memmove(p->buf, &p->buf[p->readidx], remainbuf); - p->readidx = 0; - p->writeidx = remainbuf; - } else { - /* nothing to move, just zero the indexes */ - p->readidx = p->writeidx = 0; - } - - /* now read a big chunk from the network into the temp buffer */ - nread = - LIBSSH2_RECV(session, &p->buf[remainbuf], - PACKETBUFSIZE - remainbuf, - LIBSSH2_SOCKET_RECV_FLAGS(session)); - if (nread <= 0) { - /* check if this is due to EAGAIN and return the special - return code if so, error out normally otherwise */ - if ((nread < 0) && (nread == -EAGAIN)) { - session->socket_block_directions |= - LIBSSH2_SESSION_BLOCK_INBOUND; - return LIBSSH2_ERROR_EAGAIN; - } - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes (got %d)", - PACKETBUFSIZE - remainbuf, -nread); - return LIBSSH2_ERROR_SOCKET_RECV; - } - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Recved %d/%d bytes to %p+%d", nread, - PACKETBUFSIZE - remainbuf, p->buf, remainbuf); - - debugdump(session, "libssh2_transport_read() raw", - &p->buf[remainbuf], nread); - /* advance write pointer */ - p->writeidx += nread; - - /* update remainbuf counter */ - remainbuf = p->writeidx - p->readidx; - } - - /* how much data to deal with from the buffer */ - numbytes = remainbuf; - - if (!p->total_num) { - /* No payload package area allocated yet. To know the - size of this payload, we need to decrypt the first - blocksize data. */ - - if (numbytes < blocksize) { - /* we can't act on anything less than blocksize, but this - check is only done for the initial block since once we have - got the start of a block we can in fact deal with fractions - */ - session->socket_block_directions |= - LIBSSH2_SESSION_BLOCK_INBOUND; - return LIBSSH2_ERROR_EAGAIN; - } - - if (encrypted) { - rc = decrypt(session, &p->buf[p->readidx], block, blocksize); - if (rc != LIBSSH2_ERROR_NONE) { - return rc; - } - /* save the first 5 bytes of the decrypted package, to be - used in the hash calculation later down. */ - memcpy(p->init, &p->buf[p->readidx], 5); - } else { - /* the data is plain, just copy it verbatim to - the working block buffer */ - memcpy(block, &p->buf[p->readidx], blocksize); - } - - /* advance the read pointer */ - p->readidx += blocksize; - - /* we now have the initial blocksize bytes decrypted, - * and we can extract packet and padding length from it - */ - p->packet_length = _libssh2_ntohu32(block); - if (p->packet_length < 1) - return LIBSSH2_ERROR_DECRYPT; - - p->padding_length = block[4]; - - /* total_num is the number of bytes following the initial - (5 bytes) packet length and padding length fields */ - total_num = - p->packet_length - 1 + - (encrypted ? session->remote.mac->mac_len : 0); - - /* RFC4253 section 6.1 Maximum Packet Length says: - * - * "All implementations MUST be able to process - * packets with uncompressed payload length of 32768 - * bytes or less and total packet size of 35000 bytes - * or less (including length, padding length, payload, - * padding, and MAC.)." - */ - if (total_num > LIBSSH2_PACKET_MAXPAYLOAD) { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; - } - - /* Get a packet handle put data into. We get one to - hold all data, including padding and MAC. */ - p->payload = LIBSSH2_ALLOC(session, total_num); - if (!p->payload) { - return LIBSSH2_ERROR_ALLOC; - } - p->total_num = total_num; - /* init write pointer to start of payload buffer */ - p->wptr = p->payload; - - if (blocksize > 5) { - /* copy the data from index 5 to the end of - the blocksize from the temporary buffer to - the start of the decrypted buffer */ - memcpy(p->wptr, &block[5], blocksize - 5); - p->wptr += blocksize - 5; /* advance write pointer */ - } - - /* init the data_num field to the number of bytes of - the package read so far */ - p->data_num = p->wptr - p->payload; - - /* we already dealt with a blocksize worth of data */ - numbytes -= blocksize; - } - - /* how much there is left to add to the current payload - package */ - remainpack = p->total_num - p->data_num; - - if (numbytes > remainpack) { - /* if we have more data in the buffer than what is going into this - particular packet, we limit this round to this packet only */ - numbytes = remainpack; - } - - if (encrypted) { - /* At the end of the incoming stream, there is a MAC, - and we don't want to decrypt that since we need it - "raw". We MUST however decrypt the padding data - since it is used for the hash later on. */ - int skip = session->remote.mac->mac_len; - - /* if what we have plus numbytes is bigger than the - total minus the skip margin, we should lower the - amount to decrypt even more */ - if ((p->data_num + numbytes) > (p->total_num - skip)) { - numdecrypt = (p->total_num - skip) - p->data_num; - } else { - int frac; - numdecrypt = numbytes; - frac = numdecrypt % blocksize; - if (frac) { - /* not an aligned amount of blocks, - align it */ - numdecrypt -= frac; - /* and make it no unencrypted data - after it */ - numbytes = 0; - } - } - } else { - /* unencrypted data should not be decrypted at all */ - numdecrypt = 0; - } - - /* if there are bytes to decrypt, do that */ - if (numdecrypt > 0) { - /* now decrypt the lot */ - rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt); - if (rc != LIBSSH2_ERROR_NONE) { - return rc; - } - - /* advance the read pointer */ - p->readidx += numdecrypt; - /* advance write pointer */ - p->wptr += numdecrypt; - /* increse data_num */ - p->data_num += numdecrypt; - - /* bytes left to take care of without decryption */ - numbytes -= numdecrypt; - } - - /* if there are bytes to copy that aren't decrypted, simply - copy them as-is to the target buffer */ - if (numbytes > 0) { - memcpy(p->wptr, &p->buf[p->readidx], numbytes); - - /* advance the read pointer */ - p->readidx += numbytes; - /* advance write pointer */ - p->wptr += numbytes; - /* increse data_num */ - p->data_num += numbytes; - } - - /* now check how much data there's left to read to finish the - current packet */ - remainpack = p->total_num - p->data_num; - - if (!remainpack) { - /* we have a full packet */ - libssh2_transport_read_point1: - rc = fullpacket(session, encrypted); - if (rc == LIBSSH2_ERROR_EAGAIN) { - - if (session->packAdd_state != libssh2_NB_state_idle) - { - /* fullpacket only returns LIBSSH2_ERROR_EAGAIN if - * libssh2_packet_add returns LIBSSH2_ERROR_EAGAIN. If that - * returns LIBSSH2_ERROR_EAGAIN but the packAdd_state is idle, - * then the packet has been added to the brigade, but some - * immediate action that was taken based on the packet - * type (such as key re-exchange) is not yet complete. - * Clear the way for a new packet to be read in. - */ - session->readPack_encrypted = encrypted; - session->readPack_state = libssh2_NB_state_jump1; - } - - return rc; - } - - p->total_num = 0; /* no packet buffer available */ - - return rc; - } - } while (1); /* loop */ - - return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */ -} - -static int -send_existing(LIBSSH2_SESSION *session, const unsigned char *data, - size_t data_len, ssize_t *ret) -{ - ssize_t rc; - ssize_t length; - struct transportpacket *p = &session->packet; - - if (!p->olen) { - *ret = 0; - return LIBSSH2_ERROR_NONE; - } - - /* send as much as possible of the existing packet */ - if ((data != p->odata) || (data_len != p->olen)) { - /* When we are about to complete the sending of a packet, it is vital - that the caller doesn't try to send a new/different packet since - we don't add this one up until the previous one has been sent. To - make the caller really notice his/hers flaw, we return error for - this case */ - return LIBSSH2_ERROR_BAD_USE; - } - - *ret = 1; /* set to make our parent return */ - - /* number of bytes left to send */ - length = p->ototal_num - p->osent; - - rc = LIBSSH2_SEND(session, &p->outbuf[p->osent], length, - LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (rc < 0) - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", length, -rc); - else { - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p+%d", rc, length, p->outbuf, - p->osent); - debugdump(session, "libssh2_transport_write send()", - &p->outbuf[p->osent], rc); - } - - if (rc == length) { - /* the remainder of the package was sent */ - p->ototal_num = 0; - p->olen = 0; - /* we leave *ret set so that the parent returns as we MUST return back - a send success now, so that we don't risk sending EAGAIN later - which then would confuse the parent function */ - return LIBSSH2_ERROR_NONE; - - } - else if (rc < 0) { - /* nothing was sent */ - if (rc != -EAGAIN) - /* send failure! */ - return LIBSSH2_ERROR_SOCKET_SEND; - - session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND; - return LIBSSH2_ERROR_EAGAIN; - } - - p->osent += rc; /* we sent away this much data */ - - return rc < length ? LIBSSH2_ERROR_EAGAIN : LIBSSH2_ERROR_NONE; -} - -/* - * libssh2_transport_send - * - * Send a packet, encrypting it and adding a MAC code if necessary - * Returns 0 on success, non-zero on failure. - * - * The data is provided as _two_ data areas that are combined by this - * function. The 'data' part is sent immediately before 'data2'. 'data2' may - * be set to NULL to only use a single part. - * - * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was - * not sent yet. If it does so, the caller should call this function again as - * soon as it is likely that more data can be sent, and this function MUST - * then be called with the same argument set (same data pointer and same - * data_len) until ERROR_NONE or failure is returned. - * - * This function DOES NOT call _libssh2_error() on any errors. - */ -int _libssh2_transport_send(LIBSSH2_SESSION *session, - const unsigned char *data, size_t data_len, - const unsigned char *data2, size_t data2_len) -{ - int blocksize = - (session->state & LIBSSH2_STATE_NEWKEYS) ? - session->local.crypt->blocksize : 8; - int padding_length; - size_t packet_length; - int total_length; -#ifdef RANDOM_PADDING - int rand_max; - int seed = data[0]; /* FIXME: make this random */ -#endif - struct transportpacket *p = &session->packet; - int encrypted; - ssize_t ret; - int rc; - const unsigned char *orgdata = data; - size_t orgdata_len = data_len; - - /* - * If the last read operation was interrupted in the middle of a key - * exchange, we must complete that key exchange before continuing to write - * further data. - * - * See the similar block in _libssh2_transport_read for more details. - */ - if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS && - !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) { - /* Don't write any new packets if we're still in the middle of a key - * exchange. */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the" - " key re-exchange from _libssh2_transport_send"); - rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc) - return rc; - } - - debugdump(session, "libssh2_transport_write plain", data, data_len); - if(data2) - debugdump(session, "libssh2_transport_write plain2", data2, data2_len); - - /* FIRST, check if we have a pending write to complete. send_existing - only sanity-check data and data_len and not data2 and data2_len!! */ - rc = send_existing(session, data, data_len, &ret); - if (rc) - return rc; - - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; - - if (ret) - /* set by send_existing if data was sent */ - return rc; - - encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0; - - if (encrypted && session->local.comp->compress) { - /* the idea here is that these function must fail if the output gets - larger than what fits in the assigned buffer so thus they don't - check the input size as we don't know how much it compresses */ - size_t dest_len = MAX_SSH_PACKET_LEN-5-256; - size_t dest2_len = dest_len; - - /* compress directly to the target buffer */ - rc = session->local.comp->comp(session, - &p->outbuf[5], &dest_len, - data, data_len, - &session->local.comp_abstract); - if(rc) - return rc; /* compression failure */ - - if(data2 && data2_len) { - /* compress directly to the target buffer right after where the - previous call put data */ - dest2_len -= dest_len; - - rc = session->local.comp->comp(session, - &p->outbuf[5+dest_len], &dest2_len, - data2, data2_len, - &session->local.comp_abstract); - } - else - dest2_len = 0; - if(rc) - return rc; /* compression failure */ - - data_len = dest_len + dest2_len; /* use the combined length */ - } - else { - if((data_len + data2_len) >= (MAX_SSH_PACKET_LEN-0x100)) - /* too large packet, return error for this until we make this - function split it up and send multiple SSH packets */ - return LIBSSH2_ERROR_INVAL; - - /* copy the payload data */ - memcpy(&p->outbuf[5], data, data_len); - if(data2 && data2_len) - memcpy(&p->outbuf[5+data_len], data2, data2_len); - data_len += data2_len; /* use the combined length */ - } - - - /* RFC4253 says: Note that the length of the concatenation of - 'packet_length', 'padding_length', 'payload', and 'random padding' - MUST be a multiple of the cipher block size or 8, whichever is - larger. */ - - /* Plain math: (4 + 1 + packet_length + padding_length) % blocksize == 0 */ - - packet_length = data_len + 1 + 4; /* 1 is for padding_length field - 4 for the packet_length field */ - - /* at this point we have it all except the padding */ - - /* first figure out our minimum padding amount to make it an even - block size */ - padding_length = blocksize - (packet_length % blocksize); - - /* if the padding becomes too small we add another blocksize worth - of it (taken from the original libssh2 where it didn't have any - real explanation) */ - if (padding_length < 4) { - padding_length += blocksize; - } -#ifdef RANDOM_PADDING - /* FIXME: we can add padding here, but that also makes the packets - bigger etc */ - - /* now we can add 'blocksize' to the padding_length N number of times - (to "help thwart traffic analysis") but it must be less than 255 in - total */ - rand_max = (255 - padding_length) / blocksize + 1; - padding_length += blocksize * (seed % rand_max); -#endif - - packet_length += padding_length; - - /* append the MAC length to the total_length size */ - total_length = - packet_length + (encrypted ? session->local.mac->mac_len : 0); - - /* store packet_length, which is the size of the whole packet except - the MAC and the packet_length field itself */ - _libssh2_htonu32(p->outbuf, packet_length - 4); - /* store padding_length */ - p->outbuf[4] = padding_length; - - /* fill the padding area with random junk */ - _libssh2_random(p->outbuf + 5 + data_len, padding_length); - - if (encrypted) { - size_t i; - - /* Calculate MAC hash. Put the output at index packet_length, - since that size includes the whole packet. The MAC is - calculated on the entire unencrypted packet, including all - fields except the MAC field itself. */ - session->local.mac->hash(session, p->outbuf + packet_length, - session->local.seqno, p->outbuf, - packet_length, NULL, 0, - &session->local.mac_abstract); - - /* Encrypt the whole packet data, one block size at a time. - The MAC field is not encrypted. */ - for(i = 0; i < packet_length; i += session->local.crypt->blocksize) { - unsigned char *ptr = &p->outbuf[i]; - if (session->local.crypt->crypt(session, ptr, - &session->local.crypt_abstract)) - return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */ - } - } - - session->local.seqno++; - - ret = LIBSSH2_SEND(session, p->outbuf, total_length, - LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (ret < 0) - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", total_length, -ret); - else { - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p", - ret, total_length, p->outbuf); - debugdump(session, "libssh2_transport_write send()", p->outbuf, ret); - } - - if (ret != total_length) { - if (ret >= 0 || ret == -EAGAIN) { - /* the whole packet could not be sent, save the rest */ - session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND; - p->odata = orgdata; - p->olen = orgdata_len; - p->osent = ret <= 0 ? 0 : ret; - p->ototal_num = total_length; - return LIBSSH2_ERROR_EAGAIN; - } - return LIBSSH2_ERROR_SOCKET_SEND; - } - - /* the whole thing got sent away */ - p->odata = NULL; - p->olen = 0; - - return LIBSSH2_ERROR_NONE; /* all is good */ -} diff --git a/vendor/libssh2-1.4.2/src/transport.h b/vendor/libssh2-1.4.2/src/transport.h deleted file mode 100644 index 89982a6..0000000 --- a/vendor/libssh2-1.4.2/src/transport.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef __LIBSSH2_TRANSPORT_H -#define __LIBSSH2_TRANSPORT_H - -/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2009-2010 by Daniel Stenberg - * Author: Daniel Stenberg - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 file handles reading and writing to the SECSH transport layer. RFC4253. - */ - -#include "libssh2_priv.h" -#include "packet.h" - - -/* - * libssh2_transport_send - * - * Send a packet, encrypting it and adding a MAC code if necessary - * Returns 0 on success, non-zero on failure. - * - * The data is provided as _two_ data areas that are combined by this - * function. The 'data' part is sent immediately before 'data2'. 'data2' can - * be set to NULL (or data2_len to 0) to only use a single part. - * - * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was - * not sent yet. If it does so, the caller should call this function again as - * soon as it is likely that more data can be sent, and this function MUST - * then be called with the same argument set (same data pointer and same - * data_len) until ERROR_NONE or failure is returned. - * - * This function DOES NOT call _libssh2_error() on any errors. - */ -int _libssh2_transport_send(LIBSSH2_SESSION *session, - const unsigned char *data, size_t data_len, - const unsigned char *data2, size_t data2_len); - -/* - * _libssh2_transport_read - * - * Collect a packet into the input brigade block only controls whether or not - * to wait for a packet to start. - * - * Returns packet type added to input brigade (PACKET_NONE if nothing added), - * or PACKET_FAIL on failure and PACKET_EAGAIN if it couldn't process a full - * packet. - */ - -/* - * This function reads the binary stream as specified in chapter 6 of RFC4253 - * "The Secure Shell (SSH) Transport Layer Protocol" - */ -int _libssh2_transport_read(LIBSSH2_SESSION * session); - -#endif /* __LIBSSH2_TRANSPORT_H */ diff --git a/vendor/libssh2-1.4.2/src/userauth.c b/vendor/libssh2-1.4.2/src/userauth.c deleted file mode 100644 index a0733d5..0000000 --- a/vendor/libssh2-1.4.2/src/userauth.c +++ /dev/null @@ -1,1687 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2009-2011 by Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -#include -#include - -#include - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#include "transport.h" -#include "session.h" -#include "userauth.h" - -/* libssh2_userauth_list - * - * List authentication methods - * Will yield successful login if "none" happens to be allowable for this user - * Not a common configuration for any SSH server though - * username should be NULL, or a null terminated string - */ -static char *userauth_list(LIBSSH2_SESSION *session, const char *username, - unsigned int username_len) -{ - static const unsigned char reply_codes[3] = - { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; - /* packet_type(1) + username_len(4) + service_len(4) + - service(14)"ssh-connection" + method_len(4) = 27 */ - unsigned long methods_len; - unsigned char *s; - int rc; - - if (session->userauth_list_state == libssh2_NB_state_idle) { - /* Zero the whole thing out */ - memset(&session->userauth_list_packet_requirev_state, 0, - sizeof(session->userauth_list_packet_requirev_state)); - - session->userauth_list_data_len = username_len + 27; - - s = session->userauth_list_data = - LIBSSH2_ALLOC(session, session->userauth_list_data_len); - if (!session->userauth_list_data) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for userauth_list"); - return NULL; - } - - *(s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", 14); - _libssh2_store_u32(&s, 4); /* send "none" separately */ - - session->userauth_list_state = libssh2_NB_state_created; - } - - if (session->userauth_list_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_list_data, - session->userauth_list_data_len, - (unsigned char *)"none", 4); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting userauth list"); - return NULL; - } - /* now free the packet that was sent */ - LIBSSH2_FREE(session, session->userauth_list_data); - session->userauth_list_data = NULL; - - if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-none request"); - session->userauth_list_state = libssh2_NB_state_idle; - return NULL; - } - - session->userauth_list_state = libssh2_NB_state_sent; - } - - if (session->userauth_list_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_list_data, - &session->userauth_list_data_len, 0, - NULL, 0, - &session->userauth_list_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting userauth list"); - return NULL; - } else if (rc) { - _libssh2_error(session, rc, "Failed getting response"); - session->userauth_list_state = libssh2_NB_state_idle; - return NULL; - } - - if (session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - /* Wow, who'dve thought... */ - _libssh2_error(session, LIBSSH2_ERROR_NONE, "No error"); - LIBSSH2_FREE(session, session->userauth_list_data); - session->userauth_list_data = NULL; - session->state |= LIBSSH2_STATE_AUTHENTICATED; - session->userauth_list_state = libssh2_NB_state_idle; - return NULL; - } - - methods_len = _libssh2_ntohu32(session->userauth_list_data + 1); - - /* Do note that the memory areas overlap! */ - memmove(session->userauth_list_data, session->userauth_list_data + 5, - methods_len); - session->userauth_list_data[methods_len] = '\0'; - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Permitted auth methods: %s", - session->userauth_list_data); - } - - session->userauth_list_state = libssh2_NB_state_idle; - return (char *) session->userauth_list_data; -} - -/* libssh2_userauth_list - * - * List authentication methods - * Will yield successful login if "none" happens to be allowable for this user - * Not a common configuration for any SSH server though - * username should be NULL, or a null terminated string - */ -LIBSSH2_API char * -libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user, - unsigned int user_len) -{ - char *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, - userauth_list(session, user, user_len)); - return ptr; -} - -/* - * libssh2_userauth_authenticated - * - * Returns: 0 if not yet authenticated - * 1 if already authenticated - */ -LIBSSH2_API int -libssh2_userauth_authenticated(LIBSSH2_SESSION * session) -{ - return (session->state & LIBSSH2_STATE_AUTHENTICATED)?1:0; -} - - - -/* userauth_password - * Plain ol' login - */ -static int -userauth_password(LIBSSH2_SESSION *session, - const char *username, unsigned int username_len, - const unsigned char *password, unsigned int password_len, - LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) -{ - unsigned char *s; - static const unsigned char reply_codes[4] = - { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, - SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0 - }; - int rc; - - if (session->userauth_pswd_state == libssh2_NB_state_idle) { - /* Zero the whole thing out */ - memset(&session->userauth_pswd_packet_requirev_state, 0, - sizeof(session->userauth_pswd_packet_requirev_state)); - - /* - * 40 = acket_type(1) + username_len(4) + service_len(4) + - * service(14)"ssh-connection" + method_len(4) + method(8)"password" + - * chgpwdbool(1) + password_len(4) */ - session->userauth_pswd_data_len = username_len + 40; - - session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; - - /* TODO: remove this alloc with a fixed buffer in the session - struct */ - s = session->userauth_pswd_data = - LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); - if (!session->userauth_pswd_data) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "userauth-password request"); - } - - *(s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); - _libssh2_store_str(&s, "password", sizeof("password") - 1); - *s++ = '\0'; - _libssh2_store_u32(&s, password_len); - /* 'password' is sent separately */ - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting to login using password authentication"); - - session->userauth_pswd_state = libssh2_NB_state_created; - } - - if (session->userauth_pswd_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_pswd_data, - session->userauth_pswd_data_len, - password, password_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block writing password request"); - } - - /* now free the sent packet */ - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - - if (rc) { - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-password request"); - } - - session->userauth_pswd_state = libssh2_NB_state_sent; - } - - password_response: - - if ((session->userauth_pswd_state == libssh2_NB_state_sent) - || (session->userauth_pswd_state == libssh2_NB_state_sent1) - || (session->userauth_pswd_state == libssh2_NB_state_sent2)) { - if (session->userauth_pswd_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_pswd_data, - &session->userauth_pswd_data_len, - 0, NULL, 0, - &session-> - userauth_pswd_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting"); - } else if (rc) { - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, - "Would block waiting"); - } - - if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Password authentication successful"); - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - session->state |= LIBSSH2_STATE_AUTHENTICATED; - session->userauth_pswd_state = libssh2_NB_state_idle; - return 0; - } else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Password authentication failed"); - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, - LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Authentication failed " - "(username/password)"); - } - - session->userauth_pswd_newpw = NULL; - session->userauth_pswd_newpw_len = 0; - - session->userauth_pswd_state = libssh2_NB_state_sent1; - } - - if ((session->userauth_pswd_data[0] == - SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) - || (session->userauth_pswd_data0 == - SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)) { - session->userauth_pswd_data0 = SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; - - if ((session->userauth_pswd_state == libssh2_NB_state_sent1) || - (session->userauth_pswd_state == libssh2_NB_state_sent2)) { - if (session->userauth_pswd_state == libssh2_NB_state_sent1) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Password change required"); - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - } - if (passwd_change_cb) { - if (session->userauth_pswd_state == libssh2_NB_state_sent1) { - passwd_change_cb(session, - &session->userauth_pswd_newpw, - &session->userauth_pswd_newpw_len, - &session->abstract); - if (!session->userauth_pswd_newpw) { - return _libssh2_error(session, - LIBSSH2_ERROR_PASSWORD_EXPIRED, - "Password expired, and " - "callback failed"); - } - - /* basic data_len + newpw_len(4) */ - session->userauth_pswd_data_len = - username_len + password_len + 44; - - s = session->userauth_pswd_data = - LIBSSH2_ALLOC(session, - session->userauth_pswd_data_len); - if (!session->userauth_pswd_data) { - LIBSSH2_FREE(session, - session->userauth_pswd_newpw); - session->userauth_pswd_newpw = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory " - "for userauth password " - "change request"); - } - - *(s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", - sizeof("ssh-connection") - 1); - _libssh2_store_str(&s, "password", - sizeof("password") - 1); - *s++ = 0x01; - _libssh2_store_str(&s, (char *)password, password_len); - _libssh2_store_u32(&s, - session->userauth_pswd_newpw_len); - /* send session->userauth_pswd_newpw separately */ - - session->userauth_pswd_state = libssh2_NB_state_sent2; - } - - if (session->userauth_pswd_state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_send(session, - session->userauth_pswd_data, - session->userauth_pswd_data_len, - (unsigned char *) - session->userauth_pswd_newpw, - session->userauth_pswd_newpw_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting"); - } - - /* free the allocated packets again */ - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - LIBSSH2_FREE(session, session->userauth_pswd_newpw); - session->userauth_pswd_newpw = NULL; - - if (rc) { - return _libssh2_error(session, - LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth " - "password-change request"); - } - - /* - * Ugliest use of goto ever. Blame it on the - * askN => requirev migration. - */ - session->userauth_pswd_state = libssh2_NB_state_sent; - goto password_response; - } - } - } else { - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, - "Password Expired, and no callback " - "specified"); - } - } - } - - /* FAILURE */ - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - session->userauth_pswd_state = libssh2_NB_state_idle; - - return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Authentication failed"); -} - -/* - * libssh2_userauth_password_ex - * - * Plain ol' login - */ - -LIBSSH2_API int -libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, - unsigned int username_len, const char *password, - unsigned int password_len, - LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) -{ - int rc; - BLOCK_ADJUST(rc, session, - userauth_password(session, username, username_len, - (unsigned char *)password, password_len, - passwd_change_cb)); - return rc; -} - -/* - * file_read_publickey - * - * Read a public key from an id_???.pub style file - * - * Returns an allocated string containing the decoded key in *pubkeydata - * on success. - * Returns an allocated string containing the key method (e.g. "ssh-dss") - * in method on success. - */ -static int -file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *pubkeyfile) -{ - FILE *fd; - char c; - unsigned char *pubkey = NULL, *sp1, *sp2, *tmp; - size_t pubkey_len = 0; - unsigned int tmp_len; - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s", - pubkeyfile); - /* Read Public Key */ - fd = fopen(pubkeyfile, "r"); - if (!fd) { - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to open public key file"); - } - while (!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') - pubkey_len++; - if (feof(fd)) { - /* the last character was EOF */ - pubkey_len--; - } - rewind(fd); - - if (pubkey_len <= 1) { - fclose(fd); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Invalid data in public key file"); - } - - pubkey = LIBSSH2_ALLOC(session, pubkey_len); - if (!pubkey) { - fclose(fd); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for public key data"); - } - if (fread(pubkey, 1, pubkey_len, fd) != pubkey_len) { - LIBSSH2_FREE(session, pubkey); - fclose(fd); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to read public key from file"); - } - fclose(fd); - /* - * Remove trailing whitespace - */ - while (pubkey_len && isspace(pubkey[pubkey_len - 1])) - pubkey_len--; - - if (!pubkey_len) { - LIBSSH2_FREE(session, pubkey); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Missing public key data"); - } - - if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) { - LIBSSH2_FREE(session, pubkey); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Invalid public key data"); - } - - sp1++; - - if ((sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey - 1))) == NULL) { - /* Assume that the id string is missing, but that it's okay */ - sp2 = pubkey + pubkey_len; - } - - if (libssh2_base64_decode(session, (char **) &tmp, &tmp_len, - (char *) sp1, sp2 - sp1)) { - LIBSSH2_FREE(session, pubkey); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Invalid key data, not base64 encoded"); - } - - /* Wasting some bytes here (okay, more than some), but since it's likely - * to be freed soon anyway, we'll just avoid the extra free/alloc and call - * it a wash */ - *method = pubkey; - *method_len = sp1 - pubkey - 1; - - *pubkeydata = tmp; - *pubkeydata_len = tmp_len; - - return 0; -} - - - -/* libssh2_file_read_privatekey - * Read a PEM encoded private key from an id_??? style file - */ -static int -file_read_privatekey(LIBSSH2_SESSION * session, - const LIBSSH2_HOSTKEY_METHOD ** hostkey_method, - void **hostkey_abstract, - const unsigned char *method, int method_len, - const char *privkeyfile, const char *passphrase) -{ - const LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail = - libssh2_hostkey_methods(); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading private key file: %s", - privkeyfile); - *hostkey_method = NULL; - *hostkey_abstract = NULL; - while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) { - if ((*hostkey_methods_avail)->initPEM - && strncmp((*hostkey_methods_avail)->name, (const char *) method, - method_len) == 0) { - *hostkey_method = *hostkey_methods_avail; - break; - } - hostkey_methods_avail++; - } - if (!*hostkey_method) { - return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, - "No handler for specified private key"); - } - - if ((*hostkey_method)-> - initPEM(session, privkeyfile, (unsigned char *) passphrase, - hostkey_abstract)) { - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to initialize private key from file"); - } - - return 0; -} - -struct privkey_file { - const char *filename; - const char *passphrase; -}; - -static int -sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, - const unsigned char *data, size_t data_len, void **abstract) -{ - struct privkey_file *privkey_file = (struct privkey_file *) (*abstract); - const LIBSSH2_HOSTKEY_METHOD *privkeyobj; - void *hostkey_abstract; - struct iovec datavec; - int rc; - - rc = file_read_privatekey(session, &privkeyobj, &hostkey_abstract, - session->userauth_pblc_method, - session->userauth_pblc_method_len, - privkey_file->filename, - privkey_file->passphrase); - if(rc) - return rc; - - datavec.iov_base = (void *)data; - datavec.iov_len = data_len; - - if (privkeyobj->signv(session, sig, sig_len, 1, &datavec, - &hostkey_abstract)) { - if (privkeyobj->dtor) { - privkeyobj->dtor(session, abstract); - } - return -1; - } - - if (privkeyobj->dtor) { - privkeyobj->dtor(session, &hostkey_abstract); - } - return 0; -} - - - -/* userauth_hostbased_fromfile - * Authenticate using a keypair found in the named files - */ -static int -userauth_hostbased_fromfile(LIBSSH2_SESSION *session, - const char *username, size_t username_len, - const char *publickey, const char *privatekey, - const char *passphrase, const char *hostname, - size_t hostname_len, - const char *local_username, - size_t local_username_len) -{ - int rc; - - if (session->userauth_host_state == libssh2_NB_state_idle) { - const LIBSSH2_HOSTKEY_METHOD *privkeyobj; - unsigned char *pubkeydata, *sig; - size_t pubkeydata_len; - size_t sig_len; - void *abstract; - unsigned char buf[5]; - struct iovec datavec[4]; - - /* Zero the whole thing out */ - memset(&session->userauth_host_packet_requirev_state, 0, - sizeof(session->userauth_host_packet_requirev_state)); - - if (publickey) { - rc = file_read_publickey(session, &session->userauth_host_method, - &session->userauth_host_method_len, - &pubkeydata, &pubkeydata_len, publickey); - if(rc) - /* Note: file_read_publickey() calls _libssh2_error() */ - return rc; - } - else { - /* Compute public key from private key. */ - rc = _libssh2_pub_priv_keyfile(session, - &session->userauth_host_method, - &session->userauth_host_method_len, - &pubkeydata, &pubkeydata_len, - privatekey, passphrase); - if (rc) - /* libssh2_pub_priv_keyfile calls _libssh2_error() */ - return rc; - } - - /* - * 52 = packet_type(1) + username_len(4) + servicename_len(4) + - * service_name(14)"ssh-connection" + authmethod_len(4) + - * authmethod(9)"hostbased" + method_len(4) + pubkeydata_len(4) + - * hostname_len(4) + local_username_len(4) - */ - session->userauth_host_packet_len = - username_len + session->userauth_host_method_len + hostname_len + - local_username_len + pubkeydata_len + 52; - - /* - * Preallocate space for an overall length, method name again, - * and the signature, which won't be any larger than the size of - * the publickeydata itself - */ - session->userauth_host_s = session->userauth_host_packet = - LIBSSH2_ALLOC(session, - session->userauth_host_packet_len + 4 + - (4 + session->userauth_host_method_len) + - (4 + pubkeydata_len)); - if (!session->userauth_host_packet) { - LIBSSH2_FREE(session, session->userauth_host_method); - session->userauth_host_method = NULL; - LIBSSH2_FREE(session, pubkeydata); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Out of memory"); - } - - *(session->userauth_host_s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&session->userauth_host_s, username, username_len); - _libssh2_store_str(&session->userauth_host_s, "ssh-connection", 14); - _libssh2_store_str(&session->userauth_host_s, "hostbased", 9); - _libssh2_store_str(&session->userauth_host_s, - (const char *)session->userauth_host_method, - session->userauth_host_method_len); - _libssh2_store_str(&session->userauth_host_s, (const char *)pubkeydata, - pubkeydata_len); - LIBSSH2_FREE(session, pubkeydata); - _libssh2_store_str(&session->userauth_host_s, hostname, hostname_len); - _libssh2_store_str(&session->userauth_host_s, local_username, - local_username_len); - - rc = file_read_privatekey(session, &privkeyobj, &abstract, - session->userauth_host_method, - session->userauth_host_method_len, - privatekey, passphrase); - if(rc) { - /* Note: file_read_privatekey() calls _libssh2_error() */ - LIBSSH2_FREE(session, session->userauth_host_method); - session->userauth_host_method = NULL; - LIBSSH2_FREE(session, session->userauth_host_packet); - session->userauth_host_packet = NULL; - return rc; - } - - _libssh2_htonu32(buf, session->session_id_len); - datavec[0].iov_base = (void *)buf; - datavec[0].iov_len = 4; - datavec[1].iov_base = (void *)session->session_id; - datavec[1].iov_len = session->session_id_len; - datavec[2].iov_base = (void *)session->userauth_host_packet; - datavec[2].iov_len = session->userauth_host_packet_len; - - if (privkeyobj->signv(session, &sig, &sig_len, 3, datavec, &abstract)) { - LIBSSH2_FREE(session, session->userauth_host_method); - session->userauth_host_method = NULL; - LIBSSH2_FREE(session, session->userauth_host_packet); - session->userauth_host_packet = NULL; - if (privkeyobj->dtor) { - privkeyobj->dtor(session, &abstract); - } - return -1; - } - - if (privkeyobj->dtor) { - privkeyobj->dtor(session, &abstract); - } - - if (sig_len > pubkeydata_len) { - unsigned char *newpacket; - /* Should *NEVER* happen, but...well.. better safe than sorry */ - newpacket = LIBSSH2_REALLOC(session, session->userauth_host_packet, - session->userauth_host_packet_len + 4 + - (4 + session->userauth_host_method_len) - + (4 + sig_len)); /* PK sigblob */ - if (!newpacket) { - LIBSSH2_FREE(session, sig); - LIBSSH2_FREE(session, session->userauth_host_packet); - session->userauth_host_packet = NULL; - LIBSSH2_FREE(session, session->userauth_host_method); - session->userauth_host_method = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Failed allocating additional space for " - "userauth-hostbased packet"); - } - session->userauth_host_packet = newpacket; - } - - session->userauth_host_s = - session->userauth_host_packet + session->userauth_host_packet_len; - - _libssh2_store_u32(&session->userauth_host_s, - 4 + session->userauth_host_method_len + 4 + sig_len); - _libssh2_store_str(&session->userauth_host_s, - (const char *)session->userauth_host_method, - session->userauth_host_method_len); - LIBSSH2_FREE(session, session->userauth_host_method); - session->userauth_host_method = NULL; - - _libssh2_store_str(&session->userauth_host_s, (const char *)sig, - sig_len); - LIBSSH2_FREE(session, sig); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting hostbased authentication"); - - session->userauth_host_state = libssh2_NB_state_created; - } - - if (session->userauth_host_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_host_packet, - session->userauth_host_s - - session->userauth_host_packet, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } - else if (rc) { - LIBSSH2_FREE(session, session->userauth_host_packet); - session->userauth_host_packet = NULL; - session->userauth_host_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-hostbased request"); - } - LIBSSH2_FREE(session, session->userauth_host_packet); - session->userauth_host_packet = NULL; - - session->userauth_host_state = libssh2_NB_state_sent; - } - - if (session->userauth_host_state == libssh2_NB_state_sent) { - static const unsigned char reply_codes[3] = - { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; - size_t data_len; - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_host_data, - &data_len, 0, NULL, 0, - &session-> - userauth_host_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } - - session->userauth_host_state = libssh2_NB_state_idle; - if (rc) { - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Auth failed"); - } - - if (session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Hostbased authentication successful"); - /* We are us and we've proved it. */ - LIBSSH2_FREE(session, session->userauth_host_data); - session->userauth_host_data = NULL; - session->state |= LIBSSH2_STATE_AUTHENTICATED; - return 0; - } - } - - /* This public key is not allowed for this user on this server */ - LIBSSH2_FREE(session, session->userauth_host_data); - session->userauth_host_data = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid signature for supplied public key, or bad " - "username/public key combination"); -} - -/* libssh2_userauth_hostbased_fromfile_ex - * Authenticate using a keypair found in the named files - */ -LIBSSH2_API int -libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session, - const char *user, - unsigned int user_len, - const char *publickey, - const char *privatekey, - const char *passphrase, - const char *host, - unsigned int host_len, - const char *localuser, - unsigned int localuser_len) -{ - int rc; - BLOCK_ADJUST(rc, session, - userauth_hostbased_fromfile(session, user, user_len, - publickey, privatekey, - passphrase, host, host_len, - localuser, localuser_len)); - return rc; -} - - - -int -_libssh2_userauth_publickey(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const unsigned char *pubkeydata, - unsigned long pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void *abstract) -{ - unsigned char reply_codes[4] = - { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, - SSH_MSG_USERAUTH_PK_OK, 0 - }; - int rc; - unsigned char *s; - - if (session->userauth_pblc_state == libssh2_NB_state_idle) { - - /* - * The call to _libssh2_ntohu32 later relies on pubkeydata having at - * least 4 valid bytes containing the length of the method name. - */ - if (pubkeydata_len < 4) - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid public key, too short"); - - /* Zero the whole thing out */ - memset(&session->userauth_pblc_packet_requirev_state, 0, - sizeof(session->userauth_pblc_packet_requirev_state)); - - /* - * As an optimisation, userauth_publickey_fromfile reuses a - * previously allocated copy of the method name to avoid an extra - * allocation/free. - * For other uses, we allocate and populate it here. - */ - if (!session->userauth_pblc_method) { - session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata); - - if(session->userauth_pblc_method_len > pubkeydata_len) - /* the method length simply cannot be longer than the entire - passed in data, so we use this to detect crazy input - data */ - return _libssh2_error(session, - LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid public key"); - - session->userauth_pblc_method = - LIBSSH2_ALLOC(session, session->userauth_pblc_method_len); - if (!session->userauth_pblc_method) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for public key " - "data"); - } - memcpy(session->userauth_pblc_method, pubkeydata + 4, - session->userauth_pblc_method_len); - } - /* - * The length of the method name read from plaintext prefix in the - * file must match length embedded in the key. - * TODO: The data should match too but we don't check that. Should we? - */ - else if (session->userauth_pblc_method_len != - _libssh2_ntohu32(pubkeydata)) - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid public key"); - - /* - * 45 = packet_type(1) + username_len(4) + servicename_len(4) + - * service_name(14)"ssh-connection" + authmethod_len(4) + - * authmethod(9)"publickey" + sig_included(1)'\0' + algmethod_len(4) + - * publickey_len(4) - */ - session->userauth_pblc_packet_len = - username_len + session->userauth_pblc_method_len + pubkeydata_len + - 45; - - /* - * Preallocate space for an overall length, method name again, and the - * signature, which won't be any larger than the size of the - * publickeydata itself. - * - * Note that the 'pubkeydata_len' extra bytes allocated here will not - * be used in this first send, but will be used in the later one where - * this same allocation is re-used. - */ - s = session->userauth_pblc_packet = - LIBSSH2_ALLOC(session, - session->userauth_pblc_packet_len + 4 + - (4 + session->userauth_pblc_method_len) - + (4 + pubkeydata_len)); - if (!session->userauth_pblc_packet) { - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Out of memory"); - } - - *s++ = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", 14); - _libssh2_store_str(&s, "publickey", 9); - - session->userauth_pblc_b = s; - /* Not sending signature with *this* packet */ - *s++ = 0; - - _libssh2_store_str(&s, (const char *)session->userauth_pblc_method, - session->userauth_pblc_method_len); - _libssh2_store_str(&s, (const char *)pubkeydata, pubkeydata_len); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting publickey authentication"); - - session->userauth_pblc_state = libssh2_NB_state_created; - } - - if (session->userauth_pblc_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_pblc_packet, - session->userauth_pblc_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - else if (rc) { - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-publickey request"); - } - - session->userauth_pblc_state = libssh2_NB_state_sent; - } - - if (session->userauth_pblc_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_pblc_data, - &session->userauth_pblc_data_len, 0, - NULL, 0, - &session-> - userauth_pblc_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } - else if (rc) { - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Waiting for USERAUTH response"); - } - - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Pubkey authentication prematurely successful"); - /* - * God help any SSH server that allows an UNVERIFIED - * public key to validate the user - */ - LIBSSH2_FREE(session, session->userauth_pblc_data); - session->userauth_pblc_data = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - session->state |= LIBSSH2_STATE_AUTHENTICATED; - session->userauth_pblc_state = libssh2_NB_state_idle; - return 0; - } - - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_FAILURE) { - /* This public key is not allowed for this user on this server */ - LIBSSH2_FREE(session, session->userauth_pblc_data); - session->userauth_pblc_data = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Username/PublicKey combination invalid"); - } - - /* Semi-Success! */ - LIBSSH2_FREE(session, session->userauth_pblc_data); - session->userauth_pblc_data = NULL; - - *session->userauth_pblc_b = 0x01; - session->userauth_pblc_state = libssh2_NB_state_sent1; - } - - if (session->userauth_pblc_state == libssh2_NB_state_sent1) { - unsigned char *buf; - unsigned char *sig; - size_t sig_len; - - s = buf = LIBSSH2_ALLOC(session, 4 + session->session_id_len - + session->userauth_pblc_packet_len); - if (!buf) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "userauth-publickey signed data"); - } - - _libssh2_store_str(&s, (const char *)session->session_id, - session->session_id_len); - - memcpy (s, session->userauth_pblc_packet, - session->userauth_pblc_packet_len); - s += session->userauth_pblc_packet_len; - - rc = sign_callback(session, &sig, &sig_len, buf, s - buf, abstract); - LIBSSH2_FREE(session, buf); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Callback returned error"); - } - - /* - * If this function was restarted, pubkeydata_len might still be 0 - * which will cause an unnecessary but harmless realloc here. - */ - if (sig_len > pubkeydata_len) { - unsigned char *newpacket; - /* Should *NEVER* happen, but...well.. better safe than sorry */ - newpacket = LIBSSH2_REALLOC(session, - session->userauth_pblc_packet, - session->userauth_pblc_packet_len + 4 + - (4 + session->userauth_pblc_method_len) - + (4 + sig_len)); /* PK sigblob */ - if (!newpacket) { - LIBSSH2_FREE(session, sig); - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Failed allocating additional space for " - "userauth-publickey packet"); - } - session->userauth_pblc_packet = newpacket; - } - - s = session->userauth_pblc_packet + session->userauth_pblc_packet_len; - session->userauth_pblc_b = NULL; - - _libssh2_store_u32(&s, - 4 + session->userauth_pblc_method_len + 4 + sig_len); - _libssh2_store_str(&s, (const char *)session->userauth_pblc_method, - session->userauth_pblc_method_len); - - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - - _libssh2_store_str(&s, (const char *)sig, sig_len); - LIBSSH2_FREE(session, sig); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting publickey authentication -- phase 2"); - - session->userauth_pblc_s = s; - session->userauth_pblc_state = libssh2_NB_state_sent2; - } - - if (session->userauth_pblc_state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_send(session, session->userauth_pblc_packet, - session->userauth_pblc_s - - session->userauth_pblc_packet, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-publickey request"); - } - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - - session->userauth_pblc_state = libssh2_NB_state_sent3; - } - - /* PK_OK is no longer valid */ - reply_codes[2] = 0; - - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_pblc_data, - &session->userauth_pblc_data_len, 0, NULL, 0, - &session->userauth_pblc_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting userauth list"); - } else if (rc) { - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Waiting for publickey USERAUTH response"); - } - - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Publickey authentication successful"); - /* We are us and we've proved it. */ - LIBSSH2_FREE(session, session->userauth_pblc_data); - session->userauth_pblc_data = NULL; - session->state |= LIBSSH2_STATE_AUTHENTICATED; - session->userauth_pblc_state = libssh2_NB_state_idle; - return 0; - } - - /* This public key is not allowed for this user on this server */ - LIBSSH2_FREE(session, session->userauth_pblc_data); - session->userauth_pblc_data = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid signature for supplied public key, or bad " - "username/public key combination"); -} - -/* - * userauth_publickey_fromfile - * Authenticate using a keypair found in the named files - */ -static int -userauth_publickey_fromfile(LIBSSH2_SESSION *session, - const char *username, - size_t username_len, - const char *publickey, - const char *privatekey, - const char *passphrase) -{ - unsigned char *pubkeydata = NULL; - size_t pubkeydata_len = 0; - struct privkey_file privkey_file; - void *abstract = &privkey_file; - int rc; - - privkey_file.filename = privatekey; - privkey_file.passphrase = passphrase; - - if (session->userauth_pblc_state == libssh2_NB_state_idle) { - if (publickey) { - rc = file_read_publickey(session, &session->userauth_pblc_method, - &session->userauth_pblc_method_len, - &pubkeydata, &pubkeydata_len,publickey); - if (rc) - return rc; - } - else { - /* Compute public key from private key. */ - rc = _libssh2_pub_priv_keyfile(session, - &session->userauth_pblc_method, - &session->userauth_pblc_method_len, - &pubkeydata, &pubkeydata_len, - privatekey, passphrase); - - /* _libssh2_pub_priv_keyfile calls _libssh2_error() */ - if (rc) - return rc; - } - } - - rc = _libssh2_userauth_publickey(session, username, username_len, - pubkeydata, pubkeydata_len, - sign_fromfile, &abstract); - if(pubkeydata) - LIBSSH2_FREE(session, pubkeydata); - - return rc; -} - -/* libssh2_userauth_publickey_fromfile_ex - * Authenticate using a keypair found in the named files - */ -LIBSSH2_API int -libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, - const char *user, - unsigned int user_len, - const char *publickey, - const char *privatekey, - const char *passphrase) -{ - int rc; - - if(NULL == passphrase) - /* if given a NULL pointer, make it point to a zero-length - string to save us from having to check this all over */ - passphrase=""; - - BLOCK_ADJUST(rc, session, - userauth_publickey_fromfile(session, user, user_len, - publickey, privatekey, - passphrase)); - return rc; -} - -/* libssh2_userauth_publickey_ex - * Authenticate using an external callback function - */ -LIBSSH2_API int -libssh2_userauth_publickey(LIBSSH2_SESSION *session, - const char *user, - const unsigned char *pubkeydata, - size_t pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void **abstract) -{ - int rc; - - if(!session) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, session, - _libssh2_userauth_publickey(session, user, strlen(user), - pubkeydata, pubkeydata_len, - sign_callback, abstract)); - return rc; -} - - - -/* - * userauth_keyboard_interactive - * - * Authenticate using a challenge-response authentication - */ -static int -userauth_keyboard_interactive(LIBSSH2_SESSION * session, - const char *username, - unsigned int username_len, - LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback))) -{ - unsigned char *s; - int rc; - - static const unsigned char reply_codes[4] = { - SSH_MSG_USERAUTH_SUCCESS, - SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_INFO_REQUEST, 0 - }; - unsigned int language_tag_len; - unsigned int i; - - if (session->userauth_kybd_state == libssh2_NB_state_idle) { - session->userauth_kybd_auth_name = NULL; - session->userauth_kybd_auth_instruction = NULL; - session->userauth_kybd_num_prompts = 0; - session->userauth_kybd_auth_failure = 1; - session->userauth_kybd_prompts = NULL; - session->userauth_kybd_responses = NULL; - - /* Zero the whole thing out */ - memset(&session->userauth_kybd_packet_requirev_state, 0, - sizeof(session->userauth_kybd_packet_requirev_state)); - - session->userauth_kybd_packet_len = - 1 /* byte SSH_MSG_USERAUTH_REQUEST */ - + 4 + username_len /* string user name (ISO-10646 UTF-8, as - defined in [RFC-3629]) */ - + 4 + 14 /* string service name (US-ASCII) */ - + 4 + 20 /* string "keyboard-interactive" (US-ASCII) */ - + 4 + 0 /* string language tag (as defined in - [RFC-3066]) */ - + 4 + 0 /* string submethods (ISO-10646 UTF-8) */ - ; - - session->userauth_kybd_data = s = - LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len); - if (!s) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "keyboard-interactive authentication"); - } - - *s++ = SSH_MSG_USERAUTH_REQUEST; - - /* user name */ - _libssh2_store_str(&s, username, username_len); - - /* service name */ - _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); - - /* "keyboard-interactive" */ - _libssh2_store_str(&s, "keyboard-interactive", - sizeof("keyboard-interactive") - 1); - /* language tag */ - _libssh2_store_u32(&s, 0); - - /* submethods */ - _libssh2_store_u32(&s, 0); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting keyboard-interactive authentication"); - - session->userauth_kybd_state = libssh2_NB_state_created; - } - - if (session->userauth_kybd_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_kybd_data, - session->userauth_kybd_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { - LIBSSH2_FREE(session, session->userauth_kybd_data); - session->userauth_kybd_data = NULL; - session->userauth_kybd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send keyboard-interactive request"); - } - LIBSSH2_FREE(session, session->userauth_kybd_data); - session->userauth_kybd_data = NULL; - - session->userauth_kybd_state = libssh2_NB_state_sent; - } - - for(;;) { - if (session->userauth_kybd_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_kybd_data, - &session->userauth_kybd_data_len, - 0, NULL, 0, - &session-> - userauth_kybd_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block"); - } else if (rc) { - session->userauth_kybd_state = libssh2_NB_state_idle; - return _libssh2_error(session, - LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Waiting for keyboard USERAUTH response"); - } - - if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Keyboard-interactive authentication successful"); - LIBSSH2_FREE(session, session->userauth_kybd_data); - session->userauth_kybd_data = NULL; - session->state |= LIBSSH2_STATE_AUTHENTICATED; - session->userauth_kybd_state = libssh2_NB_state_idle; - return 0; - } - - if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Keyboard-interactive authentication failed"); - LIBSSH2_FREE(session, session->userauth_kybd_data); - session->userauth_kybd_data = NULL; - session->userauth_kybd_state = libssh2_NB_state_idle; - return _libssh2_error(session, - LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Authentication failed " - "(keyboard-interactive)"); - } - - /* server requested PAM-like conversation */ - s = session->userauth_kybd_data + 1; - - /* string name (ISO-10646 UTF-8) */ - session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s); - s += 4; - if(session->userauth_kybd_auth_name_len) { - session->userauth_kybd_auth_name = - LIBSSH2_ALLOC(session, - session->userauth_kybd_auth_name_len); - if (!session->userauth_kybd_auth_name) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "keyboard-interactive 'name' " - "request field"); - goto cleanup; - } - memcpy(session->userauth_kybd_auth_name, s, - session->userauth_kybd_auth_name_len); - s += session->userauth_kybd_auth_name_len; - } - - /* string instruction (ISO-10646 UTF-8) */ - session->userauth_kybd_auth_instruction_len = _libssh2_ntohu32(s); - s += 4; - if(session->userauth_kybd_auth_instruction_len) { - session->userauth_kybd_auth_instruction = - LIBSSH2_ALLOC(session, - session->userauth_kybd_auth_instruction_len); - if (!session->userauth_kybd_auth_instruction) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "keyboard-interactive 'instruction' " - "request field"); - goto cleanup; - } - memcpy(session->userauth_kybd_auth_instruction, s, - session->userauth_kybd_auth_instruction_len); - s += session->userauth_kybd_auth_instruction_len; - } - - /* string language tag (as defined in [RFC-3066]) */ - language_tag_len = _libssh2_ntohu32(s); - s += 4; - - /* ignoring this field as deprecated */ - s += language_tag_len; - - /* int num-prompts */ - session->userauth_kybd_num_prompts = _libssh2_ntohu32(s); - s += 4; - - if(session->userauth_kybd_num_prompts) { - session->userauth_kybd_prompts = - LIBSSH2_ALLOC(session, - sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) * - session->userauth_kybd_num_prompts); - if (!session->userauth_kybd_prompts) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "keyboard-interactive prompts array"); - goto cleanup; - } - memset(session->userauth_kybd_prompts, 0, - sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) * - session->userauth_kybd_num_prompts); - - session->userauth_kybd_responses = - LIBSSH2_ALLOC(session, - sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) * - session->userauth_kybd_num_prompts); - if (!session->userauth_kybd_responses) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "keyboard-interactive responses array"); - goto cleanup; - } - memset(session->userauth_kybd_responses, 0, - sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) * - session->userauth_kybd_num_prompts); - - for(i = 0; i != session->userauth_kybd_num_prompts; ++i) { - /* string prompt[1] (ISO-10646 UTF-8) */ - session->userauth_kybd_prompts[i].length = - _libssh2_ntohu32(s); - s += 4; - session->userauth_kybd_prompts[i].text = - LIBSSH2_ALLOC(session, - session->userauth_kybd_prompts[i].length); - if (!session->userauth_kybd_prompts[i].text) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "keyboard-interactive prompt message"); - goto cleanup; - } - memcpy(session->userauth_kybd_prompts[i].text, s, - session->userauth_kybd_prompts[i].length); - s += session->userauth_kybd_prompts[i].length; - - /* boolean echo[1] */ - session->userauth_kybd_prompts[i].echo = *s++; - } - } - - response_callback(session->userauth_kybd_auth_name, - session->userauth_kybd_auth_name_len, - session->userauth_kybd_auth_instruction, - session->userauth_kybd_auth_instruction_len, - session->userauth_kybd_num_prompts, - session->userauth_kybd_prompts, - session->userauth_kybd_responses, - &session->abstract); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Keyboard-interactive response callback function" - " invoked"); - - session->userauth_kybd_packet_len = - 1 /* byte SSH_MSG_USERAUTH_INFO_RESPONSE */ - + 4 /* int num-responses */ - ; - - for(i = 0; i != session->userauth_kybd_num_prompts; ++i) { - /* string response[1] (ISO-10646 UTF-8) */ - session->userauth_kybd_packet_len += - 4 + session->userauth_kybd_responses[i].length; - } - - /* A new userauth_kybd_data area is to be allocated, free the - former one. */ - LIBSSH2_FREE(session, session->userauth_kybd_data); - - session->userauth_kybd_data = s = - LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len); - if (!s) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for keyboard-" - "interactive response packet"); - goto cleanup; - } - - *s = SSH_MSG_USERAUTH_INFO_RESPONSE; - s++; - _libssh2_store_u32(&s, session->userauth_kybd_num_prompts); - - for(i = 0; i != session->userauth_kybd_num_prompts; ++i) { - _libssh2_store_str(&s, - session->userauth_kybd_responses[i].text, - session->userauth_kybd_responses[i].length); - } - - session->userauth_kybd_state = libssh2_NB_state_sent1; - } - - if (session->userauth_kybd_state == libssh2_NB_state_sent1) { - rc = _libssh2_transport_send(session, session->userauth_kybd_data, - session->userauth_kybd_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block"); - if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-keyboard-interactive" - " request"); - goto cleanup; - } - - session->userauth_kybd_auth_failure = 0; - } - - cleanup: - /* - * It's safe to clean all the data here, because unallocated pointers - * are filled by zeroes - */ - - LIBSSH2_FREE(session, session->userauth_kybd_data); - session->userauth_kybd_data = NULL; - - if (session->userauth_kybd_prompts) { - for(i = 0; i != session->userauth_kybd_num_prompts; ++i) { - LIBSSH2_FREE(session, session->userauth_kybd_prompts[i].text); - session->userauth_kybd_prompts[i].text = NULL; - } - } - - if (session->userauth_kybd_responses) { - for(i = 0; i != session->userauth_kybd_num_prompts; ++i) { - LIBSSH2_FREE(session, - session->userauth_kybd_responses[i].text); - session->userauth_kybd_responses[i].text = NULL; - } - } - - if(session->userauth_kybd_prompts) { - LIBSSH2_FREE(session, session->userauth_kybd_prompts); - session->userauth_kybd_prompts = NULL; - } - if(session->userauth_kybd_responses) { - LIBSSH2_FREE(session, session->userauth_kybd_responses); - session->userauth_kybd_responses = NULL; - } - if(session->userauth_kybd_auth_name) { - LIBSSH2_FREE(session, session->userauth_kybd_auth_name); - session->userauth_kybd_auth_name = NULL; - } - if(session->userauth_kybd_auth_instruction) { - LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction); - session->userauth_kybd_auth_instruction = NULL; - } - - if (session->userauth_kybd_auth_failure) { - session->userauth_kybd_state = libssh2_NB_state_idle; - return -1; - } - - session->userauth_kybd_state = libssh2_NB_state_sent; - } -} - -/* - * libssh2_userauth_keyboard_interactive_ex - * - * Authenticate using a challenge-response authentication - */ -LIBSSH2_API int -libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session, - const char *user, - unsigned int user_len, - LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback))) -{ - int rc; - BLOCK_ADJUST(rc, session, - userauth_keyboard_interactive(session, user, user_len, - response_callback)); - return rc; -} diff --git a/vendor/libssh2-1.4.2/src/userauth.h b/vendor/libssh2-1.4.2/src/userauth.h deleted file mode 100644 index c0442ae..0000000 --- a/vendor/libssh2-1.4.2/src/userauth.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef LIBSSH2_USERAUTH_H -#define LIBSSH2_USERAUTH_H -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2009-2010 by Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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. - */ - -int -_libssh2_userauth_publickey(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const unsigned char *pubkeydata, - unsigned long pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void *abstract); - -#endif /* LIBSSH2_USERAUTH_H */ diff --git a/vendor/libssh2-1.4.2/src/version.c b/vendor/libssh2-1.4.2/src/version.c deleted file mode 100644 index 408f83a..0000000 --- a/vendor/libssh2-1.4.2/src/version.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2009 Daniel Stenberg. All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names - * of any other 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 OWNER 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 "libssh2_priv.h" - -/* - libssh2_version() can be used like this: - - if (!libssh2_version(LIBSSH2_VERSION_NUM)) { - fprintf (stderr, "Runtime libssh2 version too old!\n"); - exit(1); - } -*/ -LIBSSH2_API -const char *libssh2_version(int req_version_num) -{ - if(req_version_num <= LIBSSH2_VERSION_NUM) - return LIBSSH2_VERSION; - return NULL; /* this is not a suitable library! */ -} diff --git a/vendor/sigar/CMakeLists.txt b/vendor/sigar/CMakeLists.txt deleted file mode 100644 index 671ac72..0000000 --- a/vendor/sigar/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -INCLUDE_DIRECTORIES(include) - - -IF(WIN32) - INCLUDE_DIRECTORIES(src/os/win32) - SET( os_sources src/os/win32/peb.c src/os/win32/wmi.cpp src/os/win32/win32_sigar.c ) -ELSE(WIN32) - IF( APPLE ) - ADD_DEFINITIONS( -DDARWIN_HAS_LIBPROC_H ) - INCLUDE_DIRECTORIES(src/os/darwin) - SET( os_sources src/os/darwin/darwin_sigar.c ) - ELSE( APPLE ) - INCLUDE_DIRECTORIES(src/os/linux) - SET( os_sources src/os/linux/linux_sigar.c ) - ENDIF( APPLE ) - -ENDIF(WIN32) - - -SET( sources - ${os_sources} - src/sigar.c - src/sigar_cache.c - src/sigar_fileinfo.c - src/sigar_format.c - src/sigar_getline.c - src/sigar_ptql.c - src/sigar_signal.c - src/sigar_util.c - src/sigar_version_autoconf.c -) - -SETUP_LIBRARY( sigar SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC ) diff --git a/vendor/sigar/include/sigar.h b/vendor/sigar/include/sigar.h deleted file mode 100644 index 3b26cb8..0000000 --- a/vendor/sigar/include/sigar.h +++ /dev/null @@ -1,943 +0,0 @@ -/* - * Copyright (c) 2004-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_H -#define SIGAR_H - -/* System Information Gatherer And Reporter */ - -#include - -#ifndef MAX_INTERFACE_NAME_LEN -#define MAX_INTERFACE_NAME_LEN 256 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(_LP64) || \ - defined(__LP64__) || \ - defined(__64BIT__) || \ - defined(__powerpc64__) || \ - defined(__osf__) -#define SIGAR_64BIT -#endif - -/* for printf sigar_uint64_t */ -#ifdef SIGAR_64BIT -# define SIGAR_F_U64 "%lu" -#else -# define SIGAR_F_U64 "%Lu" -#endif - -#if defined(WIN32) - -typedef unsigned __int32 sigar_uint32_t; - -typedef unsigned __int64 sigar_uint64_t; - -typedef __int32 sigar_int32_t; - -typedef __int64 sigar_int64_t; - -#elif ULONG_MAX > 4294967295UL - -typedef unsigned int sigar_uint32_t; - -typedef unsigned long sigar_uint64_t; - -typedef int sigar_int32_t; - -typedef long sigar_int64_t; - -#else - -typedef unsigned int sigar_uint32_t; - -typedef unsigned long long sigar_uint64_t; - -typedef int sigar_int32_t; - -typedef long long sigar_int64_t; - -#endif - -#define SIGAR_FIELD_NOTIMPL -1 - -#define SIGAR_OK 0 -#define SIGAR_START_ERROR 20000 -#define SIGAR_ENOTIMPL (SIGAR_START_ERROR + 1) -#define SIGAR_OS_START_ERROR (SIGAR_START_ERROR*2) - -#ifdef WIN32 -# define SIGAR_ENOENT ERROR_FILE_NOT_FOUND -# define SIGAR_EACCES ERROR_ACCESS_DENIED -# define SIGAR_ENXIO ERROR_BAD_DRIVER_LEVEL -#else -# define SIGAR_ENOENT ENOENT -# define SIGAR_EACCES EACCES -# define SIGAR_ENXIO ENXIO -#endif - -#ifdef WIN32 -# define SIGAR_DECLARE(type) \ - __declspec(dllexport) type __stdcall -#else -# define SIGAR_DECLARE(type) type -#endif - -#if defined(PATH_MAX) -# define SIGAR_PATH_MAX PATH_MAX -#elif defined(MAXPATHLEN) -# define SIGAR_PATH_MAX MAXPATHLEN -#else -# define SIGAR_PATH_MAX 4096 -#endif - -#ifdef WIN32 -typedef sigar_uint64_t sigar_pid_t; -typedef unsigned long sigar_uid_t; -typedef unsigned long sigar_gid_t; -#else -#include -typedef pid_t sigar_pid_t; -typedef uid_t sigar_uid_t; -typedef gid_t sigar_gid_t; -#endif - -typedef struct sigar_t sigar_t; - -SIGAR_DECLARE(int) sigar_open(sigar_t **sigar); - -SIGAR_DECLARE(int) sigar_close(sigar_t *sigar); - -SIGAR_DECLARE(sigar_pid_t) sigar_pid_get(sigar_t *sigar); - -SIGAR_DECLARE(int) sigar_proc_kill(sigar_pid_t pid, int signum); - -SIGAR_DECLARE(int) sigar_signum_get(char *name); - -SIGAR_DECLARE(char *) sigar_strerror(sigar_t *sigar, int err); - -/* system memory info */ - -typedef struct { - sigar_uint64_t - ram, - total, - used, - free, - actual_used, - actual_free; - double used_percent; - double free_percent; -} sigar_mem_t; - -SIGAR_DECLARE(int) sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem); - -typedef struct { - sigar_uint64_t - total, - used, - free, - page_in, - page_out; -} sigar_swap_t; - -SIGAR_DECLARE(int) sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap); - -typedef struct { - sigar_uint64_t - user, - sys, - nice, - idle, - wait, - irq, - soft_irq, - stolen, - total; -} sigar_cpu_t; - -SIGAR_DECLARE(int) sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu); - -typedef struct { - unsigned long number; - unsigned long size; - sigar_cpu_t *data; -} sigar_cpu_list_t; - -SIGAR_DECLARE(int) sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist); - -SIGAR_DECLARE(int) sigar_cpu_list_destroy(sigar_t *sigar, - sigar_cpu_list_t *cpulist); - -typedef struct { - char vendor[128]; - char model[128]; - int mhz; - int mhz_max; - int mhz_min; - sigar_uint64_t cache_size; - int total_sockets; - int total_cores; - int cores_per_socket; -} sigar_cpu_info_t; - -typedef struct { - unsigned long number; - unsigned long size; - sigar_cpu_info_t *data; -} sigar_cpu_info_list_t; - -SIGAR_DECLARE(int) -sigar_cpu_info_list_get(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos); - -SIGAR_DECLARE(int) -sigar_cpu_info_list_destroy(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos); - -typedef struct { - double uptime; -} sigar_uptime_t; - -SIGAR_DECLARE(int) sigar_uptime_get(sigar_t *sigar, - sigar_uptime_t *uptime); - -typedef struct { - double loadavg[3]; -} sigar_loadavg_t; - -SIGAR_DECLARE(int) sigar_loadavg_get(sigar_t *sigar, - sigar_loadavg_t *loadavg); - -typedef struct { - unsigned long number; - unsigned long size; - sigar_pid_t *data; -} sigar_proc_list_t; - -typedef struct { - /* RLIMIT_CPU */ - sigar_uint64_t cpu_cur, cpu_max; - /* RLIMIT_FSIZE */ - sigar_uint64_t file_size_cur, file_size_max; - /* PIPE_BUF */ - sigar_uint64_t pipe_size_cur, pipe_size_max; - /* RLIMIT_DATA */ - sigar_uint64_t data_cur, data_max; - /* RLIMIT_STACK */ - sigar_uint64_t stack_cur, stack_max; - /* RLIMIT_CORE */ - sigar_uint64_t core_cur, core_max; - /* RLIMIT_RSS */ - sigar_uint64_t memory_cur, memory_max; - /* RLIMIT_NPROC */ - sigar_uint64_t processes_cur, processes_max; - /* RLIMIT_NOFILE */ - sigar_uint64_t open_files_cur, open_files_max; - /* RLIMIT_AS */ - sigar_uint64_t virtual_memory_cur, virtual_memory_max; -} sigar_resource_limit_t; - -SIGAR_DECLARE(int) sigar_resource_limit_get(sigar_t *sigar, - sigar_resource_limit_t *rlimit); - -SIGAR_DECLARE(int) sigar_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist); - -SIGAR_DECLARE(int) sigar_proc_list_destroy(sigar_t *sigar, - sigar_proc_list_t *proclist); - -typedef struct { - sigar_uint64_t total; - sigar_uint64_t sleeping; - sigar_uint64_t running; - sigar_uint64_t zombie; - sigar_uint64_t stopped; - sigar_uint64_t idle; - sigar_uint64_t threads; -} sigar_proc_stat_t; - -SIGAR_DECLARE(int) sigar_proc_stat_get(sigar_t *sigar, - sigar_proc_stat_t *procstat); - -typedef struct { - sigar_uint64_t - size, - resident, - share, - minor_faults, - major_faults, - page_faults; -} sigar_proc_mem_t; - -SIGAR_DECLARE(int) sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_mem_t *procmem); - -typedef struct { - sigar_uid_t uid; - sigar_gid_t gid; - sigar_uid_t euid; - sigar_gid_t egid; -} sigar_proc_cred_t; - -SIGAR_DECLARE(int) sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_t *proccred); - -#define SIGAR_CRED_NAME_MAX 512 - -typedef struct { - char user[SIGAR_CRED_NAME_MAX]; - char group[SIGAR_CRED_NAME_MAX]; -} sigar_proc_cred_name_t; - -SIGAR_DECLARE(int) -sigar_proc_cred_name_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_name_t *proccredname); - -typedef struct { - sigar_uint64_t - start_time, - user, - sys, - total; -} sigar_proc_time_t; - -SIGAR_DECLARE(int) sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_time_t *proctime); - -typedef struct { - /* must match sigar_proc_time_t fields */ - sigar_uint64_t - start_time, - user, - sys, - total; - sigar_uint64_t last_time; - double percent; -} sigar_proc_cpu_t; - -SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cpu_t *proccpu); - -#define SIGAR_PROC_STATE_SLEEP 'S' -#define SIGAR_PROC_STATE_RUN 'R' -#define SIGAR_PROC_STATE_STOP 'T' -#define SIGAR_PROC_STATE_ZOMBIE 'Z' -#define SIGAR_PROC_STATE_IDLE 'D' - -#define SIGAR_PROC_NAME_LEN 128 - -typedef struct { - char name[SIGAR_PROC_NAME_LEN]; - char state; - sigar_pid_t ppid; - int tty; - int priority; - int nice; - int processor; - sigar_uint64_t threads; -} sigar_proc_state_t; - -SIGAR_DECLARE(int) sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate); - -typedef struct { - unsigned long number; - unsigned long size; - char **data; -} sigar_proc_args_t; - -SIGAR_DECLARE(int) sigar_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs); - -SIGAR_DECLARE(int) sigar_proc_args_destroy(sigar_t *sigar, - sigar_proc_args_t *procargs); - -typedef struct { - void *data; /* user data */ - - enum { - SIGAR_PROC_ENV_ALL, - SIGAR_PROC_ENV_KEY - } type; - - /* used for SIGAR_PROC_ENV_KEY */ - const char *key; - int klen; - - int (*env_getter)(void *, const char *, int, char *, int); -} sigar_proc_env_t; - -SIGAR_DECLARE(int) sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv); - -typedef struct { - sigar_uint64_t total; - /* XXX - which are files, sockets, etc. */ -} sigar_proc_fd_t; - -SIGAR_DECLARE(int) sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_fd_t *procfd); - -typedef struct { - char name[SIGAR_PATH_MAX+1]; - char cwd[SIGAR_PATH_MAX+1]; - char root[SIGAR_PATH_MAX+1]; -} sigar_proc_exe_t; - -SIGAR_DECLARE(int) sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe); - -typedef struct { - void *data; /* user data */ - - int (*module_getter)(void *, char *, int); -} sigar_proc_modules_t; - -SIGAR_DECLARE(int) sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods); - -typedef struct { - sigar_uint64_t user; - sigar_uint64_t sys; - sigar_uint64_t total; -} sigar_thread_cpu_t; - -SIGAR_DECLARE(int) sigar_thread_cpu_get(sigar_t *sigar, - sigar_uint64_t id, - sigar_thread_cpu_t *cpu); - -typedef enum { - SIGAR_FSTYPE_UNKNOWN, - SIGAR_FSTYPE_NONE, - SIGAR_FSTYPE_LOCAL_DISK, - SIGAR_FSTYPE_NETWORK, - SIGAR_FSTYPE_RAM_DISK, - SIGAR_FSTYPE_CDROM, - SIGAR_FSTYPE_SWAP, - SIGAR_FSTYPE_MAX -} sigar_file_system_type_e; - -#define SIGAR_FS_NAME_LEN SIGAR_PATH_MAX -#define SIGAR_FS_INFO_LEN 256 - -typedef struct { - char dir_name[SIGAR_FS_NAME_LEN]; - char dev_name[SIGAR_FS_NAME_LEN]; - char type_name[SIGAR_FS_INFO_LEN]; /* e.g. "local" */ - char sys_type_name[SIGAR_FS_INFO_LEN]; /* e.g. "ext3" */ - char options[SIGAR_FS_INFO_LEN]; - sigar_file_system_type_e type; - unsigned long flags; -} sigar_file_system_t; - -typedef struct { - unsigned long number; - unsigned long size; - sigar_file_system_t *data; -} sigar_file_system_list_t; - -SIGAR_DECLARE(int) -sigar_file_system_list_get(sigar_t *sigar, - sigar_file_system_list_t *fslist); - -SIGAR_DECLARE(int) -sigar_file_system_list_destroy(sigar_t *sigar, - sigar_file_system_list_t *fslist); - -typedef struct { - sigar_uint64_t reads; - sigar_uint64_t writes; - sigar_uint64_t write_bytes; - sigar_uint64_t read_bytes; - sigar_uint64_t rtime; - sigar_uint64_t wtime; - sigar_uint64_t qtime; - sigar_uint64_t time; - sigar_uint64_t snaptime; - double service_time; - double queue; -} sigar_disk_usage_t; - -/* XXX for sigar_file_system_usage_t compat */ -#define disk_reads disk.reads -#define disk_writes disk.writes -#define disk_write_bytes disk.write_bytes -#define disk_read_bytes disk.read_bytes -#define disk_queue disk.queue -#define disk_service_time disk.service_time - -typedef struct { - sigar_disk_usage_t disk; - double use_percent; - sigar_uint64_t total; - sigar_uint64_t free; - sigar_uint64_t used; - sigar_uint64_t avail; - sigar_uint64_t files; - sigar_uint64_t free_files; -} sigar_file_system_usage_t; - -#undef SIGAR_DISK_USAGE_T - -SIGAR_DECLARE(int) -sigar_file_system_usage_get(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage); - -SIGAR_DECLARE(int) sigar_disk_usage_get(sigar_t *sigar, - const char *name, - sigar_disk_usage_t *disk); - -SIGAR_DECLARE(int) -sigar_file_system_ping(sigar_t *sigar, - sigar_file_system_t *fs); - -typedef struct { - enum { - SIGAR_AF_UNSPEC, - SIGAR_AF_INET, - SIGAR_AF_INET6, - SIGAR_AF_LINK - } family; - union { - sigar_uint32_t in; - sigar_uint32_t in6[4]; - unsigned char mac[8]; - } addr; -} sigar_net_address_t; - -#define SIGAR_INET6_ADDRSTRLEN 46 - -#define SIGAR_MAXDOMAINNAMELEN 256 -#define SIGAR_MAXHOSTNAMELEN 256 - -typedef struct { - char default_gateway[SIGAR_INET6_ADDRSTRLEN]; - char default_gateway_interface[MAX_INTERFACE_NAME_LEN]; - char host_name[SIGAR_MAXHOSTNAMELEN]; - char domain_name[SIGAR_MAXDOMAINNAMELEN]; - char primary_dns[SIGAR_INET6_ADDRSTRLEN]; - char secondary_dns[SIGAR_INET6_ADDRSTRLEN]; -} sigar_net_info_t; - -SIGAR_DECLARE(int) -sigar_net_info_get(sigar_t *sigar, - sigar_net_info_t *netinfo); - -#define SIGAR_RTF_UP 0x1 -#define SIGAR_RTF_GATEWAY 0x2 -#define SIGAR_RTF_HOST 0x4 - -typedef struct { - sigar_net_address_t destination; - sigar_net_address_t gateway; - sigar_net_address_t mask; - sigar_uint64_t - flags, - refcnt, - use, - metric, - mtu, - window, - irtt; - char ifname[MAX_INTERFACE_NAME_LEN]; -} sigar_net_route_t; - -typedef struct { - unsigned long number; - unsigned long size; - sigar_net_route_t *data; -} sigar_net_route_list_t; - -SIGAR_DECLARE(int) sigar_net_route_list_get(sigar_t *sigar, - sigar_net_route_list_t *routelist); - -SIGAR_DECLARE(int) sigar_net_route_list_destroy(sigar_t *sigar, - sigar_net_route_list_t *routelist); - -/* - * platforms define most of these "standard" flags, - * but of course, with different values in some cases. - */ -#define SIGAR_IFF_UP 0x1 -#define SIGAR_IFF_BROADCAST 0x2 -#define SIGAR_IFF_DEBUG 0x4 -#define SIGAR_IFF_LOOPBACK 0x8 -#define SIGAR_IFF_POINTOPOINT 0x10 -#define SIGAR_IFF_NOTRAILERS 0x20 -#define SIGAR_IFF_RUNNING 0x40 -#define SIGAR_IFF_NOARP 0x80 -#define SIGAR_IFF_PROMISC 0x100 -#define SIGAR_IFF_ALLMULTI 0x200 -#define SIGAR_IFF_MULTICAST 0x800 -#define SIGAR_IFF_SLAVE 0x1000 -#define SIGAR_IFF_MASTER 0x2000 -#define SIGAR_IFF_DYNAMIC 0x4000 - -#define SIGAR_NULL_HWADDR "00:00:00:00:00:00" - -/* scope values from linux-2.6/include/net/ipv6.h */ -#define SIGAR_IPV6_ADDR_ANY 0x0000 -#define SIGAR_IPV6_ADDR_UNICAST 0x0001 -#define SIGAR_IPV6_ADDR_MULTICAST 0x0002 -#define SIGAR_IPV6_ADDR_LOOPBACK 0x0010 -#define SIGAR_IPV6_ADDR_LINKLOCAL 0x0020 -#define SIGAR_IPV6_ADDR_SITELOCAL 0x0040 -#define SIGAR_IPV6_ADDR_COMPATv4 0x0080 - -typedef struct { - char name[MAX_INTERFACE_NAME_LEN]; - char type[64]; - char description[256]; - sigar_net_address_t hwaddr; - sigar_net_address_t address; - sigar_net_address_t destination; - sigar_net_address_t broadcast; - sigar_net_address_t netmask; - sigar_net_address_t address6; - int prefix6_length; - int scope6; - sigar_uint64_t - flags, - mtu, - metric; - int tx_queue_len; -} sigar_net_interface_config_t; - -SIGAR_DECLARE(int) -sigar_net_interface_config_get(sigar_t *sigar, - const char *name, - sigar_net_interface_config_t *ifconfig); - -SIGAR_DECLARE(int) -sigar_net_interface_config_primary_get(sigar_t *sigar, - sigar_net_interface_config_t *ifconfig); - -typedef struct { - sigar_uint64_t - /* received */ - rx_packets, - rx_bytes, - rx_errors, - rx_dropped, - rx_overruns, - rx_frame, - /* transmitted */ - tx_packets, - tx_bytes, - tx_errors, - tx_dropped, - tx_overruns, - tx_collisions, - tx_carrier, - speed; -} sigar_net_interface_stat_t; - -SIGAR_DECLARE(int) -sigar_net_interface_stat_get(sigar_t *sigar, - const char *name, - sigar_net_interface_stat_t *ifstat); - -typedef struct { - unsigned long number; - unsigned long size; - char **data; -} sigar_net_interface_list_t; - -SIGAR_DECLARE(int) -sigar_net_interface_list_get(sigar_t *sigar, - sigar_net_interface_list_t *iflist); - -SIGAR_DECLARE(int) -sigar_net_interface_list_destroy(sigar_t *sigar, - sigar_net_interface_list_t *iflist); - -#define SIGAR_NETCONN_CLIENT 0x01 -#define SIGAR_NETCONN_SERVER 0x02 - -#define SIGAR_NETCONN_TCP 0x10 -#define SIGAR_NETCONN_UDP 0x20 -#define SIGAR_NETCONN_RAW 0x40 -#define SIGAR_NETCONN_UNIX 0x80 - -enum { - SIGAR_TCP_ESTABLISHED = 1, - SIGAR_TCP_SYN_SENT, - SIGAR_TCP_SYN_RECV, - SIGAR_TCP_FIN_WAIT1, - SIGAR_TCP_FIN_WAIT2, - SIGAR_TCP_TIME_WAIT, - SIGAR_TCP_CLOSE, - SIGAR_TCP_CLOSE_WAIT, - SIGAR_TCP_LAST_ACK, - SIGAR_TCP_LISTEN, - SIGAR_TCP_CLOSING, - SIGAR_TCP_IDLE, - SIGAR_TCP_BOUND, - SIGAR_TCP_UNKNOWN -}; - -typedef struct { - unsigned long local_port; - sigar_net_address_t local_address; - unsigned long remote_port; - sigar_net_address_t remote_address; - sigar_uid_t uid; - unsigned long inode; - int type; - int state; - unsigned long send_queue; - unsigned long receive_queue; -} sigar_net_connection_t; - -typedef struct { - unsigned long number; - unsigned long size; - sigar_net_connection_t *data; -} sigar_net_connection_list_t; - -SIGAR_DECLARE(int) -sigar_net_connection_list_get(sigar_t *sigar, - sigar_net_connection_list_t *connlist, - int flags); - -SIGAR_DECLARE(int) -sigar_net_connection_list_destroy(sigar_t *sigar, - sigar_net_connection_list_t *connlist); - -typedef struct sigar_net_connection_walker_t sigar_net_connection_walker_t; - -/* alternative to sigar_net_connection_list_get */ -struct sigar_net_connection_walker_t { - sigar_t *sigar; - int flags; - void *data; /* user data */ - int (*add_connection)(sigar_net_connection_walker_t *walker, - sigar_net_connection_t *connection); -}; - -SIGAR_DECLARE(int) -sigar_net_connection_walk(sigar_net_connection_walker_t *walker); - -typedef struct { - int tcp_states[SIGAR_TCP_UNKNOWN]; - sigar_uint32_t tcp_inbound_total; - sigar_uint32_t tcp_outbound_total; - sigar_uint32_t all_inbound_total; - sigar_uint32_t all_outbound_total; -} sigar_net_stat_t; - -SIGAR_DECLARE(int) -sigar_net_stat_get(sigar_t *sigar, - sigar_net_stat_t *netstat, - int flags); - -SIGAR_DECLARE(int) -sigar_net_stat_port_get(sigar_t *sigar, - sigar_net_stat_t *netstat, - int flags, - sigar_net_address_t *address, - unsigned long port); - -/* TCP-MIB */ -typedef struct { - sigar_uint64_t active_opens; - sigar_uint64_t passive_opens; - sigar_uint64_t attempt_fails; - sigar_uint64_t estab_resets; - sigar_uint64_t curr_estab; - sigar_uint64_t in_segs; - sigar_uint64_t out_segs; - sigar_uint64_t retrans_segs; - sigar_uint64_t in_errs; - sigar_uint64_t out_rsts; -} sigar_tcp_t; - -SIGAR_DECLARE(int) -sigar_tcp_get(sigar_t *sigar, - sigar_tcp_t *tcp); - -typedef struct { - sigar_uint64_t null; - sigar_uint64_t getattr; - sigar_uint64_t setattr; - sigar_uint64_t root; - sigar_uint64_t lookup; - sigar_uint64_t readlink; - sigar_uint64_t read; - sigar_uint64_t writecache; - sigar_uint64_t write; - sigar_uint64_t create; - sigar_uint64_t remove; - sigar_uint64_t rename; - sigar_uint64_t link; - sigar_uint64_t symlink; - sigar_uint64_t mkdir; - sigar_uint64_t rmdir; - sigar_uint64_t readdir; - sigar_uint64_t fsstat; -} sigar_nfs_v2_t; - -typedef sigar_nfs_v2_t sigar_nfs_client_v2_t; -typedef sigar_nfs_v2_t sigar_nfs_server_v2_t; - -SIGAR_DECLARE(int) -sigar_nfs_client_v2_get(sigar_t *sigar, - sigar_nfs_client_v2_t *nfs); - -SIGAR_DECLARE(int) -sigar_nfs_server_v2_get(sigar_t *sigar, - sigar_nfs_server_v2_t *nfs); - -typedef struct { - sigar_uint64_t null; - sigar_uint64_t getattr; - sigar_uint64_t setattr; - sigar_uint64_t lookup; - sigar_uint64_t access; - sigar_uint64_t readlink; - sigar_uint64_t read; - sigar_uint64_t write; - sigar_uint64_t create; - sigar_uint64_t mkdir; - sigar_uint64_t symlink; - sigar_uint64_t mknod; - sigar_uint64_t remove; - sigar_uint64_t rmdir; - sigar_uint64_t rename; - sigar_uint64_t link; - sigar_uint64_t readdir; - sigar_uint64_t readdirplus; - sigar_uint64_t fsstat; - sigar_uint64_t fsinfo; - sigar_uint64_t pathconf; - sigar_uint64_t commit; -} sigar_nfs_v3_t; - -typedef sigar_nfs_v3_t sigar_nfs_client_v3_t; -typedef sigar_nfs_v3_t sigar_nfs_server_v3_t; - -SIGAR_DECLARE(int) -sigar_nfs_client_v3_get(sigar_t *sigar, - sigar_nfs_client_v3_t *nfs); - -SIGAR_DECLARE(int) -sigar_nfs_server_v3_get(sigar_t *sigar, - sigar_nfs_server_v3_t *nfs); - -SIGAR_DECLARE(int) -sigar_net_listen_address_get(sigar_t *sigar, - unsigned long port, - sigar_net_address_t *address); - -typedef struct { - char ifname[MAX_INTERFACE_NAME_LEN]; - char type[64]; - sigar_net_address_t hwaddr; - sigar_net_address_t address; - sigar_uint64_t flags; -} sigar_arp_t; - -typedef struct { - unsigned long number; - unsigned long size; - sigar_arp_t *data; -} sigar_arp_list_t; - -SIGAR_DECLARE(int) sigar_arp_list_get(sigar_t *sigar, - sigar_arp_list_t *arplist); - -SIGAR_DECLARE(int) sigar_arp_list_destroy(sigar_t *sigar, - sigar_arp_list_t *arplist); - -typedef struct { - char user[32]; - char device[32]; - char host[256]; - sigar_uint64_t time; -} sigar_who_t; - -typedef struct { - unsigned long number; - unsigned long size; - sigar_who_t *data; -} sigar_who_list_t; - -SIGAR_DECLARE(int) sigar_who_list_get(sigar_t *sigar, - sigar_who_list_t *wholist); - -SIGAR_DECLARE(int) sigar_who_list_destroy(sigar_t *sigar, - sigar_who_list_t *wholist); - -SIGAR_DECLARE(int) sigar_proc_port_get(sigar_t *sigar, - int protocol, unsigned long port, - sigar_pid_t *pid); - -typedef struct { - const char *build_date; - const char *scm_revision; - const char *version; - const char *archname; - const char *archlib; - const char *binname; - const char *description; - int major, minor, maint, build; -} sigar_version_t; - -SIGAR_DECLARE(sigar_version_t *) sigar_version_get(void); - -#define SIGAR_SYS_INFO_LEN SIGAR_MAXHOSTNAMELEN /* more than enough */ - -typedef struct { - char name[SIGAR_SYS_INFO_LEN]; /* canonicalized sysname */ - char version[SIGAR_SYS_INFO_LEN]; /* utsname.release */ - char arch[SIGAR_SYS_INFO_LEN]; - char machine[SIGAR_SYS_INFO_LEN]; - char description[SIGAR_SYS_INFO_LEN]; - char patch_level[SIGAR_SYS_INFO_LEN]; - char vendor[SIGAR_SYS_INFO_LEN]; - char vendor_version[SIGAR_SYS_INFO_LEN]; - char vendor_name[SIGAR_SYS_INFO_LEN]; /* utsname.sysname */ - char vendor_code_name[SIGAR_SYS_INFO_LEN]; -} sigar_sys_info_t; - -SIGAR_DECLARE(int) sigar_sys_info_get(sigar_t *sigar, sigar_sys_info_t *sysinfo); - -#define SIGAR_FQDN_LEN 512 - -SIGAR_DECLARE(int) sigar_fqdn_get(sigar_t *sigar, char *name, int namelen); - -SIGAR_DECLARE(int) sigar_rpc_ping(char *hostname, - int protocol, - unsigned long program, - unsigned long version); - -SIGAR_DECLARE(char *) sigar_rpc_strerror(int err); - -SIGAR_DECLARE(char *) sigar_password_get(const char *prompt); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/sigar/include/sigar_fileinfo.h b/vendor/sigar/include/sigar_fileinfo.h deleted file mode 100644 index f13a4e4..0000000 --- a/vendor/sigar/include/sigar_fileinfo.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2004-2005 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2003 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR - * ITS 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 consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -#include "sigar.h" - -typedef enum { - SIGAR_FILETYPE_NOFILE = 0, /**< no file type determined */ - SIGAR_FILETYPE_REG, /**< a regular file */ - SIGAR_FILETYPE_DIR, /**< a directory */ - SIGAR_FILETYPE_CHR, /**< a character device */ - SIGAR_FILETYPE_BLK, /**< a block device */ - SIGAR_FILETYPE_PIPE, /**< a FIFO / pipe */ - SIGAR_FILETYPE_LNK, /**< a symbolic link */ - SIGAR_FILETYPE_SOCK, /**< a [unix domain] socket */ - SIGAR_FILETYPE_UNKFILE /**< a file of some other unknown type */ -} sigar_file_type_e; - -#define SIGAR_UREAD 0x0400 /**< Read by user */ -#define SIGAR_UWRITE 0x0200 /**< Write by user */ -#define SIGAR_UEXECUTE 0x0100 /**< Execute by user */ - -#define SIGAR_GREAD 0x0040 /**< Read by group */ -#define SIGAR_GWRITE 0x0020 /**< Write by group */ -#define SIGAR_GEXECUTE 0x0010 /**< Execute by group */ - -#define SIGAR_WREAD 0x0004 /**< Read by others */ -#define SIGAR_WWRITE 0x0002 /**< Write by others */ -#define SIGAR_WEXECUTE 0x0001 /**< Execute by others */ - -typedef struct { - /** The access permissions of the file. Mimics Unix access rights. */ - sigar_uint64_t permissions; - sigar_file_type_e type; - /** The user id that owns the file */ - sigar_uid_t uid; - /** The group id that owns the file */ - sigar_gid_t gid; - /** The inode of the file. */ - sigar_uint64_t inode; - /** The id of the device the file is on. */ - sigar_uint64_t device; - /** The number of hard links to the file. */ - sigar_uint64_t nlink; - /** The size of the file */ - sigar_uint64_t size; - /** The time the file was last accessed */ - sigar_uint64_t atime; - /** The time the file was last modified */ - sigar_uint64_t mtime; - /** The time the file was last changed */ - sigar_uint64_t ctime; -} sigar_file_attrs_t; - -typedef struct { - sigar_uint64_t total; - sigar_uint64_t files; - sigar_uint64_t subdirs; - sigar_uint64_t symlinks; - sigar_uint64_t chrdevs; - sigar_uint64_t blkdevs; - sigar_uint64_t sockets; - sigar_uint64_t disk_usage; -} sigar_dir_stat_t; - -typedef sigar_dir_stat_t sigar_dir_usage_t; - -SIGAR_DECLARE(const char *) -sigar_file_attrs_type_string_get(sigar_file_type_e type); - -SIGAR_DECLARE(int) sigar_file_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs); - -SIGAR_DECLARE(int) sigar_link_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs); - -SIGAR_DECLARE(int)sigar_file_attrs_mode_get(sigar_uint64_t permissions); - -SIGAR_DECLARE(char *) -sigar_file_attrs_permissions_string_get(sigar_uint64_t permissions, - char *str); - -SIGAR_DECLARE(int) sigar_dir_stat_get(sigar_t *sigar, - const char *dir, - sigar_dir_stat_t *dirstats); - -SIGAR_DECLARE(int) sigar_dir_usage_get(sigar_t *sigar, - const char *dir, - sigar_dir_usage_t *dirusage); diff --git a/vendor/sigar/include/sigar_format.h b/vendor/sigar/include/sigar_format.h deleted file mode 100644 index 3bce29b..0000000 --- a/vendor/sigar/include/sigar_format.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2007-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_FORMAT_H -#define SIGAR_FORMAT_H - -typedef struct { - double user; - double sys; - double nice; - double idle; - double wait; - double irq; - double soft_irq; - double stolen; - double combined; -} sigar_cpu_perc_t; - -SIGAR_DECLARE(int) sigar_cpu_perc_calculate(sigar_cpu_t *prev, - sigar_cpu_t *curr, - sigar_cpu_perc_t *perc); - -SIGAR_DECLARE(int) sigar_uptime_string(sigar_t *sigar, - sigar_uptime_t *uptime, - char *buffer, - int buflen); - -SIGAR_DECLARE(char *) sigar_format_size(sigar_uint64_t size, char *buf); - -SIGAR_DECLARE(int) sigar_net_address_equals(sigar_net_address_t *addr1, - sigar_net_address_t *addr2); - -SIGAR_DECLARE(int) sigar_net_address_to_string(sigar_t *sigar, - sigar_net_address_t *address, - char *addr_str); - -SIGAR_DECLARE(const char *)sigar_net_scope_to_string(int type); - -SIGAR_DECLARE(sigar_uint32_t) sigar_net_address_hash(sigar_net_address_t *address); - -SIGAR_DECLARE(const char *)sigar_net_connection_type_get(int type); - -SIGAR_DECLARE(const char *)sigar_net_connection_state_get(int state); - -SIGAR_DECLARE(char *) sigar_net_interface_flags_to_string(sigar_uint64_t flags, char *buf); - -SIGAR_DECLARE(char *)sigar_net_services_name_get(sigar_t *sigar, - int protocol, unsigned long port); - -#endif - diff --git a/vendor/sigar/include/sigar_getline.h b/vendor/sigar/include/sigar_getline.h deleted file mode 100644 index f5bbc7c..0000000 --- a/vendor/sigar/include/sigar_getline.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SIGAR_GETLINE_H -#define SIGAR_GETLINE_H - -#include "sigar.h" - -typedef int (*sigar_getline_completer_t)(char *, int, int *); - -SIGAR_DECLARE(char *) sigar_getline(char *prompt); -SIGAR_DECLARE(void) sigar_getline_setwidth(int width); -SIGAR_DECLARE(void) sigar_getline_redraw(void); -SIGAR_DECLARE(void) sigar_getline_reset(void); -SIGAR_DECLARE(void) sigar_getline_windowchanged(); -SIGAR_DECLARE(void) sigar_getline_histinit(char *file); -SIGAR_DECLARE(void) sigar_getline_histadd(char *buf); -SIGAR_DECLARE(int) sigar_getline_eof(); -SIGAR_DECLARE(void) sigar_getline_completer_set(sigar_getline_completer_t func); - -#endif /* SIGAR_GETLINE_H */ diff --git a/vendor/sigar/include/sigar_log.h b/vendor/sigar/include/sigar_log.h deleted file mode 100644 index cc32f9a..0000000 --- a/vendor/sigar/include/sigar_log.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2004, 2006 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_LOG_H -#define SIGAR_LOG_H - -#include - -#define SIGAR_LOG_FATAL 0 -#define SIGAR_LOG_ERROR 1 -#define SIGAR_LOG_WARN 2 -#define SIGAR_LOG_INFO 3 -#define SIGAR_LOG_DEBUG 4 -#define SIGAR_LOG_TRACE 5 - -#define SIGAR_LOG_IS_FATAL(sigar) \ - (sigar->log_level >= SIGAR_LOG_FATAL) - -#define SIGAR_LOG_IS_ERROR(sigar) \ - (sigar->log_level >= SIGAR_LOG_ERROR) - -#define SIGAR_LOG_IS_WARN(sigar) \ - (sigar->log_level >= SIGAR_LOG_WARN) - -#define SIGAR_LOG_IS_INFO(sigar) \ - (sigar->log_level >= SIGAR_LOG_INFO) - -#define SIGAR_LOG_IS_DEBUG(sigar) \ - (sigar->log_level >= SIGAR_LOG_DEBUG) - -#define SIGAR_LOG_IS_TRACE(sigar) \ - (sigar->log_level >= SIGAR_LOG_TRACE) - -#define SIGAR_STRINGIFY(n) #n - -#define SIGAR_LOG_FILELINE \ - __FILE__ ":" SIGAR_STRINGIFY(__LINE__) - -#if defined(__GNUC__) -# if (__GNUC__ > 2) -# define SIGAR_FUNC __func__ -# else -# define SIGAR_FUNC __FUNCTION__ -# endif -#else -# define SIGAR_FUNC SIGAR_LOG_FILELINE -#endif - -typedef void (*sigar_log_impl_t)(sigar_t *, void *, int, char *); - -SIGAR_DECLARE(void) sigar_log_printf(sigar_t *sigar, int level, - const char *format, ...); - -SIGAR_DECLARE(void) sigar_log(sigar_t *sigar, int level, char *message); - -SIGAR_DECLARE(void) sigar_log_impl_set(sigar_t *sigar, void *data, - sigar_log_impl_t impl); - -SIGAR_DECLARE(void) sigar_log_impl_file(sigar_t *sigar, void *data, - int level, char *message); - -SIGAR_DECLARE(int) sigar_log_level_get(sigar_t *sigar); - -SIGAR_DECLARE(void) sigar_log_level_set(sigar_t *sigar, int level); - - -#endif /* SIGAR_LOG_H */ diff --git a/vendor/sigar/include/sigar_private.h b/vendor/sigar/include/sigar_private.h deleted file mode 100644 index cfc9aa2..0000000 --- a/vendor/sigar/include/sigar_private.h +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (c) 2004-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_PRIVATE_DOT_H -#define SIGAR_PRIVATE_DOT_H - -#include "sigar_log.h" -#include "sigar_ptql.h" - -#include -#include -#include - -#ifndef WIN32 -#include -#include -#ifndef DARWIN -#include -#endif -#endif - -#ifdef DMALLOC -#define _MEMORY_H /* exclude memory.h on solaris */ -#define DMALLOC_FUNC_CHECK -#include -#endif - -/* common to all os sigar_t's */ -/* XXX: this is ugly; but don't want the same stuffs - * duplicated on 4 platforms and am too lazy to change - * sigar_t to the way it was originally where sigar_t was - * common and contained a sigar_os_t. - * feel free trav ;-) - */ -#define SIGAR_T_BASE \ - int cpu_list_cores; \ - int log_level; \ - void *log_data; \ - sigar_log_impl_t log_impl; \ - void *ptql_re_data; \ - sigar_ptql_re_impl_t ptql_re_impl; \ - unsigned int ncpu; \ - unsigned long version; \ - unsigned long boot_time; \ - int ticks; \ - sigar_pid_t pid; \ - char errbuf[256]; \ - char *ifconf_buf; \ - int ifconf_len; \ - char *self_path; \ - sigar_proc_list_t *pids; \ - sigar_cache_t *fsdev; \ - sigar_cache_t *proc_cpu; \ - sigar_cache_t *net_listen; \ - sigar_cache_t *net_services_tcp; \ - sigar_cache_t *net_services_udp - -#if defined(WIN32) -# define SIGAR_INLINE __inline -#elif defined(__GNUC__) -# define SIGAR_INLINE inline -#else -# define SIGAR_INLINE -#endif - -#ifdef DMALLOC -/* linux has its own strdup macro, make sure we use dmalloc's */ -#define sigar_strdup(s) \ - dmalloc_strndup(__FILE__, __LINE__, (s), -1, 0) -#else -# ifdef WIN32 -# define sigar_strdup(s) _strdup(s) -# else -# define sigar_strdup(s) strdup(s) -# endif -#endif - -#define SIGAR_ZERO(s) \ - memset(s, '\0', sizeof(*(s))) - -#define SIGAR_STRNCPY(dest, src, len) \ - strncpy(dest, src, len); \ - dest[len-1] = '\0' - -/* we use fixed size buffers pretty much everywhere */ -/* this is strncpy + ensured \0 terminator */ -#define SIGAR_SSTRCPY(dest, src) \ - SIGAR_STRNCPY(dest, src, sizeof(dest)) - -#ifndef strEQ -#define strEQ(s1, s2) (strcmp(s1, s2) == 0) -#endif - -#ifndef strnEQ -#define strnEQ(s1, s2, n) (strncmp(s1, s2, n) == 0) -#endif - -#ifdef WIN32 -#define strcasecmp stricmp -#define strncasecmp strnicmp -#endif - -#ifndef strcaseEQ -#define strcaseEQ(s1, s2) (strcasecmp(s1, s2) == 0) -#endif - -#ifndef strncaseEQ -#define strncaseEQ(s1, s2, n) (strncasecmp(s1, s2, n) == 0) -#endif - -#ifdef offsetof -#define sigar_offsetof offsetof -#else -#define sigar_offsetof(type, field) ((size_t)(&((type *)0)->field)) -#endif - -#define SIGAR_MSEC 1000L -#define SIGAR_USEC 1000000L -#define SIGAR_NSEC 1000000000L - -#define SIGAR_SEC2NANO(s) \ - ((sigar_uint64_t)(s) * (sigar_uint64_t)SIGAR_NSEC) - -/* cpu ticks to milliseconds */ -#define SIGAR_TICK2MSEC(s) \ - ((sigar_uint64_t)(s) * ((sigar_uint64_t)SIGAR_MSEC / (double)sigar->ticks)) - -#define SIGAR_TICK2NSEC(s) \ - ((sigar_uint64_t)(s) * ((sigar_uint64_t)SIGAR_NSEC / (double)sigar->ticks)) - -/* nanoseconds to milliseconds */ -#define SIGAR_NSEC2MSEC(s) \ - ((sigar_uint64_t)(s) / ((sigar_uint64_t)1000000L)) - -#define IFTYPE_LO 2 -#define IFTYPE_ETH 3 - -#define SIGAR_LAST_PROC_EXPIRE 2 - -#define SIGAR_FS_MAX 10 - -#define SIGAR_CPU_INFO_MAX 4 - -#define SIGAR_CPU_LIST_MAX 4 - -#define SIGAR_PROC_LIST_MAX 256 - -#define SIGAR_PROC_ARGS_MAX 12 - -#define SIGAR_NET_ROUTE_LIST_MAX 6 - -#define SIGAR_NET_IFLIST_MAX 20 - -#define SIGAR_NET_CONNLIST_MAX 20 - -#define SIGAR_ARP_LIST_MAX 12 - -#define SIGAR_WHO_LIST_MAX 12 - -int sigar_os_open(sigar_t **sigar); - -int sigar_os_close(sigar_t *sigar); - -char *sigar_os_error_string(sigar_t *sigar, int err); - -char *sigar_strerror_get(int err, char *errbuf, int buflen); - -void sigar_strerror_set(sigar_t *sigar, char *msg); - -void sigar_strerror_printf(sigar_t *sigar, const char *format, ...); - -int sigar_sys_info_get_uname(sigar_sys_info_t *sysinfo); - -int sigar_os_sys_info_get(sigar_t *sigar, sigar_sys_info_t *sysinfo); - -int sigar_os_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist); - -int sigar_proc_list_create(sigar_proc_list_t *proclist); - -int sigar_proc_list_grow(sigar_proc_list_t *proclist); - -#define SIGAR_PROC_LIST_GROW(proclist) \ - if (proclist->number >= proclist->size) { \ - sigar_proc_list_grow(proclist); \ - } - -int sigar_proc_args_create(sigar_proc_args_t *proclist); - -int sigar_proc_args_grow(sigar_proc_args_t *procargs); - -#define SIGAR_PROC_ARGS_GROW(procargs) \ - if (procargs->number >= procargs->size) { \ - sigar_proc_args_grow(procargs); \ - } - -int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs); - -int sigar_file_system_list_create(sigar_file_system_list_t *fslist); - -int sigar_file_system_list_grow(sigar_file_system_list_t *fslist); - -#define SIGAR_FILE_SYSTEM_LIST_GROW(fslist) \ - if (fslist->number >= fslist->size) { \ - sigar_file_system_list_grow(fslist); \ - } - -int sigar_os_fs_type_get(sigar_file_system_t *fsp); - -/* os plugins that set fsp->type call fs_type_get directly */ -#define sigar_fs_type_init(fsp) \ - fsp->type = SIGAR_FSTYPE_UNKNOWN; \ - sigar_fs_type_get(fsp) - -void sigar_fs_type_get(sigar_file_system_t *fsp); - -int sigar_cpu_info_list_create(sigar_cpu_info_list_t *cpu_infos); - -int sigar_cpu_info_list_grow(sigar_cpu_info_list_t *cpu_infos); - -#define SIGAR_CPU_INFO_LIST_GROW(cpu_infos) \ - if (cpu_infos->number >= cpu_infos->size) { \ - sigar_cpu_info_list_grow(cpu_infos); \ - } - -int sigar_cpu_list_create(sigar_cpu_list_t *cpulist); - -int sigar_cpu_list_grow(sigar_cpu_list_t *cpulist); - -#define SIGAR_CPU_LIST_GROW(cpulist) \ - if (cpulist->number >= cpulist->size) { \ - sigar_cpu_list_grow(cpulist); \ - } - -int sigar_net_route_list_create(sigar_net_route_list_t *routelist); - -int sigar_net_route_list_grow(sigar_net_route_list_t *net_routelist); - -#define SIGAR_NET_ROUTE_LIST_GROW(routelist) \ - if (routelist->number >= routelist->size) { \ - sigar_net_route_list_grow(routelist); \ - } - -int sigar_net_interface_list_create(sigar_net_interface_list_t *iflist); - -int sigar_net_interface_list_grow(sigar_net_interface_list_t *iflist); - -#define SIGAR_NET_IFLIST_GROW(iflist) \ - if (iflist->number >= iflist->size) { \ - sigar_net_interface_list_grow(iflist); \ - } - -int sigar_net_connection_list_create(sigar_net_connection_list_t *connlist); - -int sigar_net_connection_list_grow(sigar_net_connection_list_t *connlist); - -#define SIGAR_NET_CONNLIST_GROW(connlist) \ - if (connlist->number >= connlist->size) { \ - sigar_net_connection_list_grow(connlist); \ - } - -#define sigar_net_address_set(a, val) \ - (a).addr.in = val; \ - (a).family = SIGAR_AF_INET - -#define sigar_net_address6_set(a, val) \ - memcpy(&((a).addr.in6), val, sizeof((a).addr.in6)); \ - (a).family = SIGAR_AF_INET6 - -#define SIGAR_IFHWADDRLEN 6 - -#define sigar_net_address_mac_set(a, val, len) \ - memcpy(&((a).addr.mac), val, len); \ - (a).family = SIGAR_AF_LINK - -#define sigar_hwaddr_set_null(ifconfig) \ - SIGAR_ZERO(&ifconfig->hwaddr.addr.mac); \ - ifconfig->hwaddr.family = SIGAR_AF_LINK - -int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig); - -#define sigar_net_interface_ipv6_config_init(ifconfig) \ - ifconfig->address6.family = SIGAR_AF_INET6; \ - ifconfig->prefix6_length = 0; \ - ifconfig->scope6 = 0 - -#define SIGAR_SIN6(s) ((struct sockaddr_in6 *)(s)) - -#define SIGAR_SIN6_ADDR(s) &SIGAR_SIN6(s)->sin6_addr - -#define sigar_net_interface_scope6_set(ifconfig, addr) \ - if (IN6_IS_ADDR_LINKLOCAL(addr)) \ - ifconfig->scope6 = SIGAR_IPV6_ADDR_LINKLOCAL; \ - else if (IN6_IS_ADDR_SITELOCAL(addr)) \ - ifconfig->scope6 = SIGAR_IPV6_ADDR_SITELOCAL; \ - else if (IN6_IS_ADDR_V4COMPAT(addr)) \ - ifconfig->scope6 = SIGAR_IPV6_ADDR_COMPATv4; \ - else if (IN6_IS_ADDR_LOOPBACK(addr)) \ - ifconfig->scope6 = SIGAR_IPV6_ADDR_LOOPBACK; \ - else \ - ifconfig->scope6 = SIGAR_IPV6_ADDR_ANY - -int sigar_tcp_curr_estab(sigar_t *sigar, sigar_tcp_t *tcp); - -int sigar_arp_list_create(sigar_arp_list_t *arplist); - -int sigar_arp_list_grow(sigar_arp_list_t *arplist); - -#define SIGAR_ARP_LIST_GROW(arplist) \ - if (arplist->number >= arplist->size) { \ - sigar_arp_list_grow(arplist); \ - } - -int sigar_who_list_create(sigar_who_list_t *wholist); - -int sigar_who_list_grow(sigar_who_list_t *wholist); - -#define SIGAR_WHO_LIST_GROW(wholist) \ - if (wholist->number >= wholist->size) { \ - sigar_who_list_grow(wholist); \ - } - -int sigar_user_id_get(sigar_t *sigar, const char *name, int *uid); - -int sigar_user_name_get(sigar_t *sigar, int uid, char *buf, int buflen); - -int sigar_group_name_get(sigar_t *sigar, int gid, char *buf, int buflen); - -#define SIGAR_PROC_ENV_KEY_LOOKUP() \ - if ((procenv->type == SIGAR_PROC_ENV_KEY) && \ - (pid == sigar->pid)) \ - { \ - char *value = getenv(procenv->key); \ - if (value != NULL) { \ - procenv->env_getter(procenv->data, \ - procenv->key, \ - procenv->klen, \ - value, strlen(value)); \ - } \ - return SIGAR_OK; \ - } - -#define SIGAR_DISK_STATS_INIT(disk) \ - (disk)->reads = (disk)->writes = \ - (disk)->read_bytes = (disk)->write_bytes = \ - (disk)->rtime = (disk)->wtime = (disk)->qtime = (disk)->time = \ - (disk)->queue = (disk)->service_time = SIGAR_FIELD_NOTIMPL; \ - (disk)->snaptime = 0 - -/* key used for filesystem (/) -> device (/dev/hda1) mapping */ -/* and disk_usage cache for service_time */ -#define SIGAR_FSDEV_ID(sb) \ - (S_ISBLK((sb).st_mode) ? (sb).st_rdev : ((sb).st_ino + (sb).st_dev)) - -#if defined(WIN32) || defined(NETWARE) -int sigar_get_iftype(const char *name, int *type, int *inst); -#endif - -#define SIGAR_NIC_LOOPBACK "Local Loopback" -#define SIGAR_NIC_UNSPEC "UNSPEC" -#define SIGAR_NIC_SLIP "Serial Line IP" -#define SIGAR_NIC_CSLIP "VJ Serial Line IP" -#define SIGAR_NIC_SLIP6 "6-bit Serial Line IP" -#define SIGAR_NIC_CSLIP6 "VJ 6-bit Serial Line IP" -#define SIGAR_NIC_ADAPTIVE "Adaptive Serial Line IP" -#define SIGAR_NIC_ETHERNET "Ethernet" -#define SIGAR_NIC_ASH "Ash" -#define SIGAR_NIC_FDDI "Fiber Distributed Data Interface" -#define SIGAR_NIC_HIPPI "HIPPI" -#define SIGAR_NIC_AX25 "AMPR AX.25" -#define SIGAR_NIC_ROSE "AMPR ROSE" -#define SIGAR_NIC_NETROM "AMPR NET/ROM" -#define SIGAR_NIC_X25 "generic X.25" -#define SIGAR_NIC_TUNNEL "IPIP Tunnel" -#define SIGAR_NIC_PPP "Point-to-Point Protocol" -#define SIGAR_NIC_HDLC "(Cisco)-HDLC" -#define SIGAR_NIC_LAPB "LAPB" -#define SIGAR_NIC_ARCNET "ARCnet" -#define SIGAR_NIC_DLCI "Frame Relay DLCI" -#define SIGAR_NIC_FRAD "Frame Relay Access Device" -#define SIGAR_NIC_SIT "IPv6-in-IPv4" -#define SIGAR_NIC_IRDA "IrLAP" -#define SIGAR_NIC_EC "Econet" - -#ifndef WIN32 -#include -#endif - -#define SIGAR_HOSTENT_LEN 1024 -#if defined(_AIX) -#define SIGAR_HAS_HOSTENT_DATA -#endif - -typedef struct { - char buffer[SIGAR_HOSTENT_LEN]; - int error; -#ifndef WIN32 - struct hostent hs; -#endif -#ifdef SIGAR_HAS_HOSTENT_DATA - struct hostent_data hd; -#endif -} sigar_hostent_t; - -#endif diff --git a/vendor/sigar/include/sigar_ptql.h b/vendor/sigar/include/sigar_ptql.h deleted file mode 100644 index 53d28ec..0000000 --- a/vendor/sigar/include/sigar_ptql.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2006-2007 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_PTQL_H -#define SIGAR_PTQL_H - -#define SIGAR_PTQL_MALFORMED_QUERY -1 - -typedef struct sigar_ptql_query_t sigar_ptql_query_t; - -#define SIGAR_PTQL_ERRMSG_SIZE 1024 - -typedef struct { - char message[SIGAR_PTQL_ERRMSG_SIZE]; -} sigar_ptql_error_t; - -typedef int (*sigar_ptql_re_impl_t)(void *, char *, char *); - -SIGAR_DECLARE(void) sigar_ptql_re_impl_set(sigar_t *sigar, void *data, - sigar_ptql_re_impl_t impl); - -SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **query, - char *ptql, - sigar_ptql_error_t *error); - -SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar, - sigar_ptql_query_t *query, - sigar_pid_t pid); - -SIGAR_DECLARE(int) sigar_ptql_query_destroy(sigar_ptql_query_t *query); - -SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar, - sigar_ptql_query_t *query, - sigar_pid_t *pid); - -SIGAR_DECLARE(int) sigar_ptql_query_find(sigar_t *sigar, - sigar_ptql_query_t *query, - sigar_proc_list_t *proclist); - -#endif /*SIGAR_PTQL_H*/ diff --git a/vendor/sigar/include/sigar_util.h b/vendor/sigar/include/sigar_util.h deleted file mode 100644 index bc605fc..0000000 --- a/vendor/sigar/include/sigar_util.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2004-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_UTIL_H -#define SIGAR_UTIL_H - -/* most of this is crap for dealing with linux /proc */ -#define UITOA_BUFFER_SIZE \ - (sizeof(int) * 3 + 1) - -#define SSTRLEN(s) \ - (sizeof(s)-1) - -#define sigar_strtoul(ptr) \ - strtoul(ptr, &ptr, 10) - -#define sigar_strtoull(ptr) \ - strtoull(ptr, &ptr, 10) - -#define sigar_isspace(c) \ - (isspace(((unsigned char)(c)))) - -#define sigar_isdigit(c) \ - (isdigit(((unsigned char)(c)))) - -#define sigar_isalpha(c) \ - (isalpha(((unsigned char)(c)))) - -#define sigar_isupper(c) \ - (isupper(((unsigned char)(c)))) - -#define sigar_tolower(c) \ - (tolower(((unsigned char)(c)))) - -#ifdef WIN32 -#define sigar_fileno _fileno -#define sigar_isatty _isatty -#define sigar_write _write -#else -#define sigar_fileno fileno -#define sigar_isatty isatty -#define sigar_write write -#endif - -#ifndef PROC_FS_ROOT -#define PROC_FS_ROOT "/proc/" -#endif - -#ifndef PROCP_FS_ROOT -#define PROCP_FS_ROOT "/proc/" -#endif - -sigar_int64_t sigar_time_now_millis(void); - -char *sigar_uitoa(char *buf, unsigned int n, int *len); - -int sigar_inet_ntoa(sigar_t *sigar, - sigar_uint32_t address, - char *addr_str); - -struct hostent *sigar_gethostbyname(const char *name, - sigar_hostent_t *data); - -SIGAR_INLINE char *sigar_skip_line(char *buffer, int buflen); - -SIGAR_INLINE char *sigar_skip_token(char *p); - -SIGAR_INLINE char *sigar_skip_multiple_token(char *p, int count); - -char *sigar_getword(char **line, char stop); - -char *sigar_strcasestr(const char *s1, const char *s2); - -int sigar_file2str(const char *fname, char *buffer, int buflen); - -int sigar_proc_file2str(char *buffer, int buflen, - sigar_pid_t pid, - const char *fname, - int fname_len); - -#define SIGAR_PROC_FILE2STR(buffer, pid, fname) \ - sigar_proc_file2str(buffer, sizeof(buffer), \ - pid, fname, SSTRLEN(fname)) - -#define SIGAR_PROC_FILENAME(buffer, pid, fname) \ - sigar_proc_filename(buffer, sizeof(buffer), \ - pid, fname, SSTRLEN(fname)) - -#define SIGAR_SKIP_SPACE(ptr) \ - while (sigar_isspace(*ptr)) ++ptr - -char *sigar_proc_filename(char *buffer, int buflen, - sigar_pid_t pid, - const char *fname, int fname_len); - -int sigar_proc_list_procfs_get(sigar_t *sigar, - sigar_proc_list_t *proclist); - -int sigar_proc_fd_count(sigar_t *sigar, sigar_pid_t pid, - sigar_uint64_t *total); - -/* linux + freebsd */ -int sigar_procfs_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs); - -int sigar_mem_calc_ram(sigar_t *sigar, sigar_mem_t *mem); - -int sigar_statvfs(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage); - -double sigar_file_system_usage_calc_used(sigar_t *sigar, - sigar_file_system_usage_t *fs); - -#define SIGAR_DEV_PREFIX "/dev/" - -#define SIGAR_NAME_IS_DEV(dev) \ - strnEQ(dev, SIGAR_DEV_PREFIX, SSTRLEN(SIGAR_DEV_PREFIX)) - -typedef struct { - char name[256]; - int is_partition; - sigar_disk_usage_t disk; -} sigar_iodev_t; - -sigar_iodev_t *sigar_iodev_get(sigar_t *sigar, - const char *dirname); - -int sigar_cpu_core_count(sigar_t *sigar); - -/* e.g. VM guest may have 1 virtual ncpu on multicore hosts */ -#define sigar_cpu_socket_count(sigar) \ - (sigar->ncpu < sigar->lcpu) ? sigar->ncpu : \ - (sigar->ncpu / sigar->lcpu) - -int sigar_cpu_core_rollup(sigar_t *sigar); - -void sigar_cpu_model_adjust(sigar_t *sigar, sigar_cpu_info_t *info); - -int sigar_cpu_mhz_from_model(char *model); - -char *sigar_get_self_path(sigar_t *sigar); - -#if defined(__sun) || defined(__FreeBSD__) - -#define SIGAR_HAS_DLINFO_MODULES -#include -#include - -int sigar_dlinfo_modules(sigar_t *sigar, sigar_proc_modules_t *procmods); -#endif - -typedef struct sigar_cache_entry_t sigar_cache_entry_t; - -struct sigar_cache_entry_t { - sigar_cache_entry_t *next; - sigar_uint64_t id; - void *value; -}; - -typedef struct { - sigar_cache_entry_t **entries; - unsigned int count, size; - void (*free_value)(void *ptr); -} sigar_cache_t; - -sigar_cache_t *sigar_cache_new(int size); - -sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table, - sigar_uint64_t key); - -sigar_cache_entry_t *sigar_cache_find(sigar_cache_t *table, - sigar_uint64_t key); - -void sigar_cache_destroy(sigar_cache_t *table); - -#endif /* SIGAR_UTIL_H */ diff --git a/vendor/sigar/src/os/aix/aix_sigar.c b/vendor/sigar/src/os/aix/aix_sigar.c deleted file mode 100644 index a4c0a88..0000000 --- a/vendor/sigar/src/os/aix/aix_sigar.c +++ /dev/null @@ -1,2151 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* pull in time.h before resource.h does w/ _KERNEL */ -#include -#define _KERNEL 1 -#include /* for struct file */ -#include /* for rlimit32 in 64-bit mode */ -#undef _KERNEL - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* for proc_port */ -#include -#include -#include -#include - -/* for net_connection_list */ -#include -#include -#include -#include - -/* for odm api */ -#include -#include -#include - -#include - -/* for net_interface_config ipv6 */ -#include -#include - -/* for getkerninfo */ -#include - -/* not defined in aix 4.3 */ -#ifndef SBITS -#define SBITS 16 -#endif - -#ifndef PTHRDSINFO_RUSAGE_START -#define PTHRDSINFO_RUSAGE_START 0x00000001 -#define PTHRDSINFO_RUSAGE_STOP 0x00000002 -#define PTHRDSINFO_RUSAGE_COLLECT 0x00000004 -#endif - -/* - * from libperfstat.h: - * "To calculate the load average, divide the numbers by (1<." - */ -#define FIXED_TO_DOUBLE(x) (((double)x) / (1<koffsets[i] = klist[i].n_value; - } - - return SIGAR_OK; -} - -static int kread(sigar_t *sigar, void *data, int size, long offset) -{ - if (sigar->kmem < 0) { - return SIGAR_EPERM_KMEM; - } - - if (lseek(sigar->kmem, offset, SEEK_SET) != offset) { - return errno; - } - - if (read(sigar->kmem, data, size) != size) { - return errno; - } - - return SIGAR_OK; -} - -static int sigar_thread_rusage(struct rusage *usage, int mode) -{ - return pthread_getrusage_np(pthread_self(), usage, mode); -} - -static int sigar_perfstat_memory(perfstat_memory_total_t *memory) -{ - return perfstat_memory_total(NULL, memory, sizeof(*memory), 1); -} - -static int sigar_perfstat_cpu(perfstat_cpu_total_t *cpu_total) -{ - return perfstat_cpu_total(NULL, cpu_total, sizeof(*cpu_total), 1); -} - -int sigar_os_open(sigar_t **sigar) -{ - int status, i; - int kmem = -1; - struct utsname name; - - kmem = open("/dev/kmem", O_RDONLY); - - *sigar = malloc(sizeof(**sigar)); - - (*sigar)->getprocfd = NULL; /*XXX*/ - (*sigar)->kmem = kmem; - (*sigar)->pagesize = 0; - (*sigar)->ticks = sysconf(_SC_CLK_TCK); - (*sigar)->boot_time = 0; - (*sigar)->last_pid = -1; - (*sigar)->pinfo = NULL; - (*sigar)->cpuinfo = NULL; - (*sigar)->cpuinfo_size = 0; - SIGAR_ZERO(&(*sigar)->swaps); - - i = getpagesize(); - while ((i >>= 1) > 0) { - (*sigar)->pagesize++; - } - - if (kmem > 0) { - if ((status = get_koffsets(*sigar)) != SIGAR_OK) { - /* libperfstat only mode (aix 6) */ - close((*sigar)->kmem); - (*sigar)->kmem = -1; - } - } - - (*sigar)->cpu_mhz = -1; - - (*sigar)->model[0] = '\0'; - - uname(&name); - - (*sigar)->aix_version = atoi(name.version); - - (*sigar)->thrusage = PTHRDSINFO_RUSAGE_STOP; - - (*sigar)->diskmap = NULL; - - return SIGAR_OK; -} - -static void swaps_free(swaps_t *swaps); - -int sigar_os_close(sigar_t *sigar) -{ - swaps_free(&sigar->swaps); - if (sigar->kmem > 0) { - close(sigar->kmem); - } - if (sigar->pinfo) { - free(sigar->pinfo); - } - if (sigar->cpuinfo) { - free(sigar->cpuinfo); - } - if (sigar->diskmap) { - sigar_cache_destroy(sigar->diskmap); - } - if (sigar->thrusage == PTHRDSINFO_RUSAGE_START) { - struct rusage usage; - sigar_thread_rusage(&usage, - PTHRDSINFO_RUSAGE_STOP); - } - free(sigar); - return SIGAR_OK; -} - -char *sigar_os_error_string(sigar_t *sigar, int err) -{ - switch (err) { - case SIGAR_EPERM_KMEM: - return "Failed to open /dev/kmem for reading"; - default: - return NULL; - } -} - -#define PAGESHIFT(v) \ - ((v) << sigar->pagesize) - -int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem) -{ - int status; - perfstat_memory_total_t minfo; - sigar_uint64_t kern; - - if (sigar_perfstat_memory(&minfo) == 1) { - mem->total = PAGESHIFT(minfo.real_total); - mem->free = PAGESHIFT(minfo.real_free); - kern = PAGESHIFT(minfo.numperm); /* number of pages in file cache */ - } - else { - return errno; - } - - mem->used = mem->total - mem->free; - mem->actual_used = mem->used - kern; - mem->actual_free = mem->free + kern; - - sigar_mem_calc_ram(sigar, mem); - - return SIGAR_OK; -} - -static void swaps_free(swaps_t *swaps) -{ - if (swaps->num) { - int i; - - for (i=0; inum; i++) { - free(swaps->devs[i]); - } - - free(swaps->devs); - - swaps->num = 0; - } -} - -/* - * there is no public api for parsing this file. - * well, there is something, but its super ugly and requires - * linking 2 static libraries (libodm and something else) - * maybe will switch to that if it can add value elsewhere too. - */ -#define SWAPSPACES "/etc/swapspaces" - -static int swaps_get(swaps_t *swaps) -{ - FILE *fp; - char buf[512]; - char *ptr; - struct stat statbuf; - - if (stat(SWAPSPACES, &statbuf) < 0) { - return errno; - } - - /* only re-parse if file has changed */ - if (swaps->mtime == statbuf.st_mtime) { - return 0; - } - - swaps->mtime = statbuf.st_mtime; - - /* easier to just start from scratch */ - swaps_free(swaps); - - if (!(fp = fopen(SWAPSPACES, "r"))) { - return errno; - } - - while ((ptr = fgets(buf, sizeof(buf), fp))) { - if (!isalpha(*ptr)) { - continue; - } - - if (strchr(ptr, ':')) { - int len; - - ptr = fgets(buf, sizeof(buf), fp); - - while (isspace(*ptr)) { - ++ptr; - } - - if (strncmp(ptr, "dev", 3)) { - continue; - } - ptr += 3; - while (isspace(*ptr) || (*ptr == '=')) { - ++ptr; - } - - len = strlen(ptr); - ptr[len-1] = '\0'; /* -1 == chomp \n */ - - swaps->devs = realloc(swaps->devs, swaps->num+1 * sizeof(char *)); - swaps->devs[swaps->num] = malloc(len); - memcpy(swaps->devs[swaps->num], ptr, len); - - swaps->num++; - } - } - - fclose(fp); - - return 0; -} - -/* - * documented in aix tech ref, - * but this prototype is not in any friggin header file. - * struct pginfo is in sys/vminfo.h - */ - -int swapqry(char *path, struct pginfo *info); - -static int sigar_swap_get_swapqry(sigar_t *sigar, sigar_swap_t *swap) -{ - int status, i; - - if ((status = swaps_get(&sigar->swaps)) != SIGAR_OK) { - return status; - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[swap] pagesize=%d, shift=%d", - getpagesize(), sigar->pagesize); - } - - swap->total = swap->free = 0; - - for (i=0; iswaps.num; i++) { - struct pginfo info; - - status = swapqry(sigar->swaps.devs[i], &info); - - if (status != 0) { - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[swap] swapqry(%s) failed: %s", - sigar->swaps.devs[i], - sigar_strerror(sigar, errno)); - } - continue; - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[swap] %s total=%d/%d, free=%d/%d", - sigar->swaps.devs[i], - info.size, PAGESHIFT(info.size), - info.free, PAGESHIFT(info.free)); - } - - swap->total += PAGESHIFT(info.size); /* lsps -a */ - swap->free += PAGESHIFT(info.free); - } - - swap->used = swap->total - swap->free; - - return SIGAR_OK; -} - -#define SWAP_DEV(ps) \ - ((ps.type == LV_PAGING) ? \ - ps.u.lv_paging.vgname : \ - ps.u.nfs_paging.filename) - -#define SWAP_MB_TO_BYTES(v) ((v) * (1024 * 1024)) - -int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap) -{ - perfstat_memory_total_t minfo; - perfstat_pagingspace_t ps; - perfstat_id_t id; - - id.name[0] = '\0'; - - SIGAR_ZERO(swap); - - do { - if (perfstat_pagingspace(&id, &ps, sizeof(ps), 1) != 1) { - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[swap] dev=%s query failed: %s", - SWAP_DEV(ps), - sigar_strerror(sigar, errno)); - } - continue; - } - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[swap] dev=%s: active=%s, " - "total=%lluMb, used=%lluMb", - SWAP_DEV(ps), - ((ps.active == 1) ? "yes" : "no"), - ps.mb_size, ps.mb_used); - } - if (ps.active != 1) { - continue; - } - /* convert MB sizes to bytes */ - swap->total += SWAP_MB_TO_BYTES(ps.mb_size); - swap->used += SWAP_MB_TO_BYTES(ps.mb_used); - } while (id.name[0] != '\0'); - - swap->free = swap->total - swap->used; - - if (sigar_perfstat_memory(&minfo) == 1) { - swap->page_in = minfo.pgins; - swap->page_out = minfo.pgouts; - } - else { - swap->page_in = swap->page_out = -1; - } - return SIGAR_OK; -} - -int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ - int i, status; - struct sysinfo data; - perfstat_cpu_total_t cpu_data; - - if (sigar_perfstat_cpu(&cpu_data) == 1) { - cpu->user = SIGAR_TICK2MSEC(cpu_data.user); - cpu->nice = SIGAR_FIELD_NOTIMPL; /* N/A */ - cpu->sys = SIGAR_TICK2MSEC(cpu_data.sys); - cpu->idle = SIGAR_TICK2MSEC(cpu_data.idle); - cpu->wait = SIGAR_TICK2MSEC(cpu_data.wait); - cpu->irq = 0; /*N/A*/ - cpu->soft_irq = 0; /*N/A*/ - cpu->stolen = 0; /*N/A*/ - cpu->total = cpu->user + cpu->sys + cpu->idle + cpu->wait; - return SIGAR_OK; - } - else { - return errno; - } -} - -/* - * other possible metrics we could add: - * struct cpuinfo { - * long cpu[CPU_NTIMES]; - * long pswitch; - * long syscall; - * long sysread; - * long syswrite; - * long sysfork; - * long sysexec; - * long readch; - * long writech; - * long iget; - * long namei; - * long dirblk; - * long msg; - * long sema; - * long bread; - * long bwrite; - * long lread; - * long lwrite; - * long phread; - * long phwrite; - * }; - */ - -int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist) -{ - perfstat_cpu_t data; - int i, ncpu = _system_configuration.ncpus; /* this can change */ - perfstat_id_t id; - - id.name[0] = '\0'; - - sigar_cpu_list_create(cpulist); - - for (i=0; idata[cpulist->number++]; - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "cpu%d perfstat_id='%s'", - i, id.name); - } - - if (perfstat_cpu(&id, &data, sizeof(data), 1) == 1) { - cpu->user = SIGAR_TICK2MSEC(data.user); - cpu->nice = SIGAR_FIELD_NOTIMPL; /* N/A */ - cpu->sys = SIGAR_TICK2MSEC(data.sys); - cpu->idle = SIGAR_TICK2MSEC(data.idle); - cpu->wait = SIGAR_TICK2MSEC(data.wait); - cpu->irq = 0; /*N/A*/ - cpu->soft_irq = 0; /*N/A*/ - cpu->stolen = 0; /*N/A*/ - cpu->total = cpu->user + cpu->sys + cpu->idle + cpu->wait; - } - else { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "cpu%d perfstat_cpu(%s) failed: %s", - i, id.name, sigar_strerror(sigar, errno)); - SIGAR_ZERO(cpu); - } - } - - return SIGAR_OK; -} - -static int boot_time(sigar_t *sigar, time_t *time) -{ - int fd; - struct utmp data; - - if ((fd = open(UTMP_FILE, O_RDONLY)) < 0) { - return errno; - } - - do { - if (read(fd, &data, sizeof(data)) != sizeof(data)) { - int status = errno; - close(fd); - return status; - } - } while (data.ut_type != BOOT_TIME); - - *time = data.ut_time; - - close(fd); - - return SIGAR_OK; -} - -int sigar_uptime_get(sigar_t *sigar, - sigar_uptime_t *uptime) -{ - if (sigar->boot_time == 0) { - int status; - time_t time; - - if ((status = boot_time(sigar, &time)) != SIGAR_OK) { - return status; - } - - sigar->boot_time = time; - } - - uptime->uptime = time(NULL) - sigar->boot_time; - - return SIGAR_OK; -} - -#define WHOCPY(dest, src) \ - SIGAR_SSTRCPY(dest, src); \ - if (sizeof(src) < sizeof(dest)) \ - dest[sizeof(dest)-1] = '\0' - -static int sigar_who_utmp(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - struct utmp ut; - FILE *fp; - - if (!(fp = fopen(UTMP_FILE, "r"))) { - return errno; - } - - while (fread(&ut, sizeof(ut), 1, fp) == 1) { - sigar_who_t *who; - - if (*ut.ut_name == '\0') { - continue; - } - - if (ut.ut_type != USER_PROCESS) { - continue; - } - - SIGAR_WHO_LIST_GROW(wholist); - who = &wholist->data[wholist->number++]; - - WHOCPY(who->user, ut.ut_user); - WHOCPY(who->device, ut.ut_line); - WHOCPY(who->host, ut.ut_host); - - who->time = ut.ut_time; - } - - fclose(fp); - - return SIGAR_OK; -} - -int sigar_who_list_get(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - int status; - - sigar_who_list_create(wholist); - - status = sigar_who_utmp(sigar, wholist); - if (status != SIGAR_OK) { - sigar_who_list_destroy(sigar, wholist); - return status; - } - - return SIGAR_OK; -} - -int sigar_loadavg_get(sigar_t *sigar, - sigar_loadavg_t *loadavg) -{ - int status, i; - int data[3]; - perfstat_cpu_total_t cpu_data; - - if (sigar_perfstat_cpu(&cpu_data) == 1) { - for (i=0; i<3; i++) { - loadavg->loadavg[i] = FIXED_TO_DOUBLE(cpu_data.loadavg[i]); - } - return SIGAR_OK; - } - else { - return errno; - } -} - -int sigar_os_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - pid_t pid = 0; - struct procsinfo info; - - for (;;) { - int num = getprocs(&info, sizeof(info), - NULL, 0, &pid, 1); - - if (num == 0) { - break; - } - - SIGAR_PROC_LIST_GROW(proclist); - - proclist->data[proclist->number++] = info.pi_pid; - } - - return SIGAR_OK; -} - -static int sigar_getprocs(sigar_t *sigar, sigar_pid_t pid) -{ - int status, num; - time_t timenow = time(NULL); - - if (sigar->pinfo == NULL) { - sigar->pinfo = malloc(sizeof(*sigar->pinfo)); - } - - if (sigar->last_pid == pid) { - if ((timenow - sigar->last_getprocs) < SIGAR_LAST_PROC_EXPIRE) { - return SIGAR_OK; - } - } - - sigar->last_pid = pid; - sigar->last_getprocs = timenow; - - num = getprocs(sigar->pinfo, sizeof(*sigar->pinfo), - NULL, 0, &pid, 1); - - if (num != 1) { - return ESRCH; - } - - return SIGAR_OK; -} - -int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_mem_t *procmem) -{ - int status = sigar_getprocs(sigar, pid); - struct procsinfo64 *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - procmem->size = PAGESHIFT(pinfo->pi_size); /* XXX fold in pi_dvm ? */ - procmem->share = PAGESHIFT(pinfo->pi_sdsize); - procmem->resident = PAGESHIFT(pinfo->pi_drss + pinfo->pi_trss); - - procmem->minor_faults = pinfo->pi_minflt; - procmem->major_faults = pinfo->pi_majflt; - procmem->page_faults = - procmem->minor_faults + - procmem->major_faults; - - return SIGAR_OK; -} - -int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_t *proccred) -{ - int status = sigar_getprocs(sigar, pid); - struct procsinfo64 *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - proccred->uid = pinfo->pi_cred.cr_ruid; - proccred->euid = pinfo->pi_cred.cr_uid; - if (proccred->uid == -1) { - /* - * aix 5.2 has a process named 'jfsz' - * where uid is '-1', getpwuid returns EPERM - */ - proccred->uid = proccred->euid = 0; - } - proccred->gid = pinfo->pi_cred.cr_rgid; - proccred->egid = pinfo->pi_cred.cr_gid; - - return SIGAR_OK; -} - -int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_time_t *proctime) -{ - int status = sigar_getprocs(sigar, pid); - struct procsinfo64 *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - proctime->start_time = pinfo->pi_start; - proctime->start_time *= SIGAR_MSEC; /* convert to ms */ - proctime->user = pinfo->pi_utime * SIGAR_MSEC; - proctime->sys = pinfo->pi_stime * SIGAR_MSEC; - proctime->total = proctime->user + proctime->sys; - - return SIGAR_OK; -} - -int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - int status = sigar_getprocs(sigar, pid); - struct procsinfo64 *pinfo = sigar->pinfo; - tid_t tid = 0; - struct thrdsinfo64 thrinfo; - - if (status != SIGAR_OK) { - return status; - } - - if (getthrds(pid, &thrinfo, sizeof(thrinfo), &tid, 1) == 1) { - procstate->processor = thrinfo.ti_affinity; - } - else { - procstate->processor = SIGAR_FIELD_NOTIMPL; - } - - SIGAR_SSTRCPY(procstate->name, pinfo->pi_comm); - procstate->ppid = pinfo->pi_ppid; - procstate->nice = pinfo->pi_nice; - procstate->tty = pinfo->pi_ttyd; - procstate->priority = pinfo->pi_pri; - procstate->threads = pinfo->pi_thcount; - - switch (pinfo->pi_state) { - case SACTIVE: - procstate->state = 'R'; - break; - case SIDL: - procstate->state = 'D'; - break; - case SSTOP: - procstate->state = 'S'; - break; - case SZOMB: - procstate->state = 'Z'; - break; - case SSWAP: - procstate->state = 'S'; - break; - } - - return SIGAR_OK; -} - -int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - /* XXX if buffer is not large enough args are truncated */ - char buffer[8192], *ptr; - struct procsinfo pinfo; - - pinfo.pi_pid = pid; - - if (getargs(&pinfo, sizeof(pinfo), - buffer, sizeof(buffer)) != 0) - { - return errno; - } - - ptr = buffer; - - while (*ptr) { - int alen = strlen(ptr)+1; - char *arg = malloc(alen); - - SIGAR_PROC_ARGS_GROW(procargs); - memcpy(arg, ptr, alen); - - procargs->data[procargs->number++] = arg; - - ptr += alen; - } - - return SIGAR_OK; -} - -int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ - /* XXX if buffer is not large enough args are truncated */ - char buffer[8192], *ptr; - struct procsinfo pinfo; - - pinfo.pi_pid = pid; - - if (getevars(&pinfo, sizeof(pinfo), - buffer, sizeof(buffer)) != 0) - { - return errno; - } - - ptr = buffer; - - while (*ptr) { - char *val = strchr(ptr, '='); - int klen, vlen, status; - char key[128]; /* XXX is there a max key size? */ - - if (val == NULL) { - /* not key=val format */ - procenv->env_getter(procenv->data, ptr, strlen(ptr), NULL, 0); - break; - } - - klen = val - ptr; - SIGAR_SSTRCPY(key, ptr); - key[klen] = '\0'; - ++val; - - vlen = strlen(val); - status = procenv->env_getter(procenv->data, - key, klen, val, vlen); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - - ptr += (klen + 1 + vlen + 1); - } - - return SIGAR_OK; -} - -int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_fd_t *procfd) -{ -#ifdef SIGAR_64BIT - /* XXX no getuser() in 64-bit mode */ - return SIGAR_ENOTIMPL; -#else - int i; - struct procsinfo pinfo; - struct user uinfo; - - procfd->total = 0; - pinfo.pi_pid = pid; - - if (getuser(&pinfo, sizeof(pinfo), - &uinfo, sizeof(uinfo)) != 0) { - if (errno == EINVAL) { - return SIGAR_ENOTIMPL; /*XXX 5.2+*/ - } - } - - /* see sys/user.h */ - for (i=0; itotal++; - } - } - - return SIGAR_OK; -#endif -} - -int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ - int len; - char buffer[8192]; - struct procsinfo pinfo; - - pinfo.pi_pid = pid; - - if (getargs(&pinfo, sizeof(pinfo), - buffer, sizeof(buffer)) != 0) - { - return errno; - } - /* XXX argv[0] might be relative */ - len = strlen(buffer); - SIGAR_SSTRCPY(procexe->name, buffer); - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/cwd"); - - if ((len = readlink(buffer, procexe->cwd, - sizeof(procexe->cwd)-1)) < 0) - { - return errno; - } - procexe->cwd[len] = '\0'; - - procexe->root[0] = '\0'; - - return SIGAR_OK; -} - -static int sigar_proc_modules_local_get(sigar_t *sigar, - sigar_proc_modules_t *procmods) -{ - struct ld_info *info; - char *buffer; - int size = 2048, status; - unsigned int offset; - - buffer = malloc(size); - while ((loadquery(L_GETINFO, buffer, size) == -1) && - (errno == ENOMEM)) - { - size += 2048; - buffer = realloc(buffer, size); - } - - info = (struct ld_info *)buffer; - - do { - char *name = info->ldinfo_filename; - - status = - procmods->module_getter(procmods->data, name, strlen(name)); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - free(buffer); - return status; - } - - offset = info->ldinfo_next; - info = (struct ld_info *)((char*)info + offset); - } while(offset); - - free(buffer); - - return SIGAR_OK; -} - -int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods) -{ - if (pid == sigar_pid_get(sigar)) { - return sigar_proc_modules_local_get(sigar, procmods); - } - else { - return SIGAR_ENOTIMPL; - } -} - -#define SIGAR_MICROSEC2NANO(s) \ - ((sigar_uint64_t)(s) * (sigar_uint64_t)1000) - -#define TIME_NSEC(t) \ - (SIGAR_SEC2NANO((t).tv_sec) + SIGAR_MICROSEC2NANO((t).tv_usec)) - -int sigar_thread_cpu_get(sigar_t *sigar, - sigar_uint64_t id, - sigar_thread_cpu_t *cpu) -{ - struct rusage usage; - int retval; - - if (sigar->thrusage != PTHRDSINFO_RUSAGE_START) { - sigar->thrusage = PTHRDSINFO_RUSAGE_START; - retval = - sigar_thread_rusage(&usage, - PTHRDSINFO_RUSAGE_START); - if (retval != 0) { - return retval; - } - } - - retval = - sigar_thread_rusage(&usage, - PTHRDSINFO_RUSAGE_COLLECT); - if (retval != 0) { - return retval; - } - - cpu->user = TIME_NSEC(usage.ru_utime); - cpu->sys = TIME_NSEC(usage.ru_stime); - cpu->total = TIME_NSEC(usage.ru_utime) + TIME_NSEC(usage.ru_stime); - - return SIGAR_OK; -} - -int sigar_os_fs_type_get(sigar_file_system_t *fsp) -{ - return fsp->type; -} - -#ifndef MNT_NFS4 -/* another one documented in aix tech ref - * with no friggin prototype in any header file... - * ...but added in 5.2 - */ -int mntctl(int command, int size, char *buffer); -#endif - -int sigar_file_system_list_get(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - int i, size, num; - char *buf, *mntlist; - - /* get required size */ - if (mntctl(MCTL_QUERY, sizeof(size), (char *)&size) < 0) { - return errno; - } - - mntlist = buf = malloc(size); - - if ((num = mntctl(MCTL_QUERY, size, buf)) < 0) { - free(buf); - return errno; - } - - sigar_file_system_list_create(fslist); - - for (i=0; ivmt_length; - - SIGAR_FILE_SYSTEM_LIST_GROW(fslist); - - fsp = &fslist->data[fslist->number++]; - - switch (ent->vmt_gfstype) { - case MNT_AIX: - typename = "aix"; - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - break; - case MNT_JFS: - typename = "jfs"; - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - break; - case MNT_NFS: - case MNT_NFS3: - typename = "nfs"; - fsp->type = SIGAR_FSTYPE_NETWORK; - break; - case MNT_CDROM: - fsp->type = SIGAR_FSTYPE_CDROM; - break; - case MNT_SFS: - case MNT_CACHEFS: - case MNT_AUTOFS: - default: - if (ent->vmt_flags & MNT_REMOTE) { - fsp->type = SIGAR_FSTYPE_NETWORK; - } - else { - fsp->type = SIGAR_FSTYPE_NONE; - } - } - - SIGAR_SSTRCPY(fsp->dir_name, vmt2dataptr(ent, VMT_STUB)); - SIGAR_SSTRCPY(fsp->options, vmt2dataptr(ent, VMT_ARGS)); - - devname = vmt2dataptr(ent, VMT_OBJECT); - - if (fsp->type == SIGAR_FSTYPE_NETWORK) { - char *hostname = vmt2dataptr(ent, VMT_HOSTNAME); -#if 0 - /* XXX: these do not seem reliable */ - int hostname_len = vmt2datasize(ent, VMT_HOSTNAME)-1; /* -1 == skip '\0' */ - int devname_len = vmt2datasize(ent, VMT_OBJECT); /* includes '\0' */ -#else - int hostname_len = strlen(hostname); - int devname_len = strlen(devname) + 1; -#endif - int total_len = hostname_len + devname_len + 1; /* 1 == strlen(":") */ - - if (total_len > sizeof(fsp->dev_name)) { - /* justincase - prevent overflow. chances: slim..none */ - SIGAR_SSTRCPY(fsp->dev_name, devname); - } - else { - /* sprintf(fsp->devname, "%s:%s", hostname, devname) */ - char *ptr = fsp->dev_name; - - memcpy(ptr, hostname, hostname_len); - ptr += hostname_len; - - *ptr++ = ':'; - - memcpy(ptr, devname, devname_len); - } - } - else { - SIGAR_SSTRCPY(fsp->dev_name, devname); - } - - /* we set fsp->type, just looking up sigar.c:fstype_names[type] */ - sigar_fs_type_get(fsp); - - if (typename == NULL) { - typename = fsp->type_name; - } - - SIGAR_SSTRCPY(fsp->sys_type_name, typename); - } - - free(buf); - - return SIGAR_OK; -} - -typedef struct { - char name[IDENTIFIER_LENGTH]; - long addr; -} aix_diskio_t; - -static int create_diskmap(sigar_t *sigar) -{ - int i, total, num; - perfstat_disk_t *disk; - perfstat_id_t id; - - total = perfstat_disk(NULL, NULL, sizeof(*disk), 0); - if (total < 1) { - return ENOENT; - } - - disk = malloc(total * sizeof(*disk)); - id.name[0] = '\0'; - - num = perfstat_disk(&id, disk, sizeof(*disk), total); - if (num < 1) { - free(disk); - return ENOENT; - } - - sigar->diskmap = sigar_cache_new(25); - - odm_initialize(); - - for (i=0; iname, "label", 0, &num))) { - retval = stat(attr->value, &sb); - - if (retval == 0) { - aix_diskio_t *diskio = malloc(sizeof(*diskio)); - SIGAR_SSTRCPY(diskio->name, disk[i].name); - diskio->addr = -1; - ent = sigar_cache_get(sigar->diskmap, SIGAR_FSDEV_ID(sb)); - ent->value = diskio; - } - - free(attr); - } - } - - odm_free_list(dv, &info); - } - - free(disk); - odm_terminate(); - - return SIGAR_OK; -} - -int sigar_disk_usage_get(sigar_t *sigar, const char *name, - sigar_disk_usage_t *usage) -{ - perfstat_disk_t disk; - perfstat_id_t id; - - SIGAR_SSTRCPY(id.name, name); - - if (perfstat_disk(&id, &disk, sizeof(disk), 1) != 1) { - return ENXIO; - } - - usage->reads = disk.rblks; - usage->writes = disk.wblks; - usage->read_bytes = disk.rblks * disk.bsize; - usage->write_bytes = disk.wblks * disk.bsize; - usage->queue = disk.qdepth; - usage->time = disk.time; - usage->rtime = SIGAR_FIELD_NOTIMPL; - usage->wtime = SIGAR_FIELD_NOTIMPL; - - return SIGAR_OK; -} - -int sigar_file_system_usage_get(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage) -{ - sigar_cache_entry_t *ent; - struct stat sb; - int status; - - status = sigar_statvfs(sigar, dirname, fsusage); - - if (status != SIGAR_OK) { - return status; - } - - fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage); - - SIGAR_DISK_STATS_INIT(&fsusage->disk); - - if (!sigar->diskmap) { - status = create_diskmap(sigar); - if (status != SIGAR_OK) { - return SIGAR_OK; - } - } - - status = stat(dirname, &sb); - if (status == 0) { - sigar_cache_entry_t *ent = - sigar_cache_get(sigar->diskmap, SIGAR_FSDEV_ID(sb)); - if (!ent->value) { - return SIGAR_OK; - } - sigar_disk_usage_get(sigar, ((aix_diskio_t *)ent->value)->name, &fsusage->disk); - } - - return SIGAR_OK; -} - -/* from sys/systemcfg.h, not defined in 4.3 headers */ -#ifndef POWER_4 -#define POWER_4 0x0800 -#endif -#ifndef POWER_MPC7450 -#define POWER_MPC7450 0x1000 -#endif -#ifndef POWER_5 -#define POWER_5 0x2000 -#endif - -static char *sigar_get_odm_model(sigar_t *sigar) -{ - if (sigar->model[0] == '\0') { - struct CuAt *odm_obj; - int num; - - odm_initialize(); - - if ((odm_obj = getattr("proc0", "type", 0, &num))) { - SIGAR_SSTRCPY(sigar->model, odm_obj->value); - free(odm_obj); - } - - odm_terminate(); - } - - return sigar->model; -} - -#define SIGAR_CPU_CACHE_SIZE \ - (_system_configuration.L2_cache_size / 1024) - -static int sigar_get_cpu_mhz(sigar_t *sigar) -{ - if (sigar->cpu_mhz == SIGAR_FIELD_NOTIMPL) { - perfstat_cpu_total_t data; - - if (sigar_perfstat_cpu(&data) == 1) { - sigar->cpu_mhz = data.processorHZ / 1000000; - } - else { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "perfstat_cpu_total failed: %s", - sigar_strerror(sigar, errno)); - } - } - - return sigar->cpu_mhz; -} - -static char *get_cpu_arch(void) -{ - switch (_system_configuration.architecture) { - case POWER_RS: - return "Power Classic"; - case POWER_PC: - return "PowerPC"; - case IA64: - return "IA64"; - default: - return "PowerPC"; /* what else could it be */ - } -} - -static char *get_ppc_cpu_model(void) -{ - switch (_system_configuration.implementation) { - case POWER_RS1: - return "RS1"; - case POWER_RSC: - return "RSC"; - case POWER_RS2: - return "RS2"; - case POWER_601: - return "601"; - case POWER_603: - return "603"; - case POWER_604: - return "604"; - case POWER_620: - return "620"; - case POWER_630: - return "630"; - case POWER_A35: - return "A35"; - case POWER_RS64II: - return "RS64-II"; - case POWER_RS64III: - return "RS64-III"; - case POWER_4: - return "POWER4"; - case POWER_MPC7450: - return "MPC7450"; - case POWER_5: - return "POWER5"; - default: - return "Unknown"; - } -} - -static char *get_ia64_cpu_model(void) -{ - switch (_system_configuration.implementation) { - case IA64_M1: - return "M1"; - case IA64_M2: - return "M2"; - default: - return "Unknown"; - } -} - -static char *get_cpu_model(void) -{ - if (_system_configuration.architecture == IA64) { - return get_ia64_cpu_model(); - } - else { - return get_ppc_cpu_model(); - } -} - -int sigar_cpu_info_list_get(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos) -{ - int i; - int ncpu = _system_configuration.ncpus; /* this can change */ - char *arch = get_cpu_arch(), *model = get_cpu_model(); - - /*XXX should only do this once*/ - sigar_cpu_info_list_create(cpu_infos); - - for (i=0; idata[cpu_infos->number++]; - - info->total_cores = ncpu; - info->cores_per_socket = 1; /*XXX*/ - info->total_sockets = ncpu; /*XXX*/ - - info->cache_size = SIGAR_CPU_CACHE_SIZE; - - info->mhz = sigar_get_cpu_mhz(sigar); - - if (*arch == 'P') { - SIGAR_SSTRCPY(info->vendor, "IBM"); - } - else if (*arch == 'I') { - SIGAR_SSTRCPY(info->vendor, "Intel"); - } - else { - SIGAR_SSTRCPY(info->vendor, "Unknown"); - } - - snprintf(info->model, sizeof(info->model), - "%s %s", arch, model); - } - - return SIGAR_OK; -} -/* XXX net_route_list copy-n-pasted from darwin_sigar.c; only diff is getkerninfo instead of sysctl */ -#define rt_s_addr(sa) ((struct sockaddr_in *)(sa))->sin_addr.s_addr - -#ifndef SA_SIZE -#define SA_SIZE(sa) \ - ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ - sizeof(long) : \ - 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) -#endif - -int sigar_net_route_list_get(sigar_t *sigar, - sigar_net_route_list_t *routelist) -{ - int needed; - int bit; - char *buf, *next, *lim; - struct rt_msghdr *rtm; - - needed = getkerninfo(KINFO_RT_DUMP, NULL, NULL, 0); - if (needed <= 0) { - return errno; - } - - buf = malloc(needed); - - if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0) { - return errno; - } - - sigar_net_route_list_create(routelist); - - lim = buf + needed; - - for (next = buf; next < lim; next += rtm->rtm_msglen) { - struct sockaddr *sa; - sigar_net_route_t *route; - rtm = (struct rt_msghdr *)next; - - if (rtm->rtm_type != RTM_GET) { - continue; - } - - sa = (struct sockaddr *)(rtm + 1); - - if (sa->sa_family != AF_INET) { - continue; - } - - SIGAR_NET_ROUTE_LIST_GROW(routelist); - route = &routelist->data[routelist->number++]; - SIGAR_ZERO(route); - - route->flags = rtm->rtm_flags; - if_indextoname(rtm->rtm_index, route->ifname); - - for (bit=RTA_DST; - bit && ((char *)sa < lim); - bit <<= 1) - { - if ((rtm->rtm_addrs & bit) == 0) { - continue; - } - switch (bit) { - case RTA_DST: - sigar_net_address_set(route->destination, - rt_s_addr(sa)); - break; - case RTA_GATEWAY: - if (sa->sa_family == AF_INET) { - sigar_net_address_set(route->gateway, - rt_s_addr(sa)); - } - break; - case RTA_NETMASK: - sigar_net_address_set(route->mask, - rt_s_addr(sa)); - break; - case RTA_IFA: - break; - } - - sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); - } - } - - free(buf); - - return SIGAR_OK; -} - -int sigar_net_interface_stat_get(sigar_t *sigar, - const char *name, - sigar_net_interface_stat_t *ifstat) -{ - perfstat_id_t id; - perfstat_netinterface_t data; - - sigar_log(sigar, SIGAR_LOG_DEBUG, "[ifstat] using libperfstat"); - - SIGAR_SSTRCPY(id.name, name); - - if (perfstat_netinterface(&id, &data, sizeof(data), 1) == 1) { - ifstat->rx_bytes = data.ibytes; - ifstat->rx_packets = data.ipackets; - ifstat->rx_errors = data.ierrors; - ifstat->rx_dropped = SIGAR_FIELD_NOTIMPL; - ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->rx_frame = SIGAR_FIELD_NOTIMPL; - - ifstat->tx_bytes = data.obytes; - ifstat->tx_packets = data.opackets; - ifstat->tx_errors = data.oerrors; - ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL; - ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->tx_collisions = data.collisions; - ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL; - - ifstat->speed = data.bitrate; - - return SIGAR_OK; - } - else { - return errno; - } -} - -int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig) -{ - int sock; - struct in6_ifreq ifr; - - if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - return errno; - } - - SIGAR_SSTRCPY(ifr.ifr_name, name); - - if (ioctl(sock, SIOCGIFADDR6, &ifr) == 0) { - struct in6_addr *addr = SIGAR_SIN6_ADDR(&ifr.ifr_Addr); - - sigar_net_address6_set(ifconfig->address6, addr); - sigar_net_interface_scope6_set(ifconfig, addr); - - if (ioctl(sock, SIOCGIFNETMASK6, &ifr) == 0) { - addr = SIGAR_SIN6_ADDR(&ifr.ifr_Addr); - ifconfig->prefix6_length = SIGAR_SIN6(&ifr.ifr_Addr)->sin6_len; /*XXX*/ - } - } - - close(sock); - return SIGAR_OK; -} - -#define IS_TCP_SERVER(state, flags) \ - ((flags & SIGAR_NETCONN_SERVER) && (state == TCPS_LISTEN)) - -#define IS_TCP_CLIENT(state, flags) \ - ((flags & SIGAR_NETCONN_CLIENT) && (state != TCPS_LISTEN)) - -static int net_conn_get_tcp(sigar_net_connection_walker_t *walker) -{ - sigar_t *sigar = walker->sigar; - int flags = walker->flags; - int status; - struct inpcb tcp_inpcb; - struct tcpcb tcpcb; - struct inpcb *entry; - - status = kread(sigar, &tcp_inpcb, sizeof(tcp_inpcb), - sigar->koffsets[KOFFSET_TCB]); - - if (status != SIGAR_OK) { - return status; - } - - entry = tcp_inpcb.inp_next; - while (entry) { - struct inpcb pcb; - int state; - - status = kread(sigar, &pcb, sizeof(pcb), (long)entry); - if (status != SIGAR_OK) { - return status; - } - status = kread(sigar, &tcpcb, sizeof(tcpcb), (long)pcb.inp_ppcb); - if (status != SIGAR_OK) { - return status; - } - - state = tcpcb.t_state; - if ((IS_TCP_SERVER(state, flags) || - IS_TCP_CLIENT(state, flags))) - { - sigar_net_connection_t conn; - - SIGAR_ZERO(&conn); - - conn.type = SIGAR_NETCONN_TCP; - - sigar_net_address_set(conn.local_address, - pcb.inp_laddr.s_addr); - - sigar_net_address_set(conn.remote_address, - pcb.inp_faddr.s_addr); - - conn.local_port = ntohs(pcb.inp_lport); - conn.remote_port = ntohs(pcb.inp_fport); - - conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL; - - switch (state) { - case TCPS_CLOSED: - conn.state = SIGAR_TCP_CLOSE; - break; - case TCPS_LISTEN: - conn.state = SIGAR_TCP_LISTEN; - break; - case TCPS_SYN_SENT: - conn.state = SIGAR_TCP_SYN_SENT; - break; - case TCPS_SYN_RECEIVED: - conn.state = SIGAR_TCP_SYN_RECV; - break; - case TCPS_ESTABLISHED: - conn.state = SIGAR_TCP_ESTABLISHED; - break; - case TCPS_CLOSE_WAIT: - conn.state = SIGAR_TCP_CLOSE_WAIT; - break; - case TCPS_FIN_WAIT_1: - conn.state = SIGAR_TCP_FIN_WAIT1; - break; - case TCPS_CLOSING: - conn.state = SIGAR_TCP_CLOSING; - break; - case TCPS_LAST_ACK: - conn.state = SIGAR_TCP_LAST_ACK; - break; - case TCPS_FIN_WAIT_2: - conn.state = SIGAR_TCP_FIN_WAIT2; - break; - case TCPS_TIME_WAIT: - conn.state = SIGAR_TCP_TIME_WAIT; - break; - default: - conn.state = SIGAR_TCP_UNKNOWN; - break; - } - - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - } - - entry = pcb.inp_next; - if (entry == tcp_inpcb.inp_next) { - break; - } - } - - return SIGAR_OK; -} - -int sigar_net_connection_walk(sigar_net_connection_walker_t *walker) -{ - int status; - - if (walker->flags & SIGAR_NETCONN_TCP) { - status = net_conn_get_tcp(walker); - - if (status != SIGAR_OK) { - return status; - } - } -#if 0 - if (walker->flags & SIGAR_NETCONN_UDP) { - status = net_conn_get_udp(walker); - - if (status != SIGAR_OK) { - return status; - } - } -#endif - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_tcp_get(sigar_t *sigar, - sigar_tcp_t *tcp) -{ - perfstat_id_t id; - perfstat_protocol_t proto; - - SIGAR_SSTRCPY(id.name, "tcp"); - - if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) { - return ENOENT; - } - - tcp->active_opens = proto.u.tcp.initiated; - tcp->passive_opens = proto.u.tcp.accepted; - tcp->attempt_fails = proto.u.tcp.dropped; - tcp->estab_resets = proto.u.tcp.dropped; - tcp->curr_estab = proto.u.tcp.established; - tcp->in_segs = proto.u.tcp.ipackets; - tcp->out_segs = proto.u.tcp.opackets; - tcp->retrans_segs = 0; - tcp->in_errs = proto.u.tcp.ierrors; - tcp->out_rsts = 0; -} - -#define NFS_V2_STAT_SET(type) \ - nfs->null = proto.u.nfsv2.type.null; \ - nfs->getattr = proto.u.nfsv2.type.getattr; \ - nfs->setattr = proto.u.nfsv2.type.setattr; \ - nfs->root = proto.u.nfsv2.type.root; \ - nfs->lookup = proto.u.nfsv2.type.lookup; \ - nfs->readlink = proto.u.nfsv2.type.readlink; \ - nfs->read = proto.u.nfsv2.type.read; \ - nfs->writecache = proto.u.nfsv2.type.writecache; \ - nfs->write = proto.u.nfsv2.type.write; \ - nfs->create = proto.u.nfsv2.type.create; \ - nfs->remove = proto.u.nfsv2.type.remove; \ - nfs->rename = proto.u.nfsv2.type.rename; \ - nfs->link = proto.u.nfsv2.type.link; \ - nfs->symlink = proto.u.nfsv2.type.symlink; \ - nfs->mkdir = proto.u.nfsv2.type.mkdir; \ - nfs->rmdir = proto.u.nfsv2.type.rmdir; \ - nfs->readdir = proto.u.nfsv2.type.readdir; \ - nfs->fsstat = proto.u.nfsv2.type.statfs - -int sigar_nfs_client_v2_get(sigar_t *sigar, - sigar_nfs_client_v2_t *nfs) -{ - perfstat_id_t id; - perfstat_protocol_t proto; - - SIGAR_SSTRCPY(id.name, "nfsv2"); - - if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) { - return ENOENT; - } - - NFS_V2_STAT_SET(client); - - return SIGAR_OK; -} - -int sigar_nfs_server_v2_get(sigar_t *sigar, - sigar_nfs_server_v2_t *nfs) -{ - perfstat_id_t id; - perfstat_protocol_t proto; - - SIGAR_SSTRCPY(id.name, "nfsv2"); - - if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) { - return ENOENT; - } - - NFS_V2_STAT_SET(server); - - return SIGAR_OK; -} - -#define NFS_V3_STAT_SET(type) \ - nfs->null = proto.u.nfsv3.type.null; \ - nfs->getattr = proto.u.nfsv3.type.getattr; \ - nfs->setattr = proto.u.nfsv3.type.setattr; \ - nfs->lookup = proto.u.nfsv3.type.lookup; \ - nfs->access = proto.u.nfsv3.type.access; \ - nfs->readlink = proto.u.nfsv3.type.readlink; \ - nfs->read = proto.u.nfsv3.type.read; \ - nfs->write = proto.u.nfsv3.type.write; \ - nfs->create = proto.u.nfsv3.type.create; \ - nfs->mkdir = proto.u.nfsv3.type.mkdir; \ - nfs->symlink = proto.u.nfsv3.type.symlink; \ - nfs->mknod = proto.u.nfsv3.type.mknod; \ - nfs->remove = proto.u.nfsv3.type.remove; \ - nfs->rmdir = proto.u.nfsv3.type.rmdir; \ - nfs->rename = proto.u.nfsv3.type.rename; \ - nfs->link = proto.u.nfsv3.type.link; \ - nfs->readdir = proto.u.nfsv3.type.readdir; \ - nfs->readdirplus = proto.u.nfsv3.type.readdirplus; \ - nfs->fsstat = proto.u.nfsv3.type.fsstat; \ - nfs->fsinfo = proto.u.nfsv3.type.fsinfo; \ - nfs->pathconf = proto.u.nfsv3.type.pathconf; \ - nfs->commit = proto.u.nfsv3.type.commit - -int sigar_nfs_client_v3_get(sigar_t *sigar, - sigar_nfs_client_v3_t *nfs) -{ - perfstat_id_t id; - perfstat_protocol_t proto; - - SIGAR_SSTRCPY(id.name, "nfsv3"); - - if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) { - return ENOENT; - } - - NFS_V3_STAT_SET(client); - - return SIGAR_OK; -} - -int sigar_nfs_server_v3_get(sigar_t *sigar, - sigar_nfs_server_v3_t *nfs) -{ - perfstat_id_t id; - perfstat_protocol_t proto; - - SIGAR_SSTRCPY(id.name, "nfsv3"); - - if (perfstat_protocol(&id, &proto, sizeof(proto), 1) != 1) { - return ENOENT; - } - - NFS_V3_STAT_SET(server); - - return SIGAR_OK; -} - -#include -/* - * cannot find any related aix docs on reading the ARP table, - * this impl was gleaned from the above .h file and truss -f arp -an - */ -int sigar_arp_list_get(sigar_t *sigar, - sigar_arp_list_t *arplist) -{ - int status = SIGAR_OK; - long arptabsize; - int i, size, retval; - struct arptab *arptabp; - - size = sizeof(arptabsize); - retval = getkerninfo(KINFO_READ, &arptabsize, &size, - sigar->koffsets[KOFFSET_ARPTABSIZE]); - if (retval != sizeof(arptabsize)) { - return errno; - } - - size = sizeof(arptabp); - retval = getkerninfo(KINFO_READ, &arptabp, &size, - sigar->koffsets[KOFFSET_ARPTABP]); - if (retval != sizeof(arptabp)) { - return errno; - } - - sigar_arp_list_create(arplist); - status = SIGAR_OK; - - for (i=0; idata[arplist->number++]; - - sigar_net_address_set(arp->address, - ent.at_iaddr.s_addr); - - sigar_net_address_mac_set(arp->hwaddr, - ent.hwaddr, - sizeof(arp->hwaddr.addr.mac)); - - if_indextoname(ifp.if_index, arp->ifname); - - arp->flags = ent.at_flags; - SIGAR_SSTRCPY(arp->type, "ether"); /* XXX ifp.if_type */ - } - - if (status != SIGAR_OK) { - sigar_arp_list_destroy(sigar, arplist); - } - - return status; -} - -/* derived from pidentd's k_aix432.c */ -int sigar_proc_port_get(sigar_t *sigar, int protocol, - unsigned long port, sigar_pid_t *pidp) -{ - struct procsinfo pinfo; - struct fdsinfo finfo; - pid_t pid = 0; - int type; - - switch (protocol) { - case SIGAR_NETCONN_TCP: - type = IPPROTO_TCP; - break; - case SIGAR_NETCONN_UDP: - type = IPPROTO_UDP; - break; - default: - return SIGAR_ENOTIMPL; - } - - for (;;) { - int fd, status; - int num = getprocs(&pinfo, sizeof(pinfo), - &finfo, sizeof(finfo), - &pid, 1); - - if (num == 0) { - break; - } - - if ((pinfo.pi_state == 0) || (pinfo.pi_state == SZOMB)) { - continue; - } - - for (fd = 0; fd < pinfo.pi_maxofile; fd++) { - struct file file; - struct socket socket, *sockp; - struct protosw protosw; - struct domain domain; - struct inpcb inpcb; - long ptr; - - if (!(ptr = (long)finfo.pi_ufd[fd].fp)) { - continue; - } - - status = kread(sigar, &file, sizeof(file), ptr); - if (status != SIGAR_OK) { - continue; - } - - if (file.f_type != DTYPE_SOCKET) { - continue; - } - - if (!(sockp = (struct socket *)file.f_data)) { - continue; - } - - status = kread(sigar, &socket, sizeof(socket), (long)sockp); - if (status != SIGAR_OK) { - continue; - } - - if (!(ptr = (long)socket.so_proto)) { - continue; - } - - status = kread(sigar, &protosw, sizeof(protosw), ptr); - if (status != SIGAR_OK) { - continue; - } - - if (protosw.pr_protocol != type) { - continue; - } - - if (!(ptr = (long)protosw.pr_domain)) { - continue; - } - - status = kread(sigar, &domain, sizeof(domain), ptr); - if (status != SIGAR_OK) { - continue; - } - - if ((domain.dom_family != AF_INET) && - domain.dom_family != AF_INET6) - { - continue; - } - - if (!(ptr = (long)socket.so_pcb)) { - continue; - } - - status = kread(sigar, &inpcb, sizeof(inpcb), ptr); - if (status != SIGAR_OK) { - continue; - } - - if (sockp != inpcb.inp_socket) { - continue; - } - - if (inpcb.inp_lport != port) { - continue; - } - - *pidp = pinfo.pi_pid; - - return SIGAR_OK; - } - } - - return ENOENT; -} - -int sigar_os_sys_info_get(sigar_t *sigar, - sigar_sys_info_t *sysinfo) -{ - struct utsname name; - - uname(&name); - - SIGAR_SSTRCPY(sysinfo->vendor, "IBM"); - SIGAR_SSTRCPY(sysinfo->arch, get_cpu_arch()); - /* utsname.machine is a sequence number */ - /* XXX odm might have something better */ - snprintf(sysinfo->machine, - sizeof(sysinfo->machine), - "%s %s", - sysinfo->arch, get_cpu_model()); - - snprintf(sysinfo->version, - sizeof(sysinfo->version), - "%s.%s", - name.version, name.release); - - SIGAR_SSTRCPY(sysinfo->vendor_version, sysinfo->version); - - snprintf(sysinfo->description, - sizeof(sysinfo->description), - "%s %s", - sysinfo->name, sysinfo->version); - - return SIGAR_OK; -} diff --git a/vendor/sigar/src/os/aix/sigar_os.h b/vendor/sigar/src/os/aix/sigar_os.h deleted file mode 100644 index 5ee7cf0..0000000 --- a/vendor/sigar/src/os/aix/sigar_os.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2004-2007, 2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_OS_H -#define SIGAR_OS_H - -#include -#include -#include -#include -#include - -enum { - KOFFSET_LOADAVG, - KOFFSET_VAR, - KOFFSET_SYSINFO, - KOFFSET_IFNET, - KOFFSET_VMINFO, - KOFFSET_CPUINFO, - KOFFSET_TCB, - KOFFSET_ARPTABSIZE, - KOFFSET_ARPTABP, - KOFFSET_MAX -}; - -typedef struct { - time_t mtime; - int num; - char **devs; -} swaps_t; - -typedef int (*proc_fd_func_t) (sigar_t *, sigar_pid_t, sigar_proc_fd_t *); - -struct sigar_t { - SIGAR_T_BASE; - int kmem; - /* offsets for seeking on kmem */ - long koffsets[KOFFSET_MAX]; - proc_fd_func_t getprocfd; - int pagesize; - swaps_t swaps; - time_t last_getprocs; - sigar_pid_t last_pid; - struct procsinfo64 *pinfo; - struct cpuinfo *cpuinfo; - int cpuinfo_size; - int cpu_mhz; - char model[128]; - int aix_version; - int thrusage; - sigar_cache_t *diskmap; -}; - -#define HAVE_STRERROR_R - -#define SIGAR_EPERM_KMEM (SIGAR_OS_START_ERROR+EACCES) - -#endif /* SIGAR_OS_H */ diff --git a/vendor/sigar/src/os/darwin/darwin_sigar.c b/vendor/sigar/src/os/darwin/darwin_sigar.c deleted file mode 100644 index 0e154b0..0000000 --- a/vendor/sigar/src/os/darwin/darwin_sigar.c +++ /dev/null @@ -1,3711 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -#include -#include -#if !(defined(__FreeBSD__) && (__FreeBSD_version >= 800000)) -#include -#endif -#include - -#ifdef DARWIN -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if !defined(HAVE_SHARED_REGION_H) && defined(__MAC_10_5) /* see Availability.h */ -# define HAVE_SHARED_REGION_H /* suckit autoconf */ -#endif -#ifdef HAVE_SHARED_REGION_H -#include /* does not exist in 10.4 SDK */ -#else -#include /* deprecated in Leopard */ -#endif -#include -#define __OPENTRANSPORTPROVIDERS__ -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#endif - -#if defined(__FreeBSD__) && (__FreeBSD_version >= 500013) -#define SIGAR_FREEBSD5_NFSSTAT -#include -#include -#else -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#ifdef __NetBSD__ -#include -#include -#include -#define SRUN LSRUN -#define SSLEEP LSSLEEP -#define SDEAD LSDEAD -#define SONPROC LSONPROC -#define SSUSPENDED LSSUSPENDED -#include -#endif -#include -#include - -#define NMIB(mib) (sizeof(mib)/sizeof(mib[0])) - -#ifdef __FreeBSD__ -# if (__FreeBSD_version >= 500013) -# define SIGAR_FREEBSD5 -# else -# define SIGAR_FREEBSD4 -# endif -#endif - -#if defined(SIGAR_FREEBSD5) - -#define KI_FD ki_fd -#define KI_PID ki_pid -#define KI_PPID ki_ppid -#define KI_PRI ki_pri.pri_user -#define KI_NICE ki_nice -#define KI_COMM ki_comm -#define KI_STAT ki_stat -#define KI_UID ki_ruid -#define KI_GID ki_rgid -#define KI_EUID ki_svuid -#define KI_EGID ki_svgid -#define KI_SIZE ki_size -#define KI_RSS ki_rssize -#define KI_TSZ ki_tsize -#define KI_DSZ ki_dsize -#define KI_SSZ ki_ssize -#define KI_FLAG ki_flag -#define KI_START ki_start - -#elif defined(DARWIN) || defined(SIGAR_FREEBSD4) || defined(__OpenBSD__) || defined(__NetBSD__) - -#define KI_FD kp_proc.p_fd -#define KI_PID kp_proc.p_pid -#define KI_PPID kp_eproc.e_ppid -#define KI_PRI kp_proc.p_priority -#define KI_NICE kp_proc.p_nice -#define KI_COMM kp_proc.p_comm -#define KI_STAT kp_proc.p_stat -#define KI_UID kp_eproc.e_pcred.p_ruid -#define KI_GID kp_eproc.e_pcred.p_rgid -#define KI_EUID kp_eproc.e_pcred.p_svuid -#define KI_EGID kp_eproc.e_pcred.p_svgid -#define KI_SIZE XXX -#define KI_RSS kp_eproc.e_vm.vm_rssize -#define KI_TSZ kp_eproc.e_vm.vm_tsize -#define KI_DSZ kp_eproc.e_vm.vm_dsize -#define KI_SSZ kp_eproc.e_vm.vm_ssize -#define KI_FLAG kp_eproc.e_flag -#define KI_START kp_proc.p_starttime - -#endif - -#ifndef DARWIN - -#define PROCFS_STATUS(status) \ - ((((status) != SIGAR_OK) && !sigar->proc_mounted) ? \ - SIGAR_ENOTIMPL : status) - -static int get_koffsets(sigar_t *sigar) -{ - int i; - struct nlist klist[] = { - { "_cp_time" }, - { "_cnt" }, -#if defined(__OpenBSD__) || defined(__NetBSD__) - { "_tcpstat" }, - { "_tcbtable" }, -#endif - { NULL } - }; - - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - kvm_nlist(sigar->kmem, klist); - - for (i=0; ikoffsets[i] = klist[i].n_value; - } - - return SIGAR_OK; -} - -static int kread(sigar_t *sigar, void *data, int size, long offset) -{ - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - if (kvm_read(sigar->kmem, offset, data, size) != size) { - return errno; - } - - return SIGAR_OK; -} -#endif - -int sigar_os_open(sigar_t **sigar) -{ - int mib[2]; - int ncpu; - size_t len; - struct timeval boottime; -#ifndef DARWIN - struct stat sb; -#endif - - len = sizeof(ncpu); - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - if (sysctl(mib, NMIB(mib), &ncpu, &len, NULL, 0) < 0) { - return errno; - } - - len = sizeof(boottime); - mib[0] = CTL_KERN; - mib[1] = KERN_BOOTTIME; - if (sysctl(mib, NMIB(mib), &boottime, &len, NULL, 0) < 0) { - return errno; - } - - *sigar = malloc(sizeof(**sigar)); - -#ifdef DARWIN - (*sigar)->mach_port = mach_host_self(); -# ifdef DARWIN_HAS_LIBPROC_H - if (((*sigar)->libproc = dlopen("/usr/lib/libproc.dylib", 0))) { - (*sigar)->proc_pidinfo = dlsym((*sigar)->libproc, "proc_pidinfo"); - (*sigar)->proc_pidfdinfo = dlsym((*sigar)->libproc, "proc_pidfdinfo"); - } -# endif -#else - (*sigar)->kmem = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); - if (stat("/proc/curproc", &sb) < 0) { - (*sigar)->proc_mounted = 0; - } - else { - (*sigar)->proc_mounted = 1; - } -#endif - -#ifndef DARWIN - get_koffsets(*sigar); -#endif - - (*sigar)->ncpu = ncpu; - (*sigar)->lcpu = -1; - (*sigar)->argmax = 0; - (*sigar)->boot_time = boottime.tv_sec; /* XXX seems off a bit */ - - (*sigar)->pagesize = getpagesize(); -#ifdef __FreeBSD__ - (*sigar)->ticks = 100; /* sysconf(_SC_CLK_TCK) == 128 !? */ -#else - (*sigar)->ticks = sysconf(_SC_CLK_TCK); -#endif - (*sigar)->last_pid = -1; - - (*sigar)->pinfo = NULL; - - return SIGAR_OK; -} - -int sigar_os_close(sigar_t *sigar) -{ - if (sigar->pinfo) { - free(sigar->pinfo); - } -#ifndef DARWIN - if (sigar->kmem) { - kvm_close(sigar->kmem); - } -#endif - free(sigar); - return SIGAR_OK; -} - -char *sigar_os_error_string(sigar_t *sigar, int err) -{ - switch (err) { - case SIGAR_EPERM_KMEM: - return "Failed to open /dev/kmem for reading"; - case SIGAR_EPROC_NOENT: - return "/proc filesystem is not mounted"; - default: - return NULL; - } -} - -/* ARG_MAX in FreeBSD 6.0 == 262144, which blows up the stack */ -#define SIGAR_ARG_MAX 65536 - -#ifdef DARWIN -static size_t sigar_argmax_get(sigar_t *sigar) -{ -#ifdef KERN_ARGMAX - int mib[] = { CTL_KERN, KERN_ARGMAX }; - size_t size = sizeof(sigar->argmax); - - if (sigar->argmax != 0) { - return sigar->argmax; - } - if (sysctl(mib, NMIB(mib), &sigar->argmax, &size, NULL, 0) == 0) { - return sigar->argmax; - } -#endif - return SIGAR_ARG_MAX; -} -#endif /* DARWIN */ - -#if defined(DARWIN) -static int sigar_vmstat(sigar_t *sigar, vm_statistics_data_t *vmstat) -{ - kern_return_t status; - mach_msg_type_number_t count = sizeof(*vmstat) / sizeof(integer_t); - - status = host_statistics(sigar->mach_port, HOST_VM_INFO, - (host_info_t)vmstat, &count); - - if (status == KERN_SUCCESS) { - return SIGAR_OK; - } - else { - return errno; - } -} -#elif defined(__FreeBSD__) -static int sigar_vmstat(sigar_t *sigar, struct vmmeter *vmstat) -{ - int status; - size_t size = sizeof(unsigned int); - - status = kread(sigar, vmstat, sizeof(*vmstat), - sigar->koffsets[KOFFSET_VMMETER]); - - if (status == SIGAR_OK) { - return SIGAR_OK; - } - - SIGAR_ZERO(vmstat); - - /* derived from src/usr.bin/vmstat/vmstat.c */ - /* only collect the ones we actually use */ -#define GET_VM_STATS(cat, name, used) \ - if (used) sysctlbyname("vm.stats." #cat "." #name, &vmstat->name, &size, NULL, 0) - - /* sys */ - GET_VM_STATS(sys, v_swtch, 0); - GET_VM_STATS(sys, v_trap, 0); - GET_VM_STATS(sys, v_syscall, 0); - GET_VM_STATS(sys, v_intr, 0); - GET_VM_STATS(sys, v_soft, 0); - - /* vm */ - GET_VM_STATS(vm, v_vm_faults, 0); - GET_VM_STATS(vm, v_cow_faults, 0); - GET_VM_STATS(vm, v_cow_optim, 0); - GET_VM_STATS(vm, v_zfod, 0); - GET_VM_STATS(vm, v_ozfod, 0); - GET_VM_STATS(vm, v_swapin, 1); - GET_VM_STATS(vm, v_swapout, 1); - GET_VM_STATS(vm, v_swappgsin, 0); - GET_VM_STATS(vm, v_swappgsout, 0); - GET_VM_STATS(vm, v_vnodein, 1); - GET_VM_STATS(vm, v_vnodeout, 1); - GET_VM_STATS(vm, v_vnodepgsin, 0); - GET_VM_STATS(vm, v_vnodepgsout, 0); - GET_VM_STATS(vm, v_intrans, 0); - GET_VM_STATS(vm, v_reactivated, 0); - GET_VM_STATS(vm, v_pdwakeups, 0); - GET_VM_STATS(vm, v_pdpages, 0); - GET_VM_STATS(vm, v_dfree, 0); - GET_VM_STATS(vm, v_pfree, 0); - GET_VM_STATS(vm, v_tfree, 0); - GET_VM_STATS(vm, v_page_size, 0); - GET_VM_STATS(vm, v_page_count, 0); - GET_VM_STATS(vm, v_free_reserved, 0); - GET_VM_STATS(vm, v_free_target, 0); - GET_VM_STATS(vm, v_free_min, 0); - GET_VM_STATS(vm, v_free_count, 1); - GET_VM_STATS(vm, v_wire_count, 0); - GET_VM_STATS(vm, v_active_count, 0); - GET_VM_STATS(vm, v_inactive_target, 0); - GET_VM_STATS(vm, v_inactive_count, 1); - GET_VM_STATS(vm, v_cache_count, 1); - GET_VM_STATS(vm, v_cache_min, 0); - GET_VM_STATS(vm, v_cache_max, 0); - GET_VM_STATS(vm, v_pageout_free_min, 0); - GET_VM_STATS(vm, v_interrupt_free_min, 0); - GET_VM_STATS(vm, v_forks, 0); - GET_VM_STATS(vm, v_vforks, 0); - GET_VM_STATS(vm, v_rforks, 0); - GET_VM_STATS(vm, v_kthreads, 0); - GET_VM_STATS(vm, v_forkpages, 0); - GET_VM_STATS(vm, v_vforkpages, 0); - GET_VM_STATS(vm, v_rforkpages, 0); - GET_VM_STATS(vm, v_kthreadpages, 0); -#undef GET_VM_STATS - - return SIGAR_OK; -} -#elif defined(__OpenBSD__) || defined(__NetBSD__) -static int sigar_vmstat(sigar_t *sigar, struct uvmexp *vmstat) -{ - size_t size = sizeof(*vmstat); - int mib[] = { CTL_VM, VM_UVMEXP }; - if (sysctl(mib, NMIB(mib), vmstat, &size, NULL, 0) < 0) { - return errno; - } - else { - return SIGAR_OK; - } -} -#endif - -int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem) -{ - sigar_uint64_t kern = 0; -#ifdef DARWIN - vm_statistics_data_t vmstat; - uint64_t mem_total; -#else - unsigned long mem_total; -#endif -#if defined(__FreeBSD__) - struct vmmeter vmstat; -#elif defined(__OpenBSD__) || defined(__NetBSD__) - struct uvmexp vmstat; -#endif - int mib[2]; - size_t len; - int status; - - mib[0] = CTL_HW; - - mib[1] = HW_PAGESIZE; - len = sizeof(sigar->pagesize); - if (sysctl(mib, NMIB(mib), &sigar->pagesize, &len, NULL, 0) < 0) { - return errno; - } - -#ifdef DARWIN - mib[1] = HW_MEMSIZE; -#else - mib[1] = HW_PHYSMEM; -#endif - len = sizeof(mem_total); - if (sysctl(mib, NMIB(mib), &mem_total, &len, NULL, 0) < 0) { - return errno; - } - - mem->total = mem_total; - -#if defined(DARWIN) - if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) { - return status; - } - - mem->free = vmstat.free_count; - mem->free *= sigar->pagesize; - kern = vmstat.inactive_count; - kern *= sigar->pagesize; -#elif defined(__FreeBSD__) - if ((status = sigar_vmstat(sigar, &vmstat)) == SIGAR_OK) { - kern = vmstat.v_cache_count + vmstat.v_inactive_count; - kern *= sigar->pagesize; - mem->free = vmstat.v_free_count; - mem->free *= sigar->pagesize; - } -#elif defined(__OpenBSD__) || defined(__NetBSD__) - if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) { - return status; - } - mem->free = vmstat.free; - kern = vmstat.inactive; -# if defined(__OpenBSD__) - kern += vmstat.vnodepages + vmstat.vtextpages; -# elif defined(__NetBSD__) - kern += vmstat.filepages + vmstat.execpages; -# endif - kern *= sigar->pagesize; -#endif - - mem->used = mem->total - mem->free; - - mem->actual_free = mem->free + kern; - mem->actual_used = mem->used - kern; - - sigar_mem_calc_ram(sigar, mem); - - return SIGAR_OK; -} - -#define SWI_MAXMIB 3 - -#ifdef SIGAR_FREEBSD5 -/* code in this function is based on FreeBSD 5.3 kvm_getswapinfo.c */ -static int getswapinfo_sysctl(struct kvm_swap *swap_ary, - int swap_max) -{ - int ti, ttl; - size_t mibi, len, size; - int soid[SWI_MAXMIB]; - struct xswdev xsd; - struct kvm_swap tot; - int unswdev, dmmax; - - /* XXX this can be optimized by using os_open */ - size = sizeof(dmmax); - if (sysctlbyname("vm.dmmax", &dmmax, &size, NULL, 0) == -1) { - return errno; - } - - mibi = SWI_MAXMIB - 1; - if (sysctlnametomib("vm.swap_info", soid, &mibi) == -1) { - return errno; - } - - bzero(&tot, sizeof(tot)); - for (unswdev = 0;; unswdev++) { - soid[mibi] = unswdev; - len = sizeof(xsd); - if (sysctl(soid, mibi + 1, &xsd, &len, NULL, 0) == -1) { - if (errno == ENOENT) { - break; - } - return errno; - } -#if 0 - if (len != sizeof(xsd)) { - _kvm_err(kd, kd->program, "struct xswdev has unexpected " - "size; kernel and libkvm out of sync?"); - return -1; - } - if (xsd.xsw_version != XSWDEV_VERSION) { - _kvm_err(kd, kd->program, "struct xswdev version " - "mismatch; kernel and libkvm out of sync?"); - return -1; - } -#endif - ttl = xsd.xsw_nblks - dmmax; - if (unswdev < swap_max - 1) { - bzero(&swap_ary[unswdev], sizeof(swap_ary[unswdev])); - swap_ary[unswdev].ksw_total = ttl; - swap_ary[unswdev].ksw_used = xsd.xsw_used; - swap_ary[unswdev].ksw_flags = xsd.xsw_flags; - } - tot.ksw_total += ttl; - tot.ksw_used += xsd.xsw_used; - } - - ti = unswdev; - if (ti >= swap_max) { - ti = swap_max - 1; - } - if (ti >= 0) { - swap_ary[ti] = tot; - } - - return SIGAR_OK; -} -#else -#define getswapinfo_sysctl(swap_ary, swap_max) SIGAR_ENOTIMPL -#endif - -#define SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) ((val * bsize) >> 1) - -#ifdef DARWIN -#define VM_DIR "/private/var/vm" -#define SWAPFILE "swapfile" - -static int sigar_swap_fs_get(sigar_t *sigar, sigar_swap_t *swap) /* <= 10.3 */ -{ - DIR *dirp; - struct dirent *ent; - char swapfile[SSTRLEN(VM_DIR) + SSTRLEN("/") + SSTRLEN(SWAPFILE) + 12]; - struct stat swapstat; - struct statfs vmfs; - sigar_uint64_t val, bsize; - - swap->used = swap->total = swap->free = 0; - - if (!(dirp = opendir(VM_DIR))) { - return errno; - } - - /* looking for "swapfile0", "swapfile1", etc. */ - while ((ent = readdir(dirp))) { - char *ptr = swapfile; - - if ((ent->d_namlen < SSTRLEN(SWAPFILE)+1) || /* n/a, see comment above */ - (ent->d_namlen > SSTRLEN(SWAPFILE)+11)) /* ensure no overflow */ - { - continue; - } - - if (!strnEQ(ent->d_name, SWAPFILE, SSTRLEN(SWAPFILE))) { - continue; - } - - /* sprintf(swapfile, "%s/%s", VM_DIR, ent->d_name) */ - - memcpy(ptr, VM_DIR, SSTRLEN(VM_DIR)); - ptr += SSTRLEN(VM_DIR); - - *ptr++ = '/'; - - memcpy(ptr, ent->d_name, ent->d_namlen+1); - - if (stat(swapfile, &swapstat) < 0) { - continue; - } - - swap->used += swapstat.st_size; - } - - closedir(dirp); - - if (statfs(VM_DIR, &vmfs) < 0) { - return errno; - } - - bsize = vmfs.f_bsize / 512; - val = vmfs.f_bfree; - swap->total = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) + swap->used; - - swap->free = swap->total - swap->used; - - return SIGAR_OK; -} - -static int sigar_swap_sysctl_get(sigar_t *sigar, sigar_swap_t *swap) - -{ -#ifdef VM_SWAPUSAGE /* => 10.4 */ - struct xsw_usage sw_usage; - size_t size = sizeof(sw_usage); - int mib[] = { CTL_VM, VM_SWAPUSAGE }; - - if (sysctl(mib, NMIB(mib), &sw_usage, &size, NULL, 0) != 0) { - return errno; - } - - swap->total = sw_usage.xsu_total; - swap->used = sw_usage.xsu_used; - swap->free = sw_usage.xsu_avail; - - return SIGAR_OK; -#else - return SIGAR_ENOTIMPL; /* <= 10.3 */ -#endif -} -#endif /* DARWIN */ - -int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap) -{ - int status; -#if defined(DARWIN) - vm_statistics_data_t vmstat; - - if (sigar_swap_sysctl_get(sigar, swap) != SIGAR_OK) { - status = sigar_swap_fs_get(sigar, swap); /* <= 10.3 */ - if (status != SIGAR_OK) { - return status; - } - } - - if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) { - return status; - } - swap->page_in = vmstat.pageins; - swap->page_out = vmstat.pageouts; -#elif defined(__FreeBSD__) - struct kvm_swap kswap[1]; - struct vmmeter vmstat; - - if (getswapinfo_sysctl(kswap, 1) != SIGAR_OK) { - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - if (kvm_getswapinfo(sigar->kmem, kswap, 1, 0) < 0) { - return errno; - } - } - - if (kswap[0].ksw_total == 0) { - swap->total = 0; - swap->used = 0; - swap->free = 0; - return SIGAR_OK; - } - - swap->total = kswap[0].ksw_total * sigar->pagesize; - swap->used = kswap[0].ksw_used * sigar->pagesize; - swap->free = swap->total - swap->used; - - if ((status = sigar_vmstat(sigar, &vmstat)) == SIGAR_OK) { - swap->page_in = vmstat.v_swapin + vmstat.v_vnodein; - swap->page_out = vmstat.v_swapout + vmstat.v_vnodeout; - } - else { - swap->page_in = swap->page_out = -1; - } -#elif defined(__OpenBSD__) || defined(__NetBSD__) - struct uvmexp vmstat; - - if ((status = sigar_vmstat(sigar, &vmstat)) != SIGAR_OK) { - return status; - } - swap->total = vmstat.swpages * sigar->pagesize; - swap->used = vmstat.swpginuse * sigar->pagesize; - swap->free = swap->total - swap->used; - swap->page_in = vmstat.pageins; - swap->page_out = vmstat.pdpageouts; -#endif - - return SIGAR_OK; -} - -#ifndef KERN_CPTIME -#define KERN_CPTIME KERN_CP_TIME -#endif - -#if defined(__NetBSD__) -typedef uint64_t cp_time_t; -#else -typedef unsigned long cp_time_t; -#endif - -int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ -#if defined(DARWIN) - kern_return_t status; - mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; - host_cpu_load_info_data_t cpuload; - - status = host_statistics(sigar->mach_port, HOST_CPU_LOAD_INFO, - (host_info_t)&cpuload, &count); - - if (status != KERN_SUCCESS) { - return errno; - } - - cpu->user = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_USER]); - cpu->sys = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_SYSTEM]); - cpu->idle = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_IDLE]); - cpu->nice = SIGAR_TICK2MSEC(cpuload.cpu_ticks[CPU_STATE_NICE]); - cpu->wait = 0; /*N/A*/ - cpu->irq = 0; /*N/A*/ - cpu->soft_irq = 0; /*N/A*/ - cpu->stolen = 0; /*N/A*/ - cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle; - -#elif defined(__FreeBSD__) || (__OpenBSD__) || defined(__NetBSD__) - int status; - cp_time_t cp_time[CPUSTATES]; - size_t size = sizeof(cp_time); - -# if defined(__OpenBSD__) || defined(__NetBSD__) - int mib[] = { CTL_KERN, KERN_CPTIME }; - if (sysctl(mib, NMIB(mib), &cp_time, &size, NULL, 0) == -1) { - status = errno; - } -# else - /* try sysctl first, does not require /dev/kmem perms */ - if (sysctlbyname("kern.cp_time", &cp_time, &size, NULL, 0) == -1) { - status = kread(sigar, &cp_time, sizeof(cp_time), - sigar->koffsets[KOFFSET_CPUINFO]); - } -# endif - else { - status = SIGAR_OK; - } - - if (status != SIGAR_OK) { - return status; - } - - cpu->user = SIGAR_TICK2MSEC(cp_time[CP_USER]); - cpu->nice = SIGAR_TICK2MSEC(cp_time[CP_NICE]); - cpu->sys = SIGAR_TICK2MSEC(cp_time[CP_SYS]); - cpu->idle = SIGAR_TICK2MSEC(cp_time[CP_IDLE]); - cpu->wait = 0; /*N/A*/ - cpu->irq = SIGAR_TICK2MSEC(cp_time[CP_INTR]); - cpu->soft_irq = 0; /*N/A*/ - cpu->stolen = 0; /*N/A*/ - cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle + cpu->irq; -#endif - - return SIGAR_OK; -} - -#if defined(__FreeBSD__) && (__FreeBSD_version >= 700000) -#define HAVE_KERN_CP_TIMES /* kern.cp_times came later than 7.0, not sure exactly when */ -static int sigar_cp_times_get(sigar_t *sigar, sigar_cpu_list_t *cpulist) -{ - int maxcpu, status; - size_t len = sizeof(maxcpu), size; - long *times; - - if (sysctlbyname("kern.smp.maxcpus", &maxcpu, &len, NULL, 0) == -1) { - return errno; - } - - size = sizeof(long) * maxcpu * CPUSTATES; - times = malloc(size); - if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1) { - status = errno; - } - else { - int i, maxid = (size / CPUSTATES / sizeof(long)); - long *cp_time = times; - status = SIGAR_OK; - - for (i=0; idata[cpulist->number++]; - cpu->user = SIGAR_TICK2MSEC(cp_time[CP_USER]); - cpu->nice = SIGAR_TICK2MSEC(cp_time[CP_NICE]); - cpu->sys = SIGAR_TICK2MSEC(cp_time[CP_SYS]); - cpu->idle = SIGAR_TICK2MSEC(cp_time[CP_IDLE]); - cpu->wait = 0; /*N/A*/ - cpu->irq = SIGAR_TICK2MSEC(cp_time[CP_INTR]); - cpu->soft_irq = 0; /*N/A*/ - cpu->stolen = 0; /*N/A*/ - cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle + cpu->irq; - cp_time += CPUSTATES; - } - } - - free(times); - return status; -} -#endif - -int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist) -{ -#ifdef DARWIN - kern_return_t status; - mach_msg_type_number_t count; - processor_cpu_load_info_data_t *cpuload; - natural_t i, ncpu; - - status = host_processor_info(sigar->mach_port, - PROCESSOR_CPU_LOAD_INFO, - &ncpu, - (processor_info_array_t*)&cpuload, - &count); - - if (status != KERN_SUCCESS) { - return errno; - } - - sigar_cpu_list_create(cpulist); - - for (i=0; idata[cpulist->number++]; - - cpu->user = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_USER]); - cpu->sys = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_SYSTEM]); - cpu->idle = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_IDLE]); - cpu->nice = SIGAR_TICK2MSEC(cpuload[i].cpu_ticks[CPU_STATE_NICE]); - cpu->wait = 0; /*N/A*/ - cpu->irq = 0; /*N/A*/ - cpu->soft_irq = 0; /*N/A*/ - cpu->stolen = 0; /*N/A*/ - cpu->total = cpu->user + cpu->nice + cpu->sys + cpu->idle; - } - - vm_deallocate(mach_task_self(), (vm_address_t)cpuload, count); - - return SIGAR_OK; -#else - int status, i; - sigar_cpu_t *cpu; - - sigar_cpu_list_create(cpulist); - -#ifdef HAVE_KERN_CP_TIMES - if ((status = sigar_cp_times_get(sigar, cpulist)) == SIGAR_OK) { - return SIGAR_OK; - } -#endif - /* XXX no multi cpu in freebsd < 7.0, howbout others? - * for now just report all metrics on the 1st cpu - * 0's for the rest - */ - cpu = &cpulist->data[cpulist->number++]; - - status = sigar_cpu_get(sigar, cpu); - if (status != SIGAR_OK) { - return status; - } - - for (i=1; incpu; i++) { - SIGAR_CPU_LIST_GROW(cpulist); - - cpu = &cpulist->data[cpulist->number++]; - SIGAR_ZERO(cpu); - } - - return SIGAR_OK; -#endif -} - -int sigar_uptime_get(sigar_t *sigar, - sigar_uptime_t *uptime) -{ - uptime->uptime = time(NULL) - sigar->boot_time; - - return SIGAR_OK; -} - -int sigar_loadavg_get(sigar_t *sigar, - sigar_loadavg_t *loadavg) -{ - getloadavg(loadavg->loadavg, 3); - - return SIGAR_OK; -} - -#if defined(DARWIN) && defined(DARWIN_HAS_LIBPROC_H) - -static int proc_fdinfo_get(sigar_t *sigar, sigar_pid_t pid, int *num) -{ - int rsize; - const int init_size = PROC_PIDLISTFD_SIZE * 32; - - if (!sigar->libproc) { - return SIGAR_ENOTIMPL; - } - - if (sigar->ifconf_len == 0) { - sigar->ifconf_len = init_size; - sigar->ifconf_buf = malloc(sigar->ifconf_len); - } - - while (1) { - rsize = sigar->proc_pidinfo(pid, PROC_PIDLISTFDS, 0, - sigar->ifconf_buf, sigar->ifconf_len); - if (rsize <= 0) { - return errno; - } - if ((rsize + PROC_PIDLISTFD_SIZE) < sigar->ifconf_len) { - break; - } - - sigar->ifconf_len += init_size; - sigar->ifconf_buf = realloc(sigar->ifconf_buf, sigar->ifconf_len); - } - - *num = rsize / PROC_PIDLISTFD_SIZE; - - return SIGAR_OK; -} - -#endif - -#ifndef KERN_PROC_PROC -/* freebsd 4.x */ -#define KERN_PROC_PROC KERN_PROC_ALL -#endif - -int sigar_os_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ -#if defined(DARWIN) || defined(SIGAR_FREEBSD5) || defined(__OpenBSD__) || defined(__NetBSD__) - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 }; - int i, num; - size_t len; - struct kinfo_proc *proc; - - if (sysctl(mib, NMIB(mib), NULL, &len, NULL, 0) < 0) { - return errno; - } - - proc = malloc(len); - - if (sysctl(mib, NMIB(mib), proc, &len, NULL, 0) < 0) { - free(proc); - return errno; - } - - num = len/sizeof(*proc); - - for (i=0; idata[proclist->number++] = proc[i].KI_PID; - } - - free(proc); - - return SIGAR_OK; -#else - int i, num; - struct kinfo_proc *proc; - - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - proc = kvm_getprocs(sigar->kmem, KERN_PROC_PROC, 0, &num); - - for (i=0; idata[proclist->number++] = proc[i].KI_PID; - } -#endif - - return SIGAR_OK; -} - -static int sigar_get_pinfo(sigar_t *sigar, sigar_pid_t pid) -{ -#if defined(__OpenBSD__) || defined(__NetBSD__) - int mib[] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, 0, sizeof(*sigar->pinfo), 1 }; -#else - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 0 }; -#endif - size_t len = sizeof(*sigar->pinfo); - time_t timenow = time(NULL); - mib[3] = pid; - - if (sigar->pinfo == NULL) { - sigar->pinfo = malloc(len); - } - - if (sigar->last_pid == pid) { - if ((timenow - sigar->last_getprocs) < SIGAR_LAST_PROC_EXPIRE) { - return SIGAR_OK; - } - } - - sigar->last_pid = pid; - sigar->last_getprocs = timenow; - - if (sysctl(mib, NMIB(mib), sigar->pinfo, &len, NULL, 0) < 0) { - return errno; - } - - return SIGAR_OK; -} - -#if defined(SHARED_TEXT_REGION_SIZE) && defined(SHARED_DATA_REGION_SIZE) -# define GLOBAL_SHARED_SIZE (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE) /* 10.4 SDK */ -#endif - -#if defined(DARWIN) && defined(DARWIN_HAS_LIBPROC_H) && !defined(GLOBAL_SHARED_SIZE) -/* get the CPU type of the process for the given pid */ -static int sigar_proc_cpu_type(sigar_t *sigar, sigar_pid_t pid, cpu_type_t *type) -{ - int status; - int mib[CTL_MAXNAME]; - size_t len, miblen = NMIB(mib); - - status = sysctlnametomib("sysctl.proc_cputype", mib, &miblen); - if (status != SIGAR_OK) { - return status; - } - - mib[miblen] = pid; - len = sizeof(*type); - return sysctl(mib, miblen + 1, type, &len, NULL, 0); -} - -/* shared memory region size for the given cpu_type_t */ -static mach_vm_size_t sigar_shared_region_size(cpu_type_t type) -{ - switch (type) { - case CPU_TYPE_ARM: - return SHARED_REGION_SIZE_ARM; - case CPU_TYPE_POWERPC: - return SHARED_REGION_SIZE_PPC; - case CPU_TYPE_POWERPC64: - return SHARED_REGION_SIZE_PPC64; - case CPU_TYPE_I386: - return SHARED_REGION_SIZE_I386; - case CPU_TYPE_X86_64: - return SHARED_REGION_SIZE_X86_64; - default: - return SHARED_REGION_SIZE_I386; /* assume 32-bit x86|ppc */ - } -} -#endif /* DARWIN */ - -int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_mem_t *procmem) -{ -#if defined(DARWIN) - mach_port_t task, self = mach_task_self(); - kern_return_t status; - task_basic_info_data_t info; - task_events_info_data_t events; - mach_msg_type_number_t count; -# ifdef DARWIN_HAS_LIBPROC_H - struct proc_taskinfo pti; - struct proc_regioninfo pri; - - if (sigar->libproc) { - int sz = - sigar->proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti)); - - if (sz == sizeof(pti)) { - procmem->size = pti.pti_virtual_size; - procmem->resident = pti.pti_resident_size; - procmem->page_faults = pti.pti_faults; - procmem->minor_faults = SIGAR_FIELD_NOTIMPL; - procmem->major_faults = SIGAR_FIELD_NOTIMPL; - procmem->share = SIGAR_FIELD_NOTIMPL; - - sz = sigar->proc_pidinfo(pid, PROC_PIDREGIONINFO, 0, &pri, sizeof(pri)); - if (sz == sizeof(pri)) { - if (pri.pri_share_mode == SM_EMPTY) { - mach_vm_size_t shared_size; -#ifdef GLOBAL_SHARED_SIZE - shared_size = GLOBAL_SHARED_SIZE; /* 10.4 SDK */ -#else - cpu_type_t cpu_type; - - if (sigar_proc_cpu_type(sigar, pid, &cpu_type) == SIGAR_OK) { - shared_size = sigar_shared_region_size(cpu_type); - } - else { - shared_size = SHARED_REGION_SIZE_I386; /* assume 32-bit x86|ppc */ - } -#endif - if (procmem->size > shared_size) { - procmem->size -= shared_size; /* SIGAR-123 */ - } - } - } - return SIGAR_OK; - } - } -# endif - - status = task_for_pid(self, pid, &task); - - if (status != KERN_SUCCESS) { - return errno; - } - - count = TASK_BASIC_INFO_COUNT; - status = task_info(task, TASK_BASIC_INFO, (task_info_t)&info, &count); - if (status != KERN_SUCCESS) { - return errno; - } - - count = TASK_EVENTS_INFO_COUNT; - status = task_info(task, TASK_EVENTS_INFO, (task_info_t)&events, &count); - if (status == KERN_SUCCESS) { - procmem->page_faults = events.faults; - } - else { - procmem->page_faults = SIGAR_FIELD_NOTIMPL; - } - - procmem->minor_faults = SIGAR_FIELD_NOTIMPL; - procmem->major_faults = SIGAR_FIELD_NOTIMPL; - - if (task != self) { - mach_port_deallocate(self, task); - } - - procmem->size = info.virtual_size; - procmem->resident = info.resident_size; - procmem->share = SIGAR_FIELD_NOTIMPL; - - return SIGAR_OK; -#elif defined(__FreeBSD__) - int status = sigar_get_pinfo(sigar, pid); - bsd_pinfo_t *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - procmem->size = - (pinfo->KI_TSZ + pinfo->KI_DSZ + pinfo->KI_SSZ) * sigar->pagesize; - - procmem->resident = pinfo->KI_RSS * sigar->pagesize; - - procmem->share = SIGAR_FIELD_NOTIMPL; - - procmem->page_faults = SIGAR_FIELD_NOTIMPL; - procmem->minor_faults = SIGAR_FIELD_NOTIMPL; - procmem->major_faults = SIGAR_FIELD_NOTIMPL; -#elif defined(__OpenBSD__) || defined(__NetBSD__) - int status = sigar_get_pinfo(sigar, pid); - bsd_pinfo_t *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - procmem->size = - (pinfo->p_vm_tsize + pinfo->p_vm_dsize + pinfo->p_vm_ssize) * sigar->pagesize; - - procmem->resident = pinfo->p_vm_rssize * sigar->pagesize; - - procmem->share = SIGAR_FIELD_NOTIMPL; - - procmem->minor_faults = pinfo->p_uru_minflt; - procmem->major_faults = pinfo->p_uru_majflt; - procmem->page_faults = procmem->minor_faults + procmem->major_faults; -#endif - return SIGAR_OK; -} - -int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_t *proccred) -{ - int status = sigar_get_pinfo(sigar, pid); - bsd_pinfo_t *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - -#if defined(__OpenBSD__) || defined(__NetBSD__) - proccred->uid = pinfo->p_ruid; - proccred->gid = pinfo->p_rgid; - proccred->euid = pinfo->p_uid; - proccred->egid = pinfo->p_gid; -#else - proccred->uid = pinfo->KI_UID; - proccred->gid = pinfo->KI_GID; - proccred->euid = pinfo->KI_EUID; - proccred->egid = pinfo->KI_EGID; -#endif - - return SIGAR_OK; -} - -#define tv2msec(tv) \ - (((sigar_uint64_t)tv.tv_sec * SIGAR_MSEC) + (((sigar_uint64_t)tv.tv_usec) / 1000)) - -#ifdef DARWIN -#define tval2msec(tval) \ - ((tval.seconds * SIGAR_MSEC) + (tval.microseconds / 1000)) - -#define tval2nsec(tval) \ - (SIGAR_SEC2NANO((tval).seconds) + SIGAR_MICROSEC2NANO((tval).microseconds)) - -static int get_proc_times(sigar_t *sigar, sigar_pid_t pid, sigar_proc_time_t *time) -{ - unsigned int count; - time_value_t utime = {0, 0}, stime = {0, 0}; - task_basic_info_data_t ti; - task_thread_times_info_data_t tti; - task_port_t task, self; - kern_return_t status; -# ifdef DARWIN_HAS_LIBPROC_H - if (sigar->libproc) { - struct proc_taskinfo pti; - int sz = - sigar->proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti)); - - if (sz == sizeof(pti)) { - time->user = SIGAR_NSEC2MSEC(pti.pti_total_user); - time->sys = SIGAR_NSEC2MSEC(pti.pti_total_system); - time->total = time->user + time->sys; - return SIGAR_OK; - } - } -# endif - - self = mach_task_self(); - status = task_for_pid(self, pid, &task); - if (status != KERN_SUCCESS) { - return errno; - } - - count = TASK_BASIC_INFO_COUNT; - status = task_info(task, TASK_BASIC_INFO, - (task_info_t)&ti, &count); - if (status != KERN_SUCCESS) { - if (task != self) { - mach_port_deallocate(self, task); - } - return errno; - } - - count = TASK_THREAD_TIMES_INFO_COUNT; - status = task_info(task, TASK_THREAD_TIMES_INFO, - (task_info_t)&tti, &count); - if (status != KERN_SUCCESS) { - if (task != self) { - mach_port_deallocate(self, task); - } - return errno; - } - - time_value_add(&utime, &ti.user_time); - time_value_add(&stime, &ti.system_time); - time_value_add(&utime, &tti.user_time); - time_value_add(&stime, &tti.system_time); - - time->user = tval2msec(utime); - time->sys = tval2msec(stime); - time->total = time->user + time->sys; - - return SIGAR_OK; -} -#endif - -int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_time_t *proctime) -{ -#ifdef SIGAR_FREEBSD4 - struct user user; -#endif - int status = sigar_get_pinfo(sigar, pid); - bsd_pinfo_t *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - -#if defined(DARWIN) - if ((status = get_proc_times(sigar, pid, proctime)) != SIGAR_OK) { - return status; - } - proctime->start_time = tv2msec(pinfo->KI_START); -#elif defined(SIGAR_FREEBSD5) - proctime->user = tv2msec(pinfo->ki_rusage.ru_utime); - proctime->sys = tv2msec(pinfo->ki_rusage.ru_stime); - proctime->total = proctime->user + proctime->sys; - proctime->start_time = tv2msec(pinfo->KI_START); -#elif defined(SIGAR_FREEBSD4) - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - status = kread(sigar, &user, sizeof(user), - (u_long)pinfo->kp_proc.p_addr); - if (status != SIGAR_OK) { - return status; - } - - proctime->user = tv2msec(user.u_stats.p_ru.ru_utime); - proctime->sys = tv2msec(user.u_stats.p_ru.ru_stime); - proctime->total = proctime->user + proctime->sys; - proctime->start_time = tv2msec(user.u_stats.p_start); -#elif defined(__OpenBSD__) || defined(__NetBSD__) - /* XXX *_usec */ - proctime->user = pinfo->p_uutime_sec * SIGAR_MSEC; - proctime->sys = pinfo->p_ustime_sec * SIGAR_MSEC; - proctime->total = proctime->user + proctime->sys; - proctime->start_time = pinfo->p_ustart_sec * SIGAR_MSEC; -#endif - - return SIGAR_OK; -} - -#ifdef DARWIN -/* thread state mapping derived from ps.tproj */ -static const char const thread_states[] = { - /*0*/ '-', - /*1*/ SIGAR_PROC_STATE_RUN, - /*2*/ SIGAR_PROC_STATE_ZOMBIE, - /*3*/ SIGAR_PROC_STATE_SLEEP, - /*4*/ SIGAR_PROC_STATE_IDLE, - /*5*/ SIGAR_PROC_STATE_STOP, - /*6*/ SIGAR_PROC_STATE_STOP, - /*7*/ '?' -}; - -static int thread_state_get(thread_basic_info_data_t *info) -{ - switch (info->run_state) { - case TH_STATE_RUNNING: - return 1; - case TH_STATE_UNINTERRUPTIBLE: - return 2; - case TH_STATE_WAITING: - return (info->sleep_time > 20) ? 4 : 3; - case TH_STATE_STOPPED: - return 5; - case TH_STATE_HALTED: - return 6; - default: - return 7; - } -} - -static int sigar_proc_threads_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - mach_port_t task, self = mach_task_self(); - kern_return_t status; - thread_array_t threads; - mach_msg_type_number_t count, i; - int state = TH_STATE_HALTED + 1; - - status = task_for_pid(self, pid, &task); - if (status != KERN_SUCCESS) { - return errno; - } - - status = task_threads(task, &threads, &count); - if (status != KERN_SUCCESS) { - return errno; - } - - procstate->threads = count; - - for (i=0; istate = thread_states[state]; - - return SIGAR_OK; -} -#endif - -int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - int status = sigar_get_pinfo(sigar, pid); - bsd_pinfo_t *pinfo = sigar->pinfo; -#if defined(__OpenBSD__) || defined(__NetBSD__) - int state = pinfo->p_stat; -#else - int state = pinfo->KI_STAT; -#endif - - if (status != SIGAR_OK) { - return status; - } - -#if defined(__OpenBSD__) || defined(__NetBSD__) - SIGAR_SSTRCPY(procstate->name, pinfo->p_comm); - procstate->ppid = pinfo->p_ppid; - procstate->priority = pinfo->p_priority; - procstate->nice = pinfo->p_nice; - procstate->tty = pinfo->p_tdev; - procstate->threads = SIGAR_FIELD_NOTIMPL; - procstate->processor = pinfo->p_cpuid; -#else - SIGAR_SSTRCPY(procstate->name, pinfo->KI_COMM); - procstate->ppid = pinfo->KI_PPID; - procstate->priority = pinfo->KI_PRI; - procstate->nice = pinfo->KI_NICE; - procstate->tty = SIGAR_FIELD_NOTIMPL; /*XXX*/ - procstate->threads = SIGAR_FIELD_NOTIMPL; - procstate->processor = SIGAR_FIELD_NOTIMPL; -#endif - -#ifdef DARWIN - status = sigar_proc_threads_get(sigar, pid, procstate); - if (status == SIGAR_OK) { - return status; - } -#endif - - switch (state) { - case SIDL: - procstate->state = 'D'; - break; - case SRUN: -#ifdef SONPROC - case SONPROC: -#endif - procstate->state = 'R'; - break; - case SSLEEP: - procstate->state = 'S'; - break; - case SSTOP: - procstate->state = 'T'; - break; - case SZOMB: - procstate->state = 'Z'; - break; - default: - procstate->state = '?'; - break; - } - - return SIGAR_OK; -} - -#if defined(DARWIN) -typedef struct { - char *buf, *ptr, *end; - int count; -} sigar_kern_proc_args_t; - -static void sigar_kern_proc_args_destroy(sigar_kern_proc_args_t *kargs) -{ - if (kargs->buf) { - free(kargs->buf); - kargs->buf = NULL; - } -} - -/* re-usable hack for use by proc_args and proc_env */ -static int sigar_kern_proc_args_get(sigar_t *sigar, - sigar_pid_t pid, - char *exe, - sigar_kern_proc_args_t *kargs) -{ - /* - * derived from: - * http://darwinsource.opendarwin.org/10.4.1/adv_cmds-79.1/ps.tproj/print.c - */ - int mib[3], len; - size_t size = sigar_argmax_get(sigar); - - kargs->buf = malloc(size); - - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - - if (sysctl(mib, NMIB(mib), kargs->buf, &size, NULL, 0) < 0) { - sigar_kern_proc_args_destroy(kargs); - return errno; - } - - kargs->end = &kargs->buf[size]; - - memcpy(&kargs->count, kargs->buf, sizeof(kargs->count)); - kargs->ptr = kargs->buf + sizeof(kargs->count); - - len = strlen(kargs->ptr); - if (exe) { - memcpy(exe, kargs->ptr, len+1); - } - kargs->ptr += len+1; - - if (kargs->ptr == kargs->end) { - sigar_kern_proc_args_destroy(kargs); - return exe ? SIGAR_OK : ENOENT; - } - - for (; kargs->ptr < kargs->end; kargs->ptr++) { - if (*kargs->ptr != '\0') { - break; /* start of argv[0] */ - } - } - - if (kargs->ptr == kargs->end) { - sigar_kern_proc_args_destroy(kargs); - return exe ? SIGAR_OK : ENOENT; - } - - return SIGAR_OK; -} - -static int kern_proc_args_skip_argv(sigar_kern_proc_args_t *kargs) -{ - char *ptr = kargs->ptr; - char *end = kargs->end; - int count = kargs->count; - - /* skip over argv */ - while ((ptr < end) && (count-- > 0)) { - int alen = strlen(ptr)+1; - - ptr += alen; - } - - kargs->ptr = ptr; - kargs->end = end; - kargs->count = 0; - - if (ptr >= end) { - return ENOENT; - } - - return SIGAR_OK; -} -#endif - -int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ -#if defined(DARWIN) - int status, count; - sigar_kern_proc_args_t kargs; - char *ptr, *end; - - status = sigar_kern_proc_args_get(sigar, pid, NULL, &kargs); - if (status != SIGAR_OK) { - return status; - } - - count = kargs.count; - ptr = kargs.ptr; - end = kargs.end; - - while ((ptr < end) && (count-- > 0)) { - int slen = strlen(ptr); - int alen = slen+1; - char *arg; - - /* - * trim trailing whitespace. - * seen w/ postgresql, probably related - * to messing with argv[0] - */ - while (*(ptr + (slen-1)) == ' ') { - if (--slen <= 0) { - break; - } - } - - arg = malloc(slen+1); - - SIGAR_PROC_ARGS_GROW(procargs); - memcpy(arg, ptr, slen); - *(arg+slen) = '\0'; - - procargs->data[procargs->number++] = arg; - - ptr += alen; - } - - sigar_kern_proc_args_destroy(&kargs); - return SIGAR_OK; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - char buffer[SIGAR_ARG_MAX+1], *ptr=buffer; - size_t len = sizeof(buffer); -# ifdef __NetBSD__ - int mib[] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ARGV }; - mib[2] = pid; -# else - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, 0 }; - mib[3] = pid; -# endif - - if (sysctl(mib, NMIB(mib), buffer, &len, NULL, 0) < 0) { - return errno; - } - - if (len == 0) { - procargs->number = 0; - return SIGAR_OK; - } - - buffer[len] = '\0'; - - while (len > 0) { - int alen = strlen(ptr)+1; - char *arg = malloc(alen); - - SIGAR_PROC_ARGS_GROW(procargs); - memcpy(arg, ptr, alen); - - procargs->data[procargs->number++] = arg; - - len -= alen; - if (len > 0) { - ptr += alen; - } - } - - return SIGAR_OK; -#elif defined(__OpenBSD__) - char buffer[SIGAR_ARG_MAX+1], **ptr=(char **)buffer; - size_t len = sizeof(buffer); - int mib[] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ARGV }; - mib[2] = pid; - - if (sysctl(mib, NMIB(mib), buffer, &len, NULL, 0) < 0) { - return errno; - } - - if (len == 0) { - procargs->number = 0; - return SIGAR_OK; - } - - for (; *ptr; ptr++) { - int alen = strlen(*ptr)+1; - char *arg = malloc(alen); - - SIGAR_PROC_ARGS_GROW(procargs); - memcpy(arg, *ptr, alen); - - procargs->data[procargs->number++] = arg; - } - - return SIGAR_OK; -#else - return SIGAR_ENOTIMPL; -#endif -} - -int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ -#ifdef DARWIN - int status, count; - sigar_kern_proc_args_t kargs; - char *ptr, *end; - - status = sigar_kern_proc_args_get(sigar, pid, NULL, &kargs); - if (status != SIGAR_OK) { - return status; - } - - status = kern_proc_args_skip_argv(&kargs); - if (status != SIGAR_OK) { - sigar_kern_proc_args_destroy(&kargs); - return status; - } - - count = kargs.count; - ptr = kargs.ptr; - end = kargs.end; - - /* into environ */ - while (ptr < end) { - char *val = strchr(ptr, '='); - int klen, vlen, status; - char key[256]; /* XXX is there a max key size? */ - - if (val == NULL) { - /* not key=val format */ - break; - } - - klen = val - ptr; - SIGAR_SSTRCPY(key, ptr); - key[klen] = '\0'; - ++val; - - vlen = strlen(val); - status = procenv->env_getter(procenv->data, - key, klen, val, vlen); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - - ptr += (klen + 1 + vlen + 1); - - if (*ptr == '\0') { - break; - } - } - - sigar_kern_proc_args_destroy(&kargs); - return SIGAR_OK; -#else - char **env; - struct kinfo_proc *pinfo; - int num; - - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - pinfo = kvm_getprocs(sigar->kmem, KERN_PROC_PID, pid, &num); - if (!pinfo || (num < 1)) { - return errno; - } - - if (!(env = kvm_getenvv(sigar->kmem, pinfo, 9086))) { - return errno; - } - - while (*env) { - char *ptr = *env++; - char *val = strchr(ptr, '='); - int klen, vlen, status; - char key[128]; /* XXX is there a max key size? */ - - if (val == NULL) { - /* not key=val format */ - procenv->env_getter(procenv->data, ptr, strlen(ptr), NULL, 0); - break; - } - - klen = val - ptr; - SIGAR_SSTRCPY(key, ptr); - key[klen] = '\0'; - ++val; - - vlen = strlen(val); - status = procenv->env_getter(procenv->data, - key, klen, val, vlen); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - - ptr += (klen + 1 + vlen + 1); - } - - return SIGAR_OK; -#endif -} - -int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_fd_t *procfd) -{ -#ifdef __FreeBSD__ - int status; - bsd_pinfo_t *pinfo; - struct filedesc filed; -#if 0 - struct file **ofiles; - int nfiles, i; - size_t size; -#endif - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - if ((status = sigar_get_pinfo(sigar, pid)) != SIGAR_OK) { - return status; - } - pinfo = sigar->pinfo; - - status = kread(sigar, &filed, sizeof(filed), (u_long)pinfo->KI_FD); - if (status != SIGAR_OK) { - return status; - } -#if 0 - nfiles = filed.fd_lastfile+1; - size = sizeof(*ofiles) * nfiles; - ofiles = malloc(size); - status = kread(sigar, ofiles, size, (u_long)filed.fd_ofiles); - if (status != SIGAR_OK) { - free(ofiles); - return status; - } - - procfd->total = 0; - for (i=0; itotal++; - } - - free(ofiles); -#else - /* seems the same as the above */ - procfd->total = filed.fd_lastfile; -#endif - - return SIGAR_OK; -#else - return SIGAR_ENOTIMPL; -#endif -} - -int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ -#ifdef DARWIN - int status; - sigar_kern_proc_args_t kargs; - - status = sigar_kern_proc_args_get(sigar, pid, procexe->name, &kargs); - if (status != SIGAR_OK) { - return status; - } - - procexe->cwd[0] = '\0'; - procexe->root[0] = '\0'; - - /* attempt to determine cwd from $PWD */ - status = kern_proc_args_skip_argv(&kargs); - if (status == SIGAR_OK) { - char *ptr = kargs.ptr; - char *end = kargs.end; - - /* into environ */ - while (ptr < end) { - int len = strlen(ptr); - - if ((len > 4) && - (ptr[0] == 'P') && - (ptr[1] == 'W') && - (ptr[2] == 'D') && - (ptr[3] == '=')) - { - memcpy(procexe->cwd, ptr+4, len-3); - break; - } - - ptr += len+1; - } - } - - sigar_kern_proc_args_destroy(&kargs); - - return SIGAR_OK; -#else - int len; - char name[1024]; - - procexe->cwd[0] = '\0'; - procexe->root[0] = '\0'; - - (void)SIGAR_PROC_FILENAME(name, pid, "/file"); - - if ((len = readlink(name, procexe->name, - sizeof(procexe->name)-1)) < 0) - { - return PROCFS_STATUS(errno); - } - - procexe->name[len] = '\0'; - - return SIGAR_OK; -#endif -} - -#ifdef DARWIN -static int sigar_dlinfo_modules(sigar_t *sigar, sigar_proc_modules_t *procmods) -{ - uint32_t i, count = _dyld_image_count(); - - for (i=0; imodule_getter(procmods->data, - (char *)name, strlen(name)); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - } - return SIGAR_OK; -} -#endif /* DARWIN */ - -int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods) -{ -#if defined(SIGAR_HAS_DLINFO_MODULES) || defined(DARWIN) - if (pid == sigar_pid_get(sigar)) { - return sigar_dlinfo_modules(sigar, procmods); - } -#endif - return SIGAR_ENOTIMPL; -} - -#define SIGAR_MICROSEC2NANO(s) \ - ((sigar_uint64_t)(s) * (sigar_uint64_t)1000) - -#define TIME_NSEC(t) \ - (SIGAR_SEC2NANO((t).tv_sec) + SIGAR_MICROSEC2NANO((t).tv_usec)) - -int sigar_thread_cpu_get(sigar_t *sigar, - sigar_uint64_t id, - sigar_thread_cpu_t *cpu) -{ -#if defined(DARWIN) - mach_port_t self = mach_thread_self(); - thread_basic_info_data_t info; - mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; - kern_return_t status; - - status = thread_info(self, THREAD_BASIC_INFO, - (thread_info_t)&info, &count); - if (status != KERN_SUCCESS) { - return errno; - } - - mach_port_deallocate(mach_task_self(), self); - - cpu->user = tval2nsec(info.user_time); - cpu->sys = tval2nsec(info.system_time); - cpu->total = cpu->user + cpu->sys; -#elif defined(__NetBSD__) - return SIGAR_ENOTIMPL; /* http://tinyurl.com/chbvln */ -#else - /* XXX this is not per-thread, it is for the whole-process. - * just want to use for the shell time command at the moment. - */ - struct rusage usage; - getrusage(RUSAGE_SELF, &usage); - - cpu->user = TIME_NSEC(usage.ru_utime); - cpu->sys = TIME_NSEC(usage.ru_stime); - cpu->total = TIME_NSEC(usage.ru_utime) + TIME_NSEC(usage.ru_stime); -#endif - - return SIGAR_OK; -} - -int sigar_os_fs_type_get(sigar_file_system_t *fsp) -{ - char *type = fsp->sys_type_name; - - /* see sys/disklabel.h */ - switch (*type) { - case 'f': - if (strEQ(type, "ffs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'h': - if (strEQ(type, "hfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'u': - if (strEQ(type, "ufs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - } - - return fsp->type; -} - -static void get_fs_options(char *opts, int osize, long flags) -{ - *opts = '\0'; - if (flags & MNT_RDONLY) strncat(opts, "ro", osize); - else strncat(opts, "rw", osize); - if (flags & MNT_SYNCHRONOUS) strncat(opts, ",sync", osize); - if (flags & MNT_NOEXEC) strncat(opts, ",noexec", osize); - if (flags & MNT_NOSUID) strncat(opts, ",nosuid", osize); -#ifdef MNT_NODEV - if (flags & MNT_NODEV) strncat(opts, ",nodev", osize); -#endif -#ifdef MNT_UNION - if (flags & MNT_UNION) strncat(opts, ",union", osize); -#endif - if (flags & MNT_ASYNC) strncat(opts, ",async", osize); -#ifdef MNT_NOATIME - if (flags & MNT_NOATIME) strncat(opts, ",noatime", osize); -#endif -#ifdef MNT_NOCLUSTERR - if (flags & MNT_NOCLUSTERR) strncat(opts, ",noclusterr", osize); -#endif -#ifdef MNT_NOCLUSTERW - if (flags & MNT_NOCLUSTERW) strncat(opts, ",noclusterw", osize); -#endif -#ifdef MNT_NOSYMFOLLOW - if (flags & MNT_NOSYMFOLLOW) strncat(opts, ",nosymfollow", osize); -#endif -#ifdef MNT_SUIDDIR - if (flags & MNT_SUIDDIR) strncat(opts, ",suiddir", osize); -#endif -#ifdef MNT_SOFTDEP - if (flags & MNT_SOFTDEP) strncat(opts, ",soft-updates", osize); -#endif - if (flags & MNT_LOCAL) strncat(opts, ",local", osize); - if (flags & MNT_QUOTA) strncat(opts, ",quota", osize); - if (flags & MNT_ROOTFS) strncat(opts, ",rootfs", osize); -#ifdef MNT_USER - if (flags & MNT_USER) strncat(opts, ",user", osize); -#endif -#ifdef MNT_IGNORE - if (flags & MNT_IGNORE) strncat(opts, ",ignore", osize); -#endif - if (flags & MNT_EXPORTED) strncat(opts, ",nfs", osize); -} - -#ifdef __NetBSD__ -#define sigar_statfs statvfs -#define sigar_getfsstat getvfsstat -#define sigar_f_flags f_flag -#else -#define sigar_statfs statfs -#define sigar_getfsstat getfsstat -#define sigar_f_flags f_flags -#endif - -int sigar_file_system_list_get(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - struct sigar_statfs *fs; - int num, i; - int is_debug = SIGAR_LOG_IS_DEBUG(sigar); - long len; - - if ((num = sigar_getfsstat(NULL, 0, MNT_NOWAIT)) < 0) { - return errno; - } - - len = sizeof(*fs) * num; - fs = malloc(len); - - if ((num = sigar_getfsstat(fs, len, MNT_NOWAIT)) < 0) { - free(fs); - return errno; - } - - sigar_file_system_list_create(fslist); - - for (i=0; idata[fslist->number++]; - - SIGAR_SSTRCPY(fsp->dir_name, fs[i].f_mntonname); - SIGAR_SSTRCPY(fsp->dev_name, fs[i].f_mntfromname); - SIGAR_SSTRCPY(fsp->sys_type_name, fs[i].f_fstypename); - get_fs_options(fsp->options, sizeof(fsp->options)-1, fs[i].sigar_f_flags); - - sigar_fs_type_init(fsp); - } - - free(fs); - return SIGAR_OK; -} - -#ifdef DARWIN -#define IoStatGetValue(key, val) \ - if ((number = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatistics##key)))) \ - CFNumberGetValue(number, kCFNumberSInt64Type, &val) -#endif - -int sigar_disk_usage_get(sigar_t *sigar, const char *name, - sigar_disk_usage_t *disk) -{ -#if defined(DARWIN) - kern_return_t status; - io_registry_entry_t parent; - io_service_t service; - CFDictionaryRef props; - CFNumberRef number; - sigar_iodev_t *iodev = sigar_iodev_get(sigar, name); - char dname[256], *ptr; - - SIGAR_DISK_STATS_INIT(disk); - - if (!iodev) { - return ENXIO; - } - - /* "/dev/disk0s1" -> "disk0" */ /* XXX better way? */ - ptr = &iodev->name[SSTRLEN(SIGAR_DEV_PREFIX)]; - SIGAR_SSTRCPY(dname, ptr); - ptr = dname; - if (strnEQ(ptr, "disk", 4)) { - ptr += 4; - if ((ptr = strchr(ptr, 's')) && isdigit(*(ptr+1))) { - *ptr = '\0'; - } - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[disk_usage] map %s -> %s", - iodev->name, dname); - } - - /* e.g. name == "disk0" */ - service = IOServiceGetMatchingService(kIOMasterPortDefault, - IOBSDNameMatching(kIOMasterPortDefault, 0, dname)); - - if (!service) { - return errno; - } - - status = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); - if (status != KERN_SUCCESS) { - IOObjectRelease(service); - return status; - } - - status = IORegistryEntryCreateCFProperties(parent, - (CFMutableDictionaryRef *)&props, - kCFAllocatorDefault, - kNilOptions); - if (props) { - CFDictionaryRef stats = - (CFDictionaryRef)CFDictionaryGetValue(props, - CFSTR(kIOBlockStorageDriverStatisticsKey)); - - if (stats) { - IoStatGetValue(ReadsKey, disk->reads); - IoStatGetValue(BytesReadKey, disk->read_bytes); - IoStatGetValue(TotalReadTimeKey, disk->rtime); - IoStatGetValue(WritesKey, disk->writes); - IoStatGetValue(BytesWrittenKey, disk->write_bytes); - IoStatGetValue(TotalWriteTimeKey, disk->wtime); - disk->time = disk->rtime + disk->wtime; - } - - CFRelease(props); - } - - IOObjectRelease(service); - IOObjectRelease(parent); - - return SIGAR_OK; -#elif defined(__FreeBSD__) - /* XXX incomplete */ - struct sigar_statfs buf; - - if (sigar_statfs(name, &buf) < 0) { - return errno; - } - - SIGAR_DISK_STATS_INIT(disk); - - disk->reads = buf.f_syncreads + buf.f_asyncreads; - disk->writes = buf.f_syncwrites + buf.f_asyncwrites; - return SIGAR_OK; -#else - SIGAR_DISK_STATS_INIT(disk); - return SIGAR_ENOTIMPL; -#endif -} - -int sigar_file_system_usage_get(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage) -{ - int status = sigar_statvfs(sigar, dirname, fsusage); - - if (status != SIGAR_OK) { - return status; - } - - fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage); - - sigar_disk_usage_get(sigar, dirname, &fsusage->disk); - - return SIGAR_OK; -} - -#ifdef DARWIN -#define CTL_HW_FREQ_MAX "hw.cpufrequency_max" -#define CTL_HW_FREQ_MIN "hw.cpufrequency_min" -#else -/* XXX FreeBSD 5.x+ only? */ -#define CTL_HW_FREQ "machdep.tsc_freq" -#endif - -int sigar_cpu_info_list_get(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos) -{ - int i; - unsigned int mhz, mhz_min, mhz_max; - int cache_size=SIGAR_FIELD_NOTIMPL; - size_t size; - char model[128], vendor[128], *ptr; - - size = sizeof(mhz); - - (void)sigar_cpu_core_count(sigar); - -#if defined(DARWIN) - { - int mib[] = { CTL_HW, HW_CPU_FREQ }; - size = sizeof(mhz); - if (sysctl(mib, NMIB(mib), &mhz, &size, NULL, 0) < 0) { - mhz = SIGAR_FIELD_NOTIMPL; - } - } - if (sysctlbyname(CTL_HW_FREQ_MAX, &mhz_max, &size, NULL, 0) < 0) { - mhz_max = SIGAR_FIELD_NOTIMPL; - } - if (sysctlbyname(CTL_HW_FREQ_MIN, &mhz_min, &size, NULL, 0) < 0) { - mhz_min = SIGAR_FIELD_NOTIMPL; - } -#elif defined(__FreeBSD__) - if (sysctlbyname(CTL_HW_FREQ, &mhz, &size, NULL, 0) < 0) { - mhz = SIGAR_FIELD_NOTIMPL; - } - /* TODO */ - mhz_max = SIGAR_FIELD_NOTIMPL; - mhz_min = SIGAR_FIELD_NOTIMPL; -#else - /*XXX OpenBSD*/ - mhz = SIGAR_FIELD_NOTIMPL; - mhz_max = SIGAR_FIELD_NOTIMPL; - mhz_min = SIGAR_FIELD_NOTIMPL; -#endif - - if (mhz != SIGAR_FIELD_NOTIMPL) { - mhz /= 1000000; - } - if (mhz_max != SIGAR_FIELD_NOTIMPL) { - mhz_max /= 1000000; - } - if (mhz_min != SIGAR_FIELD_NOTIMPL) { - mhz_min /= 1000000; - } - - size = sizeof(model); -#ifdef __OpenBSD__ - if (1) { -#else - if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) { -#endif - int mib[] = { CTL_HW, HW_MODEL }; - size = sizeof(model); - if (sysctl(mib, NMIB(mib), &model[0], &size, NULL, 0) < 0) { -#ifdef DARWIN - strcpy(model, "powerpc"); -#else - strcpy(model, "Unknown"); -#endif - } - } - - if (mhz == SIGAR_FIELD_NOTIMPL) { - /* freebsd4 */ - mhz = sigar_cpu_mhz_from_model(model); - } - /* XXX not sure */ - if (mhz_max == SIGAR_FIELD_NOTIMPL) { - mhz_max = 0; - } - if (mhz_min == SIGAR_FIELD_NOTIMPL) { - mhz_min = 0; - } - - -#ifdef DARWIN - size = sizeof(vendor); - if (sysctlbyname("machdep.cpu.vendor", &vendor, &size, NULL, 0) < 0) { - SIGAR_SSTRCPY(vendor, "Apple"); - } - else { - /* GenuineIntel -> Intel */ - if (strstr(vendor, "Intel")) { - SIGAR_SSTRCPY(vendor, "Intel"); - } - } -#endif - - if ((ptr = strchr(model, ' '))) { - if (strstr(model, "Intel")) { - SIGAR_SSTRCPY(vendor, "Intel"); - } - else if (strstr(model, "AMD")) { - SIGAR_SSTRCPY(vendor, "AMD"); - } - else { - SIGAR_SSTRCPY(vendor, "Unknown"); - } - SIGAR_SSTRCPY(model, ptr+1); - } - -#ifdef DARWIN - { - int mib[] = { CTL_HW, HW_L2CACHESIZE }; /* in bytes */ - size = sizeof(cache_size); - if (sysctl(mib, NMIB(mib), &cache_size, &size, NULL, 0) < 0) { - cache_size = SIGAR_FIELD_NOTIMPL; - } - else { - cache_size /= 1024; /* convert to KB */ - } - } -#endif - - sigar_cpu_info_list_create(cpu_infos); - - for (i=0; incpu; i++) { - sigar_cpu_info_t *info; - - SIGAR_CPU_INFO_LIST_GROW(cpu_infos); - - info = &cpu_infos->data[cpu_infos->number++]; - - SIGAR_SSTRCPY(info->vendor, vendor); - SIGAR_SSTRCPY(info->model, model); - sigar_cpu_model_adjust(sigar, info); - - info->mhz = mhz; - info->mhz_max = mhz_max; - info->mhz_min = mhz_min; - info->cache_size = cache_size; - info->total_cores = sigar->ncpu; - info->cores_per_socket = sigar->lcpu; - info->total_sockets = sigar_cpu_socket_count(sigar); - } - - return SIGAR_OK; -} - -#define rt_s_addr(sa) ((struct sockaddr_in *)(sa))->sin_addr.s_addr - -#ifndef SA_SIZE -#define SA_SIZE(sa) \ - ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ - sizeof(long) : \ - 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) -#endif - -int sigar_net_route_list_get(sigar_t *sigar, - sigar_net_route_list_t *routelist) -{ - size_t needed; - int bit; - char *buf, *next, *lim; - struct rt_msghdr *rtm; - int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0 }; - - if (sysctl(mib, NMIB(mib), NULL, &needed, NULL, 0) < 0) { - return errno; - } -#if __FreeBSD_version >= 800000 - if (needed == 0) { - return SIGAR_ENOTIMPL; /*XXX hoping this is an 8.0beta bug*/ - } -#endif - buf = malloc(needed); - - if (sysctl(mib, NMIB(mib), buf, &needed, NULL, 0) < 0) { - free(buf); - return errno; - } - - sigar_net_route_list_create(routelist); - - lim = buf + needed; - for (next = buf; next < lim; next += rtm->rtm_msglen) { - struct sockaddr *sa; - sigar_net_route_t *route; - rtm = (struct rt_msghdr *)next; - - if (rtm->rtm_type != RTM_GET) { - continue; - } - - sa = (struct sockaddr *)(rtm + 1); - - if (sa->sa_family != AF_INET) { - continue; - } - - SIGAR_NET_ROUTE_LIST_GROW(routelist); - route = &routelist->data[routelist->number++]; - SIGAR_ZERO(route); - - route->flags = rtm->rtm_flags; - if_indextoname(rtm->rtm_index, route->ifname); - - for (bit=RTA_DST; - bit && ((char *)sa < lim); - bit <<= 1) - { - if ((rtm->rtm_addrs & bit) == 0) { - continue; - } - switch (bit) { - case RTA_DST: - sigar_net_address_set(route->destination, - rt_s_addr(sa)); - break; - case RTA_GATEWAY: - if (sa->sa_family == AF_INET) { - sigar_net_address_set(route->gateway, - rt_s_addr(sa)); - } - break; - case RTA_NETMASK: - sigar_net_address_set(route->mask, - rt_s_addr(sa)); - break; - case RTA_IFA: - break; - } - - sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); - } - } - - free(buf); - - return SIGAR_OK; -} - -typedef enum { - IFMSG_ITER_LIST, - IFMSG_ITER_GET -} ifmsg_iter_e; - -typedef struct { - const char *name; - ifmsg_iter_e type; - union { - sigar_net_interface_list_t *iflist; - struct if_msghdr *ifm; - } data; -} ifmsg_iter_t; - -static int sigar_ifmsg_init(sigar_t *sigar) -{ - int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 }; - size_t len; - - if (sysctl(mib, NMIB(mib), NULL, &len, NULL, 0) < 0) { - return errno; - } - - if (sigar->ifconf_len < len) { - sigar->ifconf_buf = realloc(sigar->ifconf_buf, len); - sigar->ifconf_len = len; - } - - if (sysctl(mib, NMIB(mib), sigar->ifconf_buf, &len, NULL, 0) < 0) { - return errno; - } - - return SIGAR_OK; -} - -/** - * @param name name of the interface - * @param name_len length of name (w/o \0) - */ -static int has_ifaddr(char *name, size_t name_len) -{ - int sock, status; - struct ifreq ifr; - - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - return errno; - } - strncpy(ifr.ifr_name, name, MIN(sizeof(ifr.ifr_name) - 1, name_len)); - ifr.ifr_name[MIN(sizeof(ifr.ifr_name) - 1, name_len)] = '\0'; - if (ioctl(sock, SIOCGIFADDR, &ifr) == 0) { - status = SIGAR_OK; - } - else { - status = errno; - } - - close(sock); - return status; -} - -static int sigar_ifmsg_iter(sigar_t *sigar, ifmsg_iter_t *iter) -{ - char *end = sigar->ifconf_buf + sigar->ifconf_len; - char *ptr = sigar->ifconf_buf; - - if (iter->type == IFMSG_ITER_LIST) { - sigar_net_interface_list_create(iter->data.iflist); - } - - while (ptr < end) { - char *name; - struct sockaddr_dl *sdl; - struct if_msghdr *ifm = (struct if_msghdr *)ptr; - - if (ifm->ifm_type != RTM_IFINFO) { - break; - } - - ptr += ifm->ifm_msglen; - - while (ptr < end) { - struct if_msghdr *next = (struct if_msghdr *)ptr; - - if (next->ifm_type != RTM_NEWADDR) { - break; - } - - ptr += next->ifm_msglen; - } - - sdl = (struct sockaddr_dl *)(ifm + 1); - if (sdl->sdl_family != AF_LINK) { - continue; - } - - switch (iter->type) { - case IFMSG_ITER_LIST: - if (sdl->sdl_type == IFT_OTHER) { - if (has_ifaddr(sdl->sdl_data, sdl->sdl_nlen) != SIGAR_OK) { - break; - } - } - else if (!((sdl->sdl_type == IFT_ETHER) || - (sdl->sdl_type == IFT_LOOP))) - { - break; /* XXX deal w/ other weirdo interfaces */ - } - - SIGAR_NET_IFLIST_GROW(iter->data.iflist); - - /* sdl_data doesn't include a trailing \0, it is only sdl_nlen long */ - name = malloc(sdl->sdl_nlen+1); - memcpy(name, sdl->sdl_data, sdl->sdl_nlen); - name[sdl->sdl_nlen] = '\0'; /* add the missing \0 */ - - iter->data.iflist->data[iter->data.iflist->number++] = name; - break; - - case IFMSG_ITER_GET: - if (strlen(iter->name) == sdl->sdl_nlen && 0 == memcmp(iter->name, sdl->sdl_data, sdl->sdl_nlen)) { - iter->data.ifm = ifm; - return SIGAR_OK; - } - } - } - - switch (iter->type) { - case IFMSG_ITER_LIST: - return SIGAR_OK; - - case IFMSG_ITER_GET: - default: - return ENXIO; - } -} - -int sigar_net_interface_list_get(sigar_t *sigar, - sigar_net_interface_list_t *iflist) -{ - int status; - ifmsg_iter_t iter; - - if ((status = sigar_ifmsg_init(sigar)) != SIGAR_OK) { - return status; - } - - iter.type = IFMSG_ITER_LIST; - iter.data.iflist = iflist; - - return sigar_ifmsg_iter(sigar, &iter); -} - -#include - -/* in6_prefixlen derived from freebsd/sbin/ifconfig/af_inet6.c */ -static int sigar_in6_prefixlen(struct sockaddr *netmask) -{ - struct in6_addr *addr = SIGAR_SIN6_ADDR(netmask); - u_char *name = (u_char *)addr; - int size = sizeof(*addr); - int byte, bit, plen = 0; - - for (byte = 0; byte < size; byte++, plen += 8) { - if (name[byte] != 0xff) { - break; - } - } - if (byte == size) { - return plen; - } - for (bit = 7; bit != 0; bit--, plen++) { - if (!(name[byte] & (1 << bit))) { - break; - } - } - for (; bit != 0; bit--) { - if (name[byte] & (1 << bit)) { - return 0; - } - } - byte++; - for (; byte < size; byte++) { - if (name[byte]) { - return 0; - } - } - return plen; -} - -int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig) -{ - int status = SIGAR_ENOENT; - struct ifaddrs *addrs, *ifa; - - if (getifaddrs(&addrs) != 0) { - return errno; - } - - for (ifa=addrs; ifa; ifa=ifa->ifa_next) { - if (ifa->ifa_addr && - (ifa->ifa_addr->sa_family == AF_INET6) && - strEQ(ifa->ifa_name, name)) - { - status = SIGAR_OK; - break; - } - } - - if (status == SIGAR_OK) { - struct in6_addr *addr = SIGAR_SIN6_ADDR(ifa->ifa_addr); - - sigar_net_address6_set(ifconfig->address6, addr); - sigar_net_interface_scope6_set(ifconfig, addr); - ifconfig->prefix6_length = sigar_in6_prefixlen(ifa->ifa_netmask); - } - - freeifaddrs(addrs); - - return status; -} - -int sigar_net_interface_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig) -{ - int sock; - int status; - ifmsg_iter_t iter; - struct if_msghdr *ifm; - struct sockaddr_dl *sdl; - struct ifreq ifr; - - if (!name) { - return sigar_net_interface_config_primary_get(sigar, ifconfig); - } - - if (sigar->ifconf_len == 0) { - if ((status = sigar_ifmsg_init(sigar)) != SIGAR_OK) { - return status; - } - } - - SIGAR_ZERO(ifconfig); - - iter.type = IFMSG_ITER_GET; - iter.name = name; - - if ((status = sigar_ifmsg_iter(sigar, &iter)) != SIGAR_OK) { - return status; - } - - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - return errno; - } - - ifm = iter.data.ifm; - - SIGAR_SSTRCPY(ifconfig->name, name); - - sdl = (struct sockaddr_dl *)(ifm + 1); - - sigar_net_address_mac_set(ifconfig->hwaddr, - LLADDR(sdl), - sdl->sdl_alen); - - ifconfig->flags = ifm->ifm_flags; - ifconfig->mtu = ifm->ifm_data.ifi_mtu; - ifconfig->metric = ifm->ifm_data.ifi_metric; - - SIGAR_SSTRCPY(ifr.ifr_name, name); - -#define ifr_s_addr(ifr) \ - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr - - if (!ioctl(sock, SIOCGIFADDR, &ifr)) { - sigar_net_address_set(ifconfig->address, - ifr_s_addr(ifr)); - } - - if (!ioctl(sock, SIOCGIFNETMASK, &ifr)) { - sigar_net_address_set(ifconfig->netmask, - ifr_s_addr(ifr)); - } - - if (ifconfig->flags & IFF_LOOPBACK) { - sigar_net_address_set(ifconfig->destination, - ifconfig->address.addr.in); - sigar_net_address_set(ifconfig->broadcast, 0); - SIGAR_SSTRCPY(ifconfig->type, - SIGAR_NIC_LOOPBACK); - } - else { - if (!ioctl(sock, SIOCGIFDSTADDR, &ifr)) { - sigar_net_address_set(ifconfig->destination, - ifr_s_addr(ifr)); - } - - if (!ioctl(sock, SIOCGIFBRDADDR, &ifr)) { - sigar_net_address_set(ifconfig->broadcast, - ifr_s_addr(ifr)); - } - SIGAR_SSTRCPY(ifconfig->type, - SIGAR_NIC_ETHERNET); - } - - close(sock); - - /* XXX can we get a better description like win32? */ - SIGAR_SSTRCPY(ifconfig->description, - ifconfig->name); - - sigar_net_interface_ipv6_config_init(ifconfig); - sigar_net_interface_ipv6_config_get(sigar, name, ifconfig); - - return SIGAR_OK; -} - -int sigar_net_interface_stat_get(sigar_t *sigar, const char *name, - sigar_net_interface_stat_t *ifstat) -{ - int status; - ifmsg_iter_t iter; - struct if_msghdr *ifm; - - if ((status = sigar_ifmsg_init(sigar)) != SIGAR_OK) { - return status; - } - - iter.type = IFMSG_ITER_GET; - iter.name = name; - - if ((status = sigar_ifmsg_iter(sigar, &iter)) != SIGAR_OK) { - return status; - } - - ifm = iter.data.ifm; - - ifstat->rx_bytes = ifm->ifm_data.ifi_ibytes; - ifstat->rx_packets = ifm->ifm_data.ifi_ipackets; - ifstat->rx_errors = ifm->ifm_data.ifi_ierrors; - ifstat->rx_dropped = ifm->ifm_data.ifi_iqdrops; - ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->rx_frame = SIGAR_FIELD_NOTIMPL; - - ifstat->tx_bytes = ifm->ifm_data.ifi_obytes; - ifstat->tx_packets = ifm->ifm_data.ifi_opackets; - ifstat->tx_errors = ifm->ifm_data.ifi_oerrors; - ifstat->tx_collisions = ifm->ifm_data.ifi_collisions; - ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL; - ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL; - - ifstat->speed = ifm->ifm_data.ifi_baudrate; - - return SIGAR_OK; -} - -static int net_connection_state_get(int state) -{ - switch (state) { - case TCPS_CLOSED: - return SIGAR_TCP_CLOSE; - case TCPS_LISTEN: - return SIGAR_TCP_LISTEN; - case TCPS_SYN_SENT: - return SIGAR_TCP_SYN_SENT; - case TCPS_SYN_RECEIVED: - return SIGAR_TCP_SYN_RECV; - case TCPS_ESTABLISHED: - return SIGAR_TCP_ESTABLISHED; - case TCPS_CLOSE_WAIT: - return SIGAR_TCP_CLOSE_WAIT; - case TCPS_FIN_WAIT_1: - return SIGAR_TCP_FIN_WAIT1; - case TCPS_CLOSING: - return SIGAR_TCP_CLOSING; - case TCPS_LAST_ACK: - return SIGAR_TCP_LAST_ACK; - case TCPS_FIN_WAIT_2: - return SIGAR_TCP_FIN_WAIT2; - case TCPS_TIME_WAIT: - return SIGAR_TCP_TIME_WAIT; - default: - return SIGAR_TCP_UNKNOWN; - } -} - -#if defined(__OpenBSD__) || defined(__NetBSD__) -static int net_connection_get(sigar_net_connection_walker_t *walker, int proto) -{ - int status; - int istcp = 0, type; - int flags = walker->flags; - struct inpcbtable table; - struct inpcb *head, *next, *prev; - sigar_t *sigar = walker->sigar; - u_long offset; - - switch (proto) { - case IPPROTO_TCP: - offset = sigar->koffsets[KOFFSET_TCBTABLE]; - istcp = 1; - type = SIGAR_NETCONN_TCP; - break; - case IPPROTO_UDP: - default: - return SIGAR_ENOTIMPL; - } - - - status = kread(sigar, &table, sizeof(table), offset); - - if (status != SIGAR_OK) { - return status; - } - - prev = head = - (struct inpcb *)&CIRCLEQ_FIRST(&((struct inpcbtable *)offset)->inpt_queue); - - next = (struct inpcb *)CIRCLEQ_FIRST(&table.inpt_queue); - - while (next != head) { - struct inpcb inpcb; - struct tcpcb tcpcb; - struct socket socket; - - status = kread(sigar, &inpcb, sizeof(inpcb), (long)next); - prev = next; - next = (struct inpcb *)CIRCLEQ_NEXT(&inpcb, inp_queue); - - kread(sigar, &socket, sizeof(socket), (u_long)inpcb.inp_socket); - - if ((((flags & SIGAR_NETCONN_SERVER) && socket.so_qlimit) || - ((flags & SIGAR_NETCONN_CLIENT) && !socket.so_qlimit))) - { - sigar_net_connection_t conn; - - SIGAR_ZERO(&conn); - - if (istcp) { - kread(sigar, &tcpcb, sizeof(tcpcb), (u_long)inpcb.inp_ppcb); - } - -#ifdef __NetBSD__ - if (inpcb.inp_af == AF_INET6) { - /*XXX*/ - continue; - } -#else - if (inpcb.inp_flags & INP_IPV6) { - sigar_net_address6_set(conn.local_address, - &inpcb.inp_laddr6.s6_addr); - - sigar_net_address6_set(conn.remote_address, - &inpcb.inp_faddr6.s6_addr); - } -#endif - else { - sigar_net_address_set(conn.local_address, - inpcb.inp_laddr.s_addr); - - sigar_net_address_set(conn.remote_address, - inpcb.inp_faddr.s_addr); - } - - conn.local_port = ntohs(inpcb.inp_lport); - conn.remote_port = ntohs(inpcb.inp_fport); - conn.receive_queue = socket.so_rcv.sb_cc; - conn.send_queue = socket.so_snd.sb_cc; - conn.uid = socket.so_pgid; - conn.type = type; - - if (!istcp) { - conn.state = SIGAR_TCP_UNKNOWN; - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - continue; - } - - conn.state = net_connection_state_get(tcpcb.t_state); - - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - } - } - - return SIGAR_OK; -} -#else -static int net_connection_get(sigar_net_connection_walker_t *walker, int proto) -{ - int flags = walker->flags; - int type, istcp = 0; - char *buf; - const char *mibvar; - struct tcpcb *tp = NULL; - struct inpcb *inp; - struct xinpgen *xig, *oxig; - struct xsocket *so; - size_t len; - - switch (proto) { - case IPPROTO_TCP: - mibvar = "net.inet.tcp.pcblist"; - istcp = 1; - type = SIGAR_NETCONN_TCP; - break; - case IPPROTO_UDP: - mibvar = "net.inet.udp.pcblist"; - type = SIGAR_NETCONN_UDP; - break; - default: - mibvar = "net.inet.raw.pcblist"; - type = SIGAR_NETCONN_RAW; - break; - } - - len = 0; - if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { - return errno; - } - if ((buf = malloc(len)) == 0) { - return errno; - } - if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { - free(buf); - return errno; - } - - oxig = xig = (struct xinpgen *)buf; - for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); - xig->xig_len > sizeof(struct xinpgen); - xig = (struct xinpgen *)((char *)xig + xig->xig_len)) - { - if (istcp) { - struct xtcpcb *cb = (struct xtcpcb *)xig; - tp = &cb->xt_tp; - inp = &cb->xt_inp; - so = &cb->xt_socket; - } - else { - struct xinpcb *cb = (struct xinpcb *)xig; - inp = &cb->xi_inp; - so = &cb->xi_socket; - } - - if (so->xso_protocol != proto) { - continue; - } - - if (inp->inp_gencnt > oxig->xig_gen) { - continue; - } - - if ((((flags & SIGAR_NETCONN_SERVER) && so->so_qlimit) || - ((flags & SIGAR_NETCONN_CLIENT) && !so->so_qlimit))) - { - sigar_net_connection_t conn; - - SIGAR_ZERO(&conn); - - if (inp->inp_vflag & INP_IPV6) { - sigar_net_address6_set(conn.local_address, - &inp->in6p_laddr.s6_addr); - - sigar_net_address6_set(conn.remote_address, - &inp->in6p_faddr.s6_addr); - } - else { - sigar_net_address_set(conn.local_address, - inp->inp_laddr.s_addr); - - sigar_net_address_set(conn.remote_address, - inp->inp_faddr.s_addr); - } - - conn.local_port = ntohs(inp->inp_lport); - conn.remote_port = ntohs(inp->inp_fport); - conn.receive_queue = so->so_rcv.sb_cc; - conn.send_queue = so->so_snd.sb_cc; - conn.uid = so->so_pgid; - conn.type = type; - - if (!istcp) { - conn.state = SIGAR_TCP_UNKNOWN; - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - continue; - } - - conn.state = net_connection_state_get(tp->t_state); - - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - } - } - - free(buf); - - return SIGAR_OK; -} -#endif - -int sigar_net_connection_walk(sigar_net_connection_walker_t *walker) -{ - int flags = walker->flags; - int status; - - if (flags & SIGAR_NETCONN_TCP) { - status = net_connection_get(walker, IPPROTO_TCP); - if (status != SIGAR_OK) { - return status; - } - } - if (flags & SIGAR_NETCONN_UDP) { - status = net_connection_get(walker, IPPROTO_UDP); - if (status != SIGAR_OK) { - return status; - } - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_tcp_get(sigar_t *sigar, - sigar_tcp_t *tcp) -{ - struct tcpstat mib; -#if !defined(TCPCTL_STATS) && (defined(__OpenBSD__) || defined(__NetBSD__)) - int status = - kread(sigar, &mib, sizeof(mib), - sigar->koffsets[KOFFSET_TCPSTAT]); - if (status != SIGAR_OK) { - return status; - } -#else - int var[4] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_STATS }; - size_t len = sizeof(mib); - - if (sysctl(var, NMIB(var), &mib, &len, NULL, 0) < 0) { - return errno; - } -#endif - - tcp->active_opens = mib.tcps_connattempt; - tcp->passive_opens = mib.tcps_accepts; - tcp->attempt_fails = mib.tcps_conndrops; - tcp->estab_resets = mib.tcps_drops; - if (sigar_tcp_curr_estab(sigar, tcp) != SIGAR_OK) { - tcp->curr_estab = -1; - } - tcp->in_segs = mib.tcps_rcvtotal; - tcp->out_segs = mib.tcps_sndtotal - mib.tcps_sndrexmitpack; - tcp->retrans_segs = mib.tcps_sndrexmitpack; - tcp->in_errs = - mib.tcps_rcvbadsum + - mib.tcps_rcvbadoff + - mib.tcps_rcvmemdrop + - mib.tcps_rcvshort; - tcp->out_rsts = -1; /* XXX mib.tcps_sndctrl - mib.tcps_closed; ? */ - - return SIGAR_OK; -} - -#ifndef SIGAR_FREEBSD5_NFSSTAT -static int get_nfsstats(struct nfsstats *stats) -{ - size_t len = sizeof(*stats); - int mib[] = { CTL_VFS, 2, NFS_NFSSTATS }; - - if (sysctl(mib, NMIB(mib), stats, &len, NULL, 0) < 0) { - return errno; - } - else { - return SIGAR_OK; - } -} -#endif - -#if defined(__OpenBSD__) -typedef uint64_t rpc_cnt_t; -#else -typedef int rpc_cnt_t; -#endif - -static void map_nfs_stats(sigar_nfs_v3_t *nfs, rpc_cnt_t *rpc) -{ - nfs->null = rpc[NFSPROC_NULL]; - nfs->getattr = rpc[NFSPROC_GETATTR]; - nfs->setattr = rpc[NFSPROC_SETATTR]; - nfs->lookup = rpc[NFSPROC_LOOKUP]; - nfs->access = rpc[NFSPROC_ACCESS]; - nfs->readlink = rpc[NFSPROC_READLINK]; - nfs->read = rpc[NFSPROC_READ]; - nfs->write = rpc[NFSPROC_WRITE]; - nfs->create = rpc[NFSPROC_CREATE]; - nfs->mkdir = rpc[NFSPROC_MKDIR]; - nfs->symlink = rpc[NFSPROC_SYMLINK]; - nfs->mknod = rpc[NFSPROC_MKNOD]; - nfs->remove = rpc[NFSPROC_REMOVE]; - nfs->rmdir = rpc[NFSPROC_RMDIR]; - nfs->rename = rpc[NFSPROC_RENAME]; - nfs->link = rpc[NFSPROC_LINK]; - nfs->readdir = rpc[NFSPROC_READDIR]; - nfs->readdirplus = rpc[NFSPROC_READDIRPLUS]; - nfs->fsstat = rpc[NFSPROC_FSSTAT]; - nfs->fsinfo = rpc[NFSPROC_FSINFO]; - nfs->pathconf = rpc[NFSPROC_PATHCONF]; - nfs->commit = rpc[NFSPROC_COMMIT]; -} - -int sigar_nfs_client_v2_get(sigar_t *sigar, - sigar_nfs_client_v2_t *nfs) -{ - return SIGAR_ENOTIMPL; -} - -int sigar_nfs_server_v2_get(sigar_t *sigar, - sigar_nfs_server_v2_t *nfs) -{ - return SIGAR_ENOTIMPL; -} - -int sigar_nfs_client_v3_get(sigar_t *sigar, - sigar_nfs_client_v3_t *nfs) -{ -#ifdef SIGAR_FREEBSD5_NFSSTAT - struct nfsstats stats; - size_t size = sizeof(stats); - - if (sysctlbyname("vfs.nfs.nfsstats", &stats, &size, NULL, 0) == -1) { - return errno; - } - - map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.rpccnt[0]); -#else - int status; - struct nfsstats stats; - - if ((status = get_nfsstats(&stats)) != SIGAR_OK) { - return status; - } - - map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.rpccnt[0]); -#endif - - return SIGAR_OK; -} - -int sigar_nfs_server_v3_get(sigar_t *sigar, - sigar_nfs_server_v3_t *nfs) -{ -#ifdef SIGAR_FREEBSD5_NFSSTAT - struct nfsrvstats stats; - size_t size = sizeof(stats); - - if (sysctlbyname("vfs.nfsrv.nfsrvstats", &stats, &size, NULL, 0) == -1) { - return errno; - } - - map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.srvrpccnt[0]); -#else - int status; - struct nfsstats stats; - - if ((status = get_nfsstats(&stats)) != SIGAR_OK) { - return status; - } - - map_nfs_stats((sigar_nfs_v3_t *)nfs, &stats.srvrpccnt[0]); -#endif - - return SIGAR_OK; -} - -static char *get_hw_type(int type) -{ - switch (type) { - case IFT_ETHER: - return "ether"; - case IFT_ISO88025: - return "tr"; - case IFT_FDDI: - return "fddi"; - case IFT_ATM: - return "atm"; - case IFT_L2VLAN: - return "vlan"; - case IFT_IEEE1394: - return "firewire"; -#ifdef IFT_BRIDGE - case IFT_BRIDGE: - return "bridge"; -#endif - default: - return "unknown"; - } -} - -int sigar_arp_list_get(sigar_t *sigar, - sigar_arp_list_t *arplist) -{ - size_t needed; - char *lim, *buf, *next; - struct rt_msghdr *rtm; - struct sockaddr_inarp *sin; - struct sockaddr_dl *sdl; - int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO }; - - if (sysctl(mib, NMIB(mib), NULL, &needed, NULL, 0) < 0) { - return errno; - } - - if (needed == 0) { /* empty cache */ - return 0; - } - - buf = malloc(needed); - - if (sysctl(mib, NMIB(mib), buf, &needed, NULL, 0) < 0) { - free(buf); - return errno; - } - - sigar_arp_list_create(arplist); - - lim = buf + needed; - for (next = buf; next < lim; next += rtm->rtm_msglen) { - sigar_arp_t *arp; - - SIGAR_ARP_LIST_GROW(arplist); - arp = &arplist->data[arplist->number++]; - - rtm = (struct rt_msghdr *)next; - sin = (struct sockaddr_inarp *)(rtm + 1); - sdl = (struct sockaddr_dl *)((char *)sin + SA_SIZE(sin)); - - sigar_net_address_set(arp->address, sin->sin_addr.s_addr); - sigar_net_address_mac_set(arp->hwaddr, LLADDR(sdl), sdl->sdl_alen); - if_indextoname(sdl->sdl_index, arp->ifname); - arp->flags = rtm->rtm_flags; - - SIGAR_SSTRCPY(arp->type, get_hw_type(sdl->sdl_type)); - } - - free(buf); - - return SIGAR_OK; -} - -#if defined(__FreeBSD__) && /*XXX*/ (__FreeBSD_version < 800000) - -#define _KERNEL -#include -#undef _KERNEL - -/* derived from - * /usr/ports/security/pidentd/work/pidentd-3.0.16/src/k_freebsd2.c - */ -int sigar_proc_port_get(sigar_t *sigar, int protocol, - unsigned long port, sigar_pid_t *pid) -{ - struct nlist nl[2]; - struct inpcbhead tcb; - struct socket *sockp = NULL; - struct kinfo_proc *pinfo; - struct inpcb *head, pcbp; - int i, nentries, status; - - if (protocol != SIGAR_NETCONN_TCP) { - return SIGAR_ENOTIMPL; - } - - if (!sigar->kmem) { - return SIGAR_EPERM_KMEM; - } - - nl[0].n_name = "_tcb"; /* XXX cache */ - nl[1].n_name = ""; - if (kvm_nlist(sigar->kmem, nl) < 0) { - return errno; - } - - status = kread(sigar, &tcb, sizeof(tcb), nl[0].n_value); - if (status != SIGAR_OK) { - return status; - } - - for (head = tcb.lh_first; head != NULL; - head = pcbp.inp_list.le_next) - { - status = kread(sigar, &pcbp, sizeof(pcbp), (long)head); - if (status != SIGAR_OK) { - return status; - } - if (!(pcbp.inp_vflag & INP_IPV4)) { - continue; - } - if (pcbp.inp_fport != 0) { - continue; - } - if (ntohs(pcbp.inp_lport) == port) { - sockp = pcbp.inp_socket; - break; - } - } - - if (!sockp) { - return ENOENT; - } - - pinfo = kvm_getprocs(sigar->kmem, KERN_PROC_PROC, 0, &nentries); - if (!pinfo) { - return errno; - } - - for (i=0; ilibproc) { - return SIGAR_ENOTIMPL; - } - - status = sigar_proc_list_get(sigar, &pids); - if (status != SIGAR_OK) { - return status; - } - - for (i=0; iifconf_buf; - - for (n=0; nproc_fdtype != PROX_FDTYPE_SOCKET) { - continue; - } - rsize = sigar->proc_pidfdinfo(pids.data[i], fdp->proc_fd, - PROC_PIDFDSOCKETINFO, &si, sizeof(si)); - if (rsize != sizeof(si)) { - continue; - } - if (si.psi.soi_kind != SOCKINFO_TCP) { - continue; - } - if (si.psi.soi_proto.pri_tcp.tcpsi_state != TSI_S_LISTEN) { - continue; - } - family = si.psi.soi_family; - if (!((family == AF_INET) || (family == AF_INET6))) { - continue; - } - lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport); - if (lport == port) { - *pid = pids.data[i]; - found = 1; - break; - } - } - } - - sigar_proc_list_destroy(sigar, &pids); - - return found ? SIGAR_OK : ENOENT; -} - -#else - -int sigar_proc_port_get(sigar_t *sigar, int protocol, - unsigned long port, sigar_pid_t *pid) -{ - return SIGAR_ENOTIMPL; -} - -#endif - -int sigar_os_sys_info_get(sigar_t *sigar, - sigar_sys_info_t *sysinfo) -{ -#ifdef DARWIN - char *codename = NULL; - SInt32 version, version_major, version_minor, version_fix; - - SIGAR_SSTRCPY(sysinfo->name, "MacOSX"); - SIGAR_SSTRCPY(sysinfo->vendor_name, "Mac OS X"); - SIGAR_SSTRCPY(sysinfo->vendor, "Apple"); - - if (Gestalt(gestaltSystemVersion, &version) == noErr) { - if (version >= 0x00001040) { - Gestalt('sys1' /*gestaltSystemVersionMajor*/, &version_major); - Gestalt('sys2' /*gestaltSystemVersionMinor*/, &version_minor); - Gestalt('sys3' /*gestaltSystemVersionBugFix*/, &version_fix); - } - else { - version_fix = version & 0xf; - version >>= 4; - version_minor = version & 0xf; - version >>= 4; - version_major = version - (version >> 4) * 6; - } - } - else { - return SIGAR_ENOTIMPL; - } - - snprintf(sysinfo->vendor_version, - sizeof(sysinfo->vendor_version), - "%d.%d", - (int)version_major, (int)version_minor); - - snprintf(sysinfo->version, - sizeof(sysinfo->version), - "%s.%d", - sysinfo->vendor_version, (int)version_fix); - - if (version_major == 10) { - switch (version_minor) { - case 2: - codename = "Jaguar"; - break; - case 3: - codename = "Panther"; - break; - case 4: - codename = "Tiger"; - break; - case 5: - codename = "Leopard"; - break; - case 6: - codename = "Snow Leopard"; - break; - case 7: - codename = "Lion"; - break; - default: - codename = "Unknown"; - break; - } - } - else { - return SIGAR_ENOTIMPL; - } - - SIGAR_SSTRCPY(sysinfo->vendor_code_name, codename); - - snprintf(sysinfo->description, - sizeof(sysinfo->description), - "%s %s", - sysinfo->vendor_name, sysinfo->vendor_code_name); -#else - char *ptr; - -#if defined(__FreeBSD__) - SIGAR_SSTRCPY(sysinfo->name, "FreeBSD"); -#elif defined(__OpenBSD__) - SIGAR_SSTRCPY(sysinfo->name, "OpenBSD"); -#elif defined(__NetBSD__) - SIGAR_SSTRCPY(sysinfo->name, "NetBSD"); -#else - SIGAR_SSTRCPY(sysinfo->name, "Unknown"); -#endif - SIGAR_SSTRCPY(sysinfo->vendor_name, sysinfo->name); - SIGAR_SSTRCPY(sysinfo->vendor, sysinfo->name); - SIGAR_SSTRCPY(sysinfo->vendor_version, - sysinfo->version); - - if ((ptr = strstr(sysinfo->vendor_version, "-"))) { - /* STABLE, RELEASE, CURRENT */ - *ptr++ = '\0'; - SIGAR_SSTRCPY(sysinfo->vendor_code_name, ptr); - } - - snprintf(sysinfo->description, - sizeof(sysinfo->description), - "%s %s", - sysinfo->name, sysinfo->version); -#endif - - return SIGAR_OK; -} diff --git a/vendor/sigar/src/os/darwin/sigar_os.h b/vendor/sigar/src/os/darwin/sigar_os.h deleted file mode 100644 index ee00100..0000000 --- a/vendor/sigar/src/os/darwin/sigar_os.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2004-2006, 2008 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_OS_H -#define SIGAR_OS_H -#ifdef __APPLE__ -#define DARWIN -#endif - -#ifdef DARWIN -/// Added to allow this code to compile with gcc4.7 vs Apple's built in compiler. -#define __private_extern__ extern - - - - -#include -#include -#ifdef DARWIN_HAS_LIBPROC_H -#include -#include -typedef int (*proc_pidinfo_func_t)(int, int, uint64_t, void *, int); -typedef int (*proc_pidfdinfo_func_t)(int, int, int, void *, int); -#endif -#else -#include -#endif - -#ifdef __NetBSD__ -#include -#endif -#include - -enum { - KOFFSET_CPUINFO, - KOFFSET_VMMETER, -#if defined(__OpenBSD__) || defined(__NetBSD__) - KOFFSET_TCPSTAT, - KOFFSET_TCBTABLE, -#endif - KOFFSET_MAX -}; - -#if defined(__OpenBSD__) || defined(__NetBSD__) -typedef struct kinfo_proc2 bsd_pinfo_t; -#else -typedef struct kinfo_proc bsd_pinfo_t; -#endif - -struct sigar_t { - SIGAR_T_BASE; - int pagesize; - time_t last_getprocs; - sigar_pid_t last_pid; - bsd_pinfo_t *pinfo; - int lcpu; - size_t argmax; -#ifdef DARWIN - mach_port_t mach_port; -# ifdef DARWIN_HAS_LIBPROC_H - void *libproc; - proc_pidinfo_func_t proc_pidinfo; - proc_pidfdinfo_func_t proc_pidfdinfo; -# endif -#else - kvm_t *kmem; - /* offsets for seeking on kmem */ - unsigned long koffsets[KOFFSET_MAX]; - int proc_mounted; -#endif -}; - -#define SIGAR_EPERM_KMEM (SIGAR_OS_START_ERROR+EACCES) -#define SIGAR_EPROC_NOENT (SIGAR_OS_START_ERROR+2) - -#endif /* SIGAR_OS_H */ diff --git a/vendor/sigar/src/os/hpux/hpux_sigar.c b/vendor/sigar/src/os/hpux/hpux_sigar.c deleted file mode 100644 index f7a7adc..0000000 --- a/vendor/sigar/src/os/hpux/hpux_sigar.c +++ /dev/null @@ -1,1342 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -#include -#include -#ifndef __ia64__ -#include -#endif -#include -#include -#include - -#ifdef _PSTAT64 -typedef int64_t pstat_int_t; -#else -typedef int32_t pstat_int_t; -#endif - -int sigar_os_open(sigar_t **sigar) -{ - *sigar = malloc(sizeof(**sigar)); - - /* does not change while system is running */ - pstat_getstatic(&(*sigar)->pstatic, - sizeof((*sigar)->pstatic), - 1, 0); - - (*sigar)->ticks = sysconf(_SC_CLK_TCK); - - (*sigar)->last_pid = -1; - - (*sigar)->pinfo = NULL; - - (*sigar)->mib = -1; - - return SIGAR_OK; - -} - -int sigar_os_close(sigar_t *sigar) -{ - if (sigar->pinfo) { - free(sigar->pinfo); - } - if (sigar->mib >= 0) { - close_mib(sigar->mib); - } - free(sigar); - return SIGAR_OK; -} - -char *sigar_os_error_string(sigar_t *sigar, int err) -{ - return NULL; -} - -int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem) -{ - struct pst_dynamic stats; - struct pst_vminfo vminfo; - sigar_uint64_t pagesize = sigar->pstatic.page_size; - sigar_uint64_t kern; - - mem->total = sigar->pstatic.physical_memory * pagesize; - - pstat_getdynamic(&stats, sizeof(stats), 1, 0); - - mem->free = stats.psd_free * pagesize; - mem->used = mem->total - mem->free; - - pstat_getvminfo(&vminfo, sizeof(vminfo), 1, 0); - - /* "kernel dynamic memory" */ - kern = vminfo.psv_kern_dynmem * pagesize; - mem->actual_free = mem->free + kern; - mem->actual_used = mem->used - kern; - - sigar_mem_calc_ram(sigar, mem); - - return SIGAR_OK; -} - -int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap) -{ - struct pst_swapinfo swapinfo; - struct pst_vminfo vminfo; - int i=0; - - swap->total = swap->free = 0; - - while (pstat_getswap(&swapinfo, sizeof(swapinfo), 1, i++) > 0) { - swapinfo.pss_nfpgs *= 4; /* nfpgs is in 512 byte blocks */ - - if (swapinfo.pss_nblksenabled == 0) { - swapinfo.pss_nblksenabled = swapinfo.pss_nfpgs; - } - - swap->total += swapinfo.pss_nblksenabled; - swap->free += swapinfo.pss_nfpgs; - } - - swap->used = swap->total - swap->free; - - pstat_getvminfo(&vminfo, sizeof(vminfo), 1, 0); - - swap->page_in = vminfo.psv_spgin; - swap->page_out = vminfo.psv_spgout; - - return SIGAR_OK; -} - -static void get_cpu_metrics(sigar_t *sigar, - sigar_cpu_t *cpu, - pstat_int_t *cpu_time) -{ - cpu->user = SIGAR_TICK2MSEC(cpu_time[CP_USER]); - - cpu->sys = SIGAR_TICK2MSEC(cpu_time[CP_SYS] + - cpu_time[CP_SSYS]); - - cpu->nice = SIGAR_TICK2MSEC(cpu_time[CP_NICE]); - - cpu->idle = SIGAR_TICK2MSEC(cpu_time[CP_IDLE]); - - cpu->wait = SIGAR_TICK2MSEC(cpu_time[CP_SWAIT] + - cpu_time[CP_BLOCK]); - - cpu->irq = SIGAR_TICK2MSEC(cpu_time[CP_INTR]); - cpu->soft_irq = 0; /*N/A*/ - cpu->stolen = 0; /*N/A*/ - - cpu->total = - cpu->user + cpu->sys + cpu->nice + cpu->idle + cpu->wait + cpu->irq; -} - -int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ - struct pst_dynamic stats; - - pstat_getdynamic(&stats, sizeof(stats), 1, 0); - sigar->ncpu = stats.psd_proc_cnt; - - get_cpu_metrics(sigar, cpu, stats.psd_cpu_time); - - return SIGAR_OK; -} - -int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist) -{ - int i; - struct pst_dynamic stats; - - pstat_getdynamic(&stats, sizeof(stats), 1, 0); - sigar->ncpu = stats.psd_proc_cnt; - - sigar_cpu_list_create(cpulist); - - for (i=0; incpu; i++) { - sigar_cpu_t *cpu; - struct pst_processor proc; - - if (pstat_getprocessor(&proc, sizeof(proc), 1, i) < 0) { - continue; - } - - SIGAR_CPU_LIST_GROW(cpulist); - - cpu = &cpulist->data[cpulist->number++]; - - get_cpu_metrics(sigar, cpu, proc.psp_cpu_time); - } - - return SIGAR_OK; -} - -int sigar_uptime_get(sigar_t *sigar, - sigar_uptime_t *uptime) -{ - uptime->uptime = time(NULL) - sigar->pstatic.boot_time; - - return SIGAR_OK; -} - -int sigar_loadavg_get(sigar_t *sigar, - sigar_loadavg_t *loadavg) -{ - struct pst_dynamic stats; - - pstat_getdynamic(&stats, sizeof(stats), 1, 0); - - loadavg->loadavg[0] = stats.psd_avg_1_min; - loadavg->loadavg[1] = stats.psd_avg_5_min; - loadavg->loadavg[2] = stats.psd_avg_15_min; - - return SIGAR_OK; -} - -#define PROC_ELTS 16 - -int sigar_os_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - int num, idx=0; - struct pst_status proctab[PROC_ELTS]; - - while ((num = pstat_getproc(proctab, sizeof(proctab[0]), - PROC_ELTS, idx)) > 0) - { - int i; - - for (i=0; idata[proclist->number++] = - proctab[i].pst_pid; - } - - idx = proctab[num-1].pst_idx + 1; - } - - if (proclist->number == 0) { - return errno; - } - - return SIGAR_OK; -} - -static int sigar_pstat_getproc(sigar_t *sigar, sigar_pid_t pid) -{ - int status, num; - time_t timenow = time(NULL); - - if (sigar->pinfo == NULL) { - sigar->pinfo = malloc(sizeof(*sigar->pinfo)); - } - - if (sigar->last_pid == pid) { - if ((timenow - sigar->last_getprocs) < SIGAR_LAST_PROC_EXPIRE) { - return SIGAR_OK; - } - } - - sigar->last_pid = pid; - sigar->last_getprocs = timenow; - - if (pstat_getproc(sigar->pinfo, - sizeof(*sigar->pinfo), - 0, pid) == -1) - { - return errno; - } - - return SIGAR_OK; -} - -int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_mem_t *procmem) -{ - int pagesize = sigar->pstatic.page_size; - int status = sigar_pstat_getproc(sigar, pid); - struct pst_status *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - procmem->size = - pinfo->pst_vtsize + /* text */ - pinfo->pst_vdsize + /* data */ - pinfo->pst_vssize + /* stack */ - pinfo->pst_vshmsize + /* shared memory */ - pinfo->pst_vmmsize + /* mem-mapped files */ - pinfo->pst_vusize + /* U-Area & K-Stack */ - pinfo->pst_viosize; /* I/O dev mapping */ - - procmem->size *= pagesize; - - procmem->resident = pinfo->pst_rssize * pagesize; - - procmem->share = pinfo->pst_vshmsize * pagesize; - - procmem->minor_faults = pinfo->pst_minorfaults; - procmem->major_faults = pinfo->pst_majorfaults; - procmem->page_faults = - procmem->minor_faults + - procmem->major_faults; - - return SIGAR_OK; -} - -int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_t *proccred) -{ - int status = sigar_pstat_getproc(sigar, pid); - struct pst_status *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - proccred->uid = pinfo->pst_uid; - proccred->gid = pinfo->pst_gid; - proccred->euid = pinfo->pst_euid; - proccred->egid = pinfo->pst_egid; - - return SIGAR_OK; -} - -int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_time_t *proctime) -{ - int status = sigar_pstat_getproc(sigar, pid); - struct pst_status *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - proctime->start_time = pinfo->pst_start; - proctime->start_time *= SIGAR_MSEC; - proctime->user = pinfo->pst_utime * SIGAR_MSEC; - proctime->sys = pinfo->pst_stime * SIGAR_MSEC; - proctime->total = proctime->user + proctime->sys; - - return SIGAR_OK; -} - -int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - int status = sigar_pstat_getproc(sigar, pid); - struct pst_status *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - - SIGAR_SSTRCPY(procstate->name, pinfo->pst_ucomm); - procstate->ppid = pinfo->pst_ppid; - procstate->tty = makedev(pinfo->pst_term.psd_major, - pinfo->pst_term.psd_minor); - procstate->priority = pinfo->pst_pri; - procstate->nice = pinfo->pst_nice; - procstate->threads = pinfo->pst_nlwps; - procstate->processor = pinfo->pst_procnum; - - /* cast to prevent compiler warning: */ - /* Case label too big for the type of the switch expression */ - switch ((int32_t)pinfo->pst_stat) { - case PS_SLEEP: - procstate->state = 'S'; - break; - case PS_RUN: - procstate->state = 'R'; - break; - case PS_STOP: - procstate->state = 'T'; - break; - case PS_ZOMBIE: - procstate->state = 'Z'; - break; - case PS_IDLE: - procstate->state = 'D'; - break; - } - - return SIGAR_OK; -} - -int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - char *args, *arg; -#ifdef PSTAT_GETCOMMANDLINE - char buf[1024]; /* kernel limit */ - -# ifdef pstat_getcommandline /* 11i v2 + */ - if (pstat_getcommandline(buf, sizeof(buf), sizeof(buf[0]), pid) == -1) { - return errno; - } -# else - union pstun pu; - - pu.pst_command = buf; - if (pstat(PSTAT_GETCOMMANDLINE, pu, sizeof(buf), sizeof(buf[0]), pid) == -1) { - return errno; - } -# endif /* pstat_getcommandline */ - - args = buf; -#else - struct pst_status status; - - if (pstat_getproc(&status, sizeof(status), 0, pid) == -1) { - return errno; - } - - args = status.pst_cmd; -#endif - - while (*args && (arg = sigar_getword(&args, ' '))) { - SIGAR_PROC_ARGS_GROW(procargs); - procargs->data[procargs->number++] = arg; - } - - return SIGAR_OK; -} - -int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ - return SIGAR_ENOTIMPL; -} - -int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_fd_t *procfd) -{ - struct pst_status status; - int idx=0, n; - struct pst_fileinfo2 psf[16]; - - procfd->total = 0; - - if (pstat_getproc(&status, sizeof(status), 0, pid) == -1) { - return errno; - } - - /* HPUX 11.31 removed the deprecated pstat_getfile call */ - while ((n = pstat_getfile2(psf, sizeof(psf[0]), - sizeof(psf)/sizeof(psf[0]), - idx, pid)) > 0) - { - procfd->total += n; - idx = psf[n-1].psf_fd + 1; - } - - if (n == -1) { - return errno; - } - - return SIGAR_OK; -} - -int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ -#ifdef __pst_fid /* 11.11+ */ - int rc; - struct pst_status status; - - if (pstat_getproc(&status, sizeof(status), 0, pid) == -1) { - return errno; - } - - rc = pstat_getpathname(procexe->cwd, - sizeof(procexe->cwd), - &status.pst_fid_cdir); - if (rc == -1) { - return errno; - } - - rc = pstat_getpathname(procexe->name, - sizeof(procexe->name), - &status.pst_fid_text); - if (rc == -1) { - return errno; - } - - rc = pstat_getpathname(procexe->root, - sizeof(procexe->root), - &status.pst_fid_rdir); - if (rc == -1) { - return errno; - } - - return SIGAR_OK; -#else - return SIGAR_ENOTIMPL; /* 11.00 */ -#endif -} - -int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods) -{ - return SIGAR_ENOTIMPL; -} - -#define TIME_NSEC(t) \ - (SIGAR_SEC2NANO((t).tv_sec) + (sigar_uint64_t)(t).tv_nsec) - -int sigar_thread_cpu_get(sigar_t *sigar, - sigar_uint64_t id, - sigar_thread_cpu_t *cpu) -{ -#ifdef __ia64__ - /* XXX seems _lwp funcs were for solaris compat and dont exist - * on itanium. hp docs claim that have equiv functions, - * but wtf is it for _lwp_info? - */ - return SIGAR_ENOTIMPL; -#else - struct lwpinfo info; - - if (id != 0) { - return SIGAR_ENOTIMPL; - } - - _lwp_info(&info); - - cpu->user = TIME_NSEC(info.lwp_utime); - cpu->sys = TIME_NSEC(info.lwp_stime); - cpu->total = TIME_NSEC(info.lwp_utime) + TIME_NSEC(info.lwp_stime); - - return SIGAR_OK; -#endif -} - -#include - -int sigar_os_fs_type_get(sigar_file_system_t *fsp) -{ - char *type = fsp->sys_type_name; - - switch (*type) { - case 'h': - if (strEQ(type, "hfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'c': - if (strEQ(type, "cdfs")) { - fsp->type = SIGAR_FSTYPE_CDROM; - } - break; - } - - return fsp->type; -} - -int sigar_file_system_list_get(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - struct mntent *ent; - - FILE *fp; - sigar_file_system_t *fsp; - - if (!(fp = setmntent(MNT_MNTTAB, "r"))) { - return errno; - } - - sigar_file_system_list_create(fslist); - - while ((ent = getmntent(fp))) { - if ((*(ent->mnt_type) == 's') && - strEQ(ent->mnt_type, "swap")) - { - /* - * in this case, devname == "...", for - * which statfs chokes on. so skip it. - * also notice hpux df command has no swap info. - */ - continue; - } - - SIGAR_FILE_SYSTEM_LIST_GROW(fslist); - - fsp = &fslist->data[fslist->number++]; - - SIGAR_SSTRCPY(fsp->dir_name, ent->mnt_dir); - SIGAR_SSTRCPY(fsp->dev_name, ent->mnt_fsname); - SIGAR_SSTRCPY(fsp->sys_type_name, ent->mnt_type); - SIGAR_SSTRCPY(fsp->options, ent->mnt_opts); - sigar_fs_type_init(fsp); - } - - endmntent(fp); - - return SIGAR_OK; -} - -static int create_fsdev_cache(sigar_t *sigar) -{ - sigar_file_system_list_t fslist; - int i; - int status = - sigar_file_system_list_get(sigar, &fslist); - - if (status != SIGAR_OK) { - return status; - } - - sigar->fsdev = sigar_cache_new(15); - - for (i=0; itype == SIGAR_FSTYPE_LOCAL_DISK) { - sigar_cache_entry_t *ent; - struct stat sb; - - if (stat(fsp->dir_name, &sb) < 0) { - continue; - } - - ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb)); - ent->value = strdup(fsp->dev_name); - } - } - - return SIGAR_OK; -} - -int sigar_disk_usage_get(sigar_t *sigar, const char *name, - sigar_disk_usage_t *usage) -{ - return SIGAR_ENOTIMPL; -} - -int sigar_file_system_usage_get(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage) -{ - struct stat sb; - int status = sigar_statvfs(sigar, dirname, fsusage); - - if (status != SIGAR_OK) { - return status; - } - - fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage); - - SIGAR_DISK_STATS_INIT(&fsusage->disk); - - if (!sigar->fsdev) { - if (create_fsdev_cache(sigar) != SIGAR_OK) { - return SIGAR_OK; - } - } - - if (stat(dirname, &sb) == 0) { - sigar_cache_entry_t *ent; - struct pst_lvinfo lv; - struct stat devsb; - char *devname; - int retval; - - ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb)); - if (ent->value == NULL) { - return SIGAR_OK; - } - - if (stat((char *)ent->value, &devsb) < 0) { - return SIGAR_OK; - } - - retval = pstat_getlv(&lv, sizeof(lv), 0, (int)devsb.st_rdev); - - if (retval == 1) { - fsusage->disk.reads = lv.psl_rxfer; - fsusage->disk.writes = lv.psl_wxfer; - fsusage->disk.read_bytes = lv.psl_rcount; - fsusage->disk.write_bytes = lv.psl_wcount; - fsusage->disk.queue = SIGAR_FIELD_NOTIMPL; - } - } - - return SIGAR_OK; -} - -int sigar_cpu_info_list_get(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos) -{ - int i; - struct pst_dynamic stats; - - pstat_getdynamic(&stats, sizeof(stats), 1, 0); - sigar->ncpu = stats.psd_proc_cnt; - - sigar_cpu_info_list_create(cpu_infos); - - for (i=0; incpu; i++) { - sigar_cpu_info_t *info; - struct pst_processor proc; - - if (pstat_getprocessor(&proc, sizeof(proc), 1, i) < 0) { - perror("pstat_getprocessor"); - continue; - } - - SIGAR_CPU_INFO_LIST_GROW(cpu_infos); - - info = &cpu_infos->data[cpu_infos->number++]; - - info->total_cores = sigar->ncpu; - info->cores_per_socket = 1; /*XXX*/ - info->total_sockets = sigar->ncpu; /*XXX*/ - -#ifdef __ia64__ - SIGAR_SSTRCPY(info->vendor, "Intel"); /*XXX*/ - SIGAR_SSTRCPY(info->model, "Itanium"); /*XXX*/ -#else - SIGAR_SSTRCPY(info->vendor, "HP"); /*XXX*/ - SIGAR_SSTRCPY(info->model, "PA RISC"); /*XXX*/ -#endif -#ifdef PSP_MAX_CACHE_LEVELS /* 11.31+; see SIGAR-196 */ - info->mhz = proc.psp_cpu_frequency / 1000000; -#else - info->mhz = sigar->ticks * proc.psp_iticksperclktick / 1000000; -#endif - info->cache_size = SIGAR_FIELD_NOTIMPL; /*XXX*/ - } - - return SIGAR_OK; -} - -static int sigar_get_mib_info(sigar_t *sigar, - struct nmparms *parms) -{ - if (sigar->mib < 0) { - if ((sigar->mib = open_mib("/dev/ip", O_RDONLY, 0, 0)) < 0) { - return errno; - } - } - return get_mib_info(sigar->mib, parms); -} - -/* wrapper around get_physical_stat() */ -static int sigar_get_physical_stat(sigar_t *sigar, int *count) -{ - int status; - unsigned int len; - struct nmparms parms; - - len = sizeof(*count); - parms.objid = ID_ifNumber; - parms.buffer = count; - parms.len = &len; - - if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { - return status; - } - - len = sizeof(nmapi_phystat) * *count; - - if (sigar->ifconf_len < len) { - sigar->ifconf_buf = realloc(sigar->ifconf_buf, len); - sigar->ifconf_len = len; - } - - if (get_physical_stat(sigar->ifconf_buf, &len) < 0) { - return errno; - } - else { - return SIGAR_OK; - } -} - -#define SIGAR_IF_NAMESIZE 16 -/* hpux if_indextoname() does not work as advertised in 11.11 */ -static int sigar_if_indextoname(sigar_t *sigar, - char *name, - int index) -{ - int i, status, count; - nmapi_phystat *stat; - - if ((status = sigar_get_physical_stat(sigar, &count) != SIGAR_OK)) { - return status; - } - - for (i=0, stat = (nmapi_phystat *)sigar->ifconf_buf; - iif_entry.ifIndex == index) { - strncpy(name, stat->nm_device, SIGAR_IF_NAMESIZE); - return SIGAR_OK; - } - } - - return ENXIO; -} - -int sigar_net_route_list_get(sigar_t *sigar, - sigar_net_route_list_t *routelist) -{ - int status, count, i; - unsigned int len; - struct nmparms parms; - mib_ipRouteEnt *routes; - sigar_net_route_t *route; - - len = sizeof(count); - parms.objid = ID_ipRouteNumEnt; - parms.buffer = &count; - parms.len = &len; - - if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { - return status; - } - - len = count * sizeof(*routes); - routes = malloc(len); - - parms.objid = ID_ipRouteTable; - parms.buffer = routes; - parms.len = &len; - - if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { - free(routes); - return status; - } - - routelist->size = routelist->number = 0; - - sigar_net_route_list_create(routelist); - - for (i=0; idata[routelist->number++]; - SIGAR_ZERO(route); /* XXX: other fields */ - - sigar_net_address_set(route->destination, - ent->Dest); - - sigar_net_address_set(route->mask, - ent->Mask); - - sigar_net_address_set(route->gateway, - ent->NextHop); - - sigar_if_indextoname(sigar, route->ifname, ent->IfIndex); - - route->flags = SIGAR_RTF_UP; - if ((ent->Dest == 0) && - (ent->Mask == 0)) - { - route->flags |= SIGAR_RTF_GATEWAY; - } - } - - free(routes); - - return SIGAR_OK; -} - -static int get_mib_ifstat(sigar_t *sigar, - const char *name, - mib_ifEntry *mib) -{ - int i, status, count; - nmapi_phystat *stat; - - if ((status = sigar_get_physical_stat(sigar, &count) != SIGAR_OK)) { - return status; - } - - for (i=0, stat = (nmapi_phystat *)sigar->ifconf_buf; - inm_device, name)) { - memcpy(mib, &stat->if_entry, sizeof(*mib)); - return SIGAR_OK; - } - } - - return ENXIO; -} - -int sigar_net_interface_stat_get(sigar_t *sigar, const char *name, - sigar_net_interface_stat_t *ifstat) -{ - int status; - mib_ifEntry mib; - - status = get_mib_ifstat(sigar, name, &mib); - - if (status != SIGAR_OK) { - return status; - } - - ifstat->rx_bytes = mib.ifInOctets; - ifstat->rx_packets = mib.ifInUcastPkts + mib.ifInNUcastPkts; - ifstat->rx_errors = mib.ifInErrors; - ifstat->rx_dropped = mib.ifInDiscards; - ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->rx_frame = SIGAR_FIELD_NOTIMPL; - - ifstat->tx_bytes = mib.ifOutOctets; - ifstat->tx_packets = mib.ifOutUcastPkts + mib.ifOutNUcastPkts; - ifstat->tx_errors = mib.ifOutErrors; - ifstat->tx_dropped = mib.ifOutDiscards; - ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->tx_collisions = SIGAR_FIELD_NOTIMPL; - ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL; - - ifstat->speed = mib.ifSpeed; - - return SIGAR_OK; -} - -int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig) -{ - int sock; - struct if_laddrreq iflr; - - if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - return errno; - } - - SIGAR_SSTRCPY(iflr.iflr_name, name); - - if (ioctl(sock, SIOCGLIFADDR, &iflr) == 0) { - struct in6_addr *addr = SIGAR_SIN6_ADDR(&iflr.iflr_addr); - - sigar_net_address6_set(ifconfig->address6, addr); - sigar_net_interface_scope6_set(ifconfig, addr); - - if (ioctl(sock, SIOCGLIFNETMASK, &iflr) == 0) { - addr = SIGAR_SIN6_ADDR(&iflr.iflr_addr); - ifconfig->prefix6_length = 10; /*XXX*/ - } - } - - close(sock); - return SIGAR_OK; -} - -static int net_conn_get_udp_listen(sigar_net_connection_walker_t *walker) -{ - sigar_t *sigar = walker->sigar; - int flags = walker->flags; - int status, count, i; - unsigned int len; - mib_udpLsnEnt *entries; - struct nmparms parms; - - len = sizeof(count); - parms.objid = ID_udpLsnNumEnt; - parms.buffer = &count; - parms.len = &len; - - if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { - return status; - } - - if (count <= 0) { - return ENOENT; - } - - len = count * sizeof(*entries); - entries = malloc(len); - parms.objid = ID_udpLsnTable; - parms.buffer = entries; - parms.len = &len; - - if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { - free(entries); - return status; - } - - for (i=0; iLocalPort; - conn.remote_port = 0; - - sigar_net_address_set(conn.local_address, - entry->LocalAddress); - - sigar_net_address_set(conn.remote_address, 0); - - conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL; - - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - } - - free(entries); - return SIGAR_OK; -} - -static int net_conn_get_udp(sigar_net_connection_walker_t *walker) -{ - int status = SIGAR_OK; - - if (walker->flags & SIGAR_NETCONN_SERVER) { - status = net_conn_get_udp_listen(walker); - } - - return status; -} - -#define IS_TCP_SERVER(state, flags) \ - ((flags & SIGAR_NETCONN_SERVER) && (state == TCLISTEN)) - -#define IS_TCP_CLIENT(state, flags) \ - ((flags & SIGAR_NETCONN_CLIENT) && (state != TCLISTEN)) - -static int net_conn_get_tcp(sigar_net_connection_walker_t *walker) -{ - sigar_t *sigar = walker->sigar; - int flags = walker->flags; - int status, count, i; - unsigned int len; - mib_tcpConnEnt *entries; - struct nmparms parms; - - len = sizeof(count); - parms.objid = ID_tcpConnNumEnt; - parms.buffer = &count; - parms.len = &len; - - if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { - return status; - } - - if (count <= 0) { - return ENOENT; - } - - len = count * sizeof(*entries); - entries = malloc(len); - parms.objid = ID_tcpConnTable; - parms.buffer = entries; - parms.len = &len; - - if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { - free(entries); - return status; - } - - for (i=0; iState; - - if (!(IS_TCP_SERVER(state, flags) || - IS_TCP_CLIENT(state, flags))) - { - continue; - } - - SIGAR_ZERO(&conn); - - switch (state) { - case TCCLOSED: - conn.state = SIGAR_TCP_CLOSE; - break; - case TCLISTEN: - conn.state = SIGAR_TCP_LISTEN; - break; - case TCSYNSENT: - conn.state = SIGAR_TCP_SYN_SENT; - break; - case TCSYNRECEIVE: - conn.state = SIGAR_TCP_SYN_RECV; - break; - case TCESTABLISED: - conn.state = SIGAR_TCP_ESTABLISHED; - break; - case TCFINWAIT1: - conn.state = SIGAR_TCP_FIN_WAIT1; - break; - case TCFINWAIT2: - conn.state = SIGAR_TCP_FIN_WAIT2; - break; - case TCCLOSEWAIT: - conn.state = SIGAR_TCP_CLOSE_WAIT; - break; - case TCCLOSING: - conn.state = SIGAR_TCP_CLOSING; - break; - case TCLASTACK: - conn.state = SIGAR_TCP_LAST_ACK; - break; - case TCTIMEWAIT: - conn.state = SIGAR_TCP_TIME_WAIT; - break; - case TCDELETETCB: - default: - conn.state = SIGAR_TCP_UNKNOWN; - break; - } - - conn.local_port = (unsigned short)entry->LocalPort; - conn.remote_port = (unsigned short)entry->RemPort; - conn.type = SIGAR_NETCONN_TCP; - - sigar_net_address_set(conn.local_address, entry->LocalAddress); - sigar_net_address_set(conn.remote_address, entry->RemAddress); - - conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL; - - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - } - - free(entries); - - return SIGAR_OK; -} - -int sigar_net_connection_walk(sigar_net_connection_walker_t *walker) -{ - int status; - - if (walker->flags & SIGAR_NETCONN_TCP) { - status = net_conn_get_tcp(walker); - - if (status != SIGAR_OK) { - return status; - } - } - - if (walker->flags & SIGAR_NETCONN_UDP) { - status = net_conn_get_udp(walker); - - if (status != SIGAR_OK) { - return status; - } - } - - return SIGAR_OK; -} - -#define tcpsoff(x) sigar_offsetof(sigar_tcp_t, x) - -static struct { - unsigned int id; - size_t offset; -} tcps_lu[] = { -#if 0 - { ID_tcpRtoAlgorithm, tcpsoff(xxx) }, - { ID_tcpRtoMin, tcpsoff(xxx) }, - { ID_tcpRtoMax, tcpsoff(xxx) }, - { ID_tcpMaxConn, tcpsoff(max_conn) }, -#endif - { ID_tcpActiveOpens, tcpsoff(active_opens) }, - { ID_tcpPassiveOpens, tcpsoff(passive_opens) }, - { ID_tcpAttemptFails, tcpsoff(attempt_fails) }, - { ID_tcpEstabResets, tcpsoff(estab_resets) }, - { ID_tcpCurrEstab, tcpsoff(curr_estab) }, - { ID_tcpInSegs, tcpsoff(in_segs) }, - { ID_tcpOutSegs, tcpsoff(out_segs) }, - { ID_tcpRetransSegs, tcpsoff(retrans_segs) }, - { ID_tcpInErrs, tcpsoff(in_errs) }, - { ID_tcpOutRsts, tcpsoff(out_rsts) } -}; - -SIGAR_DECLARE(int) -sigar_tcp_get(sigar_t *sigar, - sigar_tcp_t *tcp) -{ - int i; - - for (i=0; idata[arplist->number++]; - - sigar_net_address_set(arp->address, - ent->NetAddr); - - sigar_net_address_mac_set(arp->hwaddr, - ent->PhysAddr.o_bytes, - ent->PhysAddr.o_length); - - sigar_if_indextoname(sigar, arp->ifname, ent->IfIndex); - - SIGAR_SSTRCPY(arp->type, "ether"); /*XXX*/ - arp->flags = 0; /*XXX*/ - } - - free(entries); - - return SIGAR_OK; -} - -int sigar_proc_port_get(sigar_t *sigar, int protocol, - unsigned long port, sigar_pid_t *pid) -{ - return SIGAR_ENOTIMPL; -} - - -int sigar_os_sys_info_get(sigar_t *sigar, - sigar_sys_info_t *sysinfo) -{ - char *vendor_version, *arch; - long cpu = sysconf(_SC_CPU_VERSION); - - switch (cpu) { - case CPU_PA_RISC1_0: - arch = "PA_RISC1.0"; - break; - case CPU_PA_RISC1_1: - arch = "PA_RISC1.1"; - break; - case CPU_PA_RISC2_0: - arch = "PA_RISC2.0"; - break; -#ifdef CPU_IA64_ARCHREV_0 - case CPU_IA64_ARCHREV_0: - arch = "ia64"; - break; -#endif - default: - arch = "unknown"; - break; - } - - SIGAR_SSTRCPY(sysinfo->arch, arch); - - SIGAR_SSTRCPY(sysinfo->name, "HPUX"); - SIGAR_SSTRCPY(sysinfo->vendor, "Hewlett-Packard"); - - if (strstr(sysinfo->version, ".11.")) { - vendor_version = "11"; - } - else { - vendor_version = sysinfo->version; - } - - SIGAR_SSTRCPY(sysinfo->vendor_version, vendor_version); - - snprintf(sysinfo->description, - sizeof(sysinfo->description), - "%s %s", - sysinfo->vendor_name, sysinfo->vendor_version); - - return SIGAR_OK; -} diff --git a/vendor/sigar/src/os/hpux/sigar_os.h b/vendor/sigar/src/os/hpux/sigar_os.h deleted file mode 100644 index ee2434a..0000000 --- a/vendor/sigar/src/os/hpux/sigar_os.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2004-2007 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_OS_H -#define SIGAR_OS_H - -#if defined(__ia64) && !defined(__ia64__) -#define __ia64__ -#endif - -#ifdef __ia64__ -#ifndef _LP64 -#define _LP64 -#endif -#endif - -#define _PSTAT64 - -#include -#include -#include -#include - -struct sigar_t { - SIGAR_T_BASE; - struct pst_static pstatic; - time_t last_getprocs; - sigar_pid_t last_pid; - struct pst_status *pinfo; - - int mib; -}; - -int hpux_get_mib_ifentry(int ppa, mib_ifEntry *mib); - -#endif /* SIGAR_OS_H */ diff --git a/vendor/sigar/src/os/linux/linux_sigar.c b/vendor/sigar/src/os/linux/linux_sigar.c deleted file mode 100644 index 0e4283f..0000000 --- a/vendor/sigar/src/os/linux/linux_sigar.c +++ /dev/null @@ -1,2782 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -#define pageshift(x) ((x) << sigar->pagesize) - -#define PROC_MEMINFO PROC_FS_ROOT "meminfo" -#define PROC_VMSTAT PROC_FS_ROOT "vmstat" -#define PROC_MTRR PROC_FS_ROOT "mtrr" -#define PROC_STAT PROC_FS_ROOT "stat" -#define PROC_UPTIME PROC_FS_ROOT "uptime" -#define PROC_LOADAVG PROC_FS_ROOT "loadavg" - -#define PROC_PSTAT "/stat" -#define PROC_PSTATUS "/status" - -#define SYS_BLOCK "/sys/block" -#define PROC_PARTITIONS PROC_FS_ROOT "partitions" -#define PROC_DISKSTATS PROC_FS_ROOT "diskstats" - -/* - * /proc/self/stat fields: - * 1 - pid - * 2 - comm - * 3 - state - * 4 - ppid - * 5 - pgrp - * 6 - session - * 7 - tty_nr - * 8 - tpgid - * 9 - flags - * 10 - minflt - * 11 - cminflt - * 12 - majflt - * 13 - cmajflt - * 14 - utime - * 15 - stime - * 16 - cutime - * 17 - cstime - * 18 - priority - * 19 - nice - * 20 - 0 (removed field) - * 21 - itrealvalue - * 22 - starttime - * 23 - vsize - * 24 - rss - * 25 - rlim - * 26 - startcode - * 27 - endcode - * 28 - startstack - * 29 - kstkesp - * 30 - kstkeip - * 31 - signal - * 32 - blocked - * 33 - sigignore - * 34 - sigcache - * 35 - wchan - * 36 - nswap - * 37 - cnswap - * 38 - exit_signal <-- looking for this. - * 39 - processor - * ... more for newer RH - */ - -#define PROC_SIGNAL_IX 38 - -static int get_proc_signal_offset(void) -{ - char buffer[BUFSIZ], *ptr=buffer; - int fields = 0; - int status = sigar_file2str(PROCP_FS_ROOT "self/stat", - buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return 1; - } - - while (*ptr) { - if (*ptr++ == ' ') { - fields++; - } - } - - return (fields - PROC_SIGNAL_IX) + 1; -} - -sigar_pid_t sigar_pid_get(sigar_t *sigar) -{ - /* XXX cannot safely cache getpid unless using nptl */ - /* we can however, cache it for optimizations in the - * case of proc_env_get for example. - */ - sigar->pid = getpid(); - return sigar->pid; -} - -static int sigar_boot_time_get(sigar_t *sigar) -{ - FILE *fp; - char buffer[BUFSIZ], *ptr; - int found = 0; - - if (!(fp = fopen(PROC_STAT, "r"))) { - return errno; - } - - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - if (strnEQ(ptr, "btime", 5)) { - if ((ptr = sigar_skip_token(ptr))) { - sigar->boot_time = sigar_strtoul(ptr); - found = 1; - } - break; - } - } - - fclose(fp); - - if (!found) { - /* should never happen */ - sigar->boot_time = time(NULL); - } - - return SIGAR_OK; -} - -int sigar_os_open(sigar_t **sigar) -{ - int i, status; - int kernel_rev, has_nptl; - struct stat sb; - struct utsname name; - - *sigar = malloc(sizeof(**sigar)); - - (*sigar)->pagesize = 0; - i = getpagesize(); - while ((i >>= 1) > 0) { - (*sigar)->pagesize++; - } - - status = sigar_boot_time_get(*sigar); - if (status != SIGAR_OK) { - return status; - } - - (*sigar)->ticks = sysconf(_SC_CLK_TCK); - - (*sigar)->ram = -1; - - (*sigar)->proc_signal_offset = -1; - - (*sigar)->last_proc_stat.pid = -1; - - (*sigar)->lcpu = -1; - - if (stat(PROC_DISKSTATS, &sb) == 0) { - (*sigar)->iostat = IOSTAT_DISKSTATS; - } - else if (stat(SYS_BLOCK, &sb) == 0) { - (*sigar)->iostat = IOSTAT_SYS; - } - else if (stat(PROC_PARTITIONS, &sb) == 0) { - /* XXX file exists does not mean is has the fields */ - (*sigar)->iostat = IOSTAT_PARTITIONS; - } - else { - (*sigar)->iostat = IOSTAT_NONE; - } - - /* hook for using mirrored /proc/net/tcp file */ - (*sigar)->proc_net = getenv("SIGAR_PROC_NET"); - - uname(&name); - /* 2.X.y.z -> just need X (unless there is ever a kernel version 3!) */ - kernel_rev = atoi(&name.release[2]); - if (kernel_rev >= 6) { - has_nptl = 1; - } - else { - has_nptl = getenv("SIGAR_HAS_NPTL") ? 1 : 0; - } - (*sigar)->has_nptl = has_nptl; - - return SIGAR_OK; -} - -int sigar_os_close(sigar_t *sigar) -{ - free(sigar); - return SIGAR_OK; -} - -char *sigar_os_error_string(sigar_t *sigar, int err) -{ - return NULL; -} - -static int sigar_cpu_total_count(sigar_t *sigar) -{ - sigar->ncpu = (int)sysconf(_SC_NPROCESSORS_CONF); - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, "[cpu] ncpu=%d\n", - sigar->ncpu); - return sigar->ncpu; -} - -static int get_ram(sigar_t *sigar, sigar_mem_t *mem) -{ - char buffer[BUFSIZ], *ptr; - FILE *fp; - int total = 0; - sigar_uint64_t sys_total = (mem->total / (1024 * 1024)); - - if (sigar->ram > 0) { - /* return cached value */ - mem->ram = sigar->ram; - return SIGAR_OK; - } - - if (sigar->ram == 0) { - return ENOENT; - } - - /* - * Memory Type Range Registers - * write-back registers add up to the total. - * Well, they are supposed to add up, but seen - * at least one configuration where that is not the - * case. - */ - if (!(fp = fopen(PROC_MTRR, "r"))) { - return errno; - } - - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - if (!(ptr = strstr(ptr, "size="))) { - continue; - } - - if (!strstr(ptr, "write-back")) { - continue; - } - - ptr += 5; - while (sigar_isspace(*ptr)) { - ++ptr; - } - - total += atoi(ptr); - } - - fclose(fp); - - if ((total - sys_total) > 256) { - /* mtrr write-back registers are way off - * kernel should not be using more that 256MB of mem - */ - total = 0; /* punt */ - } - - if (total == 0) { - return ENOENT; - } - - mem->ram = sigar->ram = total; - - return SIGAR_OK; -} - -#define MEMINFO_PARAM(a) a ":", SSTRLEN(a ":") - -static SIGAR_INLINE sigar_uint64_t sigar_meminfo(char *buffer, - char *attr, int len) -{ - sigar_uint64_t val = 0; - char *ptr, *tok; - - if ((ptr = strstr(buffer, attr))) { - ptr += len; - val = strtoull(ptr, &tok, 0); - while (*tok == ' ') { - ++tok; - } - if (*tok == 'k') { - val *= 1024; - } - else if (*tok == 'M') { - val *= (1024 * 1024); - } - } - - return val; -} - -int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem) -{ - sigar_uint64_t buffers, cached, kern; - char buffer[BUFSIZ]; - - int status = sigar_file2str(PROC_MEMINFO, - buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return status; - } - - mem->total = sigar_meminfo(buffer, MEMINFO_PARAM("MemTotal")); - mem->free = sigar_meminfo(buffer, MEMINFO_PARAM("MemFree")); - mem->used = mem->total - mem->free; - - buffers = sigar_meminfo(buffer, MEMINFO_PARAM("Buffers")); - cached = sigar_meminfo(buffer, MEMINFO_PARAM("Cached")); - - kern = buffers + cached; - mem->actual_free = mem->free + kern; - mem->actual_used = mem->used - kern; - - sigar_mem_calc_ram(sigar, mem); - - if (get_ram(sigar, mem) != SIGAR_OK) { - /* XXX other options on failure? */ - } - - return SIGAR_OK; -} - -int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap) -{ - char buffer[BUFSIZ], *ptr; - - /* XXX: we open/parse the same file here as sigar_mem_get */ - int status = sigar_file2str(PROC_MEMINFO, - buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return status; - } - - swap->total = sigar_meminfo(buffer, MEMINFO_PARAM("SwapTotal")); - swap->free = sigar_meminfo(buffer, MEMINFO_PARAM("SwapFree")); - swap->used = swap->total - swap->free; - - swap->page_in = swap->page_out = -1; - - status = sigar_file2str(PROC_VMSTAT, - buffer, sizeof(buffer)); - - if (status == SIGAR_OK) { - /* 2.6+ kernel */ - if ((ptr = strstr(buffer, "\npswpin"))) { - ptr = sigar_skip_token(ptr); - swap->page_in = sigar_strtoull(ptr); - ptr = sigar_skip_token(ptr); - swap->page_out = sigar_strtoull(ptr); - } - } - else { - /* 2.2, 2.4 kernels */ - status = sigar_file2str(PROC_STAT, - buffer, sizeof(buffer)); - if (status != SIGAR_OK) { - return status; - } - - if ((ptr = strstr(buffer, "\nswap"))) { - ptr = sigar_skip_token(ptr); - swap->page_in = sigar_strtoull(ptr); - swap->page_out = sigar_strtoull(ptr); - } - } - - return SIGAR_OK; -} - -static void get_cpu_metrics(sigar_t *sigar, sigar_cpu_t *cpu, char *line) -{ - char *ptr = sigar_skip_token(line); /* "cpu%d" */ - - cpu->user += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - cpu->nice += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - cpu->sys += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - cpu->idle += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - if (*ptr == ' ') { - /* 2.6+ kernels only */ - cpu->wait += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - cpu->irq += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - cpu->soft_irq += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - } - if (*ptr == ' ') { - /* 2.6.11+ kernels only */ - cpu->stolen += SIGAR_TICK2MSEC(sigar_strtoull(ptr)); - } - cpu->total = - cpu->user + cpu->nice + cpu->sys + cpu->idle + - cpu->wait + cpu->irq + cpu->soft_irq + cpu->stolen; -} - -int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ - char buffer[BUFSIZ]; - int status = sigar_file2str(PROC_STAT, buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return status; - } - - SIGAR_ZERO(cpu); - get_cpu_metrics(sigar, cpu, buffer); - - return SIGAR_OK; -} - -int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist) -{ - FILE *fp; - char buffer[BUFSIZ], cpu_total[BUFSIZ], *ptr; - int core_rollup = sigar_cpu_core_rollup(sigar), i=0; - sigar_cpu_t *cpu; - - if (!(fp = fopen(PROC_STAT, "r"))) { - return errno; - } - - /* skip first line */ - (void)fgets(cpu_total, sizeof(cpu_total), fp); - - sigar_cpu_list_create(cpulist); - - /* XXX: merge times of logical processors if hyperthreading */ - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - if (!strnEQ(ptr, "cpu", 3)) { - break; - } - - if (core_rollup && (i % sigar->lcpu)) { - /* merge times of logical processors */ - cpu = &cpulist->data[cpulist->number-1]; - } - else { - SIGAR_CPU_LIST_GROW(cpulist); - cpu = &cpulist->data[cpulist->number++]; - SIGAR_ZERO(cpu); - } - - get_cpu_metrics(sigar, cpu, ptr); - - i++; - } - - fclose(fp); - - if (cpulist->number == 0) { - /* likely older kernel where cpu\d is not present */ - cpu = &cpulist->data[cpulist->number++]; - SIGAR_ZERO(cpu); - get_cpu_metrics(sigar, cpu, cpu_total); - } - - return SIGAR_OK; -} - -int sigar_uptime_get(sigar_t *sigar, - sigar_uptime_t *uptime) -{ - char buffer[BUFSIZ], *ptr = buffer; - int status = sigar_file2str(PROC_UPTIME, buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return status; - } - - uptime->uptime = strtod(buffer, &ptr); - - return SIGAR_OK; -} - -int sigar_loadavg_get(sigar_t *sigar, - sigar_loadavg_t *loadavg) -{ - char buffer[BUFSIZ], *ptr = buffer; - int status = sigar_file2str(PROC_LOADAVG, buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return status; - } - - loadavg->loadavg[0] = strtod(buffer, &ptr); - loadavg->loadavg[1] = strtod(ptr, &ptr); - loadavg->loadavg[2] = strtod(ptr, &ptr); - - return SIGAR_OK; -} - -/* - * seems the easiest/fastest way to tell if a process listed in /proc - * is a thread is to check the "exit signal" flag in /proc/num/stat. - * any value other than SIGCHLD seems to be a thread. this make hulk mad. - * redhat's procps patch (named "threadbadhack.pat") does not use - * this flag to filter out threads. instead does much more expensive - * comparisions. their patch also bubbles up thread cpu times to the main - * process. functionality we currently lack. - * when nptl is in use, this is not the case and all threads spawned from - * a process have the same pid. however, it seems both old-style linux - * threads and nptl threads can be run on the same machine. - * there is also the "Tgid" field in /proc/self/status which could be used - * to detect threads, but this is not available in older kernels. - */ -static SIGAR_INLINE int proc_isthread(sigar_t *sigar, char *pidstr, int len) -{ - char buffer[BUFSIZ], *ptr=buffer; - int fd, n, offset=sigar->proc_signal_offset; - - /* sprintf(buffer, "/proc/%s/stat", pidstr) */ - memcpy(ptr, PROCP_FS_ROOT, SSTRLEN(PROCP_FS_ROOT)); - ptr += SSTRLEN(PROCP_FS_ROOT); - - memcpy(ptr, pidstr, len); - ptr += len; - - memcpy(ptr, PROC_PSTAT, SSTRLEN(PROC_PSTAT)); - ptr += SSTRLEN(PROC_PSTAT); - - *ptr = '\0'; - - if ((fd = open(buffer, O_RDONLY)) < 0) { - /* unlikely if pid was from readdir proc */ - return 0; - } - - n = read(fd, buffer, sizeof(buffer)); - close(fd); - - if (n < 0) { - return 0; /* chances: slim..none */ - } - - buffer[n--] = '\0'; - - /* exit_signal is the second to last field so we look backwards. - * XXX if newer kernels drop more turds in this file we'll need - * to go the other way. luckily linux has no real api for this shit. - */ - - /* skip trailing crap */ - while ((n > 0) && !isdigit(buffer[n--])) ; - - while (offset-- > 0) { - /* skip last field */ - while ((n > 0) && isdigit(buffer[n--])) ; - - /* skip whitespace */ - while ((n > 0) && !isdigit(buffer[n--])) ; - } - - if (n < 3) { - return 0; /* hulk smashed /proc? */ - } - - ptr = &buffer[n]; - /* - * '17' == SIGCHLD == real process. - * '33' and '0' are threads - */ - if ((*ptr++ == '1') && - (*ptr++ == '7') && - (*ptr++ == ' ')) - { - return 0; - } - - return 1; -} - -int sigar_os_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - DIR *dirp = opendir(PROCP_FS_ROOT); - struct dirent *ent, dbuf; - register const int threadbadhack = !sigar->has_nptl; - - if (!dirp) { - return errno; - } - - if (threadbadhack && (sigar->proc_signal_offset == -1)) { - sigar->proc_signal_offset = get_proc_signal_offset(); - } - - while (readdir_r(dirp, &dbuf, &ent) == 0) { - if (!ent) { - break; - } - - if (!sigar_isdigit(*ent->d_name)) { - continue; - } - - if (threadbadhack && - proc_isthread(sigar, ent->d_name, strlen(ent->d_name))) - { - continue; - } - - /* XXX: more sanity checking */ - - SIGAR_PROC_LIST_GROW(proclist); - - proclist->data[proclist->number++] = - strtoul(ent->d_name, NULL, 10); - } - - closedir(dirp); - - return SIGAR_OK; -} - -static int proc_stat_read(sigar_t *sigar, sigar_pid_t pid) -{ - char buffer[BUFSIZ], *ptr=buffer, *tmp; - unsigned int len; - linux_proc_stat_t *pstat = &sigar->last_proc_stat; - int status; - - time_t timenow = time(NULL); - - /* - * short-lived cache read/parse of last /proc/pid/stat - * as this info is spread out across a few functions. - */ - if (pstat->pid == pid) { - if ((timenow - pstat->mtime) < SIGAR_LAST_PROC_EXPIRE) { - return SIGAR_OK; - } - } - - pstat->pid = pid; - pstat->mtime = timenow; - - status = SIGAR_PROC_FILE2STR(buffer, pid, PROC_PSTAT); - - if (status != SIGAR_OK) { - return status; - } - - if (!(ptr = strchr(ptr, '('))) { - return EINVAL; - } - if (!(tmp = strrchr(++ptr, ')'))) { - return EINVAL; - } - len = tmp-ptr; - - if (len >= sizeof(pstat->name)) { - len = sizeof(pstat->name)-1; - } - - /* (1,2) */ - memcpy(pstat->name, ptr, len); - pstat->name[len] = '\0'; - ptr = tmp+1; - - SIGAR_SKIP_SPACE(ptr); - pstat->state = *ptr++; /* (3) */ - SIGAR_SKIP_SPACE(ptr); - - pstat->ppid = sigar_strtoul(ptr); /* (4) */ - ptr = sigar_skip_token(ptr); /* (5) pgrp */ - ptr = sigar_skip_token(ptr); /* (6) session */ - pstat->tty = sigar_strtoul(ptr); /* (7) */ - ptr = sigar_skip_token(ptr); /* (8) tty pgrp */ - - ptr = sigar_skip_token(ptr); /* (9) flags */ - pstat->minor_faults = sigar_strtoull(ptr); /* (10) */ - ptr = sigar_skip_token(ptr); /* (11) cmin flt */ - pstat->major_faults = sigar_strtoull(ptr); /* (12) */ - ptr = sigar_skip_token(ptr); /* (13) cmaj flt */ - - pstat->utime = SIGAR_TICK2MSEC(sigar_strtoull(ptr)); /* (14) */ - pstat->stime = SIGAR_TICK2MSEC(sigar_strtoull(ptr)); /* (15) */ - - ptr = sigar_skip_token(ptr); /* (16) cutime */ - ptr = sigar_skip_token(ptr); /* (17) cstime */ - - pstat->priority = sigar_strtoul(ptr); /* (18) */ - pstat->nice = sigar_strtoul(ptr); /* (19) */ - - ptr = sigar_skip_token(ptr); /* (20) timeout */ - ptr = sigar_skip_token(ptr); /* (21) it_real_value */ - - pstat->start_time = sigar_strtoul(ptr); /* (22) */ - pstat->start_time /= sigar->ticks; - pstat->start_time += sigar->boot_time; /* seconds */ - pstat->start_time *= 1000; /* milliseconds */ - - pstat->vsize = sigar_strtoull(ptr); /* (23) */ - pstat->rss = pageshift(sigar_strtoull(ptr)); /* (24) */ - - ptr = sigar_skip_token(ptr); /* (25) rlim */ - ptr = sigar_skip_token(ptr); /* (26) startcode */ - ptr = sigar_skip_token(ptr); /* (27) endcode */ - ptr = sigar_skip_token(ptr); /* (28) startstack */ - ptr = sigar_skip_token(ptr); /* (29) kstkesp */ - ptr = sigar_skip_token(ptr); /* (30) kstkeip */ - ptr = sigar_skip_token(ptr); /* (31) signal */ - ptr = sigar_skip_token(ptr); /* (32) blocked */ - ptr = sigar_skip_token(ptr); /* (33) sigignore */ - ptr = sigar_skip_token(ptr); /* (34) sigcache */ - ptr = sigar_skip_token(ptr); /* (35) wchan */ - ptr = sigar_skip_token(ptr); /* (36) nswap */ - ptr = sigar_skip_token(ptr); /* (37) cnswap */ - ptr = sigar_skip_token(ptr); /* (38) exit_signal */ - - pstat->processor = sigar_strtoul(ptr); /* (39) */ - - return SIGAR_OK; -} - -int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_mem_t *procmem) -{ - char buffer[BUFSIZ], *ptr=buffer; - int status = proc_stat_read(sigar, pid); - linux_proc_stat_t *pstat = &sigar->last_proc_stat; - - procmem->minor_faults = pstat->minor_faults; - procmem->major_faults = pstat->major_faults; - procmem->page_faults = - procmem->minor_faults + procmem->major_faults; - - status = SIGAR_PROC_FILE2STR(buffer, pid, "/statm"); - - if (status != SIGAR_OK) { - return status; - } - - procmem->size = pageshift(sigar_strtoull(ptr)); - procmem->resident = pageshift(sigar_strtoull(ptr)); - procmem->share = pageshift(sigar_strtoull(ptr)); - - return SIGAR_OK; -} - -#define NO_ID_MSG "[proc_cred] /proc/%lu" PROC_PSTATUS " missing " - -int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_t *proccred) -{ - char buffer[BUFSIZ], *ptr; - int status = SIGAR_PROC_FILE2STR(buffer, pid, PROC_PSTATUS); - - if (status != SIGAR_OK) { - return status; - } - - if ((ptr = strstr(buffer, "\nUid:"))) { - ptr = sigar_skip_token(ptr); - - proccred->uid = sigar_strtoul(ptr); - proccred->euid = sigar_strtoul(ptr); - } - else { - sigar_log_printf(sigar, SIGAR_LOG_WARN, - NO_ID_MSG "Uid", pid); - return ENOENT; - } - - if ((ptr = strstr(ptr, "\nGid:"))) { - ptr = sigar_skip_token(ptr); - - proccred->gid = sigar_strtoul(ptr); - proccred->egid = sigar_strtoul(ptr); - } - else { - sigar_log_printf(sigar, SIGAR_LOG_WARN, - NO_ID_MSG "Gid", pid); - return ENOENT; - } - - return SIGAR_OK; -} - -int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_time_t *proctime) -{ - int status = proc_stat_read(sigar, pid); - linux_proc_stat_t *pstat = &sigar->last_proc_stat; - - if (status != SIGAR_OK) { - return status; - } - - proctime->user = pstat->utime; - proctime->sys = pstat->stime; - proctime->total = proctime->user + proctime->sys; - proctime->start_time = pstat->start_time; - - return SIGAR_OK; -} - -static int proc_status_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - char buffer[BUFSIZ], *ptr; - int status = SIGAR_PROC_FILE2STR(buffer, pid, PROC_PSTATUS); - - if (status != SIGAR_OK) { - return status; - } - - ptr = strstr(buffer, "\nThreads:"); - if (ptr) { - /* 2.6+ kernel only */ - ptr = sigar_skip_token(ptr); - procstate->threads = sigar_strtoul(ptr); - } - else { - procstate->threads = SIGAR_FIELD_NOTIMPL; - } - - return SIGAR_OK; -} - -int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - int status = proc_stat_read(sigar, pid); - linux_proc_stat_t *pstat = &sigar->last_proc_stat; - - if (status != SIGAR_OK) { - return status; - } - - memcpy(procstate->name, pstat->name, sizeof(procstate->name)); - procstate->state = pstat->state; - - procstate->ppid = pstat->ppid; - procstate->tty = pstat->tty; - procstate->priority = pstat->priority; - procstate->nice = pstat->nice; - procstate->processor = pstat->processor; - - if (sigar_cpu_core_rollup(sigar)) { - procstate->processor /= sigar->lcpu; - } - - proc_status_get(sigar, pid, procstate); - - return SIGAR_OK; -} - -int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - return sigar_procfs_args_get(sigar, pid, procargs); -} - -/* glibc 2.8 XXX use sysconf(_SC_ARG_MAX) */ -#ifndef ARG_MAX -#define ARG_MAX 131072 -#endif - -int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ - int fd; - char buffer[ARG_MAX]; /* XXX: ARG_MAX == 130k */ - char name[BUFSIZ]; - size_t len; - char *ptr, *end; - - /* optimize if pid == $$ and type == ENV_KEY */ - SIGAR_PROC_ENV_KEY_LOOKUP(); - - (void)SIGAR_PROC_FILENAME(name, pid, "/environ"); - - if ((fd = open(name, O_RDONLY)) < 0) { - if (errno == ENOENT) { - return ESRCH; - } - return errno; - } - - len = read(fd, buffer, sizeof(buffer)); - - close(fd); - - buffer[len] = '\0'; - ptr = buffer; - - end = buffer + len; - while (ptr < end) { - char *val = strchr(ptr, '='); - int klen, vlen, status; - char key[128]; /* XXX is there a max key size? */ - - if (val == NULL) { - /* not key=val format */ - break; - } - - klen = val - ptr; - SIGAR_SSTRCPY(key, ptr); - key[klen] = '\0'; - ++val; - - vlen = strlen(val); - status = procenv->env_getter(procenv->data, - key, klen, val, vlen); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - - ptr += (klen + 1 + vlen + 1); - } - - return SIGAR_OK; -} - -int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_fd_t *procfd) -{ - int status = - sigar_proc_fd_count(sigar, pid, &procfd->total); - - return status; -} - -int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ - int len; - char name[BUFSIZ]; - - (void)SIGAR_PROC_FILENAME(name, pid, "/cwd"); - - if ((len = readlink(name, procexe->cwd, - sizeof(procexe->cwd)-1)) < 0) - { - return errno; - } - - procexe->cwd[len] = '\0'; - - (void)SIGAR_PROC_FILENAME(name, pid, "/exe"); - - if ((len = readlink(name, procexe->name, - sizeof(procexe->name)-1)) < 0) - { - return errno; - } - - procexe->name[len] = '\0'; - - (void)SIGAR_PROC_FILENAME(name, pid, "/root"); - - if ((len = readlink(name, procexe->root, - sizeof(procexe->root)-1)) < 0) - { - return errno; - } - - procexe->root[len] = '\0'; - - return SIGAR_OK; -} - -int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods) -{ - FILE *fp; - char buffer[BUFSIZ], *ptr; - unsigned long inode, last_inode = 0; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/maps"); - - if (!(fp = fopen(buffer, "r"))) { - return errno; - } - - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - int len, status; - /* skip region, flags, offset, dev */ - ptr = sigar_skip_multiple_token(ptr, 4); - inode = sigar_strtoul(ptr); - - if ((inode == 0) || (inode == last_inode)) { - last_inode = 0; - continue; - } - - last_inode = inode; - SIGAR_SKIP_SPACE(ptr); - len = strlen(ptr); - ptr[len-1] = '\0'; /* chop \n */ - - status = - procmods->module_getter(procmods->data, - ptr, len-1); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - } - - fclose(fp); - - return SIGAR_OK; -} - -int sigar_thread_cpu_get(sigar_t *sigar, - sigar_uint64_t id, - sigar_thread_cpu_t *cpu) -{ - struct tms now; - - if (id != 0) { - return SIGAR_ENOTIMPL; - } - - times(&now); - - cpu->user = SIGAR_TICK2NSEC(now.tms_utime); - cpu->sys = SIGAR_TICK2NSEC(now.tms_stime); - cpu->total = SIGAR_TICK2NSEC(now.tms_utime + now.tms_stime); - - return SIGAR_OK; -} - -#include - -int sigar_os_fs_type_get(sigar_file_system_t *fsp) -{ - char *type = fsp->sys_type_name; - - switch (*type) { - case 'e': - if (strnEQ(type, "ext", 3)) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'g': - if (strEQ(type, "gfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'h': - if (strEQ(type, "hpfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'j': - if (strnEQ(type, "jfs", 3)) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'o': - if (strnEQ(type, "ocfs", 4)) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'p': - if (strnEQ(type, "psfs", 4)) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'r': - if (strEQ(type, "reiserfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'v': - if (strEQ(type, "vzfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'x': - if (strEQ(type, "xfs") || strEQ(type, "xiafs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - } - - return fsp->type; -} - -int sigar_file_system_list_get(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - struct mntent ent; - char buf[1025]; /* buffer for strings within ent */ - FILE *fp; - sigar_file_system_t *fsp; - - if (!(fp = setmntent(MOUNTED, "r"))) { - return errno; - } - - sigar_file_system_list_create(fslist); - - while (getmntent_r(fp, &ent, buf, sizeof(buf))) { - SIGAR_FILE_SYSTEM_LIST_GROW(fslist); - - fsp = &fslist->data[fslist->number++]; - - fsp->type = SIGAR_FSTYPE_UNKNOWN; /* unknown, will be set later */ - SIGAR_SSTRCPY(fsp->dir_name, ent.mnt_dir); - SIGAR_SSTRCPY(fsp->dev_name, ent.mnt_fsname); - SIGAR_SSTRCPY(fsp->sys_type_name, ent.mnt_type); - SIGAR_SSTRCPY(fsp->options, ent.mnt_opts); - sigar_fs_type_get(fsp); - } - - endmntent(fp); - - return SIGAR_OK; -} - -#define ST_MAJOR(sb) major((sb).st_rdev) -#define ST_MINOR(sb) minor((sb).st_rdev) - -static int get_iostat_sys(sigar_t *sigar, - const char *dirname, - sigar_disk_usage_t *disk, - sigar_iodev_t **iodev) -{ - char stat[1025], dev[1025]; - char *name, *ptr, *fsdev; - int partition, status; - - if (!(*iodev = sigar_iodev_get(sigar, dirname))) { - return ENXIO; - } - - name = fsdev = (*iodev)->name; - - if (SIGAR_NAME_IS_DEV(name)) { - name += SSTRLEN(SIGAR_DEV_PREFIX); /* strip "/dev/" */ - } - - while (!sigar_isdigit(*fsdev)) { - fsdev++; - } - - partition = strtoul(fsdev, NULL, 0); - *fsdev = '\0'; - - snprintf(stat, sizeof(stat), - SYS_BLOCK "/%s/%s%d/stat", name, name, partition); - - status = sigar_file2str(stat, dev, sizeof(dev)); - if (status != SIGAR_OK) { - return status; - } - - ptr = dev; - ptr = sigar_skip_token(ptr); - disk->reads = sigar_strtoull(ptr); - ptr = sigar_skip_token(ptr); - disk->writes = sigar_strtoull(ptr); - - disk->read_bytes = SIGAR_FIELD_NOTIMPL; - disk->write_bytes = SIGAR_FIELD_NOTIMPL; - disk->queue = SIGAR_FIELD_NOTIMPL; - - return SIGAR_OK; -} - -static int get_iostat_proc_dstat(sigar_t *sigar, - const char *dirname, - sigar_disk_usage_t *disk, - sigar_iodev_t **iodev, - sigar_disk_usage_t *device_usage) -{ - FILE *fp; - char buffer[1025]; - char *ptr; - struct stat sb; - int status=ENOENT; - - SIGAR_DISK_STATS_INIT(device_usage); - - if (!(*iodev = sigar_iodev_get(sigar, dirname))) { - return ENXIO; - } - - if (stat((*iodev)->name, &sb) < 0) { - return errno; - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - PROC_DISKSTATS " %s -> %s [%d,%d]", - dirname, (*iodev)->name, - ST_MAJOR(sb), ST_MINOR(sb)); - } - - if (!(fp = fopen(PROC_DISKSTATS, "r"))) { - return errno; - } - - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - unsigned long major, minor; - - major = sigar_strtoul(ptr); - minor = sigar_strtoul(ptr); - - if ((major == ST_MAJOR(sb)) && - ((minor == ST_MINOR(sb)) || (minor == 0))) - { - int num; - unsigned long - rio, rmerge, rsect, ruse, - wio, wmerge, wsect, wuse, - running, use, aveq; - - ptr = sigar_skip_token(ptr); /* name */ - - num = sscanf(ptr, - "%lu %lu %lu %lu " - "%lu %lu %lu %lu " - "%lu %lu %lu", - &rio, /* 1 # reads issued */ - &rmerge, /* 2 # reads merged */ - &rsect, /* 3 # sectors read */ - &ruse, /* 4 # millis spent reading */ - &wio, /* 5 # writes completed */ - &wmerge, /* 6 # writes merged */ - &wsect, /* 7 # sectors written */ - &wuse, /* 8 # millis spent writing */ - &running, /* 9 # I/Os currently in progress */ - &use, /* 10 # millis spent doing I/Os */ - &aveq); /* 11 # of millis spent doing I/Os (weighted) */ - - if (num == 11) { - disk->rtime = ruse; - disk->wtime = wuse; - disk->time = use; - disk->qtime = aveq; - } - else if (num == 4) { - wio = rsect; - rsect = rmerge; - wsect = ruse; - disk->time = disk->qtime = SIGAR_FIELD_NOTIMPL; - } - else { - status = ENOENT; - } - - disk->reads = rio; - disk->writes = wio; - disk->read_bytes = rsect; - disk->write_bytes = wsect; - - /* convert sectors to bytes (512 is fixed size in 2.6 kernels) */ - disk->read_bytes *= 512; - disk->write_bytes *= 512; - - if (minor == ST_MINOR(sb)) { - status = SIGAR_OK; - break; - } - else if (minor == 0) { - memcpy(device_usage, disk, sizeof(*device_usage)); - } - } - } - - fclose(fp); - - return status; -} - -static int get_iostat_procp(sigar_t *sigar, - const char *dirname, - sigar_disk_usage_t *disk, - sigar_iodev_t **iodev) -{ - FILE *fp; - char buffer[1025]; - char *ptr; - struct stat sb; - - if (!(*iodev = sigar_iodev_get(sigar, dirname))) { - return ENXIO; - } - - if (stat((*iodev)->name, &sb) < 0) { - return errno; - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - PROC_PARTITIONS " %s -> %s [%d,%d]", - dirname, (*iodev)->name, - ST_MAJOR(sb), ST_MINOR(sb)); - } - - if (!(fp = fopen(PROC_PARTITIONS, "r"))) { - return errno; - } - - (void)fgets(buffer, sizeof(buffer), fp); /* skip header */ - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - unsigned long major, minor; - - major = sigar_strtoul(ptr); - minor = sigar_strtoul(ptr); - - if ((major == ST_MAJOR(sb)) && (minor == ST_MINOR(sb))) { - ptr = sigar_skip_token(ptr); /* blocks */ - ptr = sigar_skip_token(ptr); /* name */ - disk->reads = sigar_strtoull(ptr); /* rio */ - ptr = sigar_skip_token(ptr); /* rmerge */ - disk->read_bytes = sigar_strtoull(ptr); /* rsect */ - disk->rtime = sigar_strtoull(ptr); /* ruse */ - disk->writes = sigar_strtoull(ptr); /* wio */ - ptr = sigar_skip_token(ptr); /* wmerge */ - disk->write_bytes = sigar_strtoull(ptr); /* wsect */ - disk->wtime = sigar_strtoull(ptr); /* wuse */ - ptr = sigar_skip_token(ptr); /* running */ - disk->time = sigar_strtoull(ptr); /* use */ - disk->qtime = sigar_strtoull(ptr); /* aveq */ - - /* convert sectors to bytes (512 is fixed size in 2.6 kernels) */ - disk->read_bytes *= 512; - disk->write_bytes *= 512; - - fclose(fp); - return SIGAR_OK; - } - } - - fclose(fp); - - return ENOENT; -} - -int sigar_disk_usage_get(sigar_t *sigar, const char *name, - sigar_disk_usage_t *disk) -{ - int status; - sigar_iodev_t *iodev = NULL; - sigar_disk_usage_t device_usage; - SIGAR_DISK_STATS_INIT(disk); - - /* - * 2.2 has metrics /proc/stat, but wtf is the device mapping? - * 2.4 has /proc/partitions w/ the metrics. - * 2.6 has /proc/partitions w/o the metrics. - * instead the metrics are within the /proc-like /sys filesystem. - * also has /proc/diskstats - */ - switch (sigar->iostat) { - case IOSTAT_SYS: - status = get_iostat_sys(sigar, name, disk, &iodev); - break; - case IOSTAT_DISKSTATS: - status = get_iostat_proc_dstat(sigar, name, disk, &iodev, &device_usage); - break; - case IOSTAT_PARTITIONS: - status = get_iostat_procp(sigar, name, disk, &iodev); - break; - /* - * case IOSTAT_SOME_OTHER_WIERD_THING: - * break; - */ - case IOSTAT_NONE: - default: - status = ENOENT; - break; - } - - if ((status == SIGAR_OK) && iodev) { - sigar_uptime_t uptime; - sigar_uint64_t interval, ios; - double tput, util; - sigar_disk_usage_t *partition_usage=NULL; - - sigar_uptime_get(sigar, &uptime); - - if (iodev->is_partition && - (sigar->iostat == IOSTAT_DISKSTATS)) - { - /* 2.6 kernels do not have per-partition times */ - partition_usage = disk; - disk = &device_usage; - } - - disk->snaptime = uptime.uptime; - - if (iodev->disk.snaptime) { - interval = disk->snaptime - iodev->disk.snaptime; - } - else { - interval = disk->snaptime; - } - - ios = - (disk->reads - iodev->disk.reads) + - (disk->writes - iodev->disk.writes); - - if (disk->time == SIGAR_FIELD_NOTIMPL) { - disk->service_time = SIGAR_FIELD_NOTIMPL; - } - else { - tput = ((double)ios) * HZ / interval; - util = ((double)(disk->time - iodev->disk.time)) / interval * HZ; - disk->service_time = tput ? util / tput : 0.0; - } - if (disk->qtime == SIGAR_FIELD_NOTIMPL) { - disk->queue = SIGAR_FIELD_NOTIMPL; - } - else { - util = ((double)(disk->qtime - iodev->disk.qtime)) / interval; - disk->queue = util / 1000.0; - } - - memcpy(&iodev->disk, disk, sizeof(iodev->disk)); - if (partition_usage) { - partition_usage->service_time = disk->service_time; - partition_usage->queue = disk->queue; - } - } - - return status; -} - -int sigar_file_system_usage_get(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage) -{ - int status = sigar_statvfs(sigar, dirname, fsusage); - - if (status != SIGAR_OK) { - return status; - } - - fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage); - - (void)sigar_disk_usage_get(sigar, dirname, &fsusage->disk); - - return SIGAR_OK; -} - -static SIGAR_INLINE char *cpu_info_strval(char *ptr) -{ - if ((ptr = strchr(ptr, ':'))) { - ptr++; - while (isspace (*ptr)) ptr++; - return ptr; - } - return NULL; -} - -static SIGAR_INLINE void cpu_info_strcpy(char *ptr, char *buf, int len) -{ - int slen; - ptr = cpu_info_strval(ptr); - if (!ptr) { - return; - } - slen = strlen(ptr); - strncpy(buf, ptr, len); - buf[len] = '\0'; - if (slen < len) { - buf[slen-1] = '\0'; /* rid \n */ - } -} - -static int get_cpu_info(sigar_t *sigar, sigar_cpu_info_t *info, - FILE *fp) -{ - char buffer[BUFSIZ], *ptr; - - int found = 0; - - /* UML vm wont have "cpu MHz" or "cache size" fields */ - info->mhz = 0; - info->cache_size = 0; - -#ifdef __powerpc64__ - SIGAR_SSTRCPY(info->vendor, "IBM"); -#endif - - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - switch (*ptr) { - case 'p': /* processor : 0 */ - if (strnEQ(ptr, "processor", 9)) { - found = 1; - } - break; - case 'v': - /* "vendor_id" or "vendor" */ - if (strnEQ(ptr, "vendor", 6)) { - cpu_info_strcpy(ptr, info->vendor, sizeof(info->vendor)); - if (strEQ(info->vendor, "GenuineIntel")) { - SIGAR_SSTRCPY(info->vendor, "Intel"); - } - else if (strEQ(info->vendor, "AuthenticAMD")) { - SIGAR_SSTRCPY(info->vendor, "AMD"); - } - } - break; - case 'f': - if (strnEQ(ptr, "family", 6)) { - /* IA64 version of "model name" */ - cpu_info_strcpy(ptr, info->model, sizeof(info->model)); - sigar_cpu_model_adjust(sigar, info); - } - break; - case 'm': - if (strnEQ(ptr, "model name", 10)) { - cpu_info_strcpy(ptr, info->model, sizeof(info->model)); - sigar_cpu_model_adjust(sigar, info); - } - break; - case 'c': - if (strnEQ(ptr, "cpu MHz", 7)) { - ptr = cpu_info_strval(ptr); - info->mhz = atoi(ptr); - } - else if (strnEQ(ptr, "cache size", 10)) { - ptr = cpu_info_strval(ptr); - info->cache_size = sigar_strtoul(ptr); - } -#ifdef __powerpc64__ - /* each /proc/cpuinfo entry looks like so: - * processor : 0 - * cpu : POWER5 (gr) - * clock : 1656.392000MHz - * revision : 2.2 - */ - else if (strnEQ(ptr, "clock", 5)) { - ptr = cpu_info_strval(ptr); - info->mhz = atoi(ptr); - } - else if (strnEQ(ptr, "cpu", 3)) { - cpu_info_strcpy(ptr, info->model, sizeof(info->model)); - - if ((ptr = strchr(info->model, ' '))) { - /* "POWER5 (gr)" -> "POWER5" */ - *ptr = '\0'; - } - } -#endif - break; - /* lone \n means end of info for this processor */ - case '\n': - return found; - } - } - - return found; -} - -/* /proc/cpuinfo MHz will change w/ AMD + PowerNow */ -static void get_cpuinfo_max_freq(sigar_cpu_info_t *cpu_info, int num) -{ - int status; - char max_freq[PATH_MAX]; - snprintf(max_freq, sizeof(max_freq), - "/sys/devices/system/cpu/cpu%d" - "/cpufreq/cpuinfo_max_freq", num); - - status = - sigar_file2str(max_freq, max_freq, sizeof(max_freq)-1); - - if (status == SIGAR_OK) { - cpu_info->mhz_max = atoi(max_freq) / 1000; - } -} - -static void get_cpuinfo_min_freq(sigar_cpu_info_t *cpu_info, int num) -{ - int status; - char min_freq[PATH_MAX]; - snprintf(min_freq, sizeof(min_freq), - "/sys/devices/system/cpu/cpu%d" - "/cpufreq/cpuinfo_min_freq", num); - - status = - sigar_file2str(min_freq, min_freq, sizeof(min_freq)-1); - - if (status == SIGAR_OK) { - cpu_info->mhz_min = atoi(min_freq) / 1000; - } -} - -int sigar_cpu_info_list_get(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos) -{ - FILE *fp; - int core_rollup = sigar_cpu_core_rollup(sigar), i=0; - - if (!(fp = fopen(PROC_FS_ROOT "cpuinfo", "r"))) { - return errno; - } - - (void)sigar_cpu_total_count(sigar); - sigar_cpu_info_list_create(cpu_infos); - - while (get_cpu_info(sigar, &cpu_infos->data[cpu_infos->number], fp)) { - sigar_cpu_info_t *info; - - if (core_rollup && (i++ % sigar->lcpu)) { - continue; /* fold logical processors */ - } - - info = &cpu_infos->data[cpu_infos->number]; - get_cpuinfo_max_freq(info, cpu_infos->number); - get_cpuinfo_min_freq(info, cpu_infos->number); - - info->total_cores = sigar->ncpu; - info->cores_per_socket = sigar->lcpu; - info->total_sockets = sigar_cpu_socket_count(sigar); - - ++cpu_infos->number; - SIGAR_CPU_INFO_LIST_GROW(cpu_infos); - } - - fclose(fp); - - return SIGAR_OK; -} - -static SIGAR_INLINE unsigned int hex2int(const char *x, int len) -{ - int i; - unsigned int j; - - for (i=0, j=0; isize = routelist->number = 0; - - if (!(fp = fopen(PROC_FS_ROOT "net/route", "r"))) { - return errno; - } - - sigar_net_route_list_create(routelist); - - (void)fgets(buffer, sizeof(buffer), fp); /* skip header */ - while (fgets(buffer, sizeof(buffer), fp)) { - int num; - - SIGAR_NET_ROUTE_LIST_GROW(routelist); - route = &routelist->data[routelist->number++]; - - /* XXX rid sscanf */ - num = sscanf(buffer, ROUTE_FMT, - route->ifname, net_addr, gate_addr, - &flags, &route->refcnt, &route->use, - &route->metric, mask_addr, - &route->mtu, &route->window, &route->irtt); - - if ((num < 10) || !(flags & RTF_UP)) { - --routelist->number; - continue; - } - - route->flags = flags; - - sigar_net_address_set(route->destination, hex2int(net_addr, HEX_ENT_LEN)); - sigar_net_address_set(route->gateway, hex2int(gate_addr, HEX_ENT_LEN)); - sigar_net_address_set(route->mask, hex2int(mask_addr, HEX_ENT_LEN)); - } - - fclose(fp); - - return SIGAR_OK; -} - -int sigar_net_interface_stat_get(sigar_t *sigar, const char *name, - sigar_net_interface_stat_t *ifstat) -{ - int found = 0; - char buffer[BUFSIZ]; - FILE *fp = fopen(PROC_FS_ROOT "net/dev", "r"); - - if (!fp) { - return errno; - } - - /* skip header */ - fgets(buffer, sizeof(buffer), fp); - fgets(buffer, sizeof(buffer), fp); - - while (fgets(buffer, sizeof(buffer), fp)) { - char *ptr, *dev; - - dev = buffer; - while (isspace(*dev)) { - dev++; - } - - if (!(ptr = strchr(dev, ':'))) { - continue; - } - - *ptr++ = 0; - - if (!strEQ(dev, name)) { - continue; - } - - found = 1; - ifstat->rx_bytes = sigar_strtoull(ptr); - ifstat->rx_packets = sigar_strtoull(ptr); - ifstat->rx_errors = sigar_strtoull(ptr); - ifstat->rx_dropped = sigar_strtoull(ptr); - ifstat->rx_overruns = sigar_strtoull(ptr); - ifstat->rx_frame = sigar_strtoull(ptr); - - /* skip: compressed multicast */ - ptr = sigar_skip_multiple_token(ptr, 2); - - ifstat->tx_bytes = sigar_strtoull(ptr); - ifstat->tx_packets = sigar_strtoull(ptr); - ifstat->tx_errors = sigar_strtoull(ptr); - ifstat->tx_dropped = sigar_strtoull(ptr); - ifstat->tx_overruns = sigar_strtoull(ptr); - ifstat->tx_collisions = sigar_strtoull(ptr); - ifstat->tx_carrier = sigar_strtoull(ptr); - - ifstat->speed = SIGAR_FIELD_NOTIMPL; - - break; - } - - fclose(fp); - - return found ? SIGAR_OK : ENXIO; -} - -static SIGAR_INLINE void convert_hex_address(sigar_net_address_t *address, - char *ptr, int len) -{ - if (len > HEX_ENT_LEN) { - int i; - for (i=0; i<=3; i++, ptr+=HEX_ENT_LEN) { - address->addr.in6[i] = hex2int(ptr, HEX_ENT_LEN); - } - - address->family = SIGAR_AF_INET6; - } - else { - address->addr.in = - (len == HEX_ENT_LEN) ? hex2int(ptr, HEX_ENT_LEN) : 0; - - address->family = SIGAR_AF_INET; - } -} - -typedef struct { - sigar_net_connection_list_t *connlist; - sigar_net_connection_t *conn; - unsigned long port; -} net_conn_getter_t; - -static int proc_net_walker(sigar_net_connection_walker_t *walker, - sigar_net_connection_t *conn) -{ - net_conn_getter_t *getter = - (net_conn_getter_t *)walker->data; - - if (getter->connlist) { - SIGAR_NET_CONNLIST_GROW(getter->connlist); - memcpy(&getter->connlist->data[getter->connlist->number++], - conn, sizeof(*conn)); - } - else { - if ((getter->port == conn->local_port) && - (conn->remote_port == 0)) - { - memcpy(getter->conn, conn, sizeof(*conn)); - return !SIGAR_OK; /* break loop */ - } - } - - return SIGAR_OK; /* continue loop */ -} - -#define SKIP_WHILE(p, c) while (*p == c) p++ -#define SKIP_PAST(p, c) \ - while(*p && (*p != c)) p++; \ - SKIP_WHILE(p, c) - -typedef struct { - FILE *fp; - int (*close)(FILE *); -} xproc_t; - -static FILE *xproc_open(const char *command, xproc_t *xproc) -{ - struct stat sb; - if (stat(command, &sb) == 0) { - if (sb.st_mode & S_IXUSR) { - /* executable script for testing large - * conn table where we can sleep() to better - * simulate /proc/net/tcp behavior - */ - xproc->fp = popen(command, "r"); - xproc->close = pclose; - } - else { - xproc->fp = fopen(command, "r"); - xproc->close = fclose; - } - return xproc->fp; - } - else { - return NULL; - } -} - -static int proc_net_read(sigar_net_connection_walker_t *walker, - const char *fname, - int type) -{ - FILE *fp = NULL; - char buffer[8192]; - sigar_t *sigar = walker->sigar; - char *ptr = sigar->proc_net; - int flags = walker->flags; - xproc_t xproc = { NULL, fclose }; - - if (ptr) { - snprintf(buffer, sizeof(buffer), - "%s/%s", ptr, - fname + sizeof(PROC_FS_ROOT)-1); - - if ((fp = xproc_open(buffer, &xproc))) { - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[proc_net] using %s", - buffer); - } - } - else if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[proc_net] cannot open %s", - buffer); - } - } - - if (!(fp || (fp = fopen(fname, "r")))) { - return errno; - } - - fgets(buffer, sizeof(buffer), fp); /* skip header */ - - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - sigar_net_connection_t conn; - char *laddr, *raddr; - int laddr_len=0, raddr_len=0; - int more; - - /* skip leading space */ - SKIP_WHILE(ptr, ' '); - - /* skip "%d: " */ - SKIP_PAST(ptr, ' '); - - laddr = ptr; - while (*ptr && (*ptr != ':')) { - laddr_len++; - ptr++; - } - SKIP_WHILE(ptr, ':'); - - conn.local_port = (strtoul(ptr, &ptr, 16) & 0xffff); - - SKIP_WHILE(ptr, ' '); - - raddr = ptr; - while (*ptr && (*ptr != ':')) { - raddr_len++; - ptr++; - } - SKIP_WHILE(ptr, ':'); - - conn.remote_port = (strtoul(ptr, &ptr, 16) & 0xffff); - - SKIP_WHILE(ptr, ' '); - - if (!((conn.remote_port && (flags & SIGAR_NETCONN_CLIENT)) || - (!conn.remote_port && (flags & SIGAR_NETCONN_SERVER)))) - { - continue; - } - - conn.type = type; - - convert_hex_address(&conn.local_address, - laddr, laddr_len); - - convert_hex_address(&conn.remote_address, - raddr, raddr_len); - - /* SIGAR_TCP_* currently matches TCP_* in linux/tcp.h */ - conn.state = hex2int(ptr, 2); - ptr += 2; - SKIP_WHILE(ptr, ' '); - - conn.send_queue = hex2int(ptr, HEX_ENT_LEN); - ptr += HEX_ENT_LEN+1; /* tx + ':' */; - - conn.receive_queue = hex2int(ptr, HEX_ENT_LEN); - ptr += HEX_ENT_LEN; - SKIP_WHILE(ptr, ' '); - - SKIP_PAST(ptr, ' '); /* tr:tm->whem */ - SKIP_PAST(ptr, ' '); /* retrnsmt */ - - conn.uid = sigar_strtoul(ptr); - - SKIP_WHILE(ptr, ' '); - SKIP_PAST(ptr, ' '); /* timeout */ - - conn.inode = sigar_strtoul(ptr); - - more = walker->add_connection(walker, &conn); - if (more != SIGAR_OK) { - xproc.close(fp); - return SIGAR_OK; - } - } - - xproc.close(fp); - - return SIGAR_OK; -} - -int sigar_net_connection_walk(sigar_net_connection_walker_t *walker) -{ - int flags = walker->flags; - int status; - - if (flags & SIGAR_NETCONN_TCP) { - status = proc_net_read(walker, - PROC_FS_ROOT "net/tcp", - SIGAR_NETCONN_TCP); - - if (status != SIGAR_OK) { - return status; - } - - status = proc_net_read(walker, - PROC_FS_ROOT "net/tcp6", - SIGAR_NETCONN_TCP); - - if (!((status == SIGAR_OK) || (status == ENOENT))) { - return status; - } - } - - if (flags & SIGAR_NETCONN_UDP) { - status = proc_net_read(walker, - PROC_FS_ROOT "net/udp", - SIGAR_NETCONN_UDP); - - if (status != SIGAR_OK) { - return status; - } - - status = proc_net_read(walker, - PROC_FS_ROOT "net/udp6", - SIGAR_NETCONN_UDP); - - if (!((status == SIGAR_OK) || (status == ENOENT))) { - return status; - } - } - - if (flags & SIGAR_NETCONN_RAW) { - status = proc_net_read(walker, - PROC_FS_ROOT "net/raw", - SIGAR_NETCONN_RAW); - - if (status != SIGAR_OK) { - return status; - } - - status = proc_net_read(walker, - PROC_FS_ROOT "net/raw6", - SIGAR_NETCONN_RAW); - - if (!((status == SIGAR_OK) || (status == ENOENT))) { - return status; - } - } - - /* XXX /proc/net/unix */ - - return SIGAR_OK; -} - -int sigar_net_connection_list_get(sigar_t *sigar, - sigar_net_connection_list_t *connlist, - int flags) -{ - int status; - sigar_net_connection_walker_t walker; - net_conn_getter_t getter; - - sigar_net_connection_list_create(connlist); - - getter.conn = NULL; - getter.connlist = connlist; - - walker.sigar = sigar; - walker.flags = flags; - walker.data = &getter; - walker.add_connection = proc_net_walker; - - status = sigar_net_connection_walk(&walker); - - if (status != SIGAR_OK) { - sigar_net_connection_list_destroy(sigar, connlist); - } - - return status; -} - -static int sigar_net_connection_get(sigar_t *sigar, - sigar_net_connection_t *netconn, - unsigned long port, - int flags) -{ - int status; - sigar_net_connection_walker_t walker; - net_conn_getter_t getter; - - getter.conn = netconn; - getter.connlist = NULL; - getter.port = port; - - walker.sigar = sigar; - walker.flags = flags; - walker.data = &getter; - walker.add_connection = proc_net_walker; - - status = sigar_net_connection_walk(&walker); - - return status; -} - -int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig) -{ - FILE *fp; - char addr[32+1], ifname[8+1]; - int status = SIGAR_ENOENT; - int idx, prefix, scope, flags; - - if (!(fp = fopen(PROC_FS_ROOT "net/if_inet6", "r"))) { - return errno; - } - - while (fscanf(fp, "%32s %02x %02x %02x %02x %8s\n", - addr, &idx, &prefix, &scope, &flags, ifname) != EOF) - { - if (strEQ(name, ifname)) { - status = SIGAR_OK; - break; - } - } - - fclose(fp); - - if (status == SIGAR_OK) { - int i=0; - unsigned char *addr6 = (unsigned char *)&(ifconfig->address6.addr.in6); - char *ptr = addr; - - for (i=0; i<16; i++, ptr+=2) { - addr6[i] = (unsigned char)hex2int(ptr, 2); - } - - ifconfig->prefix6_length = prefix; - ifconfig->scope6 = scope; - } - - return status; -} - -#define SNMP_TCP_PREFIX "Tcp: " - -SIGAR_DECLARE(int) -sigar_tcp_get(sigar_t *sigar, - sigar_tcp_t *tcp) -{ - FILE *fp; - char buffer[1024], *ptr=buffer; - int status = SIGAR_ENOENT; - - if (!(fp = fopen(PROC_FS_ROOT "net/snmp", "r"))) { - return errno; - } - - while (fgets(buffer, sizeof(buffer), fp)) { - if (strnEQ(buffer, SNMP_TCP_PREFIX, sizeof(SNMP_TCP_PREFIX)-1)) { - if (fgets(buffer, sizeof(buffer), fp)) { - status = SIGAR_OK; - break; - } - } - } - - fclose(fp); - - if (status == SIGAR_OK) { - /* assuming field order, same in 2.2, 2.4 and 2.6 kernels */ - /* Tcp: RtoAlgorithm RtoMin RtoMax MaxConn */ - ptr = sigar_skip_multiple_token(ptr, 5); - tcp->active_opens = sigar_strtoull(ptr); - tcp->passive_opens = sigar_strtoull(ptr); - tcp->attempt_fails = sigar_strtoull(ptr); - tcp->estab_resets = sigar_strtoull(ptr); - tcp->curr_estab = sigar_strtoull(ptr); - tcp->in_segs = sigar_strtoull(ptr); - tcp->out_segs = sigar_strtoull(ptr); - tcp->retrans_segs = sigar_strtoull(ptr); - tcp->in_errs = sigar_strtoull(ptr); - tcp->out_rsts = sigar_strtoull(ptr); - } - - return status; -} - -static int sigar_proc_nfs_gets(char *file, char *tok, - char *buffer, size_t size) -{ - int status = ENOENT; - int len = strlen(tok); - FILE *fp = fopen(file, "r"); - - if (!fp) { - return SIGAR_ENOTIMPL; - } - - while (fgets(buffer, size, fp)) { - if (strnEQ(buffer, tok, len)) { - status = SIGAR_OK; - break; - } - } - - fclose(fp); - - return status; -} - -static int sigar_nfs_v2_get(char *file, sigar_nfs_v2_t *nfs) -{ - char buffer[BUFSIZ], *ptr=buffer; - int status = - sigar_proc_nfs_gets(file, - "proc2", buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return status; - } - - ptr = sigar_skip_multiple_token(ptr, 2); - - nfs->null = sigar_strtoull(ptr); - nfs->getattr = sigar_strtoull(ptr); - nfs->setattr = sigar_strtoull(ptr); - nfs->root = sigar_strtoull(ptr); - nfs->lookup = sigar_strtoull(ptr); - nfs->readlink = sigar_strtoull(ptr); - nfs->read = sigar_strtoull(ptr); - nfs->writecache = sigar_strtoull(ptr); - nfs->write = sigar_strtoull(ptr); - nfs->create = sigar_strtoull(ptr); - nfs->remove = sigar_strtoull(ptr); - nfs->rename = sigar_strtoull(ptr); - nfs->link = sigar_strtoull(ptr); - nfs->symlink = sigar_strtoull(ptr); - nfs->mkdir = sigar_strtoull(ptr); - nfs->rmdir = sigar_strtoull(ptr); - nfs->readdir = sigar_strtoull(ptr); - nfs->fsstat = sigar_strtoull(ptr); - - return SIGAR_OK; -} - -int sigar_nfs_client_v2_get(sigar_t *sigar, - sigar_nfs_client_v2_t *nfs) -{ - return sigar_nfs_v2_get(PROC_FS_ROOT "net/rpc/nfs", - (sigar_nfs_v2_t *)nfs); -} - -int sigar_nfs_server_v2_get(sigar_t *sigar, - sigar_nfs_server_v2_t *nfs) -{ - return sigar_nfs_v2_get(PROC_FS_ROOT "net/rpc/nfsd", - (sigar_nfs_v2_t *)nfs); -} - -static int sigar_nfs_v3_get(char *file, sigar_nfs_v3_t *nfs) -{ - char buffer[BUFSIZ], *ptr=buffer; - int status = - sigar_proc_nfs_gets(file, - "proc3", buffer, sizeof(buffer)); - - if (status != SIGAR_OK) { - return status; - } - - ptr = sigar_skip_multiple_token(ptr, 2); - - nfs->null = sigar_strtoull(ptr); - nfs->getattr = sigar_strtoull(ptr); - nfs->setattr = sigar_strtoull(ptr); - nfs->lookup = sigar_strtoull(ptr); - nfs->access = sigar_strtoull(ptr); - nfs->readlink = sigar_strtoull(ptr); - nfs->read = sigar_strtoull(ptr); - nfs->write = sigar_strtoull(ptr); - nfs->create = sigar_strtoull(ptr); - nfs->mkdir = sigar_strtoull(ptr); - nfs->symlink = sigar_strtoull(ptr); - nfs->mknod = sigar_strtoull(ptr); - nfs->remove = sigar_strtoull(ptr); - nfs->rmdir = sigar_strtoull(ptr); - nfs->rename = sigar_strtoull(ptr); - nfs->link = sigar_strtoull(ptr); - nfs->readdir = sigar_strtoull(ptr); - nfs->readdirplus = sigar_strtoull(ptr); - nfs->fsstat = sigar_strtoull(ptr); - nfs->fsinfo = sigar_strtoull(ptr); - nfs->pathconf = sigar_strtoull(ptr); - nfs->commit = sigar_strtoull(ptr); - - return SIGAR_OK; -} - -int sigar_nfs_client_v3_get(sigar_t *sigar, - sigar_nfs_client_v3_t *nfs) -{ - return sigar_nfs_v3_get(PROC_FS_ROOT "net/rpc/nfs", - (sigar_nfs_v3_t *)nfs); -} - -int sigar_nfs_server_v3_get(sigar_t *sigar, - sigar_nfs_server_v3_t *nfs) -{ - return sigar_nfs_v3_get(PROC_FS_ROOT "net/rpc/nfsd", - (sigar_nfs_v3_t *)nfs); -} - -#include - -static char *get_hw_type(int type) -{ - switch (type) { - case ARPHRD_AX25: - return "ax25"; - case ARPHRD_ECONET: - return "ec"; - case ARPHRD_ETHER: - return "ether"; - case ARPHRD_FDDI: - return "fddi"; - case ARPHRD_DLCI: - return "dlci"; - case ARPHRD_FRAD: - return "frad"; - case ARPHRD_HDLC: - return "hdlc"; - case ARPHRD_LAPB: - return "lapb"; - case ARPHRD_HIPPI: - return "hippi"; - case ARPHRD_IRDA: - return "irda"; - case ARPHRD_LOOPBACK: - return "loop"; - case ARPHRD_NETROM: - return "netrom"; - case ARPHRD_PPP: - return "ppp"; - case ARPHRD_ROSE: - return "rose"; - case ARPHRD_SIT: - return "sit"; - case ARPHRD_SLIP: - return "slip"; - case ARPHRD_CSLIP: - return "cslip"; - case ARPHRD_SLIP6: - return "slip6"; - case ARPHRD_CSLIP6: - return "cslip6"; - case ARPHRD_ADAPT: - return "adaptive"; - case ARPHRD_IEEE802: - return "tr"; - case ARPHRD_IEEE802_TR: - return "tr"; - case ARPHRD_TUNNEL: - return "tunnel"; - case ARPHRD_X25: - return "x25"; - default: - return "unknown"; - } -} - -int sigar_arp_list_get(sigar_t *sigar, - sigar_arp_list_t *arplist) -{ - FILE *fp; - char buffer[1024]; - char net_addr[128], hwaddr[128], mask_addr[128]; - int flags, type, status; - sigar_arp_t *arp; - - arplist->size = arplist->number = 0; - - if (!(fp = fopen(PROC_FS_ROOT "net/arp", "r"))) { - return errno; - } - - sigar_arp_list_create(arplist); - - (void)fgets(buffer, sizeof(buffer), fp); /* skip header */ - while (fgets(buffer, sizeof(buffer), fp)) { - int num; - - SIGAR_ARP_LIST_GROW(arplist); - arp = &arplist->data[arplist->number++]; - - /* XXX rid sscanf */ - num = sscanf(buffer, "%128s 0x%x 0x%x %128s %128s %16s", - net_addr, &type, &flags, - hwaddr, mask_addr, arp->ifname); - - if (num < 6) { - --arplist->number; - continue; - } - - arp->flags = flags; - status = inet_pton(AF_INET, net_addr, &arp->address.addr); - if (status > 0) { - arp->address.family = SIGAR_AF_INET; - } - else if ((status = inet_pton(AF_INET6, net_addr, &arp->address.addr)) > 0) { - arp->address.family = SIGAR_AF_INET6; - } - else { - sigar_log_printf(sigar, SIGAR_LOG_WARN, - "[arp] failed to parse address='%s' (%s)\n", net_addr, - ((status == 0) ? "Invalid format" : sigar_strerror(sigar, errno))); - --arplist->number; - continue; - } - - num = sscanf(hwaddr, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - &arp->hwaddr.addr.mac[0], - &arp->hwaddr.addr.mac[1], - &arp->hwaddr.addr.mac[2], - &arp->hwaddr.addr.mac[3], - &arp->hwaddr.addr.mac[4], - &arp->hwaddr.addr.mac[5]); - if (num < 6) { - sigar_log_printf(sigar, SIGAR_LOG_WARN, - "[arp] failed to parse hwaddr='%s' (%s)\n", hwaddr); - --arplist->number; - continue; - } - arp->hwaddr.family = SIGAR_AF_LINK; - - SIGAR_SSTRCPY(arp->type, get_hw_type(type)); - } - - fclose(fp); - - return SIGAR_OK; -} - -int sigar_proc_port_get(sigar_t *sigar, int protocol, - unsigned long port, sigar_pid_t *pid) -{ - int status; - sigar_net_connection_t netconn; - DIR *dirp; - struct dirent *ent, dbuf; - - SIGAR_ZERO(&netconn); - *pid = 0; - - status = sigar_net_connection_get(sigar, &netconn, port, - SIGAR_NETCONN_SERVER|protocol); - - if (status != SIGAR_OK) { - return status; - } - - if (netconn.local_port != port) { - return SIGAR_OK; /* XXX or ENOENT? */ - } - - if (!(dirp = opendir(PROCP_FS_ROOT))) { - return errno; - } - - while (readdir_r(dirp, &dbuf, &ent) == 0) { - DIR *fd_dirp; - struct dirent *fd_ent, fd_dbuf; - struct stat sb; - char fd_name[BUFSIZ], pid_name[BUFSIZ]; - int len, slen; - - if (ent == NULL) { - break; - } - - if (!sigar_isdigit(*ent->d_name)) { - continue; - } - - /* sprintf(pid_name, "/proc/%s", ent->d_name) */ - memcpy(&pid_name[0], PROCP_FS_ROOT, SSTRLEN(PROCP_FS_ROOT)); - len = SSTRLEN(PROCP_FS_ROOT); - pid_name[len++] = '/'; - - slen = strlen(ent->d_name); - memcpy(&pid_name[len], ent->d_name, slen); - len += slen; - pid_name[len] = '\0'; - - if (stat(pid_name, &sb) < 0) { - continue; - } - if (sb.st_uid != netconn.uid) { - continue; - } - - /* sprintf(fd_name, "%s/fd", pid_name) */ - memcpy(&fd_name[0], pid_name, len); - memcpy(&fd_name[len], "/fd", 3); - fd_name[len+=3] = '\0'; - - if (!(fd_dirp = opendir(fd_name))) { - continue; - } - - while (readdir_r(fd_dirp, &fd_dbuf, &fd_ent) == 0) { - char fd_ent_name[BUFSIZ]; - - if (fd_ent == NULL) { - break; - } - - if (!sigar_isdigit(*fd_ent->d_name)) { - continue; - } - - /* sprintf(fd_ent_name, "%s/%s", fd_name, fd_ent->d_name) */ - slen = strlen(fd_ent->d_name); - memcpy(&fd_ent_name[0], fd_name, len); - fd_ent_name[len] = '/'; - memcpy(&fd_ent_name[len+1], fd_ent->d_name, slen); - fd_ent_name[len+1+slen] = '\0'; - - if (stat(fd_ent_name, &sb) < 0) { - continue; - } - - if (sb.st_ino == netconn.inode) { - closedir(fd_dirp); - closedir(dirp); - *pid = strtoul(ent->d_name, NULL, 10); - return SIGAR_OK; - } - - } - - closedir(fd_dirp); - } - - closedir(dirp); - - return SIGAR_OK; -} - -static void generic_vendor_parse(char *line, sigar_sys_info_t *info) -{ - char *ptr; - int len = 0; - - while (*line) { - SIGAR_SKIP_SPACE(line); - if (!isdigit(*line)) { - ++line; - continue; - } - - ptr = line; - while ((isdigit(*ptr) || (*ptr == '.'))) { - ++ptr; - ++len; - } - - if (len) { - /* sanity check */ - if (len > sizeof(info->vendor_version)) { - continue; - } - memcpy(info->vendor_version, line, len);/*XXX*/ - info->vendor_version[len] = '\0'; - return; - } - } -} - -static void redhat_vendor_parse(char *line, sigar_sys_info_t *info) -{ - char *start, *end; - - generic_vendor_parse(line, info); /* super.parse */ - - if ((start = strchr(line, '('))) { - ++start; - if ((end = strchr(start, ')'))) { - int len = end-start; - memcpy(info->vendor_code_name, start, len);/*XXX*/ - info->vendor_code_name[len] = '\0'; - } - } - -#define RHEL_PREFIX "Red Hat Enterprise Linux " -#define CENTOS_VENDOR "CentOS" -#define SL_VENDOR "Scientific Linux" - - if (strnEQ(line, RHEL_PREFIX, sizeof(RHEL_PREFIX)-1)) { - snprintf(info->vendor_version, - sizeof(info->vendor_version), - "Enterprise Linux %c", - info->vendor_version[0]); - } - else if (strnEQ(line, CENTOS_VENDOR, sizeof(CENTOS_VENDOR)-1)) { - SIGAR_SSTRCPY(info->vendor, CENTOS_VENDOR); - } - else if (strnEQ(line, SL_VENDOR, sizeof(SL_VENDOR)-1)) { - SIGAR_SSTRCPY(info->vendor, SL_VENDOR); - } -} - -#define is_quote(c) ((c == '\'') || (c == '"')) - -static void kv_parse(char *data, sigar_sys_info_t *info, - void (*func)(sigar_sys_info_t *, char *, char *)) -{ - char *ptr = data; - int len = strlen(data); - char *end = data+len; - - while (ptr < end) { - char *val = strchr(ptr, '='); - int klen, vlen; - char key[256], *ix; - - if (!val) { - continue; - } - klen = val - ptr; - SIGAR_SSTRCPY(key, ptr); - key[klen] = '\0'; - ++val; - - if ((ix = strchr(val, '\n'))) { - *ix = '\0'; - } - vlen = strlen(val); - if (is_quote(*val)) { - if (is_quote(val[vlen-1])) { - val[vlen-1] = '\0'; - } - ++val; - } - - func(info, key, val); - - ptr += (klen + 1 + vlen + 1); - } -} - -static void lsb_parse(sigar_sys_info_t *info, - char *key, char *val) -{ - if (strEQ(key, "DISTRIB_ID")) { - SIGAR_SSTRCPY(info->vendor, val); - } - else if (strEQ(key, "DISTRIB_RELEASE")) { - SIGAR_SSTRCPY(info->vendor_version, val); - } - else if (strEQ(key, "DISTRIB_CODENAME")) { - SIGAR_SSTRCPY(info->vendor_code_name, val); - } -} - -static void lsb_vendor_parse(char *data, sigar_sys_info_t *info) -{ - kv_parse(data, info, lsb_parse); -} - -static void xen_parse(sigar_sys_info_t *info, - char *key, char *val) -{ - if (strEQ(key, "PRODUCT_VERSION")) { - SIGAR_SSTRCPY(info->vendor_version, val); - } - else if (strEQ(key, "KERNEL_VERSION")) { - SIGAR_SSTRCPY(info->version, val); - } -} - -static void xen_vendor_parse(char *data, sigar_sys_info_t *info) -{ - kv_parse(data, info, xen_parse); - - snprintf(info->description, - sizeof(info->description), - "XenServer %s", - info->vendor_version); -} - -typedef struct { - const char *name; - const char *file; - void (*parse)(char *, sigar_sys_info_t *); -} linux_vendor_info_t; - -static linux_vendor_info_t linux_vendors[] = { - { "Fedora", "/etc/fedora-release", NULL }, - { "SuSE", "/etc/SuSE-release", NULL }, - { "Gentoo", "/etc/gentoo-release", NULL }, - { "Slackware", "/etc/slackware-version", NULL }, - { "Mandrake", "/etc/mandrake-release", NULL }, - { "VMware", "/proc/vmware/version", NULL }, - { "XenSource", "/etc/xensource-inventory", xen_vendor_parse }, - { "Red Hat", "/etc/redhat-release", redhat_vendor_parse }, - { "lsb", "/etc/lsb-release", lsb_vendor_parse }, - { "Debian", "/etc/debian_version", NULL }, - { NULL } -}; - -static int get_linux_vendor_info(sigar_sys_info_t *info) -{ - int i, status = ENOENT; - /* env vars for testing */ - const char *release_file = getenv("SIGAR_OS_RELEASE_FILE"); - const char *vendor_name = getenv("SIGAR_OS_VENDOR_NAME"); - char buffer[8192], *data; - linux_vendor_info_t *vendor = NULL; - - for (i=0; linux_vendors[i].name; i++) { - struct stat sb; - vendor = &linux_vendors[i]; - - if (release_file && vendor_name) { - if (!strEQ(vendor->name, vendor_name)) { - continue; - } - } - else { - if (stat(vendor->file, &sb) < 0) { - continue; - } - release_file = vendor->file; - } - - status = - sigar_file2str(release_file, buffer, sizeof(buffer)-1); - - break; - } - - if (status != SIGAR_OK) { - return status; - } - - data = buffer; - - SIGAR_SSTRCPY(info->vendor, vendor->name); - - if (vendor->parse) { - vendor->parse(data, info); - } - else { - generic_vendor_parse(data, info); - } - - if (info->description[0] == '\0') { - snprintf(info->description, - sizeof(info->description), - "%s %s", - info->vendor, info->vendor_version); - } - - return SIGAR_OK; -} - -int sigar_os_sys_info_get(sigar_t *sigar, - sigar_sys_info_t *sysinfo) -{ - - get_linux_vendor_info(sysinfo); - - return SIGAR_OK; -} diff --git a/vendor/sigar/src/os/linux/sigar_os.h b/vendor/sigar/src/os/linux/sigar_os.h deleted file mode 100644 index 29a2ba3..0000000 --- a/vendor/sigar/src/os/linux/sigar_os.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2004-2008 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_OS_H -#define SIGAR_OS_H - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -typedef struct { - sigar_pid_t pid; - time_t mtime; - sigar_uint64_t vsize; - sigar_uint64_t rss; - sigar_uint64_t minor_faults; - sigar_uint64_t major_faults; - sigar_uint64_t ppid; - int tty; - int priority; - int nice; - sigar_uint64_t start_time; - sigar_uint64_t utime; - sigar_uint64_t stime; - char name[SIGAR_PROC_NAME_LEN]; - char state; - int processor; -} linux_proc_stat_t; - -typedef enum { - IOSTAT_NONE, - IOSTAT_PARTITIONS, /* 2.4 */ - IOSTAT_DISKSTATS, /* 2.6 */ - IOSTAT_SYS /* 2.6 */ -} linux_iostat_e; - -struct sigar_t { - SIGAR_T_BASE; - int pagesize; - int ram; - int proc_signal_offset; - linux_proc_stat_t last_proc_stat; - int lcpu; - linux_iostat_e iostat; - char *proc_net; - /* Native POSIX Thread Library 2.6+ kernel */ - int has_nptl; -}; - -#define HAVE_STRERROR_R -#ifndef __USE_XOPEN2K -/* use gnu version of strerror_r */ -#define HAVE_STRERROR_R_GLIBC -#endif -#define HAVE_READDIR_R -#define HAVE_GETPWNAM_R -#define HAVE_GETPWUID_R -#define HAVE_GETGRGID_R - -#endif /* SIGAR_OS_H */ diff --git a/vendor/sigar/src/os/solaris/get_mib2.c b/vendor/sigar/src/os/solaris/get_mib2.c deleted file mode 100644 index fbcadc6..0000000 --- a/vendor/sigar/src/os/solaris/get_mib2.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * get_mib2() -- get MIB2 information from Solaris 2.[3-7] kernel - * - * V. Abell - * Purdue University Computing Center - */ - - -/* - * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana - * 47907. All rights reserved. - * - * Written by Victor A. Abell - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * - * 1. Neither Victor A Abell nor Purdue University are responsible for - * any consequences of the use of this software. - * - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Credit to Victor A. Abell and Purdue - * University must appear in documentation and sources. - * - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 4. This notice may not be removed or altered. - */ - -/* - * Altered for sigar: - * - remove static stuff to make thread-safe by Doug MacEachern (3/11/05) - */ - -#if 0 /*ndef lint -Wall -Werror*/ -static char copyright[] = -"@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n"; -#endif - -#include "get_mib2.h" - -#include -#include -#include -#include -#include -#include - -#ifdef DMALLOC -#include -#endif - -/* - * close_mib2() - close MIB2 access - * - * return: - * - * exit = GET_MIB2_OK if close succeeded - * GET_MIB2_* is the error code. - */ - -int -close_mib2(solaris_mib2_t *mib2) -{ - if (mib2->sd < 0) { - (void) strcpy(mib2->errmsg, "close_mib2: socket not open"); - return(GET_MIB2_ERR_NOTOPEN); - } - if (close(mib2->sd)) { - (void) sprintf(mib2->errmsg, "close_mib2: %s", strerror(errno)); - return(GET_MIB2_ERR_CLOSE); - } - mib2->sd = -1; - if (mib2->db_len && mib2->db) { - mib2->db_len = 0; - free((void *)mib2->db); - mib2->db = NULL; - } - if (mib2->smb_len && mib2->smb) { - mib2->smb_len = 0; - free((void *)mib2->smb); - mib2->smb = NULL; - } - return(GET_MIB2_OK); -} - - -/* - * get_mib2() - get MIB2 data - * - * return: - * - * exit = GET_MIB2_OK if get succeeded, and: - * *opt = opthdr structure address - * *data = data buffer address - * *datalen = size of data buffer - * GET_MIB2_* is the error code for failure. - */ - -int -get_mib2(solaris_mib2_t *mib2, - struct opthdr **opt, - char **data, - int *datalen) -{ - struct strbuf d; /* streams data buffer */ - int err; /* error code */ - int f; /* flags */ - int rc; /* reply code */ - - /* - * If MIB2 access isn't open, open it and issue the preliminary stream - * messages. - */ - if (mib2->sd < 0) { - /* - * Open access. Return on error. - */ - if ((err = open_mib2(mib2))) { - return(err); - } - /* - * Set up message request and option. - */ - mib2->req = (struct T_optmgmt_req *)mib2->smb; - mib2->op = (struct opthdr *)&mib2->smb[sizeof(struct T_optmgmt_req)]; - mib2->req->PRIM_type = T_OPTMGMT_REQ; - mib2->req->OPT_offset = sizeof(struct T_optmgmt_req); - mib2->req->OPT_length = sizeof(struct opthdr); - -#if defined(MI_T_CURRENT) - mib2->req->MGMT_flags = MI_T_CURRENT; -#else /* !defined(MI_T_CURRENT) */ -# if defined(T_CURRENT) - mib2->req->MGMT_flags = T_CURRENT; -# else /* !defined(T_CURRENT) */ -#error "Neither MI_T_CURRENT nor T_CURRENT are defined." -# endif /* defined(T_CURRENT) */ -#endif /* defined(MI_T_CURRENT) */ - - mib2->op->level = MIB2_IP; - mib2->op->name = mib2->op->len = 0; - mib2->ctlbuf.buf = mib2->smb; - mib2->ctlbuf.len = mib2->req->OPT_offset + mib2->req->OPT_length; - /* - * Put the message. - */ - if (putmsg(mib2->sd, &mib2->ctlbuf, (struct strbuf *)NULL, 0) == -1) { - (void) sprintf(mib2->errmsg, - "get_mib2: putmsg request: %s", strerror(errno)); - return(GET_MIB2_ERR_PUTMSG); - } - /* - * Set up to process replies. - */ - mib2->op_ack = (struct T_optmgmt_ack *)mib2->smb; - mib2->ctlbuf.maxlen = mib2->smb_len; - mib2->err_ack = (struct T_error_ack *)mib2->smb; - mib2->op = (struct opthdr *)&mib2->smb[sizeof(struct T_optmgmt_ack)]; - } - /* - * Get the next (first) reply message. - */ - f = 0; - if ((rc = getmsg(mib2->sd, &mib2->ctlbuf, NULL, &f)) < 0) { - (void) sprintf(mib2->errmsg, "get_mib2: getmsg(reply): %s", - strerror(errno)); - return(GET_MIB2_ERR_GETMSGR); - } - /* - * Check for end of data. - */ - if (rc == 0 - && mib2->ctlbuf.len >= sizeof(struct T_optmgmt_ack) - && mib2->op_ack->PRIM_type == T_OPTMGMT_ACK - && mib2->op_ack->MGMT_flags == T_SUCCESS - && mib2->op->len == 0) - { - err = close_mib2(mib2); - if (err) { - return(err); - } - return(GET_MIB2_EOD); - } - /* - * Check for error. - */ - if (mib2->ctlbuf.len >= sizeof(struct T_error_ack) - && mib2->err_ack->PRIM_type == T_ERROR_ACK) - { - (void) sprintf(mib2->errmsg, - "get_mib2: T_ERROR_ACK: len=%d, TLI=%#x, UNIX=%#x", - mib2->ctlbuf.len, - (int)mib2->err_ack->TLI_error, - (int)mib2->err_ack->UNIX_error); - return(GET_MIB2_ERR_ACK); - } - /* - * Check for no data. - */ - if (rc != MOREDATA - || mib2->ctlbuf.len < sizeof(struct T_optmgmt_ack) - || mib2->op_ack->PRIM_type != T_OPTMGMT_ACK - || mib2->op_ack->MGMT_flags != T_SUCCESS) - { - (void) sprintf(mib2->errmsg, - "get_mib2: T_OPTMGMT_ACK: " - "rc=%d len=%d type=%#x flags=%#x", - rc, mib2->ctlbuf.len, - (int)mib2->op_ack->PRIM_type, - (int)mib2->op_ack->MGMT_flags); - return(GET_MIB2_ERR_NODATA); - } - /* - * Allocate (or enlarge) the data buffer. - */ - if (mib2->op->len >= mib2->db_len) { - mib2->db_len = mib2->op->len; - if (mib2->db == NULL) { - mib2->db = (char *)malloc(mib2->db_len); - } - else { - mib2->db = (char *)realloc(mib2->db, mib2->db_len); - } - if (mib2->db == NULL) { - (void) sprintf(mib2->errmsg, - "get_mib2: no space for %d byte data buffer", - mib2->db_len); - return(GET_MIB2_ERR_NOSPC); - } - } - /* - * Get the data part of the message -- the MIB2 part. - */ - d.maxlen = mib2->op->len; - d.buf = mib2->db; - d.len = 0; - f = 0; - if ((rc = getmsg(mib2->sd, NULL, &d, &f)) < 0) { - (void) sprintf(mib2->errmsg, "get_mib2: getmsg(data): %s", - strerror(errno)); - return(GET_MIB2_ERR_GETMSGD); - } - if (rc) { - (void) sprintf(mib2->errmsg, - "get_mib2: getmsg(data): rc=%d maxlen=%d len=%d: %s", - rc, d.maxlen, d.len, strerror(errno)); - return(GET_MIB2_ERR_GETMSGD); - } - /* - * Compose a successful return. - */ - *opt = mib2->op; - *data = mib2->db; - *datalen = d.len; - return(GET_MIB2_OK); -} - - -/* - * open_mib2() - open access to MIB2 data - * - * return: - * - * exit = GET_MIB2_OK if open succeeded - * GET_MIB2_* is the error code for failure. - */ - -int -open_mib2(solaris_mib2_t *mib2) -{ - /* - * It's an error if the stream device is already open. - */ - if (mib2->sd >= 0) { - (void) strcpy(mib2->errmsg, "open_mib2: MIB2 access already open"); - return(GET_MIB2_ERR_OPEN); - } - /* - * Open the ARP stream device, push TCP and UDP on it. - */ - if ((mib2->sd = open(GET_MIB2_ARPDEV, O_RDWR, 0600)) < 0) { - (void) sprintf(mib2->errmsg, "open_mib2: %s: %s", GET_MIB2_ARPDEV, - strerror(errno)); - return(GET_MIB2_ERR_ARPOPEN); - } - if (ioctl(mib2->sd, I_PUSH, GET_MIB2_TCPSTREAM) == -1) { - (void) sprintf(mib2->errmsg, "open_mib2: push %s: %s", - GET_MIB2_TCPSTREAM, strerror(errno)); - return(GET_MIB2_ERR_TCPPUSH); - } - if (ioctl(mib2->sd, I_PUSH, GET_MIB2_UDPSTREAM) == -1) { - (void) sprintf(mib2->errmsg, "open_mib2: push %s: %s", - GET_MIB2_UDPSTREAM, strerror(errno)); - return(GET_MIB2_ERR_UDPPUSH); - } - /* - * Allocate a stream message buffer. - */ - mib2->smb_len = sizeof(struct opthdr) + sizeof(struct T_optmgmt_req); - if (mib2->smb_len < (sizeof (struct opthdr) + sizeof(struct T_optmgmt_ack))) { - mib2->smb_len = sizeof (struct opthdr) + sizeof(struct T_optmgmt_ack); - } - if (mib2->smb_len < sizeof(struct T_error_ack)) { - mib2->smb_len = sizeof(struct T_error_ack); - } - if ((mib2->smb = (char *)malloc(mib2->smb_len)) == NULL) { - (void) strcpy(mib2->errmsg, - "open_mib2: no space for stream message buffer"); - return(GET_MIB2_ERR_NOSPC); - } - /* - * All is OK. Return that indication. - */ - return(GET_MIB2_OK); -} diff --git a/vendor/sigar/src/os/solaris/get_mib2.h b/vendor/sigar/src/os/solaris/get_mib2.h deleted file mode 100644 index 53116c5..0000000 --- a/vendor/sigar/src/os/solaris/get_mib2.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * get_mib2.h -- definitions for the get_mib2() function - * - * V. Abell - * Purdue University Computing Center - */ - - -/* - * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana - * 47907. All rights reserved. - * - * Written by Victor A. Abell - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * - * 1. Neither Victor A Abell nor Purdue University are responsible for - * any consequences of the use of this software. - * - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Credit to Victor A. Abell and Purdue - * University must appear in documentation and sources. - * - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 4. This notice may not be removed or altered. - */ - -/* - * Altered for sigar: - * - remove static stuff to make thread-safe by Doug MacEachern (3/11/05) - */ - -#if !defined(GET_MIB2_H) -#define GET_MIB2_H - - -/* - * Required header files - */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * Miscellaneous definitions - */ - -#define GET_MIB2_ARPDEV "/dev/arp" /* ARP stream devi9ce */ -#define GET_MIB2_ERRMSGL 1024 /* ErrMsg buffer length */ -#define GET_MIB2_TCPSTREAM "tcp" /* TCP stream name */ -#define GET_MIB2_UDPSTREAM "udp" /* UDP stream name */ - - -/* - * get_mib2() response codes - * - * -1 End of MIB2 information - * 0 Next MIB2 structure returned - * >0 Error code - */ - -#define GET_MIB2_EOD -1 /* end of data */ -#define GET_MIB2_OK 0 /* function succeeded */ -#define GET_MIB2_ERR_ACK 1 /* getmsg() ACK error received */ -#define GET_MIB2_ERR_ARPOPEN 2 /* error opening ARPDEV */ -#define GET_MIB2_ERR_CLOSE 3 /* MIB2 access close error */ -#define GET_MIB2_ERR_GETMSGD 4 /* error getting message data */ -#define GET_MIB2_ERR_GETMSGR 5 /* error getting message reply */ -#define GET_MIB2_ERR_NODATA 6 /* data expected; not received */ -#define GET_MIB2_ERR_NOSPC 7 /* no malloc() space */ -#define GET_MIB2_ERR_NOTOPEN 8 /* MIB2 access not open */ -#define GET_MIB2_ERR_OPEN 9 /* MIB2 access open error */ -#define GET_MIB2_ERR_PUTMSG 10 /* error putting request message */ -#define GET_MIB2_ERR_TCPPUSH 11 /* error pushing TCPSTREAM */ -#define GET_MIB2_ERR_UDPPUSH 12 /* error pushing UDPSTREAM */ - -#define GET_MIB2_ERR_MAX 13 /* maximum error number + 1 */ - - -typedef struct { - char *db; /* data buffer */ - int db_len; /* data buffer length */ - char *smb; /* stream message buffer */ - size_t smb_len; /* size of Smb[] */ - int sd; /* stream device descriptor */ - char errmsg[GET_MIB2_ERRMSGL]; /* error message buffer */ - struct T_optmgmt_ack *op_ack; /* message ACK pointer */ - struct strbuf ctlbuf; /* streams control buffer */ - struct T_error_ack *err_ack; /* message error pointer */ - struct opthdr *op; /* message option pointer */ - struct T_optmgmt_req *req; /* message request pointer */ -} solaris_mib2_t; - -/* - * Function prototypes - */ - -int close_mib2( /* close acccess to MIB2 information */ - solaris_mib2_t *mib2 - ); -int get_mib2( /* get MIB2 information */ - solaris_mib2_t *mib2, - struct opthdr **opt, /* opthdr pointer return (see - * */ - char **data, /* data buffer return address */ - int *datalen /* data buffer length return - * address */ - ); -int open_mib2( /* open acccess to MIB2 information */ - solaris_mib2_t *mib2 - ); - -#endif /* !defined(GET_MIB2_H) */ diff --git a/vendor/sigar/src/os/solaris/kstats.c b/vendor/sigar/src/os/solaris/kstats.c deleted file mode 100644 index a04ff09..0000000 --- a/vendor/sigar/src/os/solaris/kstats.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2004-2007 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -int sigar_get_kstats(sigar_t *sigar) -{ - kstat_ctl_t *kc = sigar->kc; - unsigned int i, id, ncpu = sysconf(_SC_NPROCESSORS_CONF); - int is_debug = SIGAR_LOG_IS_DEBUG(sigar); - - if (ncpu != sigar->ncpu) { - if (!sigar->ks.lcpu) { - /* init */ - sigar->ks.lcpu = ncpu; - sigar->ks.cpu = malloc(sizeof(*(sigar->ks.cpu)) * ncpu); - sigar->ks.cpu_info = malloc(sizeof(*(sigar->ks.cpu_info)) * ncpu); - sigar->ks.cpuid = malloc(sizeof(*(sigar->ks.cpuid)) * ncpu); - } - else { - sigar_log_printf(sigar, SIGAR_LOG_INFO, - "ncpu changed from %d to %d", - sigar->ncpu, ncpu); - if (ncpu > sigar->ks.lcpu) { - /* one or more cpus have been added */ - sigar->ks.cpu = realloc(sigar->ks.cpu, - sizeof(*(sigar->ks.cpu)) * ncpu); - sigar->ks.cpu_info = realloc(sigar->ks.cpu_info, - sizeof(*(sigar->ks.cpu_info)) * ncpu); - sigar->ks.cpuid = realloc(sigar->ks.cpuid, - sizeof(*(sigar->ks.cpuid)) * ncpu); - sigar->ks.lcpu = ncpu; - } - /* else or more cpus have been removed */ - } - - sigar->ncpu = ncpu; - - /* from man p_online: - * ``Processor numbers are integers, - * greater than or equal to 0, - * and are defined by the hardware platform. - * Processor numbers are not necessarily contiguous, - * but "not too sparse."`` - * so we maintain our own mapping in ks.cpuid[] - */ - - /* lookup in order, which kstat chain may not be in */ - for (i=0, id=0; iks.cpu_info[i] = cpu_info; - sigar->ks.cpu[i] = cpu_stat; - sigar->ks.cpuid[i] = id; - - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "cpu %d id=%d", i, sigar->ks.cpuid[i]); - } - i++; - } - } - - sigar->ks.system = kstat_lookup(kc, "unix", -1, "system_misc"); - sigar->ks.syspages = kstat_lookup(kc, "unix", -1, "system_pages"); - sigar->ks.mempages = kstat_lookup(kc, "bunyip", -1, "mempages"); - - return SIGAR_OK; -} - -SIGAR_INLINE kid_t sigar_kstat_update(sigar_t *sigar) -{ - kid_t id = kstat_chain_update(sigar->kc); - - switch (id) { - case -1: - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "kstat_chain_update error: %s", - sigar_strerror(sigar, errno)); - break; - case 0: - /* up-to-date */ - break; - default: - sigar_get_kstats(sigar); - sigar_log(sigar, SIGAR_LOG_DEBUG, - "kstat chain updated"); - break; - } - - return id; -} - -/* - * bincompat is not possible with certain kstat data structures between - * solaris 2.6, 2.7, 2.8, etc. alternative is to use kstat_data_lookup() - * which means everytime we want a stat, must do a linear search - * of ksp->ks_data. eek. so we meet half way and do the search for - * each key once per sigar_t instance. once the initial search has - * been done, we have a table of offsets to quickly access the stats via - * ksp->ks_data + offset. this gives us bincompat without the overhead - * of many kstat_data_lookup calls. - */ -static SIGAR_INLINE int kstat_named_offset(kstat_t *ksp, const char *name) -{ - unsigned int i; - kstat_named_t *kn; - - for (i=0, kn=ksp->ks_data; - iks_ndata; - i++, kn++) - { - if (strEQ(kn->name, name)) { - return i; - } - } - - return -2; /* not found */ -} - -static char *kstat_keys_system[] = { - "boot_time", - "avenrun_1min", - "avenrun_5min", - "avenrun_15min", - NULL -}; - -static char *kstat_keys_mempages[] = { - "pages_anon", - "pages_exec", - "pages_vnode", - NULL -}; - -static char *kstat_keys_syspages[] = { - "pagesfree", - NULL -}; - -static char **kstat_keys[] = { - kstat_keys_system, - kstat_keys_mempages, - kstat_keys_syspages, -}; - -void sigar_koffsets_lookup(kstat_t *ksp, int *offsets, int kidx) -{ - int i; - char **keys = kstat_keys[kidx]; - - for (i=0; keys[i]; i++) { - offsets[i] = kstat_named_offset(ksp, keys[i]); - } -} - diff --git a/vendor/sigar/src/os/solaris/procfs.c b/vendor/sigar/src/os/solaris/procfs.c deleted file mode 100644 index 743bd5b..0000000 --- a/vendor/sigar/src/os/solaris/procfs.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2004, 2006 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -#define my_pread(fd, ptr, type, offset) \ - (pread(fd, ptr, sizeof(type), offset) == sizeof(type)) - -int sigar_proc_psinfo_get(sigar_t *sigar, sigar_pid_t pid) -{ - int fd, retval = SIGAR_OK; - char buffer[BUFSIZ]; - time_t timenow = time(NULL); - - if (sigar->pinfo == NULL) { - sigar->pinfo = malloc(sizeof(*sigar->pinfo)); - } - - if (sigar->last_pid == pid) { - if ((timenow - sigar->last_getprocs) < SIGAR_LAST_PROC_EXPIRE) { - return SIGAR_OK; - } - } - - sigar->last_pid = pid; - sigar->last_getprocs = timenow; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/psinfo"); - - if ((fd = open(buffer, O_RDONLY)) < 0) { - return ESRCH; - } - - if (!my_pread(fd, sigar->pinfo, psinfo_t, 0)) { - retval = errno; - } - - close(fd); - - return retval; -} - -int sigar_proc_usage_get(sigar_t *sigar, prusage_t *prusage, sigar_pid_t pid) -{ - int fd, retval = SIGAR_OK; - char buffer[BUFSIZ]; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/usage"); - - if ((fd = open(buffer, O_RDONLY)) < 0) { - return ESRCH; - } - - if (!my_pread(fd, prusage, prusage_t, 0)) { - retval = errno; - } - - close(fd); - - return retval; -} - -int sigar_proc_status_get(sigar_t *sigar, pstatus_t *pstatus, sigar_pid_t pid) -{ - int fd, retval = SIGAR_OK; - char buffer[BUFSIZ]; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/status"); - - if ((fd = open(buffer, O_RDONLY)) < 0) { - return ESRCH; - } - - if (!my_pread(fd, pstatus, pstatus_t, 0)) { - retval = errno; - } - - close(fd); - - return retval; -} diff --git a/vendor/sigar/src/os/solaris/sigar_os.h b/vendor/sigar/src/os/solaris/sigar_os.h deleted file mode 100644 index 73115d8..0000000 --- a/vendor/sigar/src/os/solaris/sigar_os.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2004-2007 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_OS_H -#define SIGAR_OS_H - -#ifndef _POSIX_PTHREAD_SEMANTICS -#define _POSIX_PTHREAD_SEMANTICS -#endif - -typedef unsigned long long int u_int64_t; - -#include -#include -#ifndef DMALLOC -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "get_mib2.h" - -/* avoid -Wall warning since solaris doesnt have a prototype for this */ -int getdomainname(char *, int); - -typedef struct { - kstat_t **ks; - int num; - char *name; - int nlen; -} kstat_list_t; - -SIGAR_INLINE kid_t sigar_kstat_update(sigar_t *sigar); - -int sigar_get_kstats(sigar_t *sigar); - -void sigar_init_multi_kstats(sigar_t *sigar); - -void sigar_free_multi_kstats(sigar_t *sigar); - -int sigar_get_multi_kstats(sigar_t *sigar, - kstat_list_t *kl, - const char *name, - kstat_t **retval); - -void sigar_koffsets_lookup(kstat_t *ksp, int *offsets, int kidx); - -int sigar_proc_psinfo_get(sigar_t *sigar, sigar_pid_t pid); - -int sigar_proc_usage_get(sigar_t *sigar, prusage_t *prusage, sigar_pid_t pid); - -int sigar_proc_status_get(sigar_t *sigar, pstatus_t *pstatus, sigar_pid_t pid); - -#define CPU_ONLINE(n) \ - (p_online(n, P_STATUS) == P_ONLINE) - -typedef enum { - KSTAT_SYSTEM_BOOT_TIME, - KSTAT_SYSTEM_LOADAVG_1, - KSTAT_SYSTEM_LOADAVG_2, - KSTAT_SYSTEM_LOADAVG_3, - KSTAT_SYSTEM_MAX -} kstat_system_off_e; - -typedef enum { - KSTAT_MEMPAGES_ANON, - KSTAT_MEMPAGES_EXEC, - KSTAT_MEMPAGES_VNODE, - KSTAT_MEMPAGES_MAX -} kstat_mempages_off_e; - -typedef enum { - KSTAT_SYSPAGES_FREE, - KSTAT_SYSPAGES_MAX -} kstat_syspages_off_e; - -enum { - KSTAT_KEYS_system, - KSTAT_KEYS_mempages, - KSTAT_KEYS_syspages, -} kstat_keys_e; - -typedef struct ps_prochandle * (*proc_grab_func_t)(pid_t, int, int *); - -typedef void (*proc_free_func_t)(struct ps_prochandle *); - -typedef int (*proc_create_agent_func_t)(struct ps_prochandle *); - -typedef void (*proc_destroy_agent_func_t)(struct ps_prochandle *); - -typedef void (*proc_objname_func_t)(struct ps_prochandle *, - uintptr_t, const char *, size_t); - -typedef char * (*proc_dirname_func_t)(const char *, char *, size_t); - -typedef char * (*proc_exename_func_t)(struct ps_prochandle *, char *, size_t); - -typedef int (*proc_fstat64_func_t)(struct ps_prochandle *, int, void *); - -typedef int (*proc_getsockopt_func_t)(struct ps_prochandle *, - int, int, int, void *, int *); - -typedef int (*proc_getsockname_func_t)(struct ps_prochandle *, - int, struct sockaddr *, socklen_t *); - -struct sigar_t { - SIGAR_T_BASE; - - int solaris_version; - int use_ucb_ps; - - kstat_ctl_t *kc; - - /* kstat_lookup() as needed */ - struct { - kstat_t **cpu; - kstat_t **cpu_info; - processorid_t *cpuid; - unsigned int lcpu; /* number malloced slots in the cpu array above */ - kstat_t *system; - kstat_t *syspages; - kstat_t *mempages; - } ks; - - struct { - int system[KSTAT_SYSTEM_MAX]; - int mempages[KSTAT_MEMPAGES_MAX]; - int syspages[KSTAT_SYSPAGES_MAX]; - } koffsets; - - int pagesize; - - time_t last_getprocs; - sigar_pid_t last_pid; - psinfo_t *pinfo; - sigar_cpu_list_t cpulist; - - /* libproc.so interface */ - void *plib; - proc_grab_func_t pgrab; - proc_free_func_t pfree; - proc_create_agent_func_t pcreate_agent; - proc_destroy_agent_func_t pdestroy_agent; - proc_objname_func_t pobjname; - proc_dirname_func_t pdirname; - proc_exename_func_t pexename; - proc_fstat64_func_t pfstat64; - proc_getsockopt_func_t pgetsockopt; - proc_getsockname_func_t pgetsockname; - - sigar_cache_t *pargs; - - solaris_mib2_t mib2; -}; - -#ifdef SIGAR_64BIT -#define KSTAT_UINT ui64 -#else -#define KSTAT_UINT ui32 -#endif - -#define kSTAT_exists(v, type) \ - (sigar->koffsets.type[v] != -2) - -#define kSTAT_ptr(v, type) \ - ((kstat_named_t *)ksp->ks_data + sigar->koffsets.type[v]) - -#define kSTAT_uint(v, type) \ - (kSTAT_exists(v, type) ? kSTAT_ptr(v, type)->value.KSTAT_UINT : 0) - -#define kSTAT_ui32(v, type) \ - (kSTAT_exists(v, type) ? kSTAT_ptr(v, type)->value.ui32 : 0) - -#define kSYSTEM(v) kSTAT_ui32(v, system) - -#define kMEMPAGES(v) kSTAT_uint(v, mempages) - -#define kSYSPAGES(v) kSTAT_uint(v, syspages) - -#define sigar_koffsets_init(sigar, ksp, type) \ - if (sigar->koffsets.type[0] == -1) \ - sigar_koffsets_lookup(ksp, sigar->koffsets.type, KSTAT_KEYS_##type) - -#define sigar_koffsets_init_system(sigar, ksp) \ - sigar_koffsets_init(sigar, ksp, system) - -#define sigar_koffsets_init_mempages(sigar, ksp) \ - sigar_koffsets_init(sigar, ksp, mempages) - -#define sigar_koffsets_init_syspages(sigar, ksp) \ - sigar_koffsets_init(sigar, ksp, syspages) - -#define HAVE_READDIR_R -#define HAVE_GETPWNAM_R -#define HAVE_GETPWUID_R - -#define SIGAR_EMIB2 (SIGAR_OS_START_ERROR+1) - -#endif /* SIGAR_OS_H */ - diff --git a/vendor/sigar/src/os/solaris/solaris_sigar.c b/vendor/sigar/src/os/solaris/solaris_sigar.c deleted file mode 100644 index da9a2b6..0000000 --- a/vendor/sigar/src/os/solaris/solaris_sigar.c +++ /dev/null @@ -1,2717 +0,0 @@ -/* - * Copyright (c) 2004-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PROC_ERRNO ((errno == ENOENT) ? ESRCH : errno) -#define SIGAR_USR_UCB_PS "/usr/ucb/ps" - - -/* like kstat_lookup but start w/ ksp->ks_next instead of kc->kc_chain */ -static kstat_t * -kstat_next(kstat_t *ksp, char *ks_module, int ks_instance, char *ks_name) -{ - if (ksp) { - ksp = ksp->ks_next; - } - for (; ksp; ksp = ksp->ks_next) { - if ((ks_module == NULL || - strcmp(ksp->ks_module, ks_module) == 0) && - (ks_instance == -1 || ksp->ks_instance == ks_instance) && - (ks_name == NULL || strcmp(ksp->ks_name, ks_name) == 0)) - return ksp; - } - - errno = ENOENT; - return NULL; -} - -int sigar_os_open(sigar_t **sig) -{ - kstat_ctl_t *kc; - kstat_t *ksp; - sigar_t *sigar; - int i, status; - struct utsname name; - char *ptr; - - sigar = malloc(sizeof(*sigar)); - *sig = sigar; - - sigar->log_level = -1; /* log nothing by default */ - sigar->log_impl = NULL; - sigar->log_data = NULL; - - uname(&name); - if ((ptr = strchr(name.release, '.'))) { - ptr++; - sigar->solaris_version = atoi(ptr); - } - else { - sigar->solaris_version = 6; - } - - if ((ptr = getenv("SIGAR_USE_UCB_PS"))) { - sigar->use_ucb_ps = strEQ(ptr, "true"); - } - else { - struct stat sb; - if (stat(SIGAR_USR_UCB_PS, &sb) < 0) { - sigar->use_ucb_ps = 0; - } - else { - sigar->use_ucb_ps = 1; - } - } - - sigar->pagesize = 0; - i = sysconf(_SC_PAGESIZE); - while ((i >>= 1) > 0) { - sigar->pagesize++; - } - - sigar->ticks = sysconf(_SC_CLK_TCK); - sigar->kc = kc = kstat_open(); - - if (!kc) { - return errno; - } - - sigar->cpulist.size = 0; - sigar->ncpu = 0; - sigar->ks.cpu = NULL; - sigar->ks.cpu_info = NULL; - sigar->ks.cpuid = NULL; - sigar->ks.lcpu = 0; - - sigar->koffsets.system[0] = -1; - sigar->koffsets.mempages[0] = -1; - sigar->koffsets.syspages[0] = -1; - - if ((status = sigar_get_kstats(sigar)) != SIGAR_OK) { - fprintf(stderr, "status=%d\n", status); - } - - sigar->boot_time = 0; - - if ((ksp = sigar->ks.system) && - (kstat_read(kc, ksp, NULL) >= 0)) - { - sigar_koffsets_init_system(sigar, ksp); - - sigar->boot_time = kSYSTEM(KSTAT_SYSTEM_BOOT_TIME); - } - - sigar->last_pid = -1; - sigar->pinfo = NULL; - - sigar->plib = NULL; - sigar->pgrab = NULL; - sigar->pfree = NULL; - sigar->pobjname = NULL; - - sigar->pargs = NULL; - - SIGAR_ZERO(&sigar->mib2); - sigar->mib2.sd = -1; - - return SIGAR_OK; -} - -int sigar_os_close(sigar_t *sigar) -{ - kstat_close(sigar->kc); - if (sigar->mib2.sd != -1) { - close_mib2(&sigar->mib2); - } - - if (sigar->ks.lcpu) { - free(sigar->ks.cpu); - free(sigar->ks.cpu_info); - free(sigar->ks.cpuid); - } - if (sigar->pinfo) { - free(sigar->pinfo); - } - if (sigar->cpulist.size != 0) { - sigar_cpu_list_destroy(sigar, &sigar->cpulist); - } - if (sigar->plib) { - dlclose(sigar->plib); - } - if (sigar->pargs) { - sigar_cache_destroy(sigar->pargs); - } - free(sigar); - return SIGAR_OK; -} - -char *sigar_os_error_string(sigar_t *sigar, int err) -{ - switch (err) { - case SIGAR_EMIB2: - return sigar->mib2.errmsg; - default: - return NULL; - } -} - -int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem) -{ - kstat_ctl_t *kc = sigar->kc; - kstat_t *ksp; - sigar_uint64_t kern = 0; - - SIGAR_ZERO(mem); - - /* XXX: is mem hot swappable or can we just do this during open ? */ - mem->total = sysconf(_SC_PHYS_PAGES); - mem->total <<= sigar->pagesize; - - if (sigar_kstat_update(sigar) == -1) { - return errno; - } - - if ((ksp = sigar->ks.syspages) && kstat_read(kc, ksp, NULL) >= 0) { - sigar_koffsets_init_syspages(sigar, ksp); - - mem->free = kSYSPAGES(KSTAT_SYSPAGES_FREE); - mem->free <<= sigar->pagesize; - - mem->used = mem->total - mem->free; - } - - if ((ksp = sigar->ks.mempages) && kstat_read(kc, ksp, NULL) >= 0) { - sigar_koffsets_init_mempages(sigar, ksp); - } - - /* XXX mdb ::memstat cachelist/freelist not available to kstat, see: */ - /* http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6821980 */ - - /* ZFS ARC cache. see: http://opensolaris.org/jive/thread.jspa?messageID=393695 */ - if ((ksp = kstat_lookup(sigar->kc, "zfs", 0, "arcstats")) && - (kstat_read(sigar->kc, ksp, NULL) != -1)) - { - kstat_named_t *kn; - - if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "size"))) { - kern = kn->value.i64; - } - if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "c_min"))) { - /* c_min cannot be reclaimed they say */ - if (kern > kn->value.i64) { - kern -= kn->value.i64; - } - } - } - - mem->actual_free = mem->free + kern; - mem->actual_used = mem->used - kern; - - sigar_mem_calc_ram(sigar, mem); - - return SIGAR_OK; -} - -int sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap) -{ - kstat_t *ksp; - kstat_named_t *kn; - swaptbl_t *stab; - int num, i; - char path[PATH_MAX+1]; /* {un,re}used */ - - /* see: man swapctl(2) */ - if ((num = swapctl(SC_GETNSWP, NULL)) == -1) { - return errno; - } - - stab = malloc(num * sizeof(stab->swt_ent[0]) + sizeof(*stab)); - - stab->swt_n = num; - for (i=0; iswt_ent[i].ste_path = path; - } - - if ((num = swapctl(SC_LIST, stab)) == -1) { - free(stab); - return errno; - } - - num = num < stab->swt_n ? num : stab->swt_n; - swap->total = swap->free = 0; - for (i=0; iswt_ent[i].ste_flags & ST_INDEL) { - continue; /* swap file is being deleted */ - } - swap->total += stab->swt_ent[i].ste_pages; - swap->free += stab->swt_ent[i].ste_free; - } - free(stab); - - swap->total <<= sigar->pagesize; - swap->free <<= sigar->pagesize; - swap->used = swap->total - swap->free; - - if (sigar_kstat_update(sigar) == -1) { - return errno; - } - if (!(ksp = kstat_lookup(sigar->kc, "cpu", -1, "vm"))) { - swap->page_in = swap->page_out = SIGAR_FIELD_NOTIMPL; - return SIGAR_OK; - } - - swap->page_in = swap->page_out = 0; - - /* XXX: these stats do not exist in this form on solaris 8 or 9. - * they are in the raw cpu_stat struct, but thats not - * binary compatible - */ - do { - if (kstat_read(sigar->kc, ksp, NULL) < 0) { - break; - } - - if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "pgin"))) { - swap->page_in += kn->value.i64; /* vmstat -s | grep "page ins" */ - } - if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "pgout"))) { - swap->page_out += kn->value.i64; /* vmstat -s | grep "page outs" */ - } - } while ((ksp = kstat_next(ksp, "cpu", -1, "vm"))); - - return SIGAR_OK; -} - -#ifndef KSTAT_NAMED_STR_PTR -/* same offset as KSTAT_NAMED_STR_PTR(brand) */ -#define KSTAT_NAMED_STR_PTR(n) (char *)((n)->value.i32) -#endif - -static int get_chip_brand(sigar_t *sigar, int processor, - sigar_cpu_info_t *info) -{ - kstat_t *ksp = sigar->ks.cpu_info[processor]; - kstat_named_t *brand; - - if (sigar->solaris_version < 10) { - /* don't bother; doesn't exist. */ - return 0; - } - - if (ksp && - (kstat_read(sigar->kc, ksp, NULL) != -1) && - (brand = (kstat_named_t *)kstat_data_lookup(ksp, "brand"))) - { - char *name = KSTAT_NAMED_STR_PTR(brand); - - char *vendor = "Sun"; - char *vendors[] = { - "Intel", "AMD", NULL - }; - int i; - - if (!name) { - return 0; - } - - for (i=0; vendors[i]; i++) { - if (strstr(name, vendors[i])) { - vendor = vendors[i]; - break; - } - } - - SIGAR_SSTRCPY(info->vendor, vendor); -#if 0 - SIGAR_SSTRCPY(info->model, name); - sigar_cpu_model_adjust(sigar, info); -#endif - return 1; - } - else { - return 0; - } -} - -static void free_chip_id(void *ptr) -{ - /*noop*/ -} - -static int get_chip_id(sigar_t *sigar, int processor) -{ - kstat_t *ksp = sigar->ks.cpu_info[processor]; - kstat_named_t *chipid; - - if (ksp && - (kstat_read(sigar->kc, ksp, NULL) != -1) && - (chipid = (kstat_named_t *)kstat_data_lookup(ksp, "chip_id"))) - { - return chipid->value.i32; - } - else { - return -1; - } -} - -int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ - int status, i; - - status = sigar_cpu_list_get(sigar, &sigar->cpulist); - - if (status != SIGAR_OK) { - return status; - } - - SIGAR_ZERO(cpu); - - for (i=0; icpulist.number; i++) { - sigar_cpu_t *xcpu = &sigar->cpulist.data[i]; - - cpu->user += xcpu->user; - cpu->sys += xcpu->sys; - cpu->idle += xcpu->idle; - cpu->nice += xcpu->nice; - cpu->wait += xcpu->wait; - cpu->total = xcpu->total; - } - - return SIGAR_OK; -} - -int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist) -{ - kstat_ctl_t *kc = sigar->kc; - kstat_t *ksp; - uint_t cpuinfo[CPU_STATES]; - unsigned int i; - int is_debug = SIGAR_LOG_IS_DEBUG(sigar); - sigar_cache_t *chips; - - if (sigar_kstat_update(sigar) == -1) { - return errno; - } - - if (cpulist == &sigar->cpulist) { - if (sigar->cpulist.size == 0) { - /* create once */ - sigar_cpu_list_create(cpulist); - } - else { - /* reset, re-using cpulist.data */ - sigar->cpulist.number = 0; - } - } - else { - sigar_cpu_list_create(cpulist); - } - - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[cpu_list] OS reports %d CPUs", - sigar->ncpu); - } - - chips = sigar_cache_new(16); - chips->free_value = free_chip_id; - - for (i=0; incpu; i++) { - sigar_cpu_t *cpu; - char *buf; - int chip_id; - sigar_cache_entry_t *ent; - - if (!CPU_ONLINE(sigar->ks.cpuid[i])) { - sigar_log_printf(sigar, SIGAR_LOG_INFO, - "cpu %d (id=%d) is offline", - i, sigar->ks.cpuid[i]); - continue; - } - - if (!(ksp = sigar->ks.cpu[i])) { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "NULL ksp for cpu %d (id=%d)", - i, sigar->ks.cpuid[i]); - continue; /* shouldnot happen */ - } - - if (kstat_read(kc, ksp, NULL) < 0) { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "kstat_read failed for cpu %d (id=%d): %s", - i, sigar->ks.cpuid[i], - sigar_strerror(sigar, errno)); - continue; /* shouldnot happen */ - } - - /* - * cpu_stat_t is not binary compatible between solaris versions. - * since cpu_stat is a 'raw' kstat and not 'named' we cannot - * use name based lookups as we do for others. - * the start of the cpu_stat_t structure is binary compatible, - * which looks like so: - * typedef struct cpu_stat { - * kmutex_t cpu_stat_lock; - * cpu_sysinfo_t cpu_sysinfo; - * ... - * typedef struct cpu_sysinfo { - * ulong cpu[CPU_STATES]; - * ... - * we just copy the piece we need below: - */ - buf = ksp->ks_data; - buf += sizeof(kmutex_t); - memcpy(&cpuinfo[0], buf, sizeof(cpuinfo)); - chip_id = sigar->cpu_list_cores ? -1 : get_chip_id(sigar, i); - - if (chip_id == -1) { - SIGAR_CPU_LIST_GROW(cpulist); - cpu = &cpulist->data[cpulist->number++]; - SIGAR_ZERO(cpu); - } - else { - /* merge times of logical processors */ - ent = sigar_cache_get(chips, chip_id); - if (ent->value) { - cpu = &cpulist->data[(long)ent->value-1]; - } - else { - SIGAR_CPU_LIST_GROW(cpulist); - cpu = &cpulist->data[cpulist->number++]; - ent->value = (void *)(long)cpulist->number; - SIGAR_ZERO(cpu); - - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[cpu_list] Merging times of" - " logical processors for chip_id=%d", - chip_id); - } - } - } - - cpu->user += SIGAR_TICK2MSEC(cpuinfo[CPU_USER]); - cpu->sys += SIGAR_TICK2MSEC(cpuinfo[CPU_KERNEL]); - cpu->idle += SIGAR_TICK2MSEC(cpuinfo[CPU_IDLE]); - cpu->wait += SIGAR_TICK2MSEC(cpuinfo[CPU_WAIT]); - cpu->nice += 0; /* no cpu->nice */ - cpu->total = cpu->user + cpu->sys + cpu->idle + cpu->wait; - } - - sigar_cache_destroy(chips); - - return SIGAR_OK; -} - -int sigar_uptime_get(sigar_t *sigar, - sigar_uptime_t *uptime) -{ - if (sigar->boot_time) { - uptime->uptime = time(NULL) - sigar->boot_time; - } - else { - uptime->uptime = 0; /* XXX: shouldn't happen */ - } - - return SIGAR_OK; -} - -static int loadavg_keys[] = { - KSTAT_SYSTEM_LOADAVG_1, - KSTAT_SYSTEM_LOADAVG_2, - KSTAT_SYSTEM_LOADAVG_3 -}; - -int sigar_loadavg_get(sigar_t *sigar, - sigar_loadavg_t *loadavg) -{ - kstat_t *ksp; - int i; - - if (sigar_kstat_update(sigar) == -1) { - return errno; - } - - if (!(ksp = sigar->ks.system)) { - return -1; - } - - if (kstat_read(sigar->kc, ksp, NULL) < 0) { - return -1; - } - - sigar_koffsets_init_system(sigar, ksp); - - for (i=0; i<3; i++) { - loadavg->loadavg[i] = (double)kSYSTEM(loadavg_keys[i]) / FSCALE; - } - - return SIGAR_OK; -} - -#define LIBPROC "/usr/lib/libproc.so" - -#define CHECK_PSYM(s) \ - if (!sigar->s) { \ - sigar_log_printf(sigar, SIGAR_LOG_WARN, \ - "[%s] Symbol not found: %s", \ - SIGAR_FUNC, #s); \ - dlclose(sigar->plib); \ - sigar->plib = NULL; \ - return SIGAR_ENOTIMPL; \ - } - -static char *proc_readlink(const char *name, char *buffer, size_t size) -{ - int len; - - if ((len = readlink(name, buffer, size-1)) < 0) { - return NULL; - } - - buffer[len] = '\0'; - return buffer; -} - -static int sigar_init_libproc(sigar_t *sigar) -{ - if (sigar->plib) { - return SIGAR_OK; - } - - /* libproc.so ships with 5.8+ */ - /* interface is undocumented, see libproc.h in the sun jdk sources */ - sigar->plib = dlopen(LIBPROC, RTLD_LAZY); - - if (!sigar->plib) { - sigar_log_printf(sigar, SIGAR_LOG_WARN, - "[%s] dlopen(%s) = %s", - SIGAR_FUNC, LIBPROC, dlerror()); - return SIGAR_ENOTIMPL; - } - - sigar->pgrab = (proc_grab_func_t)dlsym(sigar->plib, "Pgrab"); - sigar->pfree = (proc_free_func_t)dlsym(sigar->plib, "Pfree"); - sigar->pcreate_agent = (proc_create_agent_func_t)dlsym(sigar->plib, "Pcreate_agent"); - sigar->pdestroy_agent = (proc_destroy_agent_func_t)dlsym(sigar->plib, "Pdestroy_agent"); - sigar->pobjname = (proc_objname_func_t)dlsym(sigar->plib, "Pobjname"); - sigar->pexename = (proc_exename_func_t)dlsym(sigar->plib, "Pexecname"); - sigar->pdirname = (proc_dirname_func_t)dlsym(sigar->plib, "proc_dirname"); - sigar->pfstat64 = (proc_fstat64_func_t)dlsym(sigar->plib, "pr_fstat64"); - sigar->pgetsockopt = (proc_getsockopt_func_t)dlsym(sigar->plib, "pr_getsockopt"); - sigar->pgetsockname = (proc_getsockname_func_t)dlsym(sigar->plib, "pr_getsockname"); - - CHECK_PSYM(pgrab); - CHECK_PSYM(pfree); - CHECK_PSYM(pobjname); - - return SIGAR_OK; -} - -/* from libproc.h, not included w/ solaris distro */ -/* Error codes from Pgrab(), Pfgrab_core(), and Pgrab_core() */ -#define G_STRANGE -1 /* Unanticipated error, errno is meaningful */ -#define G_NOPROC 1 /* No such process */ -#define G_NOCORE 2 /* No such core file */ -#define G_NOPROCORCORE 3 /* No such proc or core (for proc_arg_grab) */ -#define G_NOEXEC 4 /* Cannot locate executable file */ -#define G_ZOMB 5 /* Zombie process */ -#define G_PERM 6 /* No permission */ -#define G_BUSY 7 /* Another process has control */ -#define G_SYS 8 /* System process */ -#define G_SELF 9 /* Process is self */ -#define G_INTR 10 /* Interrupt received while grabbing */ -#define G_LP64 11 /* Process is _LP64, self is ILP32 */ -#define G_FORMAT 12 /* File is not an ELF format core file */ -#define G_ELF 13 /* Libelf error, elf_errno() is meaningful */ -#define G_NOTE 14 /* Required PT_NOTE Phdr not present in core */ - -static int sigar_pgrab(sigar_t *sigar, sigar_pid_t pid, - const char *func, - struct ps_prochandle **phandle) -{ - int pstatus; - - if (!(*phandle = sigar->pgrab(pid, 0x01, &pstatus))) { - switch (pstatus) { - case G_NOPROC: - return ESRCH; - case G_PERM: - return EACCES; - default: - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "[%s] Pgrab error=%d", - func, pstatus); - return ENOTSUP; /*XXX*/ - } - } - - return SIGAR_OK; -} - -int sigar_os_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - return sigar_proc_list_procfs_get(sigar, proclist); -} - -int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_mem_t *procmem) -{ - int status = sigar_proc_psinfo_get(sigar, pid); - psinfo_t *pinfo = sigar->pinfo; - prusage_t usage; - - if (status != SIGAR_OK) { - return status; - } - - procmem->size = pinfo->pr_size << 10; - procmem->resident = pinfo->pr_rssize << 10; - procmem->share = SIGAR_FIELD_NOTIMPL; - - if (sigar_proc_usage_get(sigar, &usage, pid) == SIGAR_OK) { - procmem->minor_faults = usage.pr_minf; - procmem->major_faults = usage.pr_majf; - procmem->page_faults = - procmem->minor_faults + - procmem->major_faults; - } - else { - procmem->minor_faults = SIGAR_FIELD_NOTIMPL; - procmem->major_faults = SIGAR_FIELD_NOTIMPL; - procmem->page_faults = SIGAR_FIELD_NOTIMPL; - } - - return SIGAR_OK; -} - -int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_t *proccred) -{ - int status = sigar_proc_psinfo_get(sigar, pid); - psinfo_t *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - proccred->uid = pinfo->pr_uid; - proccred->gid = pinfo->pr_gid; - proccred->euid = pinfo->pr_euid; - proccred->egid = pinfo->pr_egid; - - return SIGAR_OK; -} - -#define TIMESTRUCT_2MSEC(t) \ - ((t.tv_sec * MILLISEC) + (t.tv_nsec / (NANOSEC/MILLISEC))) - -int sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_time_t *proctime) -{ - prusage_t usage; - int status; - - if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) { - return status; - } - - proctime->start_time = usage.pr_create.tv_sec + sigar->boot_time; - proctime->start_time *= MILLISEC; - - if (usage.pr_utime.tv_sec < 0) { - /* XXX wtf? seen on solaris 10, only for the self process */ - pstatus_t pstatus; - - status = sigar_proc_status_get(sigar, &pstatus, pid); - if (status != SIGAR_OK) { - return status; - } - - usage.pr_utime.tv_sec = pstatus.pr_utime.tv_sec; - usage.pr_utime.tv_nsec = pstatus.pr_utime.tv_nsec; - usage.pr_stime.tv_sec = pstatus.pr_stime.tv_sec; - usage.pr_stime.tv_nsec = pstatus.pr_stime.tv_nsec; - } - - proctime->user = TIMESTRUCT_2MSEC(usage.pr_utime); - proctime->sys = TIMESTRUCT_2MSEC(usage.pr_stime); - proctime->total = proctime->user + proctime->sys; - - return SIGAR_OK; -} - -int sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - int status = sigar_proc_psinfo_get(sigar, pid); - psinfo_t *pinfo = sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - SIGAR_SSTRCPY(procstate->name, pinfo->pr_fname); - procstate->ppid = pinfo->pr_ppid; - procstate->tty = pinfo->pr_ttydev; - procstate->priority = pinfo->pr_lwp.pr_pri; - procstate->nice = pinfo->pr_lwp.pr_nice - NZERO; - procstate->threads = pinfo->pr_nlwp; - procstate->processor = pinfo->pr_lwp.pr_onpro; - - switch (pinfo->pr_lwp.pr_state) { - case SONPROC: - case SRUN: - procstate->state = 'R'; - break; - case SZOMB: - procstate->state = 'Z'; - break; - case SSLEEP: - procstate->state = 'S'; - break; - case SSTOP: - procstate->state = 'T'; - break; - case SIDL: - procstate->state = 'D'; - break; - } - - return SIGAR_OK; -} - -typedef struct { - int timestamp; - char *args; -} pargs_t; - -static void pargs_free(void *value) -{ - pargs_t *pargs = (pargs_t *)value; - if (pargs->args != NULL) { - free(pargs->args); - } - free(pargs); -} - -static int ucb_ps_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs, - int timestamp) -{ - char buffer[9086], *args=NULL, *arg; - sigar_cache_entry_t *ent; - FILE *fp; - pargs_t *pargs; - - if (!sigar->pargs) { - sigar->pargs = sigar_cache_new(15); - sigar->pargs->free_value = pargs_free; - } - - ent = sigar_cache_get(sigar->pargs, pid); - if (ent->value) { - pargs = (pargs_t *)ent->value; - if (pargs->timestamp != timestamp) { - if (pargs->args) { - free(pargs->args); - pargs->args = NULL; - } - } - } - else { - pargs = malloc(sizeof(*pargs)); - pargs->args = NULL; - ent->value = pargs; - } - - pargs->timestamp = timestamp; - - if (pargs->args) { - args = pargs->args; - } - else { - snprintf(buffer, sizeof(buffer), - SIGAR_USR_UCB_PS " -ww %ld", (long)pid); - - if (!(fp = popen(buffer, "r"))) { - return errno; - } - /* skip header */ - (void)fgets(buffer, sizeof(buffer), fp); - if ((args = fgets(buffer, sizeof(buffer), fp))) { - int len; - - /* skip PID,TT,S,TIME */ - args = sigar_skip_multiple_token(args, 4); - SIGAR_SKIP_SPACE(args); - len = strlen(args); - if (len > 0) { - args[len-1] = '\0'; /* chop \n */ - } - - pargs->args = malloc(len+1); - memcpy(pargs->args, args, len); - } - - pclose(fp); - - if (!args) { - return ESRCH; - } - } - - while (*args && (arg = sigar_getword(&args, ' '))) { - SIGAR_PROC_ARGS_GROW(procargs); - procargs->data[procargs->number++] = arg; - } - - return SIGAR_OK; -} - -int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - psinfo_t *pinfo; - int fd, status; - char buffer[9086]; - char *argvb[56]; - char **argvp = argvb; - - int n; - size_t nread = 0; - unsigned int argv_size; - - if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) { - return status; - } - pinfo = sigar->pinfo; - - if (pinfo->pr_argc == 0) { - procargs->number = 0; - return SIGAR_OK; - } - else if (pinfo->pr_dmodel != PR_MODEL_NATIVE) { - /* we are compiled in 32bit mode - * punt any 64bit native process, - * sizeof our structures can't handle. - */ - if (sigar->use_ucb_ps) { - return ucb_ps_args_get(sigar, pid, procargs, - pinfo->pr_start.tv_sec); - } - else { - return ENOTSUP; - } - } - - argv_size = sizeof(*argvp) * pinfo->pr_argc; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/as"); - - if ((fd = open(buffer, O_RDONLY)) < 0) { - if ((errno == EACCES) && sigar->use_ucb_ps) { - return ucb_ps_args_get(sigar, pid, procargs, - pinfo->pr_start.tv_sec); - } - else { - return PROC_ERRNO; - } - } - - if (argv_size > sizeof(argvb)) { - argvp = malloc(argv_size); - } - - if ((nread = pread(fd, argvp, argv_size, pinfo->pr_argv)) <= 0) { - close(fd); - if (argvp != argvb) { - free(argvp); - } - return errno; - } - - for (n = 0; n < pinfo->pr_argc; n++) { - int alen; - char *arg; - - if ((nread = pread(fd, buffer, sizeof(buffer)-1, (off_t)argvp[n])) <= 0) { - close(fd); - if (argvp != argvb) { - free(argvp); - } - return errno; - } - - buffer[nread] = '\0'; - alen = strlen(buffer)+1; - arg = malloc(alen); - memcpy(arg, buffer, alen); - - SIGAR_PROC_ARGS_GROW(procargs); - procargs->data[procargs->number++] = arg; - } - - if (argvp != argvb) { - free(argvp); - } - - close(fd); - - return SIGAR_OK; -} - -int sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ - psinfo_t *pinfo; - int fd, status; - char buffer[BUFSIZ], *offsets[512]; - size_t nread; - int n=0, max=sizeof(offsets)/sizeof(char *); - - if ((status = sigar_proc_psinfo_get(sigar, pid)) != SIGAR_OK) { - return status; - } - pinfo = sigar->pinfo; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/as"); - - if ((fd = open(buffer, O_RDONLY)) < 0) { - return PROC_ERRNO; - } - - if ((nread = pread(fd, offsets, sizeof(offsets), - pinfo->pr_envp)) <= 0) - { - close(fd); - return errno; - } - - while ((n < max) && offsets[n]) { - char *val; - int klen, vlen, status; - char key[128]; /* XXX is there a max key size? */ - - if ((nread = pread(fd, buffer, sizeof(buffer), - (off_t)offsets[n++])) <= 0) - { - close(fd); - return errno; - } - - val = strchr(buffer, '='); - - if (val == NULL) { - break; /*XXX*/ - } - - klen = val - buffer; - SIGAR_SSTRCPY(key, buffer); - key[klen] = '\0'; - ++val; - - vlen = strlen(val); - - status = procenv->env_getter(procenv->data, - key, klen, val, vlen); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - } - - close(fd); - - return SIGAR_OK; -} - -int sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_fd_t *procfd) -{ - int status = - sigar_proc_fd_count(sigar, pid, &procfd->total); - - return status; -} - -static int sigar_proc_path_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ - /* solaris 10+ */ - char buffer[BUFSIZ]; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/a.out"); - if (!proc_readlink(buffer, procexe->name, sizeof(procexe->name))) { - procexe->name[0] = '\0'; - } - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/cwd"); - if (!proc_readlink(buffer, procexe->cwd, sizeof(procexe->cwd))) { - procexe->cwd[0] = '\0'; - } - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/path/root"); - if (!proc_readlink(buffer, procexe->root, sizeof(procexe->root))) { - procexe->root[0] = '\0'; - } - - return SIGAR_OK; -} - -static int proc_module_get_exe(void *data, char *name, int len) -{ - sigar_proc_exe_t *procexe = (sigar_proc_exe_t *)data; - SIGAR_STRNCPY(procexe->name, name, sizeof(procexe->name)); - return !SIGAR_OK; /* break loop */ -} - -static int sigar_which_exe_get(sigar_t *sigar, sigar_proc_exe_t *procexe) -{ - char *path = getenv("PATH"); - char exe[PATH_MAX]; - if (path == NULL) { - return EINVAL; - } - - while (path) { - char *ptr = strchr(path, ':'); - if (!ptr) { - break; - } - exe[0] = '\0'; - strncat(exe, path, ptr-path); - strncat(exe, "/", 1); - strcat(exe, procexe->name); - if (access(exe, X_OK) == 0) { - SIGAR_STRNCPY(procexe->name, exe, sizeof(procexe->name)); - break; - } - path = ptr+1; - } - - return ENOENT; -} - -int sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ - int status; - char buffer[BUFSIZ]; - struct ps_prochandle *phandle; - - if (sigar->solaris_version >= 10) { - return sigar_proc_path_exe_get(sigar, pid, procexe); - } - - if ((status = sigar_init_libproc(sigar)) != SIGAR_OK) { - return status; - } - - procexe->name[0] = '\0'; - - /* Pgrab would return G_SELF error */ - if (pid == sigar_pid_get(sigar)) { - sigar_proc_modules_t procmods; - procmods.module_getter = proc_module_get_exe; - procmods.data = procexe; - - status = - sigar_dlinfo_modules(sigar, &procmods); - if (status == SIGAR_OK) { - if (procexe->name[0] != '/') { - sigar_which_exe_get(sigar, procexe); - } - } - } - else { - status = sigar_pgrab(sigar, pid, SIGAR_FUNC, &phandle); - - if (status == SIGAR_OK) { - sigar->pexename(phandle, procexe->name, sizeof(procexe->name)); - sigar->pfree(phandle); - } - } - - if (procexe->name[0] == '\0') { - /*XXX*/ - } - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/cwd"); - - if (!sigar->pdirname(buffer, procexe->cwd, sizeof(procexe->cwd))) { - procexe->cwd[0] = '\0'; - } - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/root"); - - if (!(sigar->pdirname(buffer, procexe->root, sizeof(procexe->root)))) { - procexe->root[0] = '\0'; - } - - return SIGAR_OK; -} - -static int sigar_read_xmaps(sigar_t *sigar, - prxmap_t *xmaps, int total, - unsigned long *last_inode, - struct ps_prochandle *phandle, - sigar_proc_modules_t *procmods) -{ - int status, i; - unsigned long inode; - char buffer[BUFSIZ]; - - for (i=0; ipobjname(phandle, xmaps[i].pr_vaddr, buffer, sizeof(buffer)); - - status = - procmods->module_getter(procmods->data, buffer, strlen(buffer)); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - return status; - } - } - - return SIGAR_OK; -} - -static int sigar_pgrab_modules(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods) -{ - int fd, pstatus; - off_t map_size, nread; - unsigned long last_inode = 0; - prxmap_t xmaps[15]; /* ~2K */ - struct ps_prochandle *phandle; - struct stat statbuf; - char buffer[BUFSIZ]; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/xmap"); - - if ((fd = open(buffer, O_RDONLY)) < 0) { - return errno; - } - - if (fstat(fd, &statbuf) < 0) { - close(fd); - return errno; - } - - map_size = statbuf.st_size; - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[%s] pid=%d, size=%d", - SIGAR_FUNC, pid, map_size); - } - - if ((pstatus = sigar_init_libproc(sigar)) != SIGAR_OK) { - close(fd); - return pstatus; - } - - pstatus = sigar_pgrab(sigar, pid, SIGAR_FUNC, &phandle); - - if (pstatus != SIGAR_OK) { - close(fd); - return pstatus; - } - - for (nread=0; nread sizeof(xmaps) ? sizeof(xmaps) : map_size; - int total = wanted / sizeof(prxmap_t); - - if (pread(fd, xmaps, wanted, nread) != wanted) { - close(fd); - sigar->pfree(phandle); - return errno; - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[%s] nread=%d, map_size=%d, wanted=%d, total=%d", - SIGAR_FUNC, - nread, map_size, wanted, total); - } - - if (sigar_read_xmaps(sigar, xmaps, total, - &last_inode, - phandle, procmods) != SIGAR_OK) - { - break; - } - - nread += wanted; - map_size -= wanted; - } - - close(fd); - - sigar->pfree(phandle); - - return SIGAR_OK; -} - -int sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods) -{ - if (pid == sigar_pid_get(sigar)) { - /* Pgrab would return G_SELF, this is faster anyhow */ - /* XXX one difference to Pgrab, first entry is not the exe name */ - return sigar_dlinfo_modules(sigar, procmods); - } - else { - return sigar_pgrab_modules(sigar, pid, procmods); - } -} - -#define TIME_NSEC(t) \ - (SIGAR_SEC2NANO((t).tv_sec) + (sigar_uint64_t)(t).tv_nsec) - -int sigar_thread_cpu_get(sigar_t *sigar, - sigar_uint64_t id, - sigar_thread_cpu_t *cpu) -{ - struct lwpinfo info; - - if (id != 0) { - return SIGAR_ENOTIMPL; - } - - _lwp_info(&info); - - cpu->user = TIME_NSEC(info.lwp_utime); - cpu->sys = TIME_NSEC(info.lwp_stime); - cpu->total = TIME_NSEC(info.lwp_utime) + TIME_NSEC(info.lwp_stime); - - return SIGAR_OK; -} - -#include - -int sigar_os_fs_type_get(sigar_file_system_t *fsp) -{ - char *type = fsp->sys_type_name; - - switch (*type) { - case 'u': - if (strEQ(type, "ufs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - /* XXX */ - } - - return fsp->type; -} - -int sigar_file_system_list_get(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - struct mnttab ent; - sigar_file_system_t *fsp; - FILE *fp = fopen(MNTTAB, "r"); - - if (!fp) { - return errno; - } - - sigar_file_system_list_create(fslist); - - while (getmntent(fp, &ent) == 0) { - if (strstr(ent.mnt_mntopts, "ignore")) { - continue; /* e.g. vold */ - } - - SIGAR_FILE_SYSTEM_LIST_GROW(fslist); - - fsp = &fslist->data[fslist->number++]; - - SIGAR_SSTRCPY(fsp->dir_name, ent.mnt_mountp); - SIGAR_SSTRCPY(fsp->dev_name, ent.mnt_special); - SIGAR_SSTRCPY(fsp->sys_type_name, ent.mnt_fstype); - SIGAR_SSTRCPY(fsp->options, ent.mnt_mntopts); - sigar_fs_type_init(fsp); - } - - fclose(fp); - - return SIGAR_OK; -} - -typedef struct { - char device[PATH_MAX]; - char name[8]; - int instance; -} fsdev_path_t; - -typedef struct { - char name[256]; - int is_partition; - sigar_disk_usage_t disk; -} iodev_t; - -static fsdev_path_t *get_fsdev_paths(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - int i, ndisk, size; - char buffer[BUFSIZ], *ptr; - char *dev, *inst, *drv; - fsdev_path_t *paths, *mapping; - FILE *fp = fopen("/etc/path_to_inst", "r"); - - if (!fp) { - return NULL; - } - - for (i=0, ndisk=0; inumber; i++) { - sigar_file_system_t *fsp = &fslist->data[i]; - if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) { - ndisk++; - } - } - - size = sizeof(*paths) * (ndisk+1); - mapping = paths = malloc(size); - memset(mapping, '\0', size); - - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - /* eat dust java */ - char *q; - - SIGAR_SKIP_SPACE(ptr); - if (*ptr == '#') { - continue; - } - if (*ptr == '"') { - ptr++; - } - dev = ptr; - if (!(q = strchr(ptr, '"'))) { - continue; - } - ptr = q+1; - *q = '\0'; - SIGAR_SKIP_SPACE(ptr); - inst = ptr; - while (sigar_isdigit(*ptr)) { - ptr++; - } - *ptr = '\0'; - ptr++; - SIGAR_SKIP_SPACE(ptr); - if (*ptr == '"') { - ptr++; - } - drv = ptr; - if (!(q = strchr(ptr, '"'))) { - continue; - } - *q = '\0'; - - if (!(strEQ(drv, "sd") || - strEQ(drv, "ssd") || - strEQ(drv, "st") || - strEQ(drv, "dad") || - strEQ(drv, "cmdk"))) - { - continue; - } - - paths->instance = atoi(inst); - if (!kstat_lookup(sigar->kc, drv, paths->instance, NULL)) { - continue; - } - - SIGAR_SSTRCPY(paths->device, dev); - SIGAR_SSTRCPY(paths->name, drv); - - if (--ndisk < 0) { - /* XXX prevent overflow */ - break; - } - paths++; - } - fclose(fp); - - return mapping; -} - -static int create_fsdev_cache(sigar_t *sigar) -{ - fsdev_path_t *paths, *mapping; - sigar_file_system_list_t fslist; - int i, j; - int status; - int debug = SIGAR_LOG_IS_DEBUG(sigar); - - sigar->fsdev = sigar_cache_new(15); - - status = sigar_file_system_list_get(sigar, &fslist); - - if (status != SIGAR_OK) { - return status; - } - - if (!(mapping = get_fsdev_paths(sigar, &fslist))) { - sigar_file_system_list_destroy(sigar, &fslist); - return ENOENT; - } - - for (i=0; itype == SIGAR_FSTYPE_LOCAL_DISK) { - char device[PATH_MAX+1], *ptr=device; - int len = readlink(fsp->dev_name, device, sizeof(device)-1); - char *s; - char partition; - - if (len < 0) { - continue; - } - device[len] = '\0'; - - if (debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, "[fsdev] name=%s, dev=%s", - fsp->dev_name, device); - } - - while (strnEQ(ptr, "../", 3)) { - ptr += 3; - } - if (strnEQ(ptr, "devices", 7)) { - ptr += 7; - } - if ((s = strchr(ptr, ':'))) { - partition = *(s+1); - } - else { - continue; - } - - for (j=0, paths=mapping; paths->name[0]; j++) { - if (strnEQ(paths->device, ptr, strlen(paths->device))) { - sigar_cache_entry_t *ent; - struct stat sb; - int retval = stat(fsp->dir_name, &sb); - iodev_t *iodev; - - if (retval == 0) { - iodev = malloc(sizeof(*iodev)); - - SIGAR_DISK_STATS_INIT(&iodev->disk); - /* e.g. sd9,g - * module == sd - * instance == 9 - * partition == 8 - */ - snprintf(iodev->name, sizeof(iodev->name), "%s%d,%c", - paths->name, paths->instance, partition); - - ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb)); - ent->value = iodev; - - if (debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fsdev] map %s -> %s", - fsp->dir_name, iodev->name); - } - } - break; - } - paths++; - } - } - } - - free(mapping); - sigar_file_system_list_destroy(sigar, &fslist); - - return SIGAR_OK; -} - -static int io_kstat_read(sigar_t *sigar, - sigar_disk_usage_t *disk, - kstat_t *ksp) -{ - kstat_io_t *io; - - kstat_read(sigar->kc, ksp, NULL); - - io = (kstat_io_t *)ksp->ks_data; - - disk->reads = io->reads; - disk->writes = io->writes; - disk->read_bytes = io->nread; - disk->write_bytes = io->nwritten; - disk->qtime = io->wlentime; - disk->rtime = io->rlentime; - disk->wtime = io->wlentime; - disk->time = disk->rtime + disk->wtime; - disk->snaptime = ksp->ks_snaptime; - - return SIGAR_OK; -} - - -static int sigar_kstat_disk_usage_get(sigar_t *sigar, const char *name, - sigar_disk_usage_t *disk, - kstat_t **kio) -{ - kstat_t *ksp; - - if (sigar_kstat_update(sigar) == -1) { - return errno; - } - - for (ksp = sigar->kc->kc_chain; - ksp; - ksp = ksp->ks_next) - { - if (ksp->ks_type != KSTAT_TYPE_IO) { - continue; - } - if (strEQ(ksp->ks_name, name)) { - int status = io_kstat_read(sigar, disk, ksp); - *kio = ksp; - return status; - } - } - - return ENXIO; -} - -static int simple_hash(const char *s) -{ - int hash = 0; - while (*s) { - hash = 31*hash + *s++; - } - return hash; -} - -int sigar_disk_usage_get(sigar_t *sigar, const char *name, - sigar_disk_usage_t *disk) -{ - kstat_t *ksp; - int status; - iodev_t *iodev = NULL; - sigar_cache_entry_t *ent; - sigar_uint64_t id; - - SIGAR_DISK_STATS_INIT(disk); - - if (!sigar->fsdev) { - if (create_fsdev_cache(sigar) != SIGAR_OK) { - return SIGAR_OK; - } - } - - if (*name == '/') { - struct stat sb; - - if (stat(name, &sb) < 0) { - return errno; - } - - id = SIGAR_FSDEV_ID(sb); - ent = sigar_cache_get(sigar->fsdev, id); - if (ent->value == NULL) { - return ENXIO; - } - iodev = (iodev_t *)ent->value; - - status = sigar_kstat_disk_usage_get(sigar, iodev->name, disk, &ksp); - } - else { - status = sigar_kstat_disk_usage_get(sigar, name, disk, &ksp); - if (status != SIGAR_OK) { - return status; - } - id = simple_hash(name); /*XXX*/ - ent = sigar_cache_get(sigar->fsdev, id); - if (ent->value) { - iodev = (iodev_t *)ent->value; - } - else { - ent->value = iodev = malloc(sizeof(*iodev)); - SIGAR_SSTRCPY(iodev->name, name); - SIGAR_DISK_STATS_INIT(&iodev->disk); - } - } - - /* service_time formula derived from opensolaris.org:iostat.c */ - if ((status == SIGAR_OK) && iodev) { - sigar_uint64_t delta; - double avw, avr, tps, mtps; - double etime, hr_etime; - - if (iodev->disk.snaptime) { - delta = disk->snaptime - iodev->disk.snaptime; - } - else { - delta = ksp->ks_crtime - ksp->ks_snaptime; - } - - hr_etime = (double)delta; - if (hr_etime == 0.0) { - hr_etime = (double)NANOSEC; - } - etime = hr_etime / (double)NANOSEC; - - tps = - (((double)(disk->reads - iodev->disk.reads)) / etime) + - (((double)(disk->writes - iodev->disk.writes)) / etime); - - delta = disk->wtime - iodev->disk.wtime; - if (delta) { - avw = (double)delta; - avw /= hr_etime; - } - else { - avw = 0.0; - } - - delta = disk->rtime - iodev->disk.rtime; - if (delta) { - avr = (double)delta; - avr /= hr_etime; - } - else { - avr = 0.0; - } - - disk->queue = avw; - disk->service_time = 0.0; - - if (tps && (avw != 0.0 || avr != 0.0)) { - mtps = 1000.0 / tps; - if (avw != 0.0) { - disk->service_time += avw * mtps; - } - if (avr != 0.0) { - disk->service_time += avr * mtps; - } - } - - memcpy(&iodev->disk, disk, sizeof(iodev->disk)); - } - - return status; -} - -int sigar_file_system_usage_get(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage) -{ - int status = sigar_statvfs(sigar, dirname, fsusage); - - if (status != SIGAR_OK) { - return status; - } - - fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage); - - sigar_disk_usage_get(sigar, dirname, &fsusage->disk); - - return SIGAR_OK; -} - -int sigar_cpu_info_list_get(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos) -{ - processor_info_t stats; - unsigned int i; - int status = SIGAR_OK; - int brand = -1; - sigar_cache_t *chips; - int is_debug = SIGAR_LOG_IS_DEBUG(sigar); - int nsockets = 0; - - if (sigar_kstat_update(sigar) == -1) { /* for sigar->ncpu */ - return errno; - } - - /* - * stats we care about will be the same for each - * online processor, so just grab the first. - */ - for (i=0; incpu; i++) { - processorid_t id = sigar->ks.cpuid[i]; - - if ((status = processor_info(id, &stats)) < 0) { - continue; - } - else { - status = SIGAR_OK; - break; - } - } - - if (status != SIGAR_OK) { - /* should never happen */ - return ENOENT; - } - - sigar_cpu_info_list_create(cpu_infos); - chips = sigar_cache_new(16); - chips->free_value = free_chip_id; - - for (i=0; incpu; i++) { - sigar_cpu_info_t *info; - int chip_id = get_chip_id(sigar, i); - - if (chip_id != -1) { - sigar_cache_entry_t *ent = - sigar_cache_get(chips, chip_id); - - if (ent->value) { - if (!sigar->cpu_list_cores) { - continue; - } - } - else { - ++nsockets; - ent->value = chips; /*anything non-NULL*/ - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[cpu_list] Merging info of" - " logical processors for chip_id=%d", - chip_id); - } - } - } - else { - ++nsockets; - } - - SIGAR_CPU_INFO_LIST_GROW(cpu_infos); - - info = &cpu_infos->data[cpu_infos->number++]; - - SIGAR_SSTRCPY(info->model, stats.pi_processor_type); - - if (brand == -1) { - brand = get_chip_brand(sigar, i, info); - } - - if (strEQ(info->model, "i386")) { - if (!brand) { - /* assume Intel on x86 */ - SIGAR_SSTRCPY(info->vendor, "Intel"); - } - SIGAR_SSTRCPY(info->model, "x86"); - } - else { - if (!brand) { - /* assume Sun */ - SIGAR_SSTRCPY(info->vendor, "Sun"); - } - /* s/sparc/Sparc/ */ - info->model[0] = toupper(info->model[0]); - } - - if (brand) { - SIGAR_SSTRCPY(info->vendor, cpu_infos->data[0].vendor); - } - - info->mhz = stats.pi_clock; - info->cache_size = SIGAR_FIELD_NOTIMPL; /*XXX*/ - } - - sigar_cache_destroy(chips); - - for (i=0; inumber; i++) { - sigar_cpu_info_t *info = &cpu_infos->data[i]; - info->total_sockets = nsockets; - info->total_cores = sigar->ncpu; - info->cores_per_socket = sigar->ncpu / nsockets; - } - - return SIGAR_OK; -} - -int sigar_net_route_list_get(sigar_t *sigar, - sigar_net_route_list_t *routelist) - -{ - char *data; - int len, rc; - struct opthdr *op; - size_t nread=0, size=0; - const char *size_from; - - sigar_net_route_list_create(routelist); - - while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) { - mib2_ipRouteEntry_t *entry; - char *end; - - if (op->level != MIB2_IP) { - continue; - } - - if (op->name == 0) { - /* we want to use this size for bincompat */ - size = ((mib2_ip_t *)data)->ipRouteEntrySize; - continue; - } - else if (op->name != MIB2_IP_21) { - continue; - } - - if (size == 0) { - size_from = "sizeof"; - size = sizeof(*entry); - } - else { - size_from = "mib2_ip"; - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[route_list] ipRouteEntrySize=%d (from %s)", - size, size_from); - } - - for (entry = (mib2_ipRouteEntry_t *)data, end = data + len; - (char *)entry < end; - nread+=size, entry = (mib2_ipRouteEntry_t *)((char *)data+nread)) - { - sigar_net_route_t *route; - int type = entry->ipRouteInfo.re_ire_type; - - /* filter same as netstat -r */ - if ((type == IRE_CACHE) || - (type == IRE_BROADCAST) || - (type == IRE_LOCAL)) - { - continue; - } - - SIGAR_NET_ROUTE_LIST_GROW(routelist); - route = &routelist->data[routelist->number++]; - - sigar_net_address_set(route->destination, - entry->ipRouteDest); - - sigar_net_address_set(route->gateway, - entry->ipRouteNextHop); - - sigar_net_address_set(route->mask, - entry->ipRouteMask); - - route->refcnt = entry->ipRouteInfo.re_ref; - route->irtt = entry->ipRouteInfo.re_rtt; - route->metric = entry->ipRouteMetric1; - - SIGAR_SSTRCPY(route->ifname, entry->ipRouteIfIndex.o_bytes); - - route->flags = RTF_UP; - if ((route->destination.addr.in == 0) && - (route->mask.addr.in == 0)) - { - route->flags |= RTF_GATEWAY; - } - - route->use = route->window = route->mtu = - SIGAR_FIELD_NOTIMPL; /*XXX*/ - } - } - - if (rc != GET_MIB2_EOD) { - close_mib2(&sigar->mib2); - return SIGAR_EMIB2; - } - - return SIGAR_OK; -} - -static void ifstat_kstat_common(sigar_net_interface_stat_t *ifstat, - kstat_named_t *data, int ndata) -{ - int i; - - for (i=0; itx_collisions = value; - } - break; - case 'd': - if (strEQ(ptr, "drop")) { - ifstat->rx_dropped = value; - ifstat->tx_dropped = value; - } - break; - case 'i': - if (strEQ(ptr, "ipackets")) { - if (ifstat->rx_packets == 0) { - ifstat->rx_packets = value; - } - } - else if (strEQ(ptr, "ipackets64")) { - ifstat->rx_packets = data[i].value.ui64; - } - else if (strEQ(ptr, "ierrors")) { - ifstat->rx_errors = value; - } - else if (strEQ(ptr, "ifspeed")) { - ifstat->speed = value; - } - break; - case 'f': - if (strEQ(ptr, "framing")) { - ifstat->rx_frame = value; - } - break; - case 'm': - if (strEQ(ptr, "missed")) { - ifstat->rx_dropped = value; - ifstat->tx_dropped = value; - } - break; - case 'n': - if (strEQ(ptr, "nocarrier")) { - ifstat->tx_carrier = value; - } - break; - case 'o': - if (strEQ(ptr, "obytes")) { - if (ifstat->tx_bytes == 0) { - ifstat->tx_bytes = value; - } - } - else if (strEQ(ptr, "obytes64")) { - ifstat->tx_bytes = data[i].value.ui64; - } - else if (strEQ(ptr, "oerrors")) { - ifstat->tx_errors = value; - } - else if (strEQ(ptr, "oflo")) { - ifstat->tx_overruns = value; - } - else if (strEQ(ptr, "opackets")) { - if (ifstat->tx_packets == 0) { - ifstat->tx_packets = value; - } - } - else if (strEQ(ptr, "opackets64")) { - ifstat->tx_packets = data[i].value.ui64; - } - else if (strEQ(ptr, "toolong_errors")) { - ifstat->tx_overruns = value; - } - break; - case 'r': - if (strEQ(ptr, "rbytes")) { - if (ifstat->rx_bytes == 0) { - ifstat->rx_bytes = value; - } - } - else if (strEQ(ptr, "rbytes64")) { - ifstat->rx_bytes = data[i].value.ui64; - } - else if (strEQ(ptr, "rx_overflow")) { - ifstat->rx_overruns = value; - } - break; - default: - break; - } - } -} - -static int sigar_net_ifstat_get_any(sigar_t *sigar, const char *name, - sigar_net_interface_stat_t *ifstat) -{ - kstat_ctl_t *kc = sigar->kc; - kstat_t *ksp; - kstat_named_t *data; - - if (sigar_kstat_update(sigar) == -1) { - return errno; - } - - if (!(ksp = kstat_lookup(kc, NULL, -1, (char *)name))) { - return ENXIO; - } - - if (kstat_read(kc, ksp, NULL) < 0) { - return ENOENT; - } - - data = (kstat_named_t *)ksp->ks_data; - - ifstat_kstat_common(ifstat, data, ksp->ks_ndata); - - return SIGAR_OK; -} - -/* loopback interface only has rx/tx packets */ -static int sigar_net_ifstat_get_lo(sigar_t *sigar, const char *name, - sigar_net_interface_stat_t *ifstat) -{ - ifstat->rx_packets = 0; - ifstat->rx_bytes = SIGAR_FIELD_NOTIMPL; - ifstat->rx_errors = SIGAR_FIELD_NOTIMPL; - ifstat->rx_dropped = SIGAR_FIELD_NOTIMPL; - ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->rx_frame = SIGAR_FIELD_NOTIMPL; - - ifstat->tx_packets = 0; - ifstat->tx_bytes = SIGAR_FIELD_NOTIMPL; - ifstat->tx_errors = SIGAR_FIELD_NOTIMPL; - ifstat->tx_dropped = SIGAR_FIELD_NOTIMPL; - ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->tx_collisions = SIGAR_FIELD_NOTIMPL; - ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL; - - ifstat->speed = SIGAR_FIELD_NOTIMPL; - - return sigar_net_ifstat_get_any(sigar, name, ifstat); -} - -int sigar_net_interface_stat_get(sigar_t *sigar, const char *name, - sigar_net_interface_stat_t *ifstat) -{ - ifstat->speed = SIGAR_FIELD_NOTIMPL; - - if (strnEQ(name, "lo", 2)) { - return sigar_net_ifstat_get_lo(sigar, name, ifstat); - } - else { - SIGAR_ZERO(ifstat); - return sigar_net_ifstat_get_any(sigar, name, ifstat); - } -} - -int sigar_net_interface_ipv6_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig) -{ - int sock; - struct lifreq lifr; - - if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - return errno; - } - - SIGAR_SSTRCPY(lifr.lifr_name, name); - - if (ioctl(sock, SIOCGLIFADDR, &lifr) == 0) { - struct in6_addr *addr = SIGAR_SIN6_ADDR(&lifr.lifr_addr); - - sigar_net_address6_set(ifconfig->address6, addr); - sigar_net_interface_scope6_set(ifconfig, addr); - ifconfig->prefix6_length = lifr.lifr_addrlen; - } - - close(sock); - return SIGAR_OK; -} - -#define TCPQ_SIZE(s) ((s) >= 0 ? (s) : 0) - -static int tcp_connection_get(sigar_net_connection_walker_t *walker, - struct mib2_tcpConnEntry *entry, - int len) -{ - int flags = walker->flags; - int status; - char *end = (char *)entry + len; - - while ((char *)entry < end) { - int state = entry->tcpConnEntryInfo.ce_state; - - if (((flags & SIGAR_NETCONN_SERVER) && (state == TCPS_LISTEN)) || - ((flags & SIGAR_NETCONN_CLIENT) && (state != TCPS_LISTEN))) - { - sigar_net_connection_t conn; - - SIGAR_ZERO(&conn); - - sigar_net_address_set(conn.local_address, entry->tcpConnLocalAddress); - sigar_net_address_set(conn.remote_address, entry->tcpConnRemAddress); - - conn.local_port = entry->tcpConnLocalPort; - conn.remote_port = entry->tcpConnRemPort; - conn.type = SIGAR_NETCONN_TCP; - conn.send_queue = - TCPQ_SIZE(entry->tcpConnEntryInfo.ce_snxt - - entry->tcpConnEntryInfo.ce_suna - 1); - conn.receive_queue = - TCPQ_SIZE(entry->tcpConnEntryInfo.ce_rnxt - - entry->tcpConnEntryInfo.ce_rack); - - switch (state) { - case TCPS_CLOSED: - conn.state = SIGAR_TCP_CLOSE; - break; - case TCPS_IDLE: - conn.state = SIGAR_TCP_IDLE; - break; - case TCPS_BOUND: - conn.state = SIGAR_TCP_BOUND; - break; - case TCPS_LISTEN: - conn.state = SIGAR_TCP_LISTEN; - break; - case TCPS_SYN_SENT: - conn.state = SIGAR_TCP_SYN_SENT; - break; - case TCPS_SYN_RCVD: - conn.state = SIGAR_TCP_SYN_RECV; - break; - case TCPS_ESTABLISHED: - conn.state = SIGAR_TCP_ESTABLISHED; - break; - case TCPS_CLOSE_WAIT: - conn.state = SIGAR_TCP_CLOSE_WAIT; - break; - case TCPS_FIN_WAIT_1: - conn.state = SIGAR_TCP_FIN_WAIT1; - break; - case TCPS_CLOSING: - conn.state = SIGAR_TCP_CLOSING; - break; - case TCPS_LAST_ACK: - conn.state = SIGAR_TCP_LAST_ACK; - break; - case TCPS_FIN_WAIT_2: - conn.state = SIGAR_TCP_FIN_WAIT2; - break; - case TCPS_TIME_WAIT: - conn.state = SIGAR_TCP_TIME_WAIT; - break; - default: - conn.state = SIGAR_TCP_UNKNOWN; - break; - } - - status = walker->add_connection(walker, &conn); - if (status != SIGAR_OK) { - return status; - } - } - - entry++; - } - - return SIGAR_OK; -} - -static int udp_connection_get(sigar_net_connection_walker_t *walker, - struct mib2_udpEntry *entry, - int len) -{ - int flags = walker->flags; - int status; - char *end = (char *)entry + len; - - while ((char *)entry < end) { - int state = entry->udpEntryInfo.ue_state; - - /* XXX dunno if this state check is right */ - if (((flags & SIGAR_NETCONN_SERVER) && (state == MIB2_UDP_idle)) || - ((flags & SIGAR_NETCONN_CLIENT) && (state != MIB2_UDP_idle))) - { - sigar_net_connection_t conn; - - SIGAR_ZERO(&conn); - - sigar_net_address_set(conn.local_address, entry->udpLocalAddress); - sigar_net_address_set(conn.remote_address, 0); - - conn.local_port = entry->udpLocalPort; - conn.remote_port = 0; - conn.type = SIGAR_NETCONN_UDP; - - status = walker->add_connection(walker, &conn); - if (status != SIGAR_OK) { - return status; - } - } - - entry++; - } - - return SIGAR_OK; -} - -int sigar_net_connection_walk(sigar_net_connection_walker_t *walker) -{ - sigar_t *sigar = walker->sigar; - int flags = walker->flags; - int status; - int want_tcp = flags & SIGAR_NETCONN_TCP; - int want_udp = flags & SIGAR_NETCONN_UDP; - char *data; - int len; - int rc; - struct opthdr *op; - - while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) { - if ((op->level == MIB2_TCP) && - (op->name == MIB2_TCP_13) && - want_tcp) - { - status = - tcp_connection_get(walker, - (struct mib2_tcpConnEntry *)data, - len); - } - else if ((op->level == MIB2_UDP) && - (op->name == MIB2_UDP_5) && - want_udp) - { - status = - udp_connection_get(walker, - (struct mib2_udpEntry *)data, - len); - } - else { - status = SIGAR_OK; - } - - if (status != SIGAR_OK) { - break; - } - } - - if (rc != GET_MIB2_EOD) { - close_mib2(&sigar->mib2); - return SIGAR_EMIB2; - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_tcp_get(sigar_t *sigar, - sigar_tcp_t *tcp) -{ - char *data; - int len; - int rc; - struct opthdr *op; - mib2_tcp_t *mib = NULL; - - while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) { - if ((op->level == MIB2_TCP) && (op->name == 0)) { - mib = (mib2_tcp_t *)data; - break; - } - } - - if (mib) { - tcp->active_opens = mib->tcpActiveOpens; - tcp->passive_opens = mib->tcpPassiveOpens; - tcp->attempt_fails = mib->tcpAttemptFails; - tcp->estab_resets = mib->tcpEstabResets; - tcp->curr_estab = mib->tcpCurrEstab; - tcp->in_segs = mib->tcpInSegs; - tcp->out_segs = mib->tcpOutSegs; - tcp->retrans_segs = mib->tcpRetransSegs; - tcp->in_errs = SIGAR_FIELD_NOTIMPL; /* XXX mib2_ip_t.tcpInErrs */ - tcp->out_rsts = mib->tcpOutRsts; - return SIGAR_OK; - } - else { - return SIGAR_ENOTIMPL; - } -} - -static int sigar_nfs_get(sigar_t *sigar, - char *type, - char **names, - char *nfs) -{ - size_t offset; - kstat_t *ksp; - int i; - - if (sigar_kstat_update(sigar) == -1) { - return errno; - } - - if (!(ksp = kstat_lookup(sigar->kc, "nfs", 0, type))) { - return SIGAR_ENOTIMPL; - } - - if (kstat_read(sigar->kc, ksp, NULL) < 0) { - return errno; - } - - for (i=0, offset=0; - names[i]; - i++, offset+=sizeof(sigar_uint64_t)) - { - sigar_uint64_t val; - kstat_named_t *kv = - kstat_data_lookup(ksp, names[i]); - - if (kv) { - val = kv->value.ui64; - } - else { - val = -1; - } - - *(sigar_uint64_t *)((char *)nfs + offset) = val; - } - - return SIGAR_OK; -} - -static char *nfs_v2_names[] = { - "null", - "getattr", - "setattr", - "root", - "lookup", - "readlink", - "read", - "wrcache", - "write", - "create", - "remove", - "rename", - "link", - "symlink", - "mkdir", - "rmdir", - "readdir", - "statfs", - NULL -}; - -int sigar_nfs_client_v2_get(sigar_t *sigar, - sigar_nfs_client_v2_t *nfs) -{ - return sigar_nfs_get(sigar, "rfsreqcnt_v2", nfs_v2_names, (char *)nfs); -} - -int sigar_nfs_server_v2_get(sigar_t *sigar, - sigar_nfs_server_v2_t *nfs) -{ - return sigar_nfs_get(sigar, "rfsproccnt_v2", nfs_v2_names, (char *)nfs); -} - -static char *nfs_v3_names[] = { - "null", - "getattr", - "setattr", - "lookup", - "access", - "readlink", - "read", - "write", - "create", - "mkdir", - "symlink", - "mknod", - "remove", - "rmdir", - "rename", - "link", - "readdir", - "readdirplus", - "fsstat", - "fsinfo", - "pathconf", - "commit", - NULL -}; - -int sigar_nfs_client_v3_get(sigar_t *sigar, - sigar_nfs_client_v3_t *nfs) -{ - return sigar_nfs_get(sigar, "rfsreqcnt_v3", nfs_v3_names, (char *)nfs); -} - -int sigar_nfs_server_v3_get(sigar_t *sigar, - sigar_nfs_server_v3_t *nfs) -{ - return sigar_nfs_get(sigar, "rfsproccnt_v3", nfs_v3_names, (char *)nfs); -} - -int sigar_arp_list_get(sigar_t *sigar, - sigar_arp_list_t *arplist) -{ - char *data; - int len, rc; - struct opthdr *op; - size_t nread=0, size=0; - const char *size_from; - - sigar_arp_list_create(arplist); - - while ((rc = get_mib2(&sigar->mib2, &op, &data, &len)) == GET_MIB2_OK) { - mib2_ipNetToMediaEntry_t *entry; - char *end; - - if (op->level != MIB2_IP) { - continue; - } - - if (op->name == 0) { - /* we want to use this size for bincompat */ - size = ((mib2_ip_t *)data)->ipNetToMediaEntrySize; - continue; - } - else if (op->name != MIB2_IP_MEDIA) { - continue; - } - - if (size == 0) { - size_from = "sizeof"; - size = sizeof(*entry); - } - else { - size_from = "mib2_ip"; - } - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[arp_list] ipNetToMediaEntrySize=%d (from %s)", - size, size_from); - } - - for (entry = (mib2_ipNetToMediaEntry_t *)data, end = data + len; - (char *)entry < end; - nread+=size, entry = (mib2_ipNetToMediaEntry_t *)((char *)data+nread)) - { - sigar_arp_t *arp; - - SIGAR_ARP_LIST_GROW(arplist); - arp = &arplist->data[arplist->number++]; - - sigar_net_address_set(arp->address, - entry->ipNetToMediaNetAddress); - - sigar_net_address_mac_set(arp->hwaddr, - entry->ipNetToMediaPhysAddress.o_bytes, - entry->ipNetToMediaPhysAddress.o_length); - - SIGAR_SSTRCPY(arp->ifname, entry->ipNetToMediaIfIndex.o_bytes); - - arp->flags = entry->ipNetToMediaInfo.ntm_flags; - SIGAR_SSTRCPY(arp->type, "ether"); /*XXX*/ - } - } - - if (rc != GET_MIB2_EOD) { - close_mib2(&sigar->mib2); - return SIGAR_EMIB2; - } - - return SIGAR_OK; -} - -static int find_port(sigar_t *sigar, struct ps_prochandle *phandle, - sigar_pid_t pid, unsigned long port) -{ - DIR *dirp; - struct dirent *ent; - char pname[PATH_MAX]; - struct stat64 statb; - int found=0; - - sprintf(pname, "/proc/%d/fd", (int)pid); - - if (!(dirp = opendir(pname))) { - return 0; - } - - while ((ent = readdir(dirp))) { - int fd; - - if (!sigar_isdigit(ent->d_name[0])) { - continue; - } - fd = atoi(ent->d_name); - - if (sigar->pfstat64(phandle, fd, &statb) == -1) { - continue; - } - - if ((statb.st_mode & S_IFMT) == S_IFSOCK) { - struct sockaddr_in sin; - struct sockaddr *sa = (struct sockaddr *)&sin; - socklen_t len = sizeof(sin); - int opt, optsz, rc; - - optsz = sizeof(opt); - rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_TYPE, &opt, &optsz); - if (rc != 0) { - continue; - } - if (opt != SOCK_STREAM) { - continue; - } - optsz = sizeof(opt); - rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_ACCEPTCONN, &opt, &optsz); - if (rc != 0) { - continue; - } - if (opt != SO_ACCEPTCONN) { - continue; - } - - rc = sigar->pgetsockname(phandle, fd, sa, &len); - if (rc != 0) { - continue; - } - - if ((sa->sa_family == AF_INET) || - (sa->sa_family == AF_INET6)) - { - if (ntohs(sin.sin_port) == port) { - found = 1; - break; - } - } - } - } - - closedir(dirp); - - return found; -} - -/* derived from /usr/bin/pfiles.c */ -int sigar_proc_port_get(sigar_t *sigar, int protocol, - unsigned long port, sigar_pid_t *pid) -{ - sigar_proc_list_t pids; - int i, status, found=0; - - if (sigar->solaris_version < 10) { - return SIGAR_ENOTIMPL; - } - - if ((status = sigar_init_libproc(sigar)) != SIGAR_OK) { - return SIGAR_ENOTIMPL; - } - status = sigar_proc_list_get(sigar, &pids); - if (status != SIGAR_OK) { - return status; - } - - for (i=0; ipcreate_agent(phandle) == 0) { - found = find_port(sigar, phandle, ps_id, port); - sigar->pdestroy_agent(phandle); - } - - sigar->pfree(phandle); - if (found) { - *pid = ps_id; - break; - } - } - - sigar_proc_list_destroy(sigar, &pids); - - return found ? SIGAR_OK : ENOENT; -} - -int sigar_os_sys_info_get(sigar_t *sigar, - sigar_sys_info_t *sys_info) -{ - char *vendor_version; - - sysinfo(SI_ARCHITECTURE, sys_info->arch, sizeof(sys_info->arch)); - - SIGAR_SSTRCPY(sys_info->name, "Solaris"); - SIGAR_SSTRCPY(sys_info->vendor, "Sun Microsystems"); - - if (strEQ(sys_info->version, "5.6")) { - vendor_version = "2.6"; - } - else { - if ((vendor_version = strchr(sys_info->version, '.'))) { - ++vendor_version; - } - else { - vendor_version = sys_info->version; - } - } - - SIGAR_SSTRCPY(sys_info->vendor_version, vendor_version); - - snprintf(sys_info->description, - sizeof(sys_info->description), - "%s %s", - sys_info->name, sys_info->vendor_version); - - return SIGAR_OK; -} diff --git a/vendor/sigar/src/os/win32/peb.c b/vendor/sigar/src/os/win32/peb.c deleted file mode 100644 index d8b2eca..0000000 --- a/vendor/sigar/src/os/win32/peb.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2004, 2006-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * functions for getting info from the Process Environment Block - */ -#define UNICODE -#define _UNICODE - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_os.h" -#include - -void dllmod_init_ntdll(sigar_t *sigar); - -#define sigar_NtQueryInformationProcess \ - sigar->ntdll.query_proc_info.func - -static int sigar_pbi_get(sigar_t *sigar, HANDLE proc, PEB *peb) -{ - int status; - PROCESS_BASIC_INFORMATION pbi; - DWORD size=sizeof(pbi); - - dllmod_init_ntdll(sigar); - - if (!sigar_NtQueryInformationProcess) { - return SIGAR_ENOTIMPL; - } - - SIGAR_ZERO(&pbi); - status = - sigar_NtQueryInformationProcess(proc, - ProcessBasicInformation, - &pbi, - size, NULL); - if (status != ERROR_SUCCESS) { - return status; - } - - if (!pbi.PebBaseAddress) { - /* likely we are 32-bit, pid process is 64-bit */ - return ERROR_DATATYPE_MISMATCH; - } - - size = sizeof(*peb); - - if (ReadProcessMemory(proc, pbi.PebBaseAddress, peb, size, NULL)) { - return SIGAR_OK; - } - else { - return GetLastError(); - } -} - -static int sigar_rtl_get(sigar_t *sigar, HANDLE proc, - RTL_USER_PROCESS_PARAMETERS *rtl) -{ - PEB peb; - int status = sigar_pbi_get(sigar, proc, &peb); - DWORD size=sizeof(*rtl); - - if (status != SIGAR_OK) { - return status; - } - - if (ReadProcessMemory(proc, peb.ProcessParameters, rtl, size, NULL)) { - return SIGAR_OK; - } - else { - return GetLastError(); - } -} - -#define rtl_bufsize(buf, uc) \ - ((sizeof(buf) < uc.Length) ? sizeof(buf) : uc.Length) - -int sigar_proc_exe_peb_get(sigar_t *sigar, HANDLE proc, - sigar_proc_exe_t *procexe) -{ - int status; - WCHAR buf[MAX_PATH+1]; - RTL_USER_PROCESS_PARAMETERS rtl; - DWORD size; - - procexe->name[0] = '\0'; - procexe->cwd[0] = '\0'; - - if ((status = sigar_rtl_get(sigar, proc, &rtl)) != SIGAR_OK) { - return status; - } - - size = rtl_bufsize(buf, rtl.ImagePathName); - memset(buf, '\0', sizeof(buf)); - - if ((size > 0) && - ReadProcessMemory(proc, rtl.ImagePathName.Buffer, buf, size, NULL)) - { - SIGAR_W2A(buf, procexe->name, sizeof(procexe->name)); - } - - size = rtl_bufsize(buf, rtl.CurrentDirectoryName); - memset(buf, '\0', sizeof(buf)); - - if ((size > 0) && - ReadProcessMemory(proc, rtl.CurrentDirectoryName.Buffer, buf, size, NULL)) - { - SIGAR_W2A(buf, procexe->cwd, sizeof(procexe->cwd)); - } - - return SIGAR_OK; -} - -int sigar_parse_proc_args(sigar_t *sigar, WCHAR *buf, - sigar_proc_args_t *procargs) -{ - char arg[SIGAR_CMDLINE_MAX]; - LPWSTR *args; - int num, i; - - if (!buf) { - buf = GetCommandLine(); - } - - args = CommandLineToArgvW(buf, &num); - - if (args == NULL) { - return SIGAR_OK; - } - - for (i=0; idata[procargs->number++] = sigar_strdup(arg); - } - - GlobalFree(args); - - return SIGAR_OK; -} - -int sigar_proc_args_peb_get(sigar_t *sigar, HANDLE proc, - sigar_proc_args_t *procargs) -{ - int status; - WCHAR buf[SIGAR_CMDLINE_MAX]; - RTL_USER_PROCESS_PARAMETERS rtl; - DWORD size; - - if ((status = sigar_rtl_get(sigar, proc, &rtl)) != SIGAR_OK) { - return status; - } - - size = rtl_bufsize(buf, rtl.CommandLine); - if (size <= 0) { - return ERROR_DATATYPE_MISMATCH; /* fallback to wmi */ - } - memset(buf, '\0', sizeof(buf)); - - if (ReadProcessMemory(proc, rtl.CommandLine.Buffer, buf, size, NULL)) { - return sigar_parse_proc_args(sigar, buf, procargs); - } - else { - return GetLastError(); - } -} - -int sigar_proc_env_peb_get(sigar_t *sigar, HANDLE proc, - WCHAR *buf, DWORD size) -{ - int status; - RTL_USER_PROCESS_PARAMETERS rtl; - MEMORY_BASIC_INFORMATION info; - - if ((status = sigar_rtl_get(sigar, proc, &rtl)) != SIGAR_OK) { - return status; - } - - memset(buf, '\0', size); - /* -2 to ensure \0\0 terminator */ - size -= 2; - - if (VirtualQueryEx(proc, rtl.Environment, &info, sizeof(info))) { - if (size > info.RegionSize) { - /* ReadProcessMemory beyond region would fail */ - size = info.RegionSize; - } - } - - if (ReadProcessMemory(proc, rtl.Environment, buf, size, NULL)) { - return SIGAR_OK; - } - else { - return GetLastError(); - } -} diff --git a/vendor/sigar/src/os/win32/sigar_os.h b/vendor/sigar/src/os/win32/sigar_os.h deleted file mode 100755 index cf61c25..0000000 --- a/vendor/sigar/src/os/win32/sigar_os.h +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_OS_H -#define SIGAR_OS_H - -#if !defined(MSVC) && defined(_MSC_VER) -#define MSVC -#endif - -#ifdef MSVC -#define WIN32_LEAN_AND_MEAN -#define snprintf _snprintf -#if _MSC_VER <= 1200 -#define SIGAR_USING_MSC6 /* Visual Studio version 6 */ -#define HAVE_MIB_IPADDRROW_WTYPE 0 -#else -#define HAVE_MIB_IPADDRROW_WTYPE 1 -#endif -#else -/* Cross compiling */ -#define _WIN32_WINNT 0x0501 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sigar_util.h" - -#ifdef MSVC -# define INT64_C(val) val##i64 -# define SIGAR_DLLFUNC(api, name) \ - struct { \ - const char *name; \ - ##api##_##name func; \ - } ##name -#else -/* The GCC compiler doesn't require/accept the ## prefix */ -# define INT64_C(val) val##L -# define SIGAR_DLLFUNC(api, name) \ - struct { \ - const char *name; \ - api##_##name func; \ - } name -#endif - -/* see apr/include/arch/win32/atime.h */ -#define EPOCH_DELTA INT64_C(11644473600000000) - -#define SIGAR_CMDLINE_MAX 4096<<2 - -/* XXX: support CP_UTF8 ? */ - -#define SIGAR_A2W(lpa, lpw, bytes) \ - (lpw[0] = 0, MultiByteToWideChar(CP_ACP, 0, \ - lpa, -1, lpw, (bytes/sizeof(WCHAR)))) - -#define SIGAR_W2A(lpw, lpa, chars) \ - (lpa[0] = '\0', WideCharToMultiByte(CP_ACP, 0, \ - lpw, -1, (LPSTR)lpa, chars, \ - NULL, NULL)) - -/* iptypes.h from vc7, not available in vc6 */ -/* copy from PSDK if using vc6 */ -#include "iptypes.h" - -/* from wtsapi32.h not in vs6.0 */ -typedef enum { - WTSInitialProgram, - WTSApplicationName, - WTSWorkingDirectory, - WTSOEMId, - WTSSessionId, - WTSUserName, - WTSWinStationName, - WTSDomainName, - WTSConnectState, - WTSClientBuildNumber, - WTSClientName, - WTSClientDirectory, - WTSClientProductId, - WTSClientHardwareId, - WTSClientAddress, - WTSClientDisplay, - WTSClientProtocolType, -} WTS_INFO_CLASS; - -typedef enum _WTS_CONNECTSTATE_CLASS { - WTSActive, - WTSConnected, - WTSConnectQuery, - WTSShadow, - WTSDisconnected, - WTSIdle, - WTSListen, - WTSReset, - WTSDown, - WTSInit -} WTS_CONNECTSTATE_CLASS; - -#define WTS_PROTOCOL_TYPE_CONSOLE 0 -#define WTS_PROTOCOL_TYPE_ICA 1 -#define WTS_PROTOCOL_TYPE_RDP 2 - -typedef struct _WTS_SESSION_INFO { - DWORD SessionId; - LPTSTR pWinStationName; - DWORD State; -} WTS_SESSION_INFO, *PWTS_SESSION_INFO; - -typedef struct _WTS_PROCESS_INFO { - DWORD SessionId; - DWORD ProcessId; - LPSTR pProcessName; - PSID pUserSid; -} WTS_PROCESS_INFO, *PWTS_PROCESS_INFO; - -typedef struct _WTS_CLIENT_ADDRESS { - DWORD AddressFamily; - BYTE Address[20]; -} WTS_CLIENT_ADDRESS, *PWTS_CLIENT_ADDRESS; - -/* the WINSTATION_INFO stuff here is undocumented - * got the howto from google groups: - * http://redirx.com/?31gy - */ -typedef enum _WINSTATION_INFO_CLASS { - WinStationInformation = 8 -} WINSTATION_INFO_CLASS; - -typedef struct _WINSTATION_INFO { - BYTE Reserved1[72]; - ULONG SessionId; - BYTE Reserved2[4]; - FILETIME ConnectTime; - FILETIME DisconnectTime; - FILETIME LastInputTime; - FILETIME LoginTime; - BYTE Reserved3[1096]; - FILETIME CurrentTime; -} WINSTATION_INFO, *PWINSTATION_INFO; - -/* end wtsapi32.h */ - -#ifdef SIGAR_USING_MSC6 - -/* from winbase.h not in vs6.0 */ -typedef struct { - DWORD dwLength; - DWORD dwMemoryLoad; - DWORDLONG ullTotalPhys; - DWORDLONG ullAvailPhys; - DWORDLONG ullTotalPageFile; - DWORDLONG ullAvailPageFile; - DWORDLONG ullTotalVirtual; - DWORDLONG ullAvailVirtual; - DWORDLONG ullAvailExtendedVirtual; -} MEMORYSTATUSEX; - -/* service manager stuff not in vs6.0 */ -typedef struct _SERVICE_STATUS_PROCESS { - DWORD dwServiceType; - DWORD dwCurrentState; - DWORD dwControlsAccepted; - DWORD dwWin32ExitCode; - DWORD dwServiceSpecificExitCode; - DWORD dwCheckPoint; - DWORD dwWaitHint; - DWORD dwProcessId; - DWORD dwServiceFlags; -} SERVICE_STATUS_PROCESS; - -typedef enum { - SC_STATUS_PROCESS_INFO = 0 -} SC_STATUS_TYPE; - -#ifndef ERROR_DATATYPE_MISMATCH -#define ERROR_DATATYPE_MISMATCH 1629L -#endif - -#endif /* _MSC_VER */ - -#include - -/* undocumented structures */ -typedef struct { - DWORD dwState; - DWORD dwLocalAddr; - DWORD dwLocalPort; - DWORD dwRemoteAddr; - DWORD dwRemotePort; - DWORD dwProcessId; -} MIB_TCPEXROW, *PMIB_TCPEXROW; - -typedef struct { - DWORD dwNumEntries; - MIB_TCPEXROW table[ANY_SIZE]; -} MIB_TCPEXTABLE, *PMIB_TCPEXTABLE; - -typedef struct { - DWORD dwLocalAddr; - DWORD dwLocalPort; - DWORD dwProcessId; -} MIB_UDPEXROW, *PMIB_UDPEXROW; - -typedef struct { - DWORD dwNumEntries; - MIB_UDPEXROW table[ANY_SIZE]; -} MIB_UDPEXTABLE, *PMIB_UDPEXTABLE; - -/* end undocumented structures */ - -/* no longer in the standard header files */ -typedef struct { - LARGE_INTEGER IdleTime; - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER DpcTime; - LARGE_INTEGER InterruptTime; - ULONG InterruptCount; -} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; - -#define SystemProcessorPerformanceInformation 8 - -/* PEB decls from msdn docs w/ slight mods */ -#define ProcessBasicInformation 0 - -typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING, *PUNICODE_STRING; - -typedef struct _PEB_LDR_DATA { - BYTE Reserved1[8]; - PVOID Reserved2[3]; - LIST_ENTRY InMemoryOrderModuleList; -} PEB_LDR_DATA, *PPEB_LDR_DATA; - -typedef struct RTL_DRIVE_LETTER_CURDIR { - USHORT Flags; - USHORT Length; - ULONG TimeStamp; - UNICODE_STRING DosPath; -} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; - -/* from: http://source.winehq.org/source/include/winternl.h */ -typedef struct _RTL_USER_PROCESS_PARAMETERS { - ULONG AllocationSize; - ULONG Size; - ULONG Flags; - ULONG DebugFlags; - HANDLE hConsole; - ULONG ProcessGroup; - HANDLE hStdInput; - HANDLE hStdOutput; - HANDLE hStdError; - UNICODE_STRING CurrentDirectoryName; - HANDLE CurrentDirectoryHandle; - UNICODE_STRING DllPath; - UNICODE_STRING ImagePathName; - UNICODE_STRING CommandLine; - PWSTR Environment; - ULONG dwX; - ULONG dwY; - ULONG dwXSize; - ULONG dwYSize; - ULONG dwXCountChars; - ULONG dwYCountChars; - ULONG dwFillAttribute; - ULONG dwFlags; - ULONG wShowWindow; - UNICODE_STRING WindowTitle; - UNICODE_STRING Desktop; - UNICODE_STRING ShellInfo; - UNICODE_STRING RuntimeInfo; - RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; -} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; - -/* from msdn docs -typedef struct _RTL_USER_PROCESS_PARAMETERS { - BYTE Reserved1[16]; - PVOID Reserved2[10]; - UNICODE_STRING ImagePathName; - UNICODE_STRING CommandLine; -} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; -*/ - -typedef struct _PEB { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[1]; - PVOID Reserved3[2]; - PPEB_LDR_DATA Ldr; - PRTL_USER_PROCESS_PARAMETERS ProcessParameters; - BYTE Reserved4[104]; - PVOID Reserved5[52]; - /*PPS_POST_PROCESS_INIT_ROUTINE*/ PVOID PostProcessInitRoutine; - BYTE Reserved6[128]; - PVOID Reserved7[1]; - ULONG SessionId; -} PEB, *PPEB; - -typedef struct _PROCESS_BASIC_INFORMATION { - PVOID Reserved1; - PPEB PebBaseAddress; - PVOID Reserved2[2]; - /*ULONG_PTR*/ UINT_PTR UniqueProcessId; - PVOID Reserved3; -} PROCESS_BASIC_INFORMATION; - -typedef struct { - sigar_pid_t pid; - int ppid; - int priority; - time_t mtime; - sigar_uint64_t size; - sigar_uint64_t resident; - char name[SIGAR_PROC_NAME_LEN]; - char state; - sigar_uint64_t handles; - sigar_uint64_t threads; - sigar_uint64_t page_faults; -} sigar_win32_pinfo_t; - -typedef struct { - const char *name; - HINSTANCE handle; -} sigar_dll_handle_t; - -typedef struct { - const char *name; - FARPROC func; -} sigar_dll_func_t; - -typedef struct { - const char *name; - HINSTANCE handle; - sigar_dll_func_t funcs[12]; -} sigar_dll_module_t; - -/* wtsapi.dll */ -typedef BOOL (CALLBACK *wtsapi_enum_sessions)(HANDLE, - DWORD, - DWORD, - PWTS_SESSION_INFO *, - DWORD *); - -typedef void (CALLBACK *wtsapi_free_mem)(PVOID); - -typedef BOOL (CALLBACK *wtsapi_query_session)(HANDLE, - DWORD, - WTS_INFO_CLASS, - LPSTR *, DWORD *); -/* iphlpapi.dll */ - -typedef DWORD (CALLBACK *iphlpapi_get_ipforward_table)(PMIB_IPFORWARDTABLE, - PULONG, - BOOL); - -typedef DWORD (CALLBACK *iphlpapi_get_ipaddr_table)(PMIB_IPADDRTABLE, - PULONG, - BOOL); - -typedef DWORD (CALLBACK *iphlpapi_get_if_table)(PMIB_IFTABLE, - PULONG, - BOOL); - -typedef DWORD (CALLBACK *iphlpapi_get_if_entry)(PMIB_IFROW); - -typedef DWORD (CALLBACK *iphlpapi_get_num_if)(PDWORD); - -typedef DWORD (CALLBACK *iphlpapi_get_tcp_table)(PMIB_TCPTABLE, - PDWORD, - BOOL); - -typedef DWORD (CALLBACK *iphlpapi_get_udp_table)(PMIB_UDPTABLE, - PDWORD, - BOOL); - -typedef DWORD (CALLBACK *iphlpapi_get_tcpx_table)(PMIB_TCPEXTABLE *, - BOOL, - HANDLE, - DWORD, - DWORD); - -typedef DWORD (CALLBACK *iphlpapi_get_udpx_table)(PMIB_UDPEXTABLE *, - BOOL, - HANDLE, - DWORD, - DWORD); - -typedef DWORD (CALLBACK *iphlpapi_get_tcp_stats)(PMIB_TCPSTATS); - -typedef DWORD (CALLBACK *iphlpapi_get_net_params)(PFIXED_INFO, - PULONG); - -typedef DWORD (CALLBACK *iphlpapi_get_adapters_info)(PIP_ADAPTER_INFO, - PULONG); - -typedef ULONG (CALLBACK *iphlpapi_get_adapters_addrs)(ULONG, - ULONG, - PVOID, - PIP_ADAPTER_ADDRESSES, - PULONG); - -/* advapi32.dll */ -typedef BOOL (CALLBACK *advapi_convert_string_sid)(LPCSTR, - PSID *); - -typedef BOOL (CALLBACK *advapi_query_service_status)(SC_HANDLE, - SC_STATUS_TYPE, - LPBYTE, - DWORD, - LPDWORD); - -typedef DWORD (CALLBACK *iphlpapi_get_ipnet_table)(PMIB_IPNETTABLE, - PDWORD, - BOOL); - -/* ntdll.dll */ -typedef DWORD (CALLBACK *ntdll_query_sys_info)(DWORD, - PVOID, - ULONG, - PULONG); - -typedef DWORD (CALLBACK *ntdll_query_proc_info)(HANDLE, - DWORD, - PVOID, - ULONG, - PULONG); - -/* psapi.dll */ -typedef BOOL (CALLBACK *psapi_enum_modules)(HANDLE, - HMODULE *, - DWORD, - LPDWORD); - -typedef DWORD (CALLBACK *psapi_get_module_name)(HANDLE, - HMODULE, - LPTSTR, - DWORD); - -typedef BOOL (CALLBACK *psapi_enum_processes)(DWORD *, - DWORD, - DWORD *); - -/* winsta.dll */ -typedef BOOLEAN (CALLBACK *winsta_query_info)(HANDLE, - ULONG, - WINSTATION_INFO_CLASS, - PVOID, - ULONG, - PULONG); - -/* kernel32.dll */ -typedef BOOL (CALLBACK *kernel_memory_status)(MEMORYSTATUSEX *); - -/* mpr.dll */ -typedef BOOL (CALLBACK *mpr_get_net_connection)(LPCTSTR, - LPTSTR, - LPDWORD); - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(wtsapi, enum_sessions); - SIGAR_DLLFUNC(wtsapi, free_mem); - SIGAR_DLLFUNC(wtsapi, query_session); - - sigar_dll_func_t end; -} sigar_wtsapi_t; - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(iphlpapi, get_ipforward_table); - SIGAR_DLLFUNC(iphlpapi, get_ipaddr_table); - SIGAR_DLLFUNC(iphlpapi, get_if_table); - SIGAR_DLLFUNC(iphlpapi, get_if_entry); - SIGAR_DLLFUNC(iphlpapi, get_num_if); - SIGAR_DLLFUNC(iphlpapi, get_tcp_table); - SIGAR_DLLFUNC(iphlpapi, get_udp_table); - SIGAR_DLLFUNC(iphlpapi, get_tcpx_table); - SIGAR_DLLFUNC(iphlpapi, get_udpx_table); - SIGAR_DLLFUNC(iphlpapi, get_tcp_stats); - SIGAR_DLLFUNC(iphlpapi, get_net_params); - SIGAR_DLLFUNC(iphlpapi, get_adapters_info); - SIGAR_DLLFUNC(iphlpapi, get_adapters_addrs); - SIGAR_DLLFUNC(iphlpapi, get_ipnet_table); - - sigar_dll_func_t end; -} sigar_iphlpapi_t; - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(advapi, convert_string_sid); - SIGAR_DLLFUNC(advapi, query_service_status); - - sigar_dll_func_t end; -} sigar_advapi_t; - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(ntdll, query_sys_info); - SIGAR_DLLFUNC(ntdll, query_proc_info); - - sigar_dll_func_t end; -} sigar_ntdll_t; - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(psapi, enum_modules); - SIGAR_DLLFUNC(psapi, enum_processes); - SIGAR_DLLFUNC(psapi, get_module_name); - - sigar_dll_func_t end; -} sigar_psapi_t; - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(winsta, query_info); - - sigar_dll_func_t end; -} sigar_winsta_t; - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(kernel, memory_status); - - sigar_dll_func_t end; -} sigar_kernel_t; - -typedef struct { - sigar_dll_handle_t handle; - - SIGAR_DLLFUNC(mpr, get_net_connection); - - sigar_dll_func_t end; -} sigar_mpr_t; - -struct sigar_t { - SIGAR_T_BASE; - char *machine; - int using_wide; - long pagesize; - HKEY handle; - char *perfbuf; - DWORD perfbuf_size; - sigar_wtsapi_t wtsapi; - sigar_iphlpapi_t iphlpapi; - sigar_advapi_t advapi; - sigar_ntdll_t ntdll; - sigar_psapi_t psapi; - sigar_winsta_t winsta; - sigar_kernel_t kernel; - sigar_mpr_t mpr; - sigar_win32_pinfo_t pinfo; - sigar_cache_t *netif_adapters; - sigar_cache_t *netif_mib_rows; - sigar_cache_t *netif_addr_rows; - sigar_cache_t *netif_names; /* dwIndex -> net_interface_config.name */ - int netif_name_short; - - WORD ws_version; - int ws_error; - int ht_enabled; - int lcpu; //number of logical cpus - int winnt; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft); - -int sigar_wsa_init(sigar_t *sigar); - -int sigar_proc_exe_peb_get(sigar_t *sigar, HANDLE proc, - sigar_proc_exe_t *procexe); - -int sigar_proc_args_peb_get(sigar_t *sigar, HANDLE proc, - sigar_proc_args_t *procargs); - -int sigar_proc_env_peb_get(sigar_t *sigar, HANDLE proc, - WCHAR *env, DWORD envlen); - -int sigar_proc_args_wmi_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs); - -int sigar_proc_exe_wmi_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe); - -int sigar_parse_proc_args(sigar_t *sigar, WCHAR *buf, - sigar_proc_args_t *procargs); - -int sigar_service_pid_get(sigar_t *sigar, char *name, sigar_pid_t *pid); - -typedef struct { - DWORD size; - DWORD count; - ENUM_SERVICE_STATUS *services; - SC_HANDLE handle; -} sigar_services_status_t; - -int sigar_services_status_get(sigar_services_status_t *ss, DWORD state); - -void sigar_services_status_close(sigar_services_status_t *ss); - -typedef struct sigar_services_walker_t sigar_services_walker_t; - -struct sigar_services_walker_t { - sigar_t *sigar; - int flags; - void *data; /* user data */ - int (*add_service)(sigar_services_walker_t *walker, char *name); -}; - -int sigar_services_query(char *ptql, - sigar_ptql_error_t *error, - sigar_services_walker_t *walker); - -char *sigar_service_exe_get(char *path, char *buffer, int basename); - -typedef struct { - WORD product_major; - WORD product_minor; - WORD product_build; - WORD product_revision; - WORD file_major; - WORD file_minor; - WORD file_build; - WORD file_revision; -} sigar_file_version_t; - -int sigar_file_version_get(sigar_file_version_t *version, - char *name, - sigar_proc_env_t *infocb); - -#ifdef __cplusplus -} -#endif - -#define SIGAR_NO_SUCH_PROCESS (SIGAR_OS_START_ERROR+1) - -#endif /* SIGAR_OS_H */ diff --git a/vendor/sigar/src/os/win32/sigar_pdh.h b/vendor/sigar/src/os/win32/sigar_pdh.h deleted file mode 100644 index 86a481a..0000000 --- a/vendor/sigar/src/os/win32/sigar_pdh.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2004, 2006 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIGAR_PDH_H -#define SIGAR_PDH_H - -/* performance data helpers */ - -#define PdhFirstObject(block) \ - ((PERF_OBJECT_TYPE *)((BYTE *) block + block->HeaderLength)) - -#define PdhNextObject(object) \ - ((PERF_OBJECT_TYPE *)((BYTE *) object + object->TotalByteLength)) - -#define PdhFirstCounter(object) \ - ((PERF_COUNTER_DEFINITION *)((BYTE *) object + object->HeaderLength)) - -#define PdhNextCounter(counter) \ - ((PERF_COUNTER_DEFINITION *)((BYTE *) counter + counter->ByteLength)) - -#define PdhGetCounterBlock(inst) \ - ((PERF_COUNTER_BLOCK *)((BYTE *) inst + inst->ByteLength)) - -#define PdhFirstInstance(object) \ - ((PERF_INSTANCE_DEFINITION *)((BYTE *) object + object->DefinitionLength)) - -#define PdhNextInstance(inst) \ - ((PERF_INSTANCE_DEFINITION *)((BYTE *)inst + inst->ByteLength + \ - PdhGetCounterBlock(inst)->ByteLength)) - -#define PdhInstanceName(inst) \ - ((wchar_t *)((BYTE *)inst + inst->NameOffset)) - -#endif /* SIGAR_PDH_H */ diff --git a/vendor/sigar/src/os/win32/win32_sigar.c b/vendor/sigar/src/os/win32/win32_sigar.c deleted file mode 100755 index 4288f08..0000000 --- a/vendor/sigar/src/os/win32/win32_sigar.c +++ /dev/null @@ -1,3992 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_pdh.h" -#include "sigar_os.h" -#include "sigar_util.h" -#include "sigar_format.h" -#include -#ifndef MSVC -#include -#endif - -#define USING_WIDE_S(s) (s)->using_wide -#define USING_WIDE() USING_WIDE_S(sigar) - -#define PERFBUF_SIZE 8192 - -#define PERF_TITLE_PROC 230 -#define PERF_TITLE_SYS_KEY "2" -#define PERF_TITLE_MEM_KEY "4" -#define PERF_TITLE_PROC_KEY "230" -#define PERF_TITLE_CPU_KEY "238" -#define PERF_TITLE_DISK_KEY "236" - -#define PERF_TITLE_CPU_USER 142 -#define PERF_TITLE_CPU_IDLE 1746 -#define PERF_TITLE_CPU_SYS 144 -#define PERF_TITLE_CPU_IRQ 698 - -typedef enum { - PERF_IX_CPU_USER, - PERF_IX_CPU_IDLE, - PERF_IX_CPU_SYS, - PERF_IX_CPU_IRQ, - PERF_IX_CPU_MAX -} perf_cpu_offsets_t; - -#define PERF_TITLE_CPUTIME 6 -#define PERF_TITLE_PAGE_FAULTS 28 -#define PERF_TITLE_MEM_VSIZE 174 -#define PERF_TITLE_MEM_SIZE 180 -#define PERF_TITLE_THREAD_CNT 680 -#define PERF_TITLE_HANDLE_CNT 952 -#define PERF_TITLE_PID 784 -#define PERF_TITLE_PPID 1410 -#define PERF_TITLE_PRIORITY 682 -#define PERF_TITLE_START_TIME 684 - -typedef enum { - PERF_IX_CPUTIME, - PERF_IX_PAGE_FAULTS, - PERF_IX_MEM_VSIZE, - PERF_IX_MEM_SIZE, - PERF_IX_THREAD_CNT, - PERF_IX_HANDLE_CNT, - PERF_IX_PID, - PERF_IX_PPID, - PERF_IX_PRIORITY, - PERF_IX_START_TIME, - PERF_IX_MAX -} perf_proc_offsets_t; - -typedef enum { - PERF_IX_DISK_TIME, - PERF_IX_DISK_READ_TIME, - PERF_IX_DISK_WRITE_TIME, - PERF_IX_DISK_READ, - PERF_IX_DISK_WRITE, - PERF_IX_DISK_READ_BYTES, - PERF_IX_DISK_WRITE_BYTES, - PERF_IX_DISK_QUEUE, - PERF_IX_DISK_MAX -} perf_disk_offsets_t; - -#define PERF_TITLE_DISK_TIME 200 /* % Disk Time */ -#define PERF_TITLE_DISK_READ_TIME 202 /* % Disk Read Time */ -#define PERF_TITLE_DISK_WRITE_TIME 204 /* % Disk Write Time */ -#define PERF_TITLE_DISK_READ 214 /* Disk Reads/sec */ -#define PERF_TITLE_DISK_WRITE 216 /* Disk Writes/sec */ -#define PERF_TITLE_DISK_READ_BYTES 220 /* Disk Read Bytes/sec */ -#define PERF_TITLE_DISK_WRITE_BYTES 222 /* Disk Write Bytes/sec */ -#define PERF_TITLE_DISK_QUEUE 198 /* Current Disk Queue Length */ - -/* - * diff is: - * ExW -> ExA - * wcounter -> counter - */ -#define MyRegQueryValue() \ - (USING_WIDE() ? \ - RegQueryValueExW(sigar->handle, \ - wcounter_key, NULL, &type, \ - sigar->perfbuf, \ - &bytes) : \ - RegQueryValueExA(sigar->handle, \ - counter_key, NULL, &type, \ - sigar->perfbuf, \ - &bytes)) - -#define PERF_VAL(ix) \ - perf_offsets[ix] ? \ - *((DWORD *)((BYTE *)counter_block + perf_offsets[ix])) : 0 - -/* 1/100ns units to milliseconds */ -#define NS100_2MSEC(t) ((t) / 10000) - -#define PERF_VAL_CPU(ix) \ - NS100_2MSEC(PERF_VAL(ix)) - -#define MS_LOOPBACK_ADAPTER "Microsoft Loopback Adapter" -#define NETIF_LA "la" - -static int get_proc_info(sigar_t *sigar, sigar_pid_t pid); -static int netif_hash(char *s); - -sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft) -{ - sigar_uint64_t time; - time = ft->dwHighDateTime; - time = time << 32; - time |= ft->dwLowDateTime; - time /= 10; - time -= EPOCH_DELTA; - return time; -} - -static DWORD perfbuf_init(sigar_t *sigar) -{ - if (!sigar->perfbuf) { - sigar->perfbuf = malloc(PERFBUF_SIZE); - sigar->perfbuf_size = PERFBUF_SIZE; - } - - return sigar->perfbuf_size; -} - -static DWORD perfbuf_grow(sigar_t *sigar) -{ - sigar->perfbuf_size += PERFBUF_SIZE; - - sigar->perfbuf = - realloc(sigar->perfbuf, sigar->perfbuf_size); - - return sigar->perfbuf_size; -} - -static char *get_counter_name(char *key) -{ - if (strEQ(key, PERF_TITLE_MEM_KEY)) { - return "Memory"; - } - else if (strEQ(key, PERF_TITLE_PROC_KEY)) { - return "Process"; - } - else if (strEQ(key, PERF_TITLE_CPU_KEY)) { - return "Processor"; - } - else if (strEQ(key, PERF_TITLE_DISK_KEY)) { - return "LogicalDisk"; - } - else { - return key; - } -} - -static PERF_OBJECT_TYPE *get_perf_object_inst(sigar_t *sigar, - char *counter_key, - DWORD inst, DWORD *err) -{ - DWORD retval, type, bytes; - WCHAR wcounter_key[MAX_PATH+1]; - PERF_DATA_BLOCK *block; - PERF_OBJECT_TYPE *object; - - *err = SIGAR_OK; - - if (USING_WIDE()) { - SIGAR_A2W(counter_key, wcounter_key, sizeof(wcounter_key)); - } - - bytes = perfbuf_init(sigar); - - while ((retval = MyRegQueryValue()) != ERROR_SUCCESS) { - if (retval == ERROR_MORE_DATA) { - bytes = perfbuf_grow(sigar); - } - else { - *err = retval; - return NULL; - } - } - - block = (PERF_DATA_BLOCK *)sigar->perfbuf; - if (block->NumObjectTypes == 0) { - counter_key = get_counter_name(counter_key); - sigar_strerror_printf(sigar, "No %s counters defined (disabled?)", - counter_key); - *err = -1; - return NULL; - } - object = PdhFirstObject(block); - - /* - * only seen on windows 2003 server when pdh.dll - * functions are in use by the same process. - * confucius say what the fuck. - */ - if (inst && (object->NumInstances == PERF_NO_INSTANCES)) { - int i; - - for (i=0; iNumObjectTypes; i++) { - if (object->NumInstances != PERF_NO_INSTANCES) { - return object; - } - object = PdhNextObject(object); - } - return NULL; - } - else { - return object; - } -} - -#define get_perf_object(sigar, counter_key, err) \ - get_perf_object_inst(sigar, counter_key, 1, err) - -static int get_mem_counters(sigar_t *sigar, sigar_swap_t *swap, sigar_mem_t *mem) -{ - int status; - PERF_OBJECT_TYPE *object = - get_perf_object_inst(sigar, PERF_TITLE_MEM_KEY, 0, &status); - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_DEFINITION *counter; - BYTE *data; - DWORD i; - - if (!object) { - return status; - } - - data = (BYTE *)((BYTE *)object + object->DefinitionLength); - - for (i=0, counter = PdhFirstCounter(object); - iNumCounters; - i++, counter = PdhNextCounter(counter)) - { - DWORD offset = counter->CounterOffset; - - switch (counter->CounterNameTitleIndex) { - case 48: /* "Pages Output/sec" */ - if (swap) swap->page_out = *((DWORD *)(data + offset)); - break; - case 76: /* "System Cache Resident Bytes" aka file cache */ - if (mem) { - sigar_uint64_t kern = *((DWORD *)(data + offset)); - mem->actual_free = mem->free + kern; - mem->actual_used = mem->used - kern; - return SIGAR_OK; - } - case 822: /* "Pages Input/sec" */ - if (swap) swap->page_in = *((DWORD *)(data + offset)); - break; - default: - continue; - } - } - - return SIGAR_OK; -} - -static void get_sysinfo(sigar_t *sigar) -{ - SYSTEM_INFO sysinfo; - - GetSystemInfo(&sysinfo); - - sigar->ncpu = sysinfo.dwNumberOfProcessors; - sigar->pagesize = sysinfo.dwPageSize; -} - -/* for C# bindings */ -SIGAR_DECLARE(sigar_t *) sigar_new(void) -{ - sigar_t *sigar; - if (sigar_open(&sigar) != SIGAR_OK) { - return NULL; - } - return sigar; -} - -static sigar_wtsapi_t sigar_wtsapi = { - "wtsapi32.dll", - NULL, - { "WTSEnumerateSessionsA", NULL }, - { "WTSFreeMemory", NULL }, - { "WTSQuerySessionInformationA", NULL }, - { NULL, NULL } -}; - -static sigar_iphlpapi_t sigar_iphlpapi = { - "iphlpapi.dll", - NULL, - { "GetIpForwardTable", NULL }, - { "GetIpAddrTable", NULL }, - { "GetIfTable", NULL }, - { "GetIfEntry", NULL }, - { "GetNumberOfInterfaces", NULL }, - { "GetTcpTable", NULL }, - { "GetUdpTable", NULL }, - { "AllocateAndGetTcpExTableFromStack", NULL }, - { "AllocateAndGetUdpExTableFromStack", NULL }, - { "GetTcpStatistics", NULL }, - { "GetNetworkParams", NULL }, - { "GetAdaptersInfo", NULL }, - { "GetAdaptersAddresses", NULL }, - { "GetIpNetTable", NULL }, - { NULL, NULL } -}; - -static sigar_advapi_t sigar_advapi = { - "advapi32.dll", - NULL, - { "ConvertStringSidToSidA", NULL }, - { "QueryServiceStatusEx", NULL }, - { NULL, NULL } -}; - -static sigar_ntdll_t sigar_ntdll = { - "ntdll.dll", - NULL, - { "NtQuerySystemInformation", NULL }, - { "NtQueryInformationProcess", NULL }, - { NULL, NULL } -}; - -static sigar_psapi_t sigar_psapi = { - "psapi.dll", - NULL, - { "EnumProcessModules", NULL }, - { "EnumProcesses", NULL }, - { "GetModuleFileNameExA", NULL }, - { NULL, NULL } -}; - -static sigar_psapi_t sigar_winsta = { - "winsta.dll", - NULL, - { "WinStationQueryInformationW", NULL }, - { NULL, NULL } -}; - -static sigar_psapi_t sigar_kernel = { - "kernel32.dll", - NULL, - { "GlobalMemoryStatusEx", NULL }, - { NULL, NULL } -}; - -static sigar_mpr_t sigar_mpr = { - "mpr.dll", - NULL, - { "WNetGetConnectionA", NULL }, - { NULL, NULL } -}; - -#define DLLMOD_COPY(name) \ - memcpy(&(sigar->name), &sigar_##name, sizeof(sigar_##name)) - -#define DLLMOD_INIT(name, all) \ - sigar_dllmod_init(sigar, (sigar_dll_module_t *)&(sigar->name), all) - -#define DLLMOD_FREE(name) \ - sigar_dllmod_free((sigar_dll_module_t *)&(sigar->name)) - -static void sigar_dllmod_free(sigar_dll_module_t *module) -{ - if (module->handle) { - FreeLibrary(module->handle); - module->handle = NULL; - } -} - -static int sigar_dllmod_init(sigar_t *sigar, - sigar_dll_module_t *module, - int all) -{ - sigar_dll_func_t *funcs = &module->funcs[0]; - int is_debug = SIGAR_LOG_IS_DEBUG(sigar); - int rc, success; - - if (module->handle == INVALID_HANDLE_VALUE) { - return ENOENT; /* XXX better rc */ - } - - if (module->handle) { - return SIGAR_OK; - } - - module->handle = LoadLibrary(module->name); - if (!(success = (module->handle ? TRUE : FALSE))) { - rc = GetLastError(); - /* dont try again */ - module->handle = INVALID_HANDLE_VALUE; - } - - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "LoadLibrary(%s): %s", - module->name, - success ? - "OK" : - sigar_strerror(sigar, rc)); - } - - if (!success) { - return rc; - } - - while (funcs->name) { - funcs->func = GetProcAddress(module->handle, funcs->name); - - if (!(success = (funcs->func ? TRUE : FALSE))) { - rc = GetLastError(); - } - - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "GetProcAddress(%s:%s): %s", - module->name, funcs->name, - success ? - "OK" : - sigar_strerror(sigar, rc)); - } - - if (all && !success) { - return rc; - } - - funcs++; - } - - return SIGAR_OK; -} - -int sigar_wsa_init(sigar_t *sigar) -{ - if (sigar->ws_version == 0) { - WSADATA data; - - if (WSAStartup(MAKEWORD(2, 0), &data)) { - sigar->ws_error = WSAGetLastError(); - WSACleanup(); - return sigar->ws_error; - } - - sigar->ws_version = data.wVersion; - } - - return SIGAR_OK; -} - -static int sigar_enable_privilege(char *name) -{ - int status; - HANDLE handle; - TOKEN_PRIVILEGES tok; - - SIGAR_ZERO(&tok); - - if (!OpenProcessToken(GetCurrentProcess(), - TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, - &handle)) - { - return GetLastError(); - } - - if (LookupPrivilegeValue(NULL, name, - &tok.Privileges[0].Luid)) - { - tok.PrivilegeCount = 1; - tok.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (AdjustTokenPrivileges(handle, FALSE, &tok, 0, NULL, 0)) { - status = SIGAR_OK; - } - else { - status = GetLastError(); - } - } - else { - status = GetLastError(); - } - - CloseHandle(handle); - - return status; -} - -static int netif_name_short(void) -{ - char value[32767]; /* max size from msdn docs */ - DWORD retval = - GetEnvironmentVariable("SIGAR_NETIF_NAME_SHORT", value, sizeof(value)); - if ((retval > 0) && (strEQ(value, "1") || (strEQ(value, "true")))) { - return 1; - } - else { - return 0; - } -} - -int sigar_os_open(sigar_t **sigar_ptr) -{ - LONG result; - HINSTANCE h; - OSVERSIONINFO version; - int i; - sigar_t *sigar; - - *sigar_ptr = sigar = malloc(sizeof(*sigar)); - sigar->machine = ""; /* local machine */ - sigar->using_wide = 0; /*XXX*/ - - sigar->perfbuf = NULL; - sigar->perfbuf_size = 0; - - version.dwOSVersionInfoSize = sizeof(version); - GetVersionEx(&version); - - /* - * 4 == NT 4.0 - * 5 == 2000, XP, 2003 Server - */ - sigar->winnt = (version.dwMajorVersion == 4); - - if (USING_WIDE_S(sigar)) { - WCHAR wmachine[MAX_PATH+1]; - - SIGAR_A2W(sigar->machine, wmachine, sizeof(wmachine)); - - result = RegConnectRegistryW(wmachine, - HKEY_PERFORMANCE_DATA, - &sigar->handle); - } - else { - result = RegConnectRegistryA(sigar->machine, - HKEY_PERFORMANCE_DATA, - &sigar->handle); - } - - get_sysinfo(sigar); - - DLLMOD_COPY(wtsapi); - DLLMOD_COPY(iphlpapi); - DLLMOD_COPY(advapi); - DLLMOD_COPY(ntdll); - DLLMOD_COPY(psapi); - DLLMOD_COPY(winsta); - DLLMOD_COPY(kernel); - DLLMOD_COPY(mpr); - - sigar->log_level = -1; /* else below segfaults */ - /* XXX init early for use by javasigar.c */ - sigar_dllmod_init(sigar, - (sigar_dll_module_t *)&sigar->advapi, - FALSE); - - sigar->netif_mib_rows = NULL; - sigar->netif_addr_rows = NULL; - sigar->netif_adapters = NULL; - sigar->netif_names = NULL; - sigar->netif_name_short = netif_name_short(); - - sigar->pinfo.pid = -1; - sigar->ws_version = 0; - sigar->lcpu = -1; - - /* increase process visibility */ - sigar_enable_privilege(SE_DEBUG_NAME); - - return result; -} - -void dllmod_init_ntdll(sigar_t *sigar) -{ - DLLMOD_INIT(ntdll, FALSE); -} - -int sigar_os_close(sigar_t *sigar) -{ - int retval; - - DLLMOD_FREE(wtsapi); - DLLMOD_FREE(iphlpapi); - DLLMOD_FREE(advapi); - DLLMOD_FREE(ntdll); - DLLMOD_FREE(psapi); - DLLMOD_FREE(winsta); - DLLMOD_FREE(kernel); - DLLMOD_FREE(mpr); - - if (sigar->perfbuf) { - free(sigar->perfbuf); - } - - retval = RegCloseKey(sigar->handle); - - if (sigar->ws_version != 0) { - WSACleanup(); - } - - if (sigar->netif_mib_rows) { - sigar_cache_destroy(sigar->netif_mib_rows); - } - - if (sigar->netif_addr_rows) { - sigar_cache_destroy(sigar->netif_addr_rows); - } - - if (sigar->netif_adapters) { - sigar_cache_destroy(sigar->netif_adapters); - } - - if (sigar->netif_names) { - sigar_cache_destroy(sigar->netif_names); - } - - free(sigar); - - return retval; -} - -char *sigar_os_error_string(sigar_t *sigar, int err) -{ - switch (err) { - case SIGAR_NO_SUCH_PROCESS: - return "No such process"; - break; - } - return NULL; -} - -#define sigar_GlobalMemoryStatusEx \ - sigar->kernel.memory_status.func - -SIGAR_DECLARE(int) sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem) -{ - DLLMOD_INIT(kernel, TRUE); - - if (sigar_GlobalMemoryStatusEx) { - MEMORYSTATUSEX memstat; - - memstat.dwLength = sizeof(memstat); - - if (!sigar_GlobalMemoryStatusEx(&memstat)) { - return GetLastError(); - } - - mem->total = memstat.ullTotalPhys; - mem->free = memstat.ullAvailPhys; - } - else { - MEMORYSTATUS memstat; - GlobalMemoryStatus(&memstat); - mem->total = memstat.dwTotalPhys; - mem->free = memstat.dwAvailPhys; - } - - mem->used = mem->total - mem->free; - - mem->actual_free = mem->free; - mem->actual_used = mem->used; - /* set actual_{free,used} */ - get_mem_counters(sigar, NULL, mem); - - sigar_mem_calc_ram(sigar, mem); - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_swap_get(sigar_t *sigar, sigar_swap_t *swap) -{ - int status; - DLLMOD_INIT(kernel, TRUE); - - if (sigar_GlobalMemoryStatusEx) { - MEMORYSTATUSEX memstat; - - memstat.dwLength = sizeof(memstat); - - if (!sigar_GlobalMemoryStatusEx(&memstat)) { - return GetLastError(); - } - - swap->total = memstat.ullTotalPageFile; - swap->free = memstat.ullAvailPageFile; - } - else { - MEMORYSTATUS memstat; - GlobalMemoryStatus(&memstat); - swap->total = memstat.dwTotalPageFile; - swap->free = memstat.dwAvailPageFile; - } - - swap->used = swap->total - swap->free; - - if (get_mem_counters(sigar, swap, NULL) != SIGAR_OK) { - swap->page_in = SIGAR_FIELD_NOTIMPL; - swap->page_out = SIGAR_FIELD_NOTIMPL; - } - - return SIGAR_OK; -} - -static PERF_INSTANCE_DEFINITION *get_cpu_instance(sigar_t *sigar, - DWORD *perf_offsets, - DWORD *num, DWORD *err) -{ - PERF_OBJECT_TYPE *object = get_perf_object(sigar, PERF_TITLE_CPU_KEY, err); - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_DEFINITION *counter; - DWORD i; - - if (!object) { - return NULL; - } - - for (i=0, counter = PdhFirstCounter(object); - iNumCounters; - i++, counter = PdhNextCounter(counter)) - { - DWORD offset = counter->CounterOffset; - - switch (counter->CounterNameTitleIndex) { - case PERF_TITLE_CPU_SYS: - perf_offsets[PERF_IX_CPU_SYS] = offset; - break; - case PERF_TITLE_CPU_USER: - perf_offsets[PERF_IX_CPU_USER] = offset; - break; - case PERF_TITLE_CPU_IDLE: - perf_offsets[PERF_IX_CPU_IDLE] = offset; - break; - case PERF_TITLE_CPU_IRQ: - perf_offsets[PERF_IX_CPU_IRQ] = offset; - break; - } - } - - if (num) { - *num = object->NumInstances; - } - - return PdhFirstInstance(object); -} - -#define SPPI_MAX 128 /* XXX unhardcode; should move off this api anyhow */ - -#define sigar_NtQuerySystemInformation \ - sigar->ntdll.query_sys_info.func - -static int get_idle_cpu(sigar_t *sigar, sigar_cpu_t *cpu, - DWORD idx, - PERF_COUNTER_BLOCK *counter_block, - DWORD *perf_offsets) -{ - cpu->idle = 0; - - if (perf_offsets[PERF_IX_CPU_IDLE]) { - cpu->idle = PERF_VAL_CPU(PERF_IX_CPU_IDLE); - } - else { - /* windows NT and 2000 do not have an Idle counter */ - DLLMOD_INIT(ntdll, FALSE); - if (sigar_NtQuerySystemInformation) { - DWORD retval, num; - SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[SPPI_MAX]; - /* into the lungs of hell */ - sigar_NtQuerySystemInformation(SystemProcessorPerformanceInformation, - &info, sizeof(info), &retval); - - if (!retval) { - return GetLastError(); - } - num = retval/sizeof(info[0]); - - if (idx == -1) { - int i; - for (i=0; iidle += NS100_2MSEC(info[i].IdleTime.QuadPart); - } - } - else if (idx < num) { - cpu->idle = NS100_2MSEC(info[idx].IdleTime.QuadPart); - } - else { - return ERROR_INVALID_DATA; - } - } - else { - return ERROR_INVALID_FUNCTION; - } - } - - return SIGAR_OK; -} - -static int sigar_cpu_perflib_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ - int status; - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_BLOCK *counter_block; - DWORD perf_offsets[PERF_IX_CPU_MAX], err; - - SIGAR_ZERO(cpu); - memset(&perf_offsets, 0, sizeof(perf_offsets)); - - inst = get_cpu_instance(sigar, (DWORD*)&perf_offsets, 0, &err); - - if (!inst) { - return err; - } - - /* first instance is total, rest are per-cpu */ - counter_block = PdhGetCounterBlock(inst); - - cpu->sys = PERF_VAL_CPU(PERF_IX_CPU_SYS); - cpu->user = PERF_VAL_CPU(PERF_IX_CPU_USER); - status = get_idle_cpu(sigar, cpu, -1, counter_block, perf_offsets); - cpu->irq = PERF_VAL_CPU(PERF_IX_CPU_IRQ); - cpu->nice = 0; /* no nice here */ - cpu->wait = 0; /*N/A?*/ - cpu->total = cpu->sys + cpu->user + cpu->idle + cpu->wait + cpu->irq; - - if (status != SIGAR_OK) { - sigar_log_printf(sigar, SIGAR_LOG_WARN, - "unable to determine idle cpu time: %s", - sigar_strerror(sigar, status)); - } - - return SIGAR_OK; -} - -static int sigar_cpu_ntsys_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ - DWORD retval, num; - int i; - SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[SPPI_MAX]; - /* into the lungs of hell */ - sigar_NtQuerySystemInformation(SystemProcessorPerformanceInformation, - &info, sizeof(info), &retval); - - if (!retval) { - return GetLastError(); - } - num = retval/sizeof(info[0]); - SIGAR_ZERO(cpu); - - for (i=0; iidle += NS100_2MSEC(info[i].IdleTime.QuadPart); - cpu->user += NS100_2MSEC(info[i].UserTime.QuadPart); - cpu->sys += NS100_2MSEC(info[i].KernelTime.QuadPart - - info[i].IdleTime.QuadPart); - cpu->irq += NS100_2MSEC(info[i].InterruptTime.QuadPart); - cpu->total += cpu->idle + cpu->user + cpu->sys; - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu) -{ - DLLMOD_INIT(ntdll, FALSE); - if (sigar_NtQuerySystemInformation) { - return sigar_cpu_ntsys_get(sigar, cpu); - } - else { - return sigar_cpu_perflib_get(sigar, cpu); - } -} - -static int sigar_cpu_list_perflib_get(sigar_t *sigar, - sigar_cpu_list_t *cpulist) -{ - int status, i, j; - PERF_INSTANCE_DEFINITION *inst; - DWORD perf_offsets[PERF_IX_CPU_MAX], num, err; - int core_rollup = sigar_cpu_core_rollup(sigar); - - memset(&perf_offsets, 0, sizeof(perf_offsets)); - - /* first instance is total, rest are per-cpu */ - inst = get_cpu_instance(sigar, (DWORD*)&perf_offsets, &num, &err); - - if (!inst) { - return err; - } - - if (!sigar->winnt) { - /* skip Processor _Total instance (NT doesnt have one) */ - --num; - inst = PdhNextInstance(inst); - } - - sigar_cpu_list_create(cpulist); - - /* verify there's a counter for each logical cpu */ - if (core_rollup && (sigar->ncpu != num)) { - core_rollup = 0; - } - - for (i=0; ilcpu)) { - /* merge times of logical processors */ - cpu = &cpulist->data[cpulist->number-1]; - } - else { - SIGAR_CPU_LIST_GROW(cpulist); - cpu = &cpulist->data[cpulist->number++]; - SIGAR_ZERO(cpu); - } - - counter_block = PdhGetCounterBlock(inst); - - cpu->sys += PERF_VAL_CPU(PERF_IX_CPU_SYS); - cpu->user += PERF_VAL_CPU(PERF_IX_CPU_USER); - cpu->irq += PERF_VAL_CPU(PERF_IX_CPU_IRQ); - get_idle_cpu(sigar, cpu, i, counter_block, perf_offsets); - cpu->nice = cpu->wait = 0; /*N/A*/ - - /*XXX adding up too much here if xeon, but not using this atm*/ - cpu->total += cpu->sys + cpu->user + cpu->idle + cpu->irq; - - inst = PdhNextInstance(inst); - } - - return SIGAR_OK; -} - -static int sigar_cpu_list_ntsys_get(sigar_t *sigar, - sigar_cpu_list_t *cpulist) -{ - DWORD retval, num; - int status, i, j; - int core_rollup = sigar_cpu_core_rollup(sigar); - - SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[SPPI_MAX]; - /* into the lungs of hell */ - sigar_NtQuerySystemInformation(SystemProcessorPerformanceInformation, - &info, sizeof(info), &retval); - - if (!retval) { - return GetLastError(); - } - num = retval/sizeof(info[0]); - - sigar_cpu_list_create(cpulist); - - /* verify there's a counter for each logical cpu */ - if (core_rollup && (sigar->ncpu != num)) { - core_rollup = 0; - } - - for (i=0; ilcpu)) { - /* merge times of logical processors */ - cpu = &cpulist->data[cpulist->number-1]; - } - else { - SIGAR_CPU_LIST_GROW(cpulist); - cpu = &cpulist->data[cpulist->number++]; - SIGAR_ZERO(cpu); - } - - idle = NS100_2MSEC(info[i].IdleTime.QuadPart); - user = NS100_2MSEC(info[i].UserTime.QuadPart); - sys = NS100_2MSEC(info[i].KernelTime.QuadPart - - info[i].IdleTime.QuadPart); - cpu->idle += idle; - cpu->user += user; - cpu->sys += sys; - cpu->nice = cpu->wait = 0; /*N/A*/ - cpu->total += idle + user + sys; - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_cpu_list_get(sigar_t *sigar, - sigar_cpu_list_t *cpulist) -{ - DLLMOD_INIT(ntdll, FALSE); - if (sigar_NtQuerySystemInformation) { - return sigar_cpu_list_ntsys_get(sigar, cpulist); - } - else { - return sigar_cpu_list_perflib_get(sigar, cpulist); - } -} - -#define PERF_TITLE_UPTIME_KEY 674 /* System Up Time */ - -SIGAR_DECLARE(int) sigar_uptime_get(sigar_t *sigar, - sigar_uptime_t *uptime) -{ - int status; - PERF_OBJECT_TYPE *object = - get_perf_object_inst(sigar, PERF_TITLE_SYS_KEY, 0, &status); - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_DEFINITION *counter; - BYTE *data; - DWORD i; - - if (!object) { - return status; - } - - data = (BYTE *)((BYTE *)object + object->DefinitionLength); - - for (i=0, counter = PdhFirstCounter(object); - iNumCounters; - i++, counter = PdhNextCounter(counter)) - { - if (counter->CounterNameTitleIndex == PERF_TITLE_UPTIME_KEY) { - DWORD offset = counter->CounterOffset; - LONGLONG time = object->PerfTime.QuadPart; - LONGLONG freq = object->PerfFreq.QuadPart; - LONGLONG counter = *((LONGLONG *)(data + offset)); - uptime->uptime = (time - counter) / freq; - return SIGAR_OK; - } - } - - /* http://msdn.microsoft.com/en-us/library/ms724408.aspx */ - return GetTickCount() / 1000; -} - -/* - * there is no api for this info. - * closest i've seen is enumerating the entire process table - * and calculating an average based on process times. - */ -SIGAR_DECLARE(int) sigar_loadavg_get(sigar_t *sigar, - sigar_loadavg_t *loadavg) -{ - return SIGAR_ENOTIMPL; -} - -#define get_process_object(sigar, err) \ - get_perf_object(sigar, PERF_TITLE_PROC_KEY, err) - -static int sigar_proc_list_get_perf(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - - PERF_OBJECT_TYPE *object; - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_DEFINITION *counter; - DWORD i, err; - DWORD perf_offsets[PERF_IX_MAX]; - - perf_offsets[PERF_IX_PID] = 0; - - object = get_process_object(sigar, &err); - - if (!object) { - return err; - } - - /* - * note we assume here: - * block->NumObjectTypes == 1 - * object->ObjectNameTitleIndex == PERF_TITLE_PROC - * - * which should always be the case. - */ - - for (i=0, counter = PdhFirstCounter(object); - iNumCounters; - i++, counter = PdhNextCounter(counter)) - { - DWORD offset = counter->CounterOffset; - - switch (counter->CounterNameTitleIndex) { - case PERF_TITLE_PID: - perf_offsets[PERF_IX_PID] = offset; - break; - } - } - - for (i=0, inst = PdhFirstInstance(object); - iNumInstances; - i++, inst = PdhNextInstance(inst)) - { - PERF_COUNTER_BLOCK *counter_block = PdhGetCounterBlock(inst); - DWORD pid = PERF_VAL(PERF_IX_PID); - - if (pid == 0) { - continue; /* dont include the system Idle process */ - } - - SIGAR_PROC_LIST_GROW(proclist); - - proclist->data[proclist->number++] = pid; - } - - return SIGAR_OK; -} - -#define sigar_EnumProcesses \ - sigar->psapi.enum_processes.func - -int sigar_os_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - DLLMOD_INIT(psapi, FALSE); - - if (sigar_EnumProcesses) { - DWORD retval, *pids; - DWORD size = 0, i; - - do { - /* re-use the perfbuf */ - if (size == 0) { - size = perfbuf_init(sigar); - } - else { - size = perfbuf_grow(sigar); - } - - if (!sigar_EnumProcesses((DWORD *)sigar->perfbuf, - sigar->perfbuf_size, - &retval)) - { - return GetLastError(); - } - } while (retval == sigar->perfbuf_size); //unlikely - - pids = (DWORD *)sigar->perfbuf; - - size = retval / sizeof(DWORD); - - for (i=0; idata[proclist->number++] = pid; - } - - return SIGAR_OK; - } - else { - return sigar_proc_list_get_perf(sigar, proclist); - } -} - -#define PROCESS_DAC (PROCESS_QUERY_INFORMATION|PROCESS_VM_READ) - -static HANDLE open_process(sigar_pid_t pid) -{ - return OpenProcess(PROCESS_DAC, 0, (DWORD)pid); -} - -/* - * Pretty good explanation of counters: - * http://www.semack.net/wiki/default.asp?db=SemackNetWiki&o=VirtualMemory - */ -SIGAR_DECLARE(int) sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_mem_t *procmem) -{ - int status = get_proc_info(sigar, pid); - sigar_win32_pinfo_t *pinfo = &sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - procmem->size = pinfo->size; /* "Virtual Bytes" */ - procmem->resident = pinfo->resident; /* "Working Set" */ - procmem->share = SIGAR_FIELD_NOTIMPL; - procmem->page_faults = pinfo->page_faults; - procmem->minor_faults = SIGAR_FIELD_NOTIMPL; - procmem->major_faults = SIGAR_FIELD_NOTIMPL; - - return SIGAR_OK; -} - -#define TOKEN_DAC (STANDARD_RIGHTS_READ | READ_CONTROL | TOKEN_QUERY) - -SIGAR_DECLARE(int) -sigar_proc_cred_name_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_name_t *proccredname) -{ - HANDLE proc, token; - DWORD len; - int success; - TOKEN_USER *user = NULL; - TOKEN_PRIMARY_GROUP *group = NULL; - SID_NAME_USE type; - char domain[SIGAR_CRED_NAME_MAX]; - - /* XXX cache lookup */ - - if (!(proc = open_process(pid))) { - return GetLastError(); - } - - if (!OpenProcessToken(proc, TOKEN_DAC, &token)) { - CloseHandle(proc); - return GetLastError(); - } - - CloseHandle(proc); - - success = - !GetTokenInformation(token, TokenUser, NULL, 0, &len) && - (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && - (user = malloc(len)) && - GetTokenInformation(token, TokenUser, user, len, &len); - - if (success) { - DWORD domain_len = sizeof(domain); - DWORD user_len = sizeof(proccredname->user); - - success = LookupAccountSid(NULL, user->User.Sid, - proccredname->user, &user_len, - domain, &domain_len, &type); - } - - if (user != NULL) { - free(user); - } - if (!success) { - CloseHandle(token); - return GetLastError(); - } - - success = - !GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &len) && - (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && - (group = malloc(len)) && - GetTokenInformation(token, TokenPrimaryGroup, group, len, &len); - - if (success) { - DWORD domain_len = sizeof(domain); - DWORD group_len = sizeof(proccredname->group); - - success = LookupAccountSid(NULL, group->PrimaryGroup, - proccredname->group, &group_len, - domain, &domain_len, &type); - } - - if (group != NULL) { - free(group); - } - - CloseHandle(token); - - if (!success) { - return GetLastError(); - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_t *proccred) -{ - return SIGAR_ENOTIMPL; -} - -#define FILETIME2MSEC(ft) \ - NS100_2MSEC(((ft.dwHighDateTime << 32) | ft.dwLowDateTime)) - -sigar_int64_t sigar_time_now_millis(void) -{ - SYSTEMTIME st; - FILETIME time; - - GetSystemTime(&st); - SystemTimeToFileTime(&st, &time); - - return sigar_FileTimeToTime(&time) / 1000; -} - -SIGAR_DECLARE(int) sigar_proc_time_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_time_t *proctime) -{ - HANDLE proc = open_process(pid); - FILETIME start_time, exit_time, system_time, user_time; - int status = ERROR_SUCCESS; - - if (!proc) { - return GetLastError(); - } - - if (!GetProcessTimes(proc, - &start_time, &exit_time, - &system_time, &user_time)) - { - status = GetLastError(); - } - - CloseHandle(proc); - - if (status != ERROR_SUCCESS) { - return status; - } - - if (start_time.dwHighDateTime) { - proctime->start_time = - sigar_FileTimeToTime(&start_time) / 1000; - } - else { - proctime->start_time = 0; - } - - proctime->user = FILETIME2MSEC(user_time); - proctime->sys = FILETIME2MSEC(system_time); - proctime->total = proctime->user + proctime->sys; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_state_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_state_t *procstate) -{ - int status = get_proc_info(sigar, pid); - sigar_win32_pinfo_t *pinfo = &sigar->pinfo; - - if (status != SIGAR_OK) { - return status; - } - - memcpy(procstate->name, pinfo->name, sizeof(procstate->name)); - procstate->state = pinfo->state; - procstate->ppid = pinfo->ppid; - procstate->priority = pinfo->priority; - procstate->nice = SIGAR_FIELD_NOTIMPL; - procstate->tty = SIGAR_FIELD_NOTIMPL; - procstate->threads = pinfo->threads; - procstate->processor = SIGAR_FIELD_NOTIMPL; - - return SIGAR_OK; -} - -static int get_proc_info(sigar_t *sigar, sigar_pid_t pid) -{ - PERF_OBJECT_TYPE *object; - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_DEFINITION *counter; - DWORD i, err; - DWORD perf_offsets[PERF_IX_MAX]; - sigar_win32_pinfo_t *pinfo = &sigar->pinfo; - time_t timenow = time(NULL); - - if (pinfo->pid == pid) { - if ((timenow - pinfo->mtime) < SIGAR_LAST_PROC_EXPIRE) { - return SIGAR_OK; - } - } - - memset(&perf_offsets, 0, sizeof(perf_offsets)); - - object = get_process_object(sigar, &err); - - if (object == NULL) { - return err; - } - - pinfo->pid = pid; - pinfo->mtime = timenow; - - /* - * note we assume here: - * block->NumObjectTypes == 1 - * object->ObjectNameTitleIndex == PERF_TITLE_PROC - * - * which should always be the case. - */ - - for (i=0, counter = PdhFirstCounter(object); - iNumCounters; - i++, counter = PdhNextCounter(counter)) - { - DWORD offset = counter->CounterOffset; - - switch (counter->CounterNameTitleIndex) { - case PERF_TITLE_CPUTIME: - perf_offsets[PERF_IX_CPUTIME] = offset; - break; - case PERF_TITLE_PAGE_FAULTS: - perf_offsets[PERF_IX_PAGE_FAULTS] = offset; - break; - case PERF_TITLE_MEM_VSIZE: - perf_offsets[PERF_IX_MEM_VSIZE] = offset; - break; - case PERF_TITLE_MEM_SIZE: - perf_offsets[PERF_IX_MEM_SIZE] = offset; - break; - case PERF_TITLE_THREAD_CNT: - perf_offsets[PERF_IX_THREAD_CNT] = offset; - break; - case PERF_TITLE_HANDLE_CNT: - perf_offsets[PERF_IX_HANDLE_CNT] = offset; - break; - case PERF_TITLE_PID: - perf_offsets[PERF_IX_PID] = offset; - break; - case PERF_TITLE_PPID: - perf_offsets[PERF_IX_PPID] = offset; - break; - case PERF_TITLE_PRIORITY: - perf_offsets[PERF_IX_PRIORITY] = offset; - break; - case PERF_TITLE_START_TIME: - perf_offsets[PERF_IX_START_TIME] = offset; - break; - } - } - - for (i=0, inst = PdhFirstInstance(object); - iNumInstances; - i++, inst = PdhNextInstance(inst)) - { - PERF_COUNTER_BLOCK *counter_block = PdhGetCounterBlock(inst); - sigar_pid_t this_pid = PERF_VAL(PERF_IX_PID); - - if (this_pid != pid) { - continue; - } - - pinfo->state = 'R'; /* XXX? */ - SIGAR_W2A(PdhInstanceName(inst), - pinfo->name, sizeof(pinfo->name)); - - pinfo->size = PERF_VAL(PERF_IX_MEM_VSIZE); - pinfo->resident = PERF_VAL(PERF_IX_MEM_SIZE); - pinfo->ppid = PERF_VAL(PERF_IX_PPID); - pinfo->priority = PERF_VAL(PERF_IX_PRIORITY); - pinfo->handles = PERF_VAL(PERF_IX_HANDLE_CNT); - pinfo->threads = PERF_VAL(PERF_IX_THREAD_CNT); - pinfo->page_faults = PERF_VAL(PERF_IX_PAGE_FAULTS); - - return SIGAR_OK; - } - - return SIGAR_NO_SUCH_PROCESS; -} - -static int sigar_remote_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - int status; - char cmdline[SIGAR_CMDLINE_MAX], *ptr = cmdline, *arg; - HANDLE proc = open_process(pid); - - if (proc) { - status = sigar_proc_args_peb_get(sigar, proc, procargs); - - CloseHandle(proc); - - if (status == SIGAR_OK) { - return status; - } - } - - /* likely we are 32-bit, pid process is 64-bit */ -#ifdef MSVC - status = sigar_proc_args_wmi_get(sigar, pid, procargs); -#endif - if (status == ERROR_NOT_FOUND) { - status = SIGAR_NO_SUCH_PROCESS; - } - return status; -} - -int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - if (pid == sigar->pid) { - return sigar_parse_proc_args(sigar, NULL, procargs); - } - else { - return sigar_remote_proc_args_get(sigar, pid, procargs); - } -} - -static int sigar_proc_env_parse(UCHAR *ptr, sigar_proc_env_t *procenv, - int multi) -{ - while (*ptr) { - char *val; - int klen, vlen, status; - char key[128]; /* XXX is there a max key size? */ - - if (*ptr == '=') { - ptr += strlen(ptr)+1; - continue; - } - - val = strchr(ptr, '='); - - if (val == NULL) { - break; /*XXX*/ - } - - klen = val - (char*)ptr; - SIGAR_SSTRCPY(key, ptr); - key[klen] = '\0'; - ++val; - - vlen = strlen(val); - - status = procenv->env_getter(procenv->data, - key, klen, val, vlen); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - return status; - } - - if (!multi) { - break; /* caller only provided 1 key=val pair */ - } - - ptr += klen + 1 + vlen + 1; - } - - return SIGAR_OK; -} - -static int sigar_local_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ - UCHAR *env = (UCHAR*)GetEnvironmentStrings(); - - sigar_proc_env_parse(env, procenv, TRUE); - - FreeEnvironmentStrings(env); - - return SIGAR_OK; -} - -static int sigar_remote_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ - int status; - HANDLE proc = open_process(pid); - WCHAR env[4096]; - - if (!proc) { - return GetLastError(); - } - - status = sigar_proc_env_peb_get(sigar, proc, env, sizeof(env)); - - CloseHandle(proc); - - if (status == SIGAR_OK) { - LPBYTE ptr = (LPBYTE)env; - DWORD size = sizeof(env); - UCHAR ent[4096]; - - while ((size > 0) && (*ptr != L'\0')) { - DWORD len = (wcslen((LPWSTR)ptr) + 1) * sizeof(WCHAR); - /* multi=FALSE so no need to: memset(ent, '\0', sizeof(ent)) */ - SIGAR_W2A((WCHAR *)ptr, ent, sizeof(ent)); - if (sigar_proc_env_parse(ent, procenv, FALSE) != SIGAR_OK) { - break; - } - size -= len; - ptr += len; - } - } - - return status; -} - -SIGAR_DECLARE(int) sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) -{ - if (pid == sigar->pid) { - if (procenv->type == SIGAR_PROC_ENV_KEY) { - char value[32767]; /* max size from msdn docs */ - DWORD retval = - GetEnvironmentVariable(procenv->key, value, sizeof(value)); - - if (retval == 0) { - if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) { - return SIGAR_OK; - } - return GetLastError(); - } - else if (retval > sizeof(value)) { - /* XXX shouldnt happen */ - return GetLastError(); - } - - procenv->env_getter(procenv->data, - procenv->key, procenv->klen, - value, retval); - return SIGAR_OK; - } - else { - return sigar_local_proc_env_get(sigar, pid, procenv); - } - } - else { - return sigar_remote_proc_env_get(sigar, pid, procenv); - } -} - -SIGAR_DECLARE(int) sigar_proc_fd_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_fd_t *procfd) -{ - int status; - sigar_win32_pinfo_t *pinfo = &sigar->pinfo; - - pinfo->pid = -1; /* force update */ - if ((status = get_proc_info(sigar, pid)) != SIGAR_OK) { - return status; - } - - procfd->total = pinfo->handles; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ - int status = SIGAR_OK; - HANDLE proc = open_process(pid); - - if (!proc) { - return GetLastError(); - } - - status = sigar_proc_exe_peb_get(sigar, proc, procexe); -#ifdef MSVC - if (procexe->name[0] == '\0') { - /* likely we are 32-bit, pid process is 64-bit */ - /* procexe->cwd[0] = XXX where else can we try? */ - status = sigar_proc_exe_wmi_get(sigar, pid, procexe); - if (status == ERROR_NOT_FOUND) { - status = SIGAR_NO_SUCH_PROCESS; - } - } -#endif - if (procexe->cwd[0] != '\0') { - /* strip trailing '\' */ - int len = strlen(procexe->cwd); - if (procexe->cwd[len-1] == '\\') { - procexe->cwd[len-1] = '\0'; - } - /* uppercase driver letter */ - procexe->cwd[0] = toupper(procexe->cwd[0]); - /* e.g. C:\ */ - strncpy(procexe->root, procexe->cwd, 3); - procexe->root[3] = '\0'; - } - else { - procexe->root[0] = '\0'; - } - - if (procexe->name[0] != '\0') { - /* uppercase driver letter */ - procexe->name[0] = toupper(procexe->name[0]); - } - - CloseHandle(proc); - - return status; -} - -#define sigar_EnumProcessModules \ - sigar->psapi.enum_modules.func - -#define sigar_GetModuleFileNameEx \ - sigar->psapi.get_module_name.func - -SIGAR_DECLARE(int) sigar_proc_modules_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_modules_t *procmods) -{ - HANDLE proc; - HMODULE modules[1024]; - DWORD size = 0; - unsigned int i; - - if (DLLMOD_INIT(psapi, TRUE) != SIGAR_OK) { - return SIGAR_ENOTIMPL; - } - - if (!(proc = open_process(pid))) { - return GetLastError(); - } - - if (!sigar_EnumProcessModules(proc, modules, sizeof(modules), &size)) { - CloseHandle(proc); - return GetLastError(); - } - - for (i=0; i<(size/sizeof(HMODULE)); i++) { - int status; - char name[MAX_PATH]; - - if (!sigar_GetModuleFileNameEx(proc, modules[i], - name, sizeof(name))) - { - continue; - } - - status = procmods->module_getter(procmods->data, - name, strlen(name)); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - } - - CloseHandle(proc); - - return SIGAR_OK; -} - -#define FT2INT64(ft) \ - ((__int64)((__int64)(ft).dwHighDateTime << 32 | \ - (__int64)(ft).dwLowDateTime)) - -SIGAR_DECLARE(int) sigar_thread_cpu_get(sigar_t *sigar, - sigar_uint64_t id, - sigar_thread_cpu_t *cpu) -{ - FILETIME start, exit, sys, user; - DWORD retval; - - if (id != 0) { - return SIGAR_ENOTIMPL; - } - - retval = GetThreadTimes(GetCurrentThread(), - &start, &exit, &sys, &user); - - if (retval == 0) { - return GetLastError(); - } - - cpu->user = FT2INT64(user) * 100; - cpu->sys = FT2INT64(sys) * 100; - cpu->total = (FT2INT64(user) + FT2INT64(sys)) * 100; - - return SIGAR_OK; -} - -int sigar_os_fs_type_get(sigar_file_system_t *fsp) -{ - return fsp->type; -} - -#ifndef FILE_READ_ONLY_VOLUME -#define FILE_READ_ONLY_VOLUME 0x00080000 -#endif -#ifndef FILE_NAMED_STREAMS -#define FILE_NAMED_STREAMS 0x00040000 -#endif -#ifndef FILE_SEQUENTIAL_WRITE_ONCE -#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000 -#endif -#ifndef FILE_SUPPORTS_TRANSACTIONS -#define FILE_SUPPORTS_TRANSACTIONS 0x00200000 -#endif - -static void get_fs_options(char *opts, int osize, long flags) -{ - *opts = '\0'; - if (flags & FILE_READ_ONLY_VOLUME) strncat(opts, "ro", osize); - else strncat(opts, "rw", osize); -#if 0 /*XXX*/ - if (flags & FILE_CASE_PRESERVED_NAMES) strncat(opts, ",casepn", osize); - if (flags & FILE_CASE_SENSITIVE_SEARCH) strncat(opts, ",casess", osize); - if (flags & FILE_FILE_COMPRESSION) strncat(opts, ",fcomp", osize); - if (flags & FILE_NAMED_STREAMS) strncat(opts, ",streams", osize); - if (flags & FILE_PERSISTENT_ACLS) strncat(opts, ",acls", osize); - if (flags & FILE_SEQUENTIAL_WRITE_ONCE) strncat(opts, ",wronce", osize); - if (flags & FILE_SUPPORTS_ENCRYPTION) strncat(opts, ",efs", osize); - if (flags & FILE_SUPPORTS_OBJECT_IDS) strncat(opts, ",oids", osize); - if (flags & FILE_SUPPORTS_REPARSE_POINTS) strncat(opts, ",reparse", osize); - if (flags & FILE_SUPPORTS_SPARSE_FILES) strncat(opts, ",sparse", osize); - if (flags & FILE_SUPPORTS_TRANSACTIONS) strncat(opts, ",trans", osize); - if (flags & FILE_UNICODE_ON_DISK) strncat(opts, ",unicode", osize); - if (flags & FILE_VOLUME_IS_COMPRESSED) strncat(opts, ",vcomp", osize); - if (flags & FILE_VOLUME_QUOTAS) strncat(opts, ",quota", osize); -#endif -} - -#define sigar_WNetGetConnection \ - sigar->mpr.get_net_connection.func - -SIGAR_DECLARE(int) sigar_file_system_list_get(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - char name[256]; - char *ptr = name; - /* XXX: hmm, Find{First,Next}Volume not available in my sdk */ - DWORD len = GetLogicalDriveStringsA(sizeof(name), name); - - DLLMOD_INIT(mpr, TRUE); - - if (len == 0) { - return GetLastError(); - } - - sigar_file_system_list_create(fslist); - - while (*ptr) { - sigar_file_system_t *fsp; - DWORD flags, serialnum=0; - char fsname[1024]; - UINT drive_type = GetDriveType(ptr); - int type; - - switch (drive_type) { - case DRIVE_FIXED: - type = SIGAR_FSTYPE_LOCAL_DISK; - break; - case DRIVE_REMOTE: - type = SIGAR_FSTYPE_NETWORK; - break; - case DRIVE_CDROM: - type = SIGAR_FSTYPE_CDROM; - break; - case DRIVE_RAMDISK: - type = SIGAR_FSTYPE_RAM_DISK; - break; - case DRIVE_REMOVABLE: - /* skip floppy, usb, etc. drives */ - ptr += strlen(ptr)+1; - continue; - default: - type = SIGAR_FSTYPE_NONE; - break; - } - - fsname[0] = '\0'; - - GetVolumeInformation(ptr, NULL, 0, &serialnum, NULL, - &flags, fsname, sizeof(fsname)); - - if (!serialnum && (drive_type == DRIVE_FIXED)) { - ptr += strlen(ptr)+1; - continue; /* ignore unformatted partitions */ - } - - SIGAR_FILE_SYSTEM_LIST_GROW(fslist); - - fsp = &fslist->data[fslist->number++]; - - fsp->type = type; - SIGAR_SSTRCPY(fsp->dir_name, ptr); - SIGAR_SSTRCPY(fsp->dev_name, ptr); - - if ((drive_type == DRIVE_REMOTE) && sigar_WNetGetConnection) { - DWORD len = sizeof(fsp->dev_name); - char drive[3] = {'\0', ':', '\0'}; /* e.g. "X:" w/o trailing "\" */ - drive[0] = fsp->dir_name[0]; - sigar_WNetGetConnection(drive, fsp->dev_name, &len); - /* ignoring failure, leaving dev_name as dir_name */ - } - - /* we set fsp->type, just looking up sigar.c:fstype_names[type] */ - sigar_fs_type_get(fsp); - - if (*fsname == '\0') { - SIGAR_SSTRCPY(fsp->sys_type_name, fsp->type_name); - } - else { - SIGAR_SSTRCPY(fsp->sys_type_name, fsname); /* CDFS, NTFS, etc */ - } - - get_fs_options(fsp->options, sizeof(fsp->options)-1, flags); - - ptr += strlen(ptr)+1; - } - - return SIGAR_OK; -} - -static PERF_INSTANCE_DEFINITION *get_disk_instance(sigar_t *sigar, - DWORD *perf_offsets, - DWORD *num, DWORD *err) -{ - PERF_OBJECT_TYPE *object = - get_perf_object(sigar, PERF_TITLE_DISK_KEY, err); - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_DEFINITION *counter; - DWORD i, found=0; - - if (!object) { - return NULL; - } - - for (i=0, counter = PdhFirstCounter(object); - iNumCounters; - i++, counter = PdhNextCounter(counter)) - { - DWORD offset = counter->CounterOffset; - - switch (counter->CounterNameTitleIndex) { - case PERF_TITLE_DISK_TIME: - perf_offsets[PERF_IX_DISK_TIME] = offset; - found = 1; - break; - case PERF_TITLE_DISK_READ_TIME: - perf_offsets[PERF_IX_DISK_READ_TIME] = offset; - found = 1; - break; - case PERF_TITLE_DISK_WRITE_TIME: - perf_offsets[PERF_IX_DISK_WRITE_TIME] = offset; - found = 1; - break; - case PERF_TITLE_DISK_READ: - perf_offsets[PERF_IX_DISK_READ] = offset; - found = 1; - break; - case PERF_TITLE_DISK_WRITE: - perf_offsets[PERF_IX_DISK_WRITE] = offset; - found = 1; - break; - case PERF_TITLE_DISK_READ_BYTES: - perf_offsets[PERF_IX_DISK_READ_BYTES] = offset; - found = 1; - break; - case PERF_TITLE_DISK_WRITE_BYTES: - perf_offsets[PERF_IX_DISK_WRITE_BYTES] = offset; - found = 1; - break; - case PERF_TITLE_DISK_QUEUE: - perf_offsets[PERF_IX_DISK_QUEUE] = offset; - found = 1; - break; - } - } - - if (!found) { - *err = ENOENT; - return NULL; - } - - if (num) { - *num = object->NumInstances; - } - - return PdhFirstInstance(object); -} - -SIGAR_DECLARE(int) sigar_disk_usage_get(sigar_t *sigar, - const char *dirname, - sigar_disk_usage_t *disk) -{ - DWORD i, err; - PERF_OBJECT_TYPE *object = - get_perf_object(sigar, PERF_TITLE_DISK_KEY, &err); - PERF_INSTANCE_DEFINITION *inst; - PERF_COUNTER_DEFINITION *counter; - DWORD perf_offsets[PERF_IX_DISK_MAX]; - - SIGAR_DISK_STATS_INIT(disk); - - if (!object) { - return err; - } - - memset(&perf_offsets, 0, sizeof(perf_offsets)); - inst = get_disk_instance(sigar, (DWORD*)&perf_offsets, 0, &err); - - if (!inst) { - return err; - } - - for (i=0, inst = PdhFirstInstance(object); - iNumInstances; - i++, inst = PdhNextInstance(inst)) - { - char drive[MAX_PATH]; - PERF_COUNTER_BLOCK *counter_block = PdhGetCounterBlock(inst); - wchar_t *name = (wchar_t *)((BYTE *)inst + inst->NameOffset); - - SIGAR_W2A(name, drive, sizeof(drive)); - - if (sigar_isdigit(*name)) { - char *ptr = strchr(drive, ' '); /* 2000 Server "0 C:" */ - - if (ptr) { - ++ptr; - SIGAR_SSTRCPY(drive, ptr); - } - else { - /* XXX NT is a number only "0", how to map? */ - } - } - - if (strnEQ(drive, dirname, 2)) { - disk->time = PERF_VAL(PERF_IX_DISK_TIME); - disk->rtime = PERF_VAL(PERF_IX_DISK_READ_TIME); - disk->wtime = PERF_VAL(PERF_IX_DISK_WRITE_TIME); - disk->reads = PERF_VAL(PERF_IX_DISK_READ); - disk->writes = PERF_VAL(PERF_IX_DISK_WRITE); - disk->read_bytes = PERF_VAL(PERF_IX_DISK_READ_BYTES); - disk->write_bytes = PERF_VAL(PERF_IX_DISK_WRITE_BYTES); - disk->queue = PERF_VAL(PERF_IX_DISK_QUEUE); - return SIGAR_OK; - } - } - - return ENXIO; -} - -SIGAR_DECLARE(int) -sigar_file_system_usage_get(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage) -{ - BOOL retval; - ULARGE_INTEGER avail, total, free; - int status; - - /* prevent dialog box if A:\ drive is empty */ - UINT errmode = SetErrorMode(SEM_FAILCRITICALERRORS); - - retval = GetDiskFreeSpaceEx(dirname, - &avail, &total, &free); - - /* restore previous error mode */ - SetErrorMode(errmode); - - if (!retval) { - return GetLastError(); - } - - fsusage->total = total.QuadPart / 1024; - fsusage->free = free.QuadPart / 1024; - fsusage->avail = avail.QuadPart / 1024; - fsusage->used = fsusage->total - fsusage->free; - fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage); - - /* N/A */ - fsusage->files = SIGAR_FIELD_NOTIMPL; - fsusage->free_files = SIGAR_FIELD_NOTIMPL; - - status = sigar_disk_usage_get(sigar, dirname, &fsusage->disk); - - return SIGAR_OK; -} - -static int sigar_cpu_info_get(sigar_t *sigar, sigar_cpu_info_t *info) -{ - HKEY key, cpu; - int i = 0; - char id[MAX_PATH + 1]; - DWORD size = 0, rc; - - RegOpenKey(HKEY_LOCAL_MACHINE, - "HARDWARE\\DESCRIPTION\\System\\CentralProcessor", &key); - - //just lookup the first id, then assume all cpus are the same. - rc = RegEnumKey(key, 0, id, sizeof(id)); - if (rc != ERROR_SUCCESS) { - RegCloseKey(key); - return rc; - } - - rc = RegOpenKey(key, id, &cpu); - if (rc != ERROR_SUCCESS) { - RegCloseKey(key); - return rc; - } - - size = sizeof(info->vendor); - if (RegQueryValueEx(cpu, "VendorIdentifier", NULL, NULL, - (LPVOID)&info->vendor, &size) || - strEQ(info->vendor, "GenuineIntel")) - { - SIGAR_SSTRCPY(info->vendor, "Intel"); - } - else { - if (strEQ(info->vendor, "AuthenticAMD")) { - SIGAR_SSTRCPY(info->vendor, "AMD"); - } - } - - size = sizeof(info->model); - if (RegQueryValueEx(cpu, "ProcessorNameString", NULL, NULL, - (LPVOID)&info->model, &size)) - { - size = sizeof(info->model); - if (RegQueryValueEx(cpu, "Identifier", NULL, NULL, - (LPVOID)&info->model, &size)) - { - SIGAR_SSTRCPY(info->model, "x86"); - } - } - else { - sigar_cpu_model_adjust(sigar, info); - } - - size = sizeof(info->mhz); // == sizeof(DWORD) - if (RegQueryValueEx(cpu, "~MHz", NULL, NULL, - (LPVOID)&info->mhz, &size)) - { - info->mhz = -1; - } - - info->cache_size = -1; //XXX - RegCloseKey(key); - RegCloseKey(cpu); - - info->total_cores = sigar->ncpu; - info->cores_per_socket = sigar->lcpu; - info->total_sockets = sigar_cpu_socket_count(sigar); - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_cpu_info_list_get(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos) -{ - int i, status; - sigar_cpu_info_t info; - int core_rollup = sigar_cpu_core_rollup(sigar); - - sigar_cpu_info_list_create(cpu_infos); - - status = sigar_cpu_info_get(sigar, &info); - - if (status != SIGAR_OK) { - return status; - } - - for (i=0; incpu; i++) { - SIGAR_CPU_INFO_LIST_GROW(cpu_infos); - - if (core_rollup && (i % sigar->lcpu)) { - continue; /* fold logical processors */ - } - - memcpy(&cpu_infos->data[cpu_infos->number++], - &info, sizeof(info)); - } - - return SIGAR_OK; -} - -#define sigar_GetNetworkParams \ - sigar->iphlpapi.get_net_params.func - -#define sigar_GetAdaptersInfo \ - sigar->iphlpapi.get_adapters_info.func - -#define sigar_GetAdaptersAddresses \ - sigar->iphlpapi.get_adapters_addrs.func - -#define sigar_GetNumberOfInterfaces \ - sigar->iphlpapi.get_num_if.func - -static sigar_cache_t *sigar_netif_cache_new(sigar_t *sigar) -{ - DWORD num = 0; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (sigar_GetNumberOfInterfaces) { - DWORD rc = sigar_GetNumberOfInterfaces(&num); - - if (rc == NO_ERROR) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "GetNumberOfInterfaces=%d", - num); - } - else { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "GetNumberOfInterfaces failed: %s", - sigar_strerror(sigar, rc)); - } - } - - if (num == 0) { - num = 10; /* reasonable default */ - } - - return sigar_cache_new(num); -} - -static int sigar_get_adapters_info(sigar_t *sigar, - PIP_ADAPTER_INFO *adapter) -{ - ULONG size = sigar->ifconf_len; - DWORD rc; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetAdaptersInfo) { - return SIGAR_ENOTIMPL; - } - - *adapter = (PIP_ADAPTER_INFO)sigar->ifconf_buf; - rc = sigar_GetAdaptersInfo(*adapter, &size); - - if (rc == ERROR_BUFFER_OVERFLOW) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "GetAdaptersInfo " - "realloc ifconf_buf old=%d, new=%d", - sigar->ifconf_len, size); - sigar->ifconf_len = size; - sigar->ifconf_buf = realloc(sigar->ifconf_buf, - sigar->ifconf_len); - - *adapter = (PIP_ADAPTER_INFO)sigar->ifconf_buf; - rc = sigar_GetAdaptersInfo(*adapter, &size); - } - - if (rc != NO_ERROR) { - return rc; - } - else { - return SIGAR_OK; - } -} - -static int sigar_get_adapter_info(sigar_t *sigar, - DWORD index, - IP_ADAPTER_INFO **adapter) -{ - sigar_cache_entry_t *entry; - *adapter = NULL; - - if (sigar->netif_adapters) { - entry = sigar_cache_get(sigar->netif_adapters, index); - if (entry->value) { - *adapter = (IP_ADAPTER_INFO *)entry->value; - } - } - else { - int status; - IP_ADAPTER_INFO *info; - - sigar->netif_adapters = - sigar_netif_cache_new(sigar); - - status = sigar_get_adapters_info(sigar, &info); - if (status != SIGAR_OK) { - return status; - } - - while (info) { - entry = sigar_cache_get(sigar->netif_adapters, - info->Index); - if (!entry->value) { - entry->value = malloc(sizeof(*info)); - } - memcpy(entry->value, info, sizeof(*info)); - if (info->Index == index) { - *adapter = info; - } - - info = info->Next; - } - } - - if (*adapter) { - return SIGAR_OK; - } - else { - return ENOENT; - } -} - -static int sigar_get_adapters_addresses(sigar_t *sigar, - ULONG family, ULONG flags, - PIP_ADAPTER_ADDRESSES *addrs, - ULONG *size) -{ - ULONG rc; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetAdaptersAddresses) { - return SIGAR_ENOTIMPL; - } - - rc = sigar_GetAdaptersAddresses(family, - flags, - NULL, - *addrs, - size); - - if (rc == ERROR_BUFFER_OVERFLOW) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "GetAdaptersAddresses realloc to %d", size); - - *addrs = realloc(*addrs, *size); - - rc = sigar_GetAdaptersAddresses(family, - flags, - NULL, - (PIP_ADAPTER_ADDRESSES)*addrs, - size); - } - - if (rc != ERROR_SUCCESS) { - return rc; - } - else { - return SIGAR_OK; - } -} - -#define sigar_GetIpAddrTable \ - sigar->iphlpapi.get_ipaddr_table.func - -static int sigar_get_ipaddr_table(sigar_t *sigar, - PMIB_IPADDRTABLE *ipaddr) -{ - ULONG size = sigar->ifconf_len; - DWORD rc; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetIpAddrTable) { - return SIGAR_ENOTIMPL; - } - - *ipaddr = (PMIB_IPADDRTABLE)sigar->ifconf_buf; - rc = sigar_GetIpAddrTable(*ipaddr, &size, FALSE); - - if (rc == ERROR_INSUFFICIENT_BUFFER) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "GetIpAddrTable " - "realloc ifconf_buf old=%d, new=%d", - sigar->ifconf_len, size); - sigar->ifconf_len = size; - sigar->ifconf_buf = realloc(sigar->ifconf_buf, - sigar->ifconf_len); - - *ipaddr = (PMIB_IPADDRTABLE)sigar->ifconf_buf; - rc = sigar_GetIpAddrTable(*ipaddr, &size, FALSE); - } - - if (rc != NO_ERROR) { - return rc; - } - else { - return SIGAR_OK; - } -} - -#ifndef MIB_IPADDR_PRIMARY -#define MIB_IPADDR_PRIMARY 0x0001 -#endif - -static int sigar_get_netif_ipaddr(sigar_t *sigar, - DWORD index, - MIB_IPADDRROW **ipaddr) -{ - sigar_cache_entry_t *entry; - *ipaddr = NULL; - - if (sigar->netif_addr_rows) { - entry = sigar_cache_get(sigar->netif_addr_rows, index); - if (entry->value) { - *ipaddr = (MIB_IPADDRROW *)entry->value; - } - } - else { - int status, i; - MIB_IPADDRTABLE *mib; - - sigar->netif_addr_rows = - sigar_netif_cache_new(sigar); - - status = sigar_get_ipaddr_table(sigar, &mib); - if (status != SIGAR_OK) { - return status; - } - - for (i=0; idwNumEntries; i++) { - MIB_IPADDRROW *row = &mib->table[i]; - short type; - -#if HAVE_MIB_IPADDRROW_WTYPE - type = row->wType; -#else - type = row->unused2; -#endif - if (!(type & MIB_IPADDR_PRIMARY)) { - continue; - } - - entry = sigar_cache_get(sigar->netif_addr_rows, - row->dwIndex); - if (!entry->value) { - entry->value = malloc(sizeof(*row)); - } - memcpy(entry->value, row, sizeof(*row)); - - if (row->dwIndex == index) { - *ipaddr = row; - } - } - } - - if (*ipaddr) { - return SIGAR_OK; - } - else { - return ENOENT; - } -} - -SIGAR_DECLARE(int) sigar_net_info_get(sigar_t *sigar, - sigar_net_info_t *netinfo) -{ - PIP_ADAPTER_INFO adapter; - FIXED_INFO *info; - ULONG len = 0; - IP_ADDR_STRING *ip; - DWORD rc; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetNetworkParams) { - return SIGAR_ENOTIMPL; - } - - SIGAR_ZERO(netinfo); - - rc = sigar_GetNetworkParams(NULL, &len); - if (rc != ERROR_BUFFER_OVERFLOW) { - return rc; - } - - info = malloc(len); - rc = sigar_GetNetworkParams(info, &len); - if (rc != NO_ERROR) { - free(info); - return rc; - } - - SIGAR_SSTRCPY(netinfo->host_name, info->HostName); - SIGAR_SSTRCPY(netinfo->domain_name, info->DomainName); - SIGAR_SSTRCPY(netinfo->primary_dns, - info->DnsServerList.IpAddress.String); - - if ((ip = info->DnsServerList.Next)) { - SIGAR_SSTRCPY(netinfo->secondary_dns, - ip->IpAddress.String); - } - - free(info); - - if (sigar_get_adapters_info(sigar, &adapter) != SIGAR_OK) { - return SIGAR_OK; - } - - while (adapter) { - /* should only be 1 */ - if (adapter->GatewayList.IpAddress.String[0]) { - SIGAR_SSTRCPY(netinfo->default_gateway, - adapter->GatewayList.IpAddress.String); - } -#if 0 - if (apapters->DhcpEnabled) { - SIGAR_SSTRCPY(netinfo->dhcp_server, - apdaters->DhcpServer.IpAddress.String); - } -#endif - adapter = adapter->Next; - } - - return SIGAR_OK; -} - -#define sigar_GetIpForwardTable \ - sigar->iphlpapi.get_ipforward_table.func - -SIGAR_DECLARE(int) sigar_net_route_list_get(sigar_t *sigar, - sigar_net_route_list_t *routelist) -{ - PMIB_IPFORWARDTABLE buffer = NULL; - ULONG bufsize = 0; - DWORD rc, i; - MIB_IPFORWARDTABLE *ipt; - sigar_net_route_t *route; - - DLLMOD_INIT(iphlpapi, FALSE); - if (!sigar_GetIpForwardTable) { - return SIGAR_ENOTIMPL; - } - - rc = sigar_GetIpForwardTable(buffer, &bufsize, FALSE); - if (rc != ERROR_INSUFFICIENT_BUFFER) { - return GetLastError(); - } - - buffer = malloc(bufsize); - rc = sigar_GetIpForwardTable(buffer, &bufsize, FALSE); - if (rc != NO_ERROR) { - free(buffer); - return GetLastError(); - } - - if (!sigar->netif_names) { - sigar_net_interface_list_get(sigar, NULL); - } - - sigar_net_route_list_create(routelist); - routelist->size = routelist->number = 0; - - ipt = buffer; - - for (i=0; idwNumEntries; i++) { - MIB_IPFORWARDROW *ipr = ipt->table + i; - sigar_cache_entry_t *entry; - - SIGAR_NET_ROUTE_LIST_GROW(routelist); - - route = &routelist->data[routelist->number++]; - SIGAR_ZERO(route); /* XXX: other fields */ - - sigar_net_address_set(route->destination, - ipr->dwForwardDest); - - sigar_net_address_set(route->mask, - ipr->dwForwardMask); - - sigar_net_address_set(route->gateway, - ipr->dwForwardNextHop); - - route->metric = ipr->dwForwardMetric1; - - route->flags = SIGAR_RTF_UP; - if ((ipr->dwForwardDest == 0) && - (ipr->dwForwardMask == 0)) - { - route->flags |= SIGAR_RTF_GATEWAY; - } - - entry = sigar_cache_get(sigar->netif_names, ipr->dwForwardIfIndex); - if (entry->value) { - SIGAR_SSTRCPY(route->ifname, (char *)entry->value); - } - } - - free(buffer); - - return SIGAR_OK; -} - -#define sigar_GetIfTable \ - sigar->iphlpapi.get_if_table.func - -#define sigar_GetIfEntry \ - sigar->iphlpapi.get_if_entry.func - -static int sigar_get_if_table(sigar_t *sigar, PMIB_IFTABLE *iftable) -{ - ULONG size = sigar->ifconf_len; - DWORD rc; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetIfTable) { - return SIGAR_ENOTIMPL; - } - - *iftable = (PMIB_IFTABLE)sigar->ifconf_buf; - rc = sigar_GetIfTable(*iftable, &size, FALSE); - - if (rc == ERROR_INSUFFICIENT_BUFFER) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "GetIfTable " - "realloc ifconf_buf old=%d, new=%d", - sigar->ifconf_len, size); - sigar->ifconf_len = size; - sigar->ifconf_buf = realloc(sigar->ifconf_buf, - sigar->ifconf_len); - - *iftable = (PMIB_IFTABLE)sigar->ifconf_buf; - rc = sigar_GetIfTable(*iftable, &size, FALSE); - } - - if (rc != NO_ERROR) { - return rc; - } - else { - return SIGAR_OK; - } -} - -static int get_mib_ifrow(sigar_t *sigar, - const char *name, - MIB_IFROW **ifrp) -{ - int status, key, cached=0; - sigar_cache_entry_t *entry; - - if (sigar->netif_mib_rows) { - cached = 1; - } - else { - status = sigar_net_interface_list_get(sigar, NULL); - if (status != SIGAR_OK) { - return status; - } - } - key = netif_hash(name); - entry = sigar_cache_get(sigar->netif_mib_rows, key); - if (!entry->value) { - return ENOENT; - } - - *ifrp = (MIB_IFROW *)entry->value; - if (cached) { - /* refresh */ - if ((status = sigar_GetIfEntry(*ifrp)) != NO_ERROR) { - return status; - } - } - - return SIGAR_OK; -} - -static int netif_hash(char *s) -{ - int hash = 0; - while (*s) { - hash = 31*hash + *s++; - } - return hash; -} - -/* Vista and later, wireless network cards are reported as IF_TYPE_IEEE80211 */ -#ifndef IF_TYPE_IEEE80211 -#define IF_TYPE_IEEE80211 71 -#endif - -static int -sigar_net_interface_name_get(sigar_t *sigar, MIB_IFROW *ifr, PIP_ADAPTER_ADDRESSES address_list, char *name) -{ - PIP_ADAPTER_ADDRESSES iter; - int lpc = 0; - - if (address_list == NULL) { - return SIGAR_ENOTIMPL; - } - - for (iter = address_list; iter != NULL; iter = iter->Next) { - for (lpc = 0; lpc < iter->PhysicalAddressLength; lpc++) { - if (iter->PhysicalAddress[lpc] != ifr->bPhysAddr[lpc]) { - break; - } - } - - if (lpc == iter->PhysicalAddressLength) { - wcstombs(name, iter->FriendlyName, MAX_INTERFACE_NAME_LEN); - name[MAX_INTERFACE_NAME_LEN-1] = '\0'; - return SIGAR_OK; - } - } - - return SIGAR_ENOENT; -} - -SIGAR_DECLARE(int) -sigar_net_interface_list_get(sigar_t *sigar, - sigar_net_interface_list_t *iflist) -{ - MIB_IFTABLE *ift; - int i, status; - int lo=0, eth=0, la=0; - PIP_ADAPTER_ADDRESSES address_list = NULL; - ULONG size = 0; - - status = sigar_get_adapters_addresses(sigar, AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, &address_list, &size); - - if (status != SIGAR_OK) { - address_list = NULL; - } - - if (!sigar->netif_mib_rows) { - sigar->netif_mib_rows = - sigar_netif_cache_new(sigar); - } - - if (!sigar->netif_names) { - sigar->netif_names = - sigar_netif_cache_new(sigar); - } - - if ((status = sigar_get_if_table(sigar, &ift)) != SIGAR_OK) { - if (address_list) { - free(address_list); - } - return status; - } - - if (iflist) { - iflist->number = 0; - iflist->size = ift->dwNumEntries; - iflist->data = - malloc(sizeof(*(iflist->data)) * iflist->size); - } - - for (i=0; idwNumEntries; i++) { - char name[MAX_INTERFACE_NAME_LEN]; - int key; - MIB_IFROW *ifr = ift->table + i; - sigar_cache_entry_t *entry; - - status = SIGAR_ENOENT; - - if (strEQ(ifr->bDescr, MS_LOOPBACK_ADAPTER)) { - /* special-case */ - sprintf(name, NETIF_LA "%d", la++); - } - else if (ifr->dwType == MIB_IF_TYPE_LOOPBACK) { - if (!sigar->netif_name_short) { - status = sigar_net_interface_name_get(sigar, ifr, address_list, name); - } - if (status != SIGAR_OK) { - sprintf(name, "lo%d", lo++); - } - } - else if ((ifr->dwType == MIB_IF_TYPE_ETHERNET) || - (ifr->dwType == IF_TYPE_IEEE80211)) - { - if (!sigar->netif_name_short && - (strstr(ifr->bDescr, "Scheduler") == NULL) && - (strstr(ifr->bDescr, "Filter") == NULL)) - { - status = sigar_net_interface_name_get(sigar, ifr, address_list, name); - } - - if (status != SIGAR_OK) { - if (sigar->netif_name_short) { - sprintf(name, "eth%d", eth++); - } - else { - snprintf(name, ifr->dwDescrLen, "%s", ifr->bDescr); - } - } - } - else { - continue; /*XXX*/ - } - - if (iflist) { - iflist->data[iflist->number++] = sigar_strdup(name); - } - - key = netif_hash(name); - entry = sigar_cache_get(sigar->netif_mib_rows, key); - if (!entry->value) { - entry->value = malloc(sizeof(*ifr)); - } - memcpy(entry->value, ifr, sizeof(*ifr)); - - /* save dwIndex -> name mapping for use by route_list */ - entry = sigar_cache_get(sigar->netif_names, ifr->dwIndex); - if (!entry->value) { - entry->value = sigar_strdup(name); - } - } - - if (address_list != NULL) { - free(address_list); - } - - return SIGAR_OK; -} - -static int sigar_net_interface_ipv6_config_find(sigar_t *sigar, int index, - sigar_net_interface_config_t *ifconfig) -{ -#ifdef SIGAR_USING_MSC6 - return SIGAR_ENOTIMPL; -#else - int status; - PIP_ADAPTER_ADDRESSES aa = (PIP_ADAPTER_ADDRESSES)sigar->ifconf_buf, addrs; - ULONG flags = GAA_FLAG_INCLUDE_PREFIX; - status = sigar_get_adapters_addresses(sigar, AF_UNSPEC, flags, &aa, &sigar->ifconf_len); - - if (status != SIGAR_OK) { - return status; - } - - for (addrs = aa; addrs; addrs = addrs->Next) { - PIP_ADAPTER_UNICAST_ADDRESS addr; - if (addrs->IfIndex != index) { - continue; - } - for (addr = addrs->FirstUnicastAddress; addr; addr = addr->Next) { - struct sockaddr *sa = addr->Address.lpSockaddr; - - if (sa->sa_family == AF_INET6) { - struct in6_addr *inet6 = SIGAR_SIN6_ADDR(sa); - - sigar_net_address6_set(ifconfig->address6, inet6); - sigar_net_interface_scope6_set(ifconfig, inet6); - if (addrs->FirstPrefix) { - ifconfig->prefix6_length = addrs->FirstPrefix->PrefixLength; - } - return SIGAR_OK; - } - } - } - return SIGAR_ENOENT; -#endif -} - -SIGAR_DECLARE(int) -sigar_net_interface_config_get(sigar_t *sigar, - const char *name, - sigar_net_interface_config_t *ifconfig) -{ - MIB_IFROW *ifr; - MIB_IPADDRROW *ipaddr; - int status; - - if (!name) { - return sigar_net_interface_config_primary_get(sigar, ifconfig); - } - - status = get_mib_ifrow(sigar, name, &ifr); - if (status != SIGAR_OK) { - return status; - } - - SIGAR_ZERO(ifconfig); - - SIGAR_SSTRCPY(ifconfig->name, name); - - ifconfig->mtu = ifr->dwMtu; - - sigar_net_address_mac_set(ifconfig->hwaddr, - ifr->bPhysAddr, - SIGAR_IFHWADDRLEN); - - SIGAR_SSTRCPY(ifconfig->description, - ifr->bDescr); - - if (ifr->dwOperStatus & MIB_IF_OPER_STATUS_OPERATIONAL) { - ifconfig->flags |= SIGAR_IFF_UP|SIGAR_IFF_RUNNING; - } - - status = sigar_get_netif_ipaddr(sigar, - ifr->dwIndex, - &ipaddr); - - if (status == SIGAR_OK) { - sigar_net_address_set(ifconfig->address, - ipaddr->dwAddr); - - sigar_net_address_set(ifconfig->netmask, - ipaddr->dwMask); - - if (ifr->dwType != MIB_IF_TYPE_LOOPBACK) { - if (ipaddr->dwBCastAddr) { - long bcast = - ipaddr->dwAddr & ipaddr->dwMask; - - bcast |= ~ipaddr->dwMask; - ifconfig->flags |= SIGAR_IFF_BROADCAST; - - sigar_net_address_set(ifconfig->broadcast, - bcast); - } - } - } - - /* hack for MS_LOOPBACK_ADAPTER */ - if (strnEQ(name, NETIF_LA, sizeof(NETIF_LA)-1)) { - ifr->dwType = MIB_IF_TYPE_LOOPBACK; - } - - if (ifr->dwType == MIB_IF_TYPE_LOOPBACK) { - ifconfig->flags |= SIGAR_IFF_LOOPBACK; - - SIGAR_SSTRCPY(ifconfig->type, - SIGAR_NIC_LOOPBACK); - } - else { - if (ipaddr) { - ifconfig->flags |= SIGAR_IFF_MULTICAST; - } - - SIGAR_SSTRCPY(ifconfig->type, - SIGAR_NIC_ETHERNET); - } - - sigar_net_interface_ipv6_config_init(ifconfig); - sigar_net_interface_ipv6_config_find(sigar, ifr->dwIndex, ifconfig); - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_net_interface_stat_get(sigar_t *sigar, const char *name, - sigar_net_interface_stat_t *ifstat) -{ - MIB_IFROW *ifr; - int status; - - status = get_mib_ifrow(sigar, name, &ifr); - if (status != SIGAR_OK) { - return status; - } - - ifstat->rx_bytes = ifr->dwInOctets; - ifstat->rx_packets = ifr->dwInUcastPkts + ifr->dwInNUcastPkts; - ifstat->rx_errors = ifr->dwInErrors; - ifstat->rx_dropped = ifr->dwInDiscards; - ifstat->rx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->rx_frame = SIGAR_FIELD_NOTIMPL; - - ifstat->tx_bytes = ifr->dwOutOctets; - ifstat->tx_packets = ifr->dwOutUcastPkts + ifr->dwOutNUcastPkts; - ifstat->tx_errors = ifr->dwOutErrors; - ifstat->tx_dropped = ifr->dwOutDiscards; - ifstat->tx_overruns = SIGAR_FIELD_NOTIMPL; - ifstat->tx_collisions = SIGAR_FIELD_NOTIMPL; - ifstat->tx_carrier = SIGAR_FIELD_NOTIMPL; - - ifstat->speed = ifr->dwSpeed; - - return SIGAR_OK; -} - -#define IS_TCP_SERVER(state, flags) \ - ((flags & SIGAR_NETCONN_SERVER) && (state == MIB_TCP_STATE_LISTEN)) - -#define IS_TCP_CLIENT(state, flags) \ - ((flags & SIGAR_NETCONN_CLIENT) && (state != MIB_TCP_STATE_LISTEN)) - -#define sigar_GetTcpTable \ - sigar->iphlpapi.get_tcp_table.func - -static int net_conn_get_tcp(sigar_net_connection_walker_t *walker) -{ - sigar_t *sigar = walker->sigar; - int flags = walker->flags; - int status, i; - DWORD rc, size=0; - PMIB_TCPTABLE tcp; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetTcpTable) { - return SIGAR_ENOTIMPL; - } - - rc = sigar_GetTcpTable(NULL, &size, FALSE); - if (rc != ERROR_INSUFFICIENT_BUFFER) { - return GetLastError(); - } - tcp = malloc(size); - rc = sigar_GetTcpTable(tcp, &size, FALSE); - if (rc) { - free(tcp); - return GetLastError(); - } - - /* go in reverse to get LISTEN states first */ - for (i = (tcp->dwNumEntries-1); i >= 0; i--) { - sigar_net_connection_t conn; - DWORD state = tcp->table[i].dwState; - - if (!(IS_TCP_SERVER(state, flags) || - IS_TCP_CLIENT(state, flags))) - { - continue; - } - - conn.local_port = htons((WORD)tcp->table[i].dwLocalPort); - conn.remote_port = htons((WORD)tcp->table[i].dwRemotePort); - - conn.type = SIGAR_NETCONN_TCP; - - sigar_net_address_set(conn.local_address, - tcp->table[i].dwLocalAddr); - - sigar_net_address_set(conn.remote_address, - tcp->table[i].dwRemoteAddr); - - conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL; - - switch (state) { - case MIB_TCP_STATE_CLOSED: - conn.state = SIGAR_TCP_CLOSE; - break; - case MIB_TCP_STATE_LISTEN: - conn.state = SIGAR_TCP_LISTEN; - break; - case MIB_TCP_STATE_SYN_SENT: - conn.state = SIGAR_TCP_SYN_SENT; - break; - case MIB_TCP_STATE_SYN_RCVD: - conn.state = SIGAR_TCP_SYN_RECV; - break; - case MIB_TCP_STATE_ESTAB: - conn.state = SIGAR_TCP_ESTABLISHED; - break; - case MIB_TCP_STATE_FIN_WAIT1: - conn.state = SIGAR_TCP_FIN_WAIT1; - break; - case MIB_TCP_STATE_FIN_WAIT2: - conn.state = SIGAR_TCP_FIN_WAIT2; - break; - case MIB_TCP_STATE_CLOSE_WAIT: - conn.state = SIGAR_TCP_CLOSE_WAIT; - break; - case MIB_TCP_STATE_CLOSING: - conn.state = SIGAR_TCP_CLOSING; - break; - case MIB_TCP_STATE_LAST_ACK: - conn.state = SIGAR_TCP_LAST_ACK; - break; - case MIB_TCP_STATE_TIME_WAIT: - conn.state = SIGAR_TCP_TIME_WAIT; - break; - case MIB_TCP_STATE_DELETE_TCB: - default: - conn.state = SIGAR_TCP_UNKNOWN; - break; - } - - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - } - - free(tcp); - return SIGAR_OK; -} - -#define IS_UDP_SERVER(conn, flags) \ - ((flags & SIGAR_NETCONN_SERVER) && !conn.remote_port) - -#define IS_UDP_CLIENT(state, flags) \ - ((flags & SIGAR_NETCONN_CLIENT) && conn.remote_port) - -#define sigar_GetUdpTable \ - sigar->iphlpapi.get_udp_table.func - -static int net_conn_get_udp(sigar_net_connection_walker_t *walker) -{ - sigar_t *sigar = walker->sigar; - int flags = walker->flags; - int status; - DWORD rc, size=0, i; - PMIB_UDPTABLE udp; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetUdpTable) { - return SIGAR_ENOTIMPL; - } - - rc = sigar_GetUdpTable(NULL, &size, FALSE); - if (rc != ERROR_INSUFFICIENT_BUFFER) { - return GetLastError(); - } - udp = malloc(size); - rc = sigar_GetUdpTable(udp, &size, FALSE); - if (rc) { - free(udp); - return GetLastError(); - } - - for (i = 0; i < udp->dwNumEntries; i++) { - sigar_net_connection_t conn; - - if (!(IS_UDP_SERVER(conn, flags) || - IS_UDP_CLIENT(conn, flags))) - { - continue; - } - - conn.local_port = htons((WORD)udp->table[i].dwLocalPort); - conn.remote_port = 0; - - conn.type = SIGAR_NETCONN_UDP; - - sigar_net_address_set(conn.local_address, - udp->table[i].dwLocalAddr); - - sigar_net_address_set(conn.remote_address, 0); - - conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL; - - if (walker->add_connection(walker, &conn) != SIGAR_OK) { - break; - } - } - - free(udp); - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_net_connection_walk(sigar_net_connection_walker_t *walker) -{ - int status; - - if (walker->flags & SIGAR_NETCONN_TCP) { - status = net_conn_get_tcp(walker); - - if (status != SIGAR_OK) { - return status; - } - } - - if (walker->flags & SIGAR_NETCONN_UDP) { - status = net_conn_get_udp(walker); - - if (status != SIGAR_OK) { - return status; - } - } - - return SIGAR_OK; -} - -#define sigar_GetTcpStatistics \ - sigar->iphlpapi.get_tcp_stats.func - -SIGAR_DECLARE(int) -sigar_tcp_get(sigar_t *sigar, - sigar_tcp_t *tcp) -{ - MIB_TCPSTATS mib; - int status; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetTcpStatistics) { - return SIGAR_ENOTIMPL; - } - - status = sigar_GetTcpStatistics(&mib); - - if (status != NO_ERROR) { - return status; - } - - tcp->active_opens = mib.dwActiveOpens; - tcp->passive_opens = mib.dwPassiveOpens; - tcp->attempt_fails = mib.dwAttemptFails; - tcp->estab_resets = mib.dwEstabResets; - tcp->curr_estab = mib.dwCurrEstab; - tcp->in_segs = mib.dwInSegs; - tcp->out_segs = mib.dwOutSegs; - tcp->retrans_segs = mib.dwRetransSegs; - tcp->in_errs = mib.dwInErrs; - tcp->out_rsts = mib.dwOutRsts; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_nfs_client_v2_get(sigar_t *sigar, - sigar_nfs_client_v2_t *nfs) -{ - return SIGAR_ENOTIMPL; -} - -SIGAR_DECLARE(int) -sigar_nfs_server_v2_get(sigar_t *sigar, - sigar_nfs_server_v2_t *nfs) -{ - return SIGAR_ENOTIMPL; -} - -SIGAR_DECLARE(int) -sigar_nfs_client_v3_get(sigar_t *sigar, - sigar_nfs_client_v3_t *nfs) -{ - return SIGAR_ENOTIMPL; -} - -SIGAR_DECLARE(int) -sigar_nfs_server_v3_get(sigar_t *sigar, - sigar_nfs_server_v3_t *nfs) -{ - return SIGAR_ENOTIMPL; -} - -#define sigar_GetTcpExTable \ - sigar->iphlpapi.get_tcpx_table.func - -#define sigar_GetUdpExTable \ - sigar->iphlpapi.get_udpx_table.func - -SIGAR_DECLARE(int) sigar_proc_port_get(sigar_t *sigar, - int protocol, - unsigned long port, - sigar_pid_t *pid) -{ - DWORD rc, i; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (protocol == SIGAR_NETCONN_TCP) { - PMIB_TCPEXTABLE tcp; - - if (!sigar_GetTcpExTable) { - return SIGAR_ENOTIMPL; - } - - rc = sigar_GetTcpExTable(&tcp, FALSE, GetProcessHeap(), - 2, 2); - - if (rc) { - return GetLastError(); - } - - for (i=0; idwNumEntries; i++) { - if (tcp->table[i].dwState != MIB_TCP_STATE_LISTEN) { - continue; - } - - if (htons((WORD)tcp->table[i].dwLocalPort) != port) { - continue; - } - - *pid = tcp->table[i].dwProcessId; - - return SIGAR_OK; - } - } - else if (protocol == SIGAR_NETCONN_UDP) { - PMIB_UDPEXTABLE udp; - - if (!sigar_GetUdpExTable) { - return SIGAR_ENOTIMPL; - } - - rc = sigar_GetUdpExTable(&udp, FALSE, GetProcessHeap(), - 2, 2); - - if (rc) { - return GetLastError(); - } - - for (i=0; idwNumEntries; i++) { - if (htons((WORD)udp->table[i].dwLocalPort) != port) { - continue; - } - - *pid = udp->table[i].dwProcessId; - - return SIGAR_OK; - } - } - else { - return SIGAR_ENOTIMPL; - } - - return ENOENT; -} - -#define sigar_GetIpNetTable \ - sigar->iphlpapi.get_ipnet_table.func - -SIGAR_DECLARE(int) sigar_arp_list_get(sigar_t *sigar, - sigar_arp_list_t *arplist) -{ - int status; - DWORD rc, size=0, i; - PMIB_IPNETTABLE ipnet; - - DLLMOD_INIT(iphlpapi, FALSE); - - if (!sigar_GetIpNetTable) { - return SIGAR_ENOTIMPL; - } - - rc = sigar_GetIpNetTable(NULL, &size, FALSE); - if (rc != ERROR_INSUFFICIENT_BUFFER) { - return GetLastError(); - } - ipnet = malloc(size); - rc = sigar_GetIpNetTable(ipnet, &size, FALSE); - if (rc) { - free(ipnet); - return GetLastError(); - } - - sigar_arp_list_create(arplist); - - if (!sigar->netif_names) { - /* dwIndex -> name map */ - sigar_net_interface_list_get(sigar, NULL); - } - - for (i = 0; i < ipnet->dwNumEntries; i++) { - sigar_arp_t *arp; - PMIB_IPNETROW entry; - sigar_cache_entry_t *ifname; - - entry = &ipnet->table[i]; - SIGAR_ARP_LIST_GROW(arplist); - arp = &arplist->data[arplist->number++]; - - sigar_net_address_set(arp->address, - entry->dwAddr); - - sigar_net_address_mac_set(arp->hwaddr, - entry->bPhysAddr, - entry->dwPhysAddrLen); - - ifname = sigar_cache_get(sigar->netif_names, entry->dwIndex); - if (ifname->value) { - SIGAR_SSTRCPY(arp->ifname, (char *)ifname->value); - } - - arp->flags = 0; /*XXX*/ - SIGAR_SSTRCPY(arp->type, "ether"); /*XXX*/ - } - - free(ipnet); - - return SIGAR_OK; -} - -#include - -static int sigar_who_net_sessions(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - NET_API_STATUS status; - LPSESSION_INFO_10 buffer=NULL, ptr; - DWORD entries=0, total_entries=0; - DWORD resume_handle=0; - DWORD i; - - do { - status = NetSessionEnum(NULL, /* server name */ - NULL, /* client name */ - NULL, /* user name */ - 10, /* level */ - (LPBYTE*)&buffer, - MAX_PREFERRED_LENGTH, - &entries, - &total_entries, - &resume_handle); - - if ((status == NERR_Success) || (status == ERROR_MORE_DATA)) { - if ((ptr = buffer)) { - for (i=0; idata[wholist->number++]; - - who->time = (time(NULL) - ptr->sesi10_time); - SIGAR_W2A((LPCWSTR)ptr->sesi10_username, - who->user, sizeof(who->user)); - SIGAR_W2A((LPCWSTR)ptr->sesi10_cname, - who->host, sizeof(who->host)); - SIGAR_SSTRCPY(who->device, "network share"); - - ptr++; - } - } - } - else { - break; - } - - if (buffer) { - NetApiBufferFree(buffer); - buffer = NULL; - } - } while (status == ERROR_MORE_DATA); - - if (buffer) { - NetApiBufferFree(buffer); - } - - return SIGAR_OK; -} - -static int get_logon_info(HKEY users, - char *username, - sigar_who_t *who) -{ - DWORD status, size, type; - HKEY key; - char key_name[MAX_PATH]; - char value[256]; - FILETIME wtime; - - who->time = 0; - - sprintf(key_name, "%s\\Volatile Environment", username); - if (RegOpenKey(users, key_name, &key) != ERROR_SUCCESS) { - return ENOENT; - } - - status = RegQueryInfoKey(key, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - &wtime); - - if (status == ERROR_SUCCESS) { - FileTimeToLocalFileTime(&wtime, &wtime); - who->time = sigar_FileTimeToTime(&wtime) / 1000000; - } - - size = sizeof(value); - status = RegQueryValueEx(key, "CLIENTNAME", - NULL, &type, value, &size); - if (status == ERROR_SUCCESS) { - if ((value[0] != '\0') && !strEQ(value, "Console")) { - SIGAR_SSTRCPY(who->host, value); - } - } - - size = sizeof(value); - status = RegQueryValueEx(key, "SESSIONNAME", - NULL, &type, value, &size); - if (status == ERROR_SUCCESS) { - SIGAR_SSTRCPY(who->device, value); - } - - RegCloseKey(key); - - return SIGAR_OK; -} - -#define sigar_ConvertStringSidToSid \ - sigar->advapi.convert_string_sid.func - -static int sigar_who_registry(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - HKEY users; - DWORD index=0, status; - - if (!sigar_ConvertStringSidToSid) { - return ENOENT; - } - - status = RegOpenKey(HKEY_USERS, NULL, &users); - if (status != ERROR_SUCCESS) { - return status; - } - - while (1) { - char subkey[MAX_PATH]; - char username[SIGAR_CRED_NAME_MAX]; - char domain[SIGAR_CRED_NAME_MAX]; - DWORD subkey_len = sizeof(subkey); - DWORD username_len = sizeof(username); - DWORD domain_len = sizeof(domain); - PSID sid; - SID_NAME_USE type; - - status = RegEnumKeyEx(users, index, subkey, &subkey_len, - NULL, NULL, NULL, NULL); - - if (status != ERROR_SUCCESS) { - break; - } - - index++; - - if ((subkey[0] == '.') || strstr(subkey, "_Classes")) { - continue; - } - - if (!sigar_ConvertStringSidToSid(subkey, &sid)) { - continue; - } - - if (LookupAccountSid(NULL, /* server */ - sid, - username, &username_len, - domain, &domain_len, - &type)) - { - sigar_who_t *who; - - SIGAR_WHO_LIST_GROW(wholist); - who = &wholist->data[wholist->number++]; - - SIGAR_SSTRCPY(who->user, username); - SIGAR_SSTRCPY(who->host, domain); - SIGAR_SSTRCPY(who->device, "console"); - - get_logon_info(users, subkey, who); - } - - LocalFree(sid); - } - - RegCloseKey(users); - - return SIGAR_OK; -} - -#define sigar_WTSEnumerateSessions \ - sigar->wtsapi.enum_sessions.func - -#define sigar_WTSFreeMemory \ - sigar->wtsapi.free_mem.func - -#define sigar_WTSQuerySessionInformation \ - sigar->wtsapi.query_session.func - -#define sigar_WinStationQueryInformation \ - sigar->winsta.query_info.func - -static int sigar_who_wts(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - DWORD count=0, i; - WTS_SESSION_INFO *sessions = NULL; - - if (DLLMOD_INIT(wtsapi, TRUE) != SIGAR_OK) { - sigar_log(sigar, SIGAR_LOG_DEBUG, - "Terminal Services api functions not available"); - return ENOENT; - } - - DLLMOD_INIT(winsta, FALSE); - - if (!sigar_WTSEnumerateSessions(0, 0, 1, &sessions, &count)) { - return GetLastError(); - } - - for (i=0; idata[wholist->number++]; - - SIGAR_SSTRCPY(who->device, sessions[i].pWinStationName); - - buffer = NULL; - bytes = 0; - if (sigar_WTSQuerySessionInformation(0, - sessionId, - WTSClientAddress, - &buffer, - &bytes)) - { - PWTS_CLIENT_ADDRESS client = - (PWTS_CLIENT_ADDRESS)buffer; - - sprintf(who->host, "%u.%u.%u.%u", - client->Address[2], - client->Address[3], - client->Address[4], - client->Address[5]); - - sigar_WTSFreeMemory(buffer); - } - else { - SIGAR_SSTRCPY(who->host, "unknown"); - } - - buffer = NULL; - bytes = 0; - if (sigar_WTSQuerySessionInformation(0, - sessionId, - WTSUserName, - &buffer, - &bytes)) - { - SIGAR_SSTRCPY(who->user, buffer); - sigar_WTSFreeMemory(buffer); - } - else { - SIGAR_SSTRCPY(who->user, "unknown"); - } - - buffer = NULL; - bytes = 0; - if (sigar_WinStationQueryInformation && - sigar_WinStationQueryInformation(0, - sessionId, - WinStationInformation, - &station_info, - sizeof(station_info), - &bytes)) - { - who->time = - sigar_FileTimeToTime(&station_info.ConnectTime) / 1000000; - } - else { - who->time = 0; - } - } - - sigar_WTSFreeMemory(sessions); - - return SIGAR_OK; -} - -int sigar_who_list_get_win32(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - sigar_who_net_sessions(sigar, wholist); - - sigar_who_registry(sigar, wholist); - - sigar_who_wts(sigar, wholist); - - return SIGAR_OK; -} - -/* see: http://msdn2.microsoft.com/en-us/library/ms724833.aspx */ -#ifndef VER_NT_WORKSTATION -#define VER_NT_WORKSTATION 0x0000001 -#endif - -#ifdef SIGAR_USING_MSC6 -#define sigar_wProductType wReserved[1] -#else -#define sigar_wProductType wProductType -#endif -#ifdef _M_X64 -#define SIGAR_ARCH "x64" -#else -#define SIGAR_ARCH "x86" -#endif - -int sigar_os_sys_info_get(sigar_t *sigar, - sigar_sys_info_t *sysinfo) -{ - OSVERSIONINFOEX version; - char *vendor_name, *vendor_version, *code_name=NULL; - - version.dwOSVersionInfoSize = sizeof(version); - GetVersionEx((OSVERSIONINFO *)&version); - - if (version.dwMajorVersion == 4) { - vendor_name = "Windows NT"; - vendor_version = "NT"; - } - else if (version.dwMajorVersion == 5) { - switch (version.dwMinorVersion) { - case 0: - vendor_name = "Windows 2000"; - vendor_version = "2000"; - break; - case 1: - vendor_name = "Windows XP"; - vendor_version = "XP"; - code_name = "Whistler"; - break; - case 2: - vendor_name = "Windows 2003"; - vendor_version = "2003"; - code_name = "Whistler Server"; - break; - default: - vendor_name = "Windows Unknown"; - break; - } - } - else if (version.dwMajorVersion == 6) { - if (version.sigar_wProductType == VER_NT_WORKSTATION) { - if (version.dwMinorVersion == 0) { - vendor_name = "Windows Vista"; - vendor_version = "Vista"; - code_name = "Longhorn"; - } - else { - vendor_name = "Windows 7"; - vendor_version = "7"; - code_name = "Vienna"; - } - } - else { - vendor_name = "Windows 2008"; - vendor_version = "2008"; - code_name = "Longhorn Server"; - } - } - - SIGAR_SSTRCPY(sysinfo->name, "Win32"); - SIGAR_SSTRCPY(sysinfo->vendor, "Microsoft"); - SIGAR_SSTRCPY(sysinfo->vendor_name, vendor_name); - SIGAR_SSTRCPY(sysinfo->vendor_version, vendor_version); - if (code_name) { - SIGAR_SSTRCPY(sysinfo->vendor_code_name, code_name); - } - - SIGAR_SSTRCPY(sysinfo->arch, SIGAR_ARCH); - - sprintf(sysinfo->version, "%d.%d", - version.dwMajorVersion, - version.dwMinorVersion); - - SIGAR_SSTRCPY(sysinfo->patch_level, - version.szCSDVersion); - - sprintf(sysinfo->description, "%s %s", - sysinfo->vendor, sysinfo->vendor_name); - - return SIGAR_OK; -} - -#define sigar_QueryServiceStatusEx \ - sigar->advapi.query_service_status.func - -int sigar_service_pid_get(sigar_t *sigar, char *name, sigar_pid_t *pid) -{ - DWORD rc = ERROR_SUCCESS, len; - SC_HANDLE mgr; - HANDLE svc; - SERVICE_STATUS_PROCESS status; - - if (!sigar_QueryServiceStatusEx) { - return SIGAR_ENOTIMPL; - } - - mgr = OpenSCManager(NULL, - SERVICES_ACTIVE_DATABASE, - SC_MANAGER_ALL_ACCESS); - - if (!mgr) { - return GetLastError(); - } - - if (!(svc = OpenService(mgr, name, SERVICE_ALL_ACCESS))) { - CloseServiceHandle(mgr); - return GetLastError(); - } - - if (sigar_QueryServiceStatusEx(svc, - SC_STATUS_PROCESS_INFO, - (LPBYTE)&status, - sizeof(status), &len)) - { - *pid = status.dwProcessId; - } - else { - *pid = -1; - rc = GetLastError(); - } - - CloseServiceHandle(svc); - CloseServiceHandle(mgr); - - return rc; -} - -int sigar_services_status_get(sigar_services_status_t *ss, DWORD state) -{ - DWORD bytes, resume=0; - BOOL retval; - - if (!ss->handle) { - ss->handle = - OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); - if (!ss->handle) { - return GetLastError(); - } - } - - retval = EnumServicesStatus(ss->handle, - SERVICE_WIN32, state, - ss->services, ss->size, - &bytes, &ss->count, &resume); - if (retval == FALSE) { - DWORD err = GetLastError(); - if (err != ERROR_MORE_DATA) { - return err; - } - - ss->services = realloc(ss->services, bytes); - ss->size = bytes; - - retval = EnumServicesStatus(ss->handle, - SERVICE_WIN32, state, - ss->services, ss->size, - &bytes, &ss->count, &resume); - - if (retval == FALSE) { - return GetLastError(); - } - } - - return SIGAR_OK; -} - -void sigar_services_status_close(sigar_services_status_t *ss) -{ - if (ss->handle) { - CloseServiceHandle(ss->handle); - } - if (ss->size) { - free(ss->services); - } - SIGAR_ZERO(ss); -} - -/* extract exe from QUERY_SERVICE_CONFIG.lpBinaryPathName - * leaves behind command-line arguments and quotes (if any) - */ -char *sigar_service_exe_get(char *path, char *buffer, int basename) -{ - char *ptr; - - if (path) { - strncpy(buffer, path, SIGAR_CMDLINE_MAX); - } - path = buffer; - - if (*path == '"') { - ++path; - if ((ptr = strchr(path, '"'))) { - *ptr = '\0'; - } - } - else { - ptr = sigar_strcasestr(path, ".exe"); - - if (ptr) { - *(ptr+4) = '\0'; - } - else { - if ((ptr = strchr(path, ' '))) { - *ptr = '\0'; - } - } - } - - if (basename && (ptr = strrchr(path, '\\'))) { - path = ++ptr; - } - - return path; -} - -static char *string_file_info_keys[] = { - "Comments", - "CompanyName", - "FileDescription", - "FileVersion", - "InternalName", - "LegalCopyright", - "LegalTrademarks", - "OriginalFilename", - "ProductName", - "ProductVersion", - "PrivateBuild", - "SpecialBuild", - NULL -}; - -int sigar_file_version_get(sigar_file_version_t *version, - char *name, - sigar_proc_env_t *infocb) -{ - DWORD handle, len; - LPTSTR data; - VS_FIXEDFILEINFO *info; - int status; - - if (!(len = GetFileVersionInfoSize(name, &handle))) { - return GetLastError(); - } - - if (len == 0) { - return !SIGAR_OK; - } - data = malloc(len); - - if (GetFileVersionInfo(name, handle, len, data)) { - if (VerQueryValue(data, "\\", &info, &len)) { - version->product_major = HIWORD(info->dwProductVersionMS); - version->product_minor = LOWORD(info->dwProductVersionMS); - version->product_build = HIWORD(info->dwProductVersionLS); - version->product_revision = LOWORD(info->dwProductVersionLS); - version->file_major = HIWORD(info->dwFileVersionMS); - version->file_minor = LOWORD(info->dwFileVersionMS); - version->file_build = HIWORD(info->dwFileVersionLS); - version->file_revision = LOWORD(info->dwFileVersionLS); - status = SIGAR_OK; - } - else { - status = GetLastError(); - } - } - else { - status = GetLastError(); - } - - if (infocb && (status == SIGAR_OK)) { - struct { - WORD lang; - WORD code_page; - } *trans; - - if (VerQueryValue(data, "\\VarFileInfo\\Translation", - &trans, &len)) - { - int i; - char buf[1024]; - void *ptr; - - for (i=0; string_file_info_keys[i]; i++) { - char *key = string_file_info_keys[i]; - sprintf(buf, "\\StringFileInfo\\%04x%04x\\%s", - trans[0].lang, trans[0].code_page, - key); - if (VerQueryValue(data, buf, &ptr, &len)) { - if (len == 0) { - continue; - } - infocb->env_getter(infocb->data, - key, strlen(key), - (char *)ptr, len); - } - } - } - } - - free(data); - return status; -} diff --git a/vendor/sigar/src/os/win32/wmi.cpp b/vendor/sigar/src/os/win32/wmi.cpp deleted file mode 100644 index bc1019d..0000000 --- a/vendor/sigar/src/os/win32/wmi.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define UNICODE -#define _UNICODE -#define _WIN32_DCOM - -#include -#include -#include -#include -#include "sigar.h" - -#pragma comment(lib, "wbemuuid.lib") - -#ifndef SIGAR_CMDLINE_MAX -#define SIGAR_CMDLINE_MAX 4096<<2 -#endif - -class WMI { - - public: - WMI(); - ~WMI(); - HRESULT Open(LPCTSTR machine=NULL, LPCTSTR user=NULL, LPCTSTR pass=NULL); - void Close(); - HRESULT GetProcStringProperty(DWORD pid, TCHAR *name, TCHAR *value, DWORD len); - HRESULT GetProcExecutablePath(DWORD pid, TCHAR *value); - HRESULT GetProcCommandLine(DWORD pid, TCHAR *value); - int GetLastError(); - - private: - IWbemServices *wbem; - HRESULT result; - BSTR GetProcQuery(DWORD pid); -}; - -WMI::WMI() -{ - wbem = NULL; - result = S_OK; - CoInitializeEx(NULL, COINIT_MULTITHREADED); -} - -WMI::~WMI() -{ - Close(); - CoUninitialize(); -} - -/* XXX must be a better way to map HRESULT */ -int WMI::GetLastError() -{ - switch (result) { - case S_OK: - return ERROR_SUCCESS; - case WBEM_E_NOT_FOUND: - return ERROR_NOT_FOUND; - case WBEM_E_ACCESS_DENIED: - return ERROR_ACCESS_DENIED; - case WBEM_E_NOT_SUPPORTED: - return SIGAR_ENOTIMPL; - default: - return ERROR_INVALID_FUNCTION; - } -} - -HRESULT WMI::Open(LPCTSTR machine, LPCTSTR user, LPCTSTR pass) -{ - IWbemLocator *locator; - wchar_t path[MAX_PATH]; - - if (wbem) { - result = S_OK; - return result; - } - - result = - CoInitializeSecurity(NULL, //Security Descriptor - -1, //COM authentication - NULL, //Authentication services - NULL, //Reserved - RPC_C_AUTHN_LEVEL_DEFAULT, //Default authentication - RPC_C_IMP_LEVEL_IMPERSONATE, //Default Impersonation - NULL, //Authentication info - EOAC_NONE, //Additional capabilities - NULL); //Reserved - - result = CoCreateInstance(CLSID_WbemLocator, - NULL, /* IUnknown */ - CLSCTX_INPROC_SERVER, - IID_IWbemLocator, - (LPVOID *)&locator); - - if (FAILED(result)) { - return result; - } - - if (machine == NULL) { - machine = L"."; - } - - wsprintf(path, L"\\\\%S\\ROOT\\CIMV2", machine); - - result = locator->ConnectServer(bstr_t(path), //Object path of WMI namespace - bstr_t(user), //User name. NULL = current user - bstr_t(pass), //User password. NULL = current - NULL, //Locale. NULL indicates current - 0, //Security flags - NULL, //Authority (e.g. Kerberos) - NULL, //Context object - &wbem); //pointer to IWbemServices proxy - - locator->Release(); - - return result; -} - -void WMI::Close() -{ - if (wbem) { - wbem->Release(); - wbem = NULL; - result = S_OK; - } -} - -BSTR WMI::GetProcQuery(DWORD pid) -{ - wchar_t query[56]; - wsprintf(query, L"Win32_Process.Handle=%d", pid); - return bstr_t(query); -} - -HRESULT WMI::GetProcStringProperty(DWORD pid, TCHAR *name, TCHAR *value, DWORD len) -{ - IWbemClassObject *obj; - VARIANT var; - - result = wbem->GetObject(GetProcQuery(pid), 0, 0, &obj, 0); - - if (FAILED(result)) { - return result; - } - - result = obj->Get(name, 0, &var, 0, 0); - - if (SUCCEEDED(result)) { - if (var.vt == VT_NULL) { - result = E_INVALIDARG; - } - else { - lstrcpyn(value, var.bstrVal, len); - } - VariantClear(&var); - } - - obj->Release(); - - return result; -} - -HRESULT WMI::GetProcExecutablePath(DWORD pid, TCHAR *value) -{ - return GetProcStringProperty(pid, L"ExecutablePath", value, MAX_PATH); -} - -HRESULT WMI::GetProcCommandLine(DWORD pid, TCHAR *value) -{ - return GetProcStringProperty(pid, L"CommandLine", value, SIGAR_CMDLINE_MAX); -} - -/* in peb.c */ -extern "C" int sigar_parse_proc_args(sigar_t *sigar, WCHAR *buf, - sigar_proc_args_t *procargs); - -extern "C" int sigar_proc_args_wmi_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - int status; - TCHAR buf[SIGAR_CMDLINE_MAX]; - WMI *wmi = new WMI(); - - if (FAILED(wmi->Open())) { - return wmi->GetLastError(); - } - - if (FAILED(wmi->GetProcCommandLine(pid, buf))) { - status = wmi->GetLastError(); - } - else { - status = sigar_parse_proc_args(sigar, buf, procargs); - } - - wmi->Close(); - delete wmi; - - return status; -} - -extern "C" int sigar_proc_exe_wmi_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_exe_t *procexe) -{ - int status; - TCHAR buf[MAX_PATH+1]; - WMI *wmi = new WMI(); - - if (FAILED(wmi->Open())) { - return wmi->GetLastError(); - } - - procexe->name[0] = '\0'; - - if (FAILED(wmi->GetProcExecutablePath(pid, buf))) { - status = wmi->GetLastError(); - } - else { - status = SIGAR_OK; - /* SIGAR_W2A(buf, procexe->name, sizeof(procexe->name)); */ - WideCharToMultiByte(CP_ACP, 0, buf, -1, - (LPSTR)procexe->name, sizeof(procexe->name), - NULL, NULL); - } - - wmi->Close(); - delete wmi; - - return status; -} diff --git a/vendor/sigar/src/sigar.c b/vendor/sigar/src/sigar.c deleted file mode 100644 index 8bd7e91..0000000 --- a/vendor/sigar/src/sigar.c +++ /dev/null @@ -1,2428 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2009-2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#ifndef WIN32 -#include -#include -#include -#endif -#if defined(__OpenBSD__) || defined(__FreeBSD__) -#include -#endif -#ifndef WIN32 -#include -#endif - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" -#include "sigar_format.h" - -SIGAR_DECLARE(int) sigar_open(sigar_t **sigar) -{ - int status = sigar_os_open(sigar); - - if (status == SIGAR_OK) { - /* use env to revert to old behavior */ - (*sigar)->cpu_list_cores = getenv("SIGAR_CPU_LIST_SOCKETS") ? 0 : 1; - (*sigar)->pid = 0; - (*sigar)->ifconf_buf = NULL; - (*sigar)->ifconf_len = 0; - (*sigar)->log_level = -1; /* log nothing by default */ - (*sigar)->log_impl = NULL; - (*sigar)->log_data = NULL; - (*sigar)->ptql_re_impl = NULL; - (*sigar)->ptql_re_data = NULL; - (*sigar)->self_path = NULL; - (*sigar)->fsdev = NULL; - (*sigar)->pids = NULL; - (*sigar)->proc_cpu = NULL; - (*sigar)->net_listen = NULL; - (*sigar)->net_services_tcp = NULL; - (*sigar)->net_services_udp = NULL; - } - - return status; -} - -SIGAR_DECLARE(int) sigar_close(sigar_t *sigar) -{ - if (sigar->ifconf_buf) { - free(sigar->ifconf_buf); - } - if (sigar->self_path) { - free(sigar->self_path); - } - if (sigar->pids) { - sigar_proc_list_destroy(sigar, sigar->pids); - free(sigar->pids); - } - if (sigar->fsdev) { - sigar_cache_destroy(sigar->fsdev); - } - if (sigar->proc_cpu) { - sigar_cache_destroy(sigar->proc_cpu); - } - if (sigar->net_listen) { - sigar_cache_destroy(sigar->net_listen); - } - if (sigar->net_services_tcp) { - sigar_cache_destroy(sigar->net_services_tcp); - } - if (sigar->net_services_udp) { - sigar_cache_destroy(sigar->net_services_udp); - } - - return sigar_os_close(sigar); -} - -#ifndef __linux__ /* linux has a special case */ -SIGAR_DECLARE(sigar_pid_t) sigar_pid_get(sigar_t *sigar) -{ - if (!sigar->pid) { - sigar->pid = getpid(); - } - - return sigar->pid; -} -#endif - -/* XXX: add clear() function */ -/* XXX: check for stale-ness using start_time */ -SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cpu_t *proccpu) -{ - sigar_cache_entry_t *entry; - sigar_proc_cpu_t *prev; - sigar_uint64_t otime, time_now = sigar_time_now_millis(); - sigar_uint64_t time_diff, total_diff; - int status; - - if (!sigar->proc_cpu) { - sigar->proc_cpu = sigar_cache_new(128); - } - - entry = sigar_cache_get(sigar->proc_cpu, pid); - if (entry->value) { - prev = (sigar_proc_cpu_t *)entry->value; - } - else { - prev = entry->value = malloc(sizeof(*prev)); - SIGAR_ZERO(prev); - } - - time_diff = time_now - prev->last_time; - proccpu->last_time = prev->last_time = time_now; - - if (time_diff == 0) { - /* we were just called within < 1 second ago. */ - memcpy(proccpu, prev, sizeof(*proccpu)); - return SIGAR_OK; - } - - otime = prev->total; - - status = - sigar_proc_time_get(sigar, pid, - (sigar_proc_time_t *)proccpu); - - if (status != SIGAR_OK) { - return status; - } - - memcpy(prev, proccpu, sizeof(*prev)); - - if (proccpu->total < otime) { - /* XXX this should not happen */ - otime = 0; - } - - if (otime == 0) { - proccpu->percent = 0.0; - /* first time called */ - return SIGAR_OK; - } - - total_diff = proccpu->total - otime; - proccpu->percent = total_diff / (double)time_diff; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_stat_get(sigar_t *sigar, - sigar_proc_stat_t *procstat) -{ - int status, i; - sigar_proc_list_t *pids; - - SIGAR_ZERO(procstat); - procstat->threads = SIGAR_FIELD_NOTIMPL; - - if ((status = sigar_proc_list_get(sigar, NULL)) != SIGAR_OK) { - return status; - } - - pids = sigar->pids; - procstat->total = pids->number; - - for (i=0; inumber; i++) { - sigar_proc_state_t state; - - status = sigar_proc_state_get(sigar, pids->data[i], &state); - if (status != SIGAR_OK) { - continue; - } - - if (state.threads != SIGAR_FIELD_NOTIMPL) { - procstat->threads += state.threads; - } - - switch (state.state) { - case SIGAR_PROC_STATE_IDLE: - procstat->idle++; - break; - case SIGAR_PROC_STATE_RUN: - procstat->running++; - break; - case SIGAR_PROC_STATE_SLEEP: - procstat->sleeping++; - break; - case SIGAR_PROC_STATE_STOP: - procstat->stopped++; - break; - case SIGAR_PROC_STATE_ZOMBIE: - procstat->zombie++; - break; - default: - break; - } - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_sys_info_get(sigar_t *sigar, - sigar_sys_info_t *sysinfo) -{ - SIGAR_ZERO(sysinfo); - -#ifndef WIN32 - sigar_sys_info_get_uname(sysinfo); -#endif - - sigar_os_sys_info_get(sigar, sysinfo); - - return SIGAR_OK; -} - -#ifndef WIN32 - -#include - -int sigar_sys_info_get_uname(sigar_sys_info_t *sysinfo) -{ - struct utsname name; - - uname(&name); - - SIGAR_SSTRCPY(sysinfo->version, name.release); - SIGAR_SSTRCPY(sysinfo->vendor_name, name.sysname); - SIGAR_SSTRCPY(sysinfo->name, name.sysname); - SIGAR_SSTRCPY(sysinfo->machine, name.machine); - SIGAR_SSTRCPY(sysinfo->arch, name.machine); - SIGAR_SSTRCPY(sysinfo->patch_level, "unknown"); - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_proc_cred_name_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_cred_name_t *proccredname) -{ - sigar_proc_cred_t cred; - - int status = sigar_proc_cred_get(sigar, pid, &cred); - - if (status != SIGAR_OK) { - return status; - } - - status = sigar_user_name_get(sigar, cred.uid, - proccredname->user, - sizeof(proccredname->user)); - - if (status != SIGAR_OK) { - return status; - } - - status = sigar_group_name_get(sigar, cred.gid, - proccredname->group, - sizeof(proccredname->group)); - - return status; -} - -#endif /* WIN32 */ - -int sigar_proc_list_create(sigar_proc_list_t *proclist) -{ - proclist->number = 0; - proclist->size = SIGAR_PROC_LIST_MAX; - proclist->data = malloc(sizeof(*(proclist->data)) * - proclist->size); - return SIGAR_OK; -} - -int sigar_proc_list_grow(sigar_proc_list_t *proclist) -{ - proclist->data = realloc(proclist->data, - sizeof(*(proclist->data)) * - (proclist->size + SIGAR_PROC_LIST_MAX)); - proclist->size += SIGAR_PROC_LIST_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_list_destroy(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - if (proclist->size) { - free(proclist->data); - proclist->number = proclist->size = 0; - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - if (proclist == NULL) { - /* internal re-use */ - if (sigar->pids == NULL) { - sigar->pids = malloc(sizeof(*sigar->pids)); - sigar_proc_list_create(sigar->pids); - } - else { - sigar->pids->number = 0; - } - proclist = sigar->pids; - } - else { - sigar_proc_list_create(proclist); - } - - return sigar_os_proc_list_get(sigar, proclist); -} - -int sigar_proc_args_create(sigar_proc_args_t *procargs) -{ - procargs->number = 0; - procargs->size = SIGAR_PROC_ARGS_MAX; - procargs->data = malloc(sizeof(*(procargs->data)) * - procargs->size); - return SIGAR_OK; -} - -int sigar_proc_args_grow(sigar_proc_args_t *procargs) -{ - procargs->data = realloc(procargs->data, - sizeof(*(procargs->data)) * - (procargs->size + SIGAR_PROC_ARGS_MAX)); - procargs->size += SIGAR_PROC_ARGS_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_args_destroy(sigar_t *sigar, - sigar_proc_args_t *procargs) -{ - unsigned int i; - - if (procargs->size) { - for (i=0; inumber; i++) { - free(procargs->data[i]); - } - free(procargs->data); - procargs->number = procargs->size = 0; - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_proc_args_get(sigar_t *sigar, - sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - int status; - sigar_proc_args_create(procargs); - status = sigar_os_proc_args_get(sigar, pid, procargs); - if (status != SIGAR_OK) { - sigar_proc_args_destroy(sigar, procargs); - } - return status; -} - -int sigar_file_system_list_create(sigar_file_system_list_t *fslist) -{ - fslist->number = 0; - fslist->size = SIGAR_FS_MAX; - fslist->data = malloc(sizeof(*(fslist->data)) * - fslist->size); - return SIGAR_OK; -} - -int sigar_file_system_list_grow(sigar_file_system_list_t *fslist) -{ - fslist->data = realloc(fslist->data, - sizeof(*(fslist->data)) * - (fslist->size + SIGAR_FS_MAX)); - fslist->size += SIGAR_FS_MAX; - - return SIGAR_OK; -} - -/* indexed with sigar_file_system_type_e */ -static const char *fstype_names[] = { - "unknown", "none", "local", "remote", "ram", "cdrom", "swap" -}; - -static int sigar_common_fs_type_get(sigar_file_system_t *fsp) -{ - char *type = fsp->sys_type_name; - - switch (*type) { - case 'n': - if (strnEQ(type, "nfs", 3)) { - fsp->type = SIGAR_FSTYPE_NETWORK; - } - break; - case 's': - if (strEQ(type, "smbfs")) { /* samba */ - fsp->type = SIGAR_FSTYPE_NETWORK; - } - else if (strEQ(type, "swap")) { - fsp->type = SIGAR_FSTYPE_SWAP; - } - break; - case 'a': - if (strEQ(type, "afs")) { - fsp->type = SIGAR_FSTYPE_NETWORK; - } - break; - case 'i': - if (strEQ(type, "iso9660")) { - fsp->type = SIGAR_FSTYPE_CDROM; - } - break; - case 'c': - if (strEQ(type, "cvfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - else if (strEQ(type, "cifs")) { - fsp->type = SIGAR_FSTYPE_NETWORK; - } - break; - case 'm': - if (strEQ(type, "msdos") || strEQ(type, "minix")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'h': - if (strEQ(type, "hpfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'v': - if (strEQ(type, "vxfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - else if (strEQ(type, "vfat")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - case 'z': - if (strEQ(type, "zfs")) { - fsp->type = SIGAR_FSTYPE_LOCAL_DISK; - } - break; - } - - return fsp->type; -} - -void sigar_fs_type_get(sigar_file_system_t *fsp) -{ - if (!(fsp->type || /* already set */ - sigar_os_fs_type_get(fsp) || /* try os specifics first */ - sigar_common_fs_type_get(fsp))) /* try common ones last */ - { - fsp->type = SIGAR_FSTYPE_NONE; - } - - if (fsp->type >= SIGAR_FSTYPE_MAX) { - fsp->type = SIGAR_FSTYPE_NONE; - } - - strcpy(fsp->type_name, fstype_names[fsp->type]); -} - - -SIGAR_DECLARE(int) -sigar_file_system_list_destroy(sigar_t *sigar, - sigar_file_system_list_t *fslist) -{ - if (fslist->size) { - free(fslist->data); - fslist->number = fslist->size = 0; - } - - return SIGAR_OK; -} - -#ifndef NFS_PROGRAM -#define NFS_PROGRAM 100003 -#endif - -#ifndef NFS_VERSION -#define NFS_VERSION 2 -#endif - -SIGAR_DECLARE(int) -sigar_file_system_ping(sigar_t *sigar, - sigar_file_system_t *fs) -{ - int status = SIGAR_OK; -#ifndef WIN32 - char *ptr; - - if ((fs->type == SIGAR_FSTYPE_NETWORK) && - strEQ(fs->sys_type_name, "nfs") && - (ptr = strchr(fs->dev_name, ':'))) - { - *ptr = '\0'; /* "hostname:/mount" -> "hostname" */ - - status = sigar_rpc_ping(fs->dev_name, - SIGAR_NETCONN_UDP, - NFS_PROGRAM, NFS_VERSION); - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fs_ping] %s -> %s: %s", - fs->dir_name, fs->dev_name, - ((status == SIGAR_OK) ? - "OK" : sigar_rpc_strerror(status))); - } - - *ptr = ':'; /* "hostname" -> "hostname:/mount" */ - } -#endif - return status; -} - -int sigar_cpu_info_list_create(sigar_cpu_info_list_t *cpu_infos) -{ - cpu_infos->number = 0; - cpu_infos->size = SIGAR_CPU_INFO_MAX; - cpu_infos->data = malloc(sizeof(*(cpu_infos->data)) * - cpu_infos->size); - return SIGAR_OK; -} - -int sigar_cpu_info_list_grow(sigar_cpu_info_list_t *cpu_infos) -{ - cpu_infos->data = realloc(cpu_infos->data, - sizeof(*(cpu_infos->data)) * - (cpu_infos->size + SIGAR_CPU_INFO_MAX)); - cpu_infos->size += SIGAR_CPU_INFO_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_cpu_info_list_destroy(sigar_t *sigar, - sigar_cpu_info_list_t *cpu_infos) -{ - if (cpu_infos->size) { - free(cpu_infos->data); - cpu_infos->number = cpu_infos->size = 0; - } - - return SIGAR_OK; -} - -int sigar_cpu_list_create(sigar_cpu_list_t *cpulist) -{ - cpulist->number = 0; - cpulist->size = SIGAR_CPU_INFO_MAX; - cpulist->data = malloc(sizeof(*(cpulist->data)) * - cpulist->size); - return SIGAR_OK; -} - -int sigar_cpu_list_grow(sigar_cpu_list_t *cpulist) -{ - cpulist->data = realloc(cpulist->data, - sizeof(*(cpulist->data)) * - (cpulist->size + SIGAR_CPU_INFO_MAX)); - cpulist->size += SIGAR_CPU_INFO_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_cpu_list_destroy(sigar_t *sigar, - sigar_cpu_list_t *cpulist) -{ - if (cpulist->size) { - free(cpulist->data); - cpulist->number = cpulist->size = 0; - } - - return SIGAR_OK; -} - -int sigar_net_route_list_create(sigar_net_route_list_t *routelist) -{ - routelist->number = 0; - routelist->size = SIGAR_NET_ROUTE_LIST_MAX; - routelist->data = malloc(sizeof(*(routelist->data)) * - routelist->size); - return SIGAR_OK; -} - -int sigar_net_route_list_grow(sigar_net_route_list_t *routelist) -{ - routelist->data = - realloc(routelist->data, - sizeof(*(routelist->data)) * - (routelist->size + SIGAR_NET_ROUTE_LIST_MAX)); - routelist->size += SIGAR_NET_ROUTE_LIST_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_net_route_list_destroy(sigar_t *sigar, - sigar_net_route_list_t *routelist) -{ - if (routelist->size) { - free(routelist->data); - routelist->number = routelist->size = 0; - } - - return SIGAR_OK; -} - -int sigar_net_interface_list_create(sigar_net_interface_list_t *iflist) -{ - iflist->number = 0; - iflist->size = SIGAR_NET_IFLIST_MAX; - iflist->data = malloc(sizeof(*(iflist->data)) * - iflist->size); - return SIGAR_OK; -} - -int sigar_net_interface_list_grow(sigar_net_interface_list_t *iflist) -{ - iflist->data = realloc(iflist->data, - sizeof(*(iflist->data)) * - (iflist->size + SIGAR_NET_IFLIST_MAX)); - iflist->size += SIGAR_NET_IFLIST_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_net_interface_list_destroy(sigar_t *sigar, - sigar_net_interface_list_t *iflist) -{ - unsigned int i; - - if (iflist->size) { - for (i=0; inumber; i++) { - free(iflist->data[i]); - } - free(iflist->data); - iflist->number = iflist->size = 0; - } - - return SIGAR_OK; -} - -int sigar_net_connection_list_create(sigar_net_connection_list_t *connlist) -{ - connlist->number = 0; - connlist->size = SIGAR_NET_CONNLIST_MAX; - connlist->data = malloc(sizeof(*(connlist->data)) * - connlist->size); - return SIGAR_OK; -} - -int sigar_net_connection_list_grow(sigar_net_connection_list_t *connlist) -{ - connlist->data = - realloc(connlist->data, - sizeof(*(connlist->data)) * - (connlist->size + SIGAR_NET_CONNLIST_MAX)); - connlist->size += SIGAR_NET_CONNLIST_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_net_connection_list_destroy(sigar_t *sigar, - sigar_net_connection_list_t *connlist) -{ - if (connlist->size) { - free(connlist->data); - connlist->number = connlist->size = 0; - } - - return SIGAR_OK; -} - -#if !defined(__linux__) -/* - * implement sigar_net_connection_list_get using sigar_net_connection_walk - * linux has its own list_get impl. - */ -static int net_connection_list_walker(sigar_net_connection_walker_t *walker, - sigar_net_connection_t *conn) -{ - sigar_net_connection_list_t *connlist = - (sigar_net_connection_list_t *)walker->data; - - SIGAR_NET_CONNLIST_GROW(connlist); - memcpy(&connlist->data[connlist->number++], - conn, sizeof(*conn)); - - return SIGAR_OK; /* continue loop */ -} - -SIGAR_DECLARE(int) -sigar_net_connection_list_get(sigar_t *sigar, - sigar_net_connection_list_t *connlist, - int flags) -{ - int status; - sigar_net_connection_walker_t walker; - - sigar_net_connection_list_create(connlist); - - walker.sigar = sigar; - walker.flags = flags; - walker.data = connlist; - walker.add_connection = net_connection_list_walker; - - status = sigar_net_connection_walk(&walker); - - if (status != SIGAR_OK) { - sigar_net_connection_list_destroy(sigar, connlist); - } - - return status; -} -#endif - -static void sigar_net_listen_address_add(sigar_t *sigar, - sigar_net_connection_t *conn) -{ - sigar_cache_entry_t *entry = - sigar_cache_get(sigar->net_listen, conn->local_port); - - if (entry->value) { - if (conn->local_address.family == SIGAR_AF_INET6) { - return; /* prefer ipv4 */ - } - } - else { - entry->value = malloc(sizeof(conn->local_address)); - } - - memcpy(entry->value, &conn->local_address, - sizeof(conn->local_address)); -} - -SIGAR_DECLARE(int) -sigar_net_listen_address_get(sigar_t *sigar, - unsigned long port, - sigar_net_address_t *address) -{ - if (!sigar->net_listen || - !sigar_cache_find(sigar->net_listen, port)) - { - sigar_net_stat_t netstat; - int status = - sigar_net_stat_get(sigar, &netstat, - SIGAR_NETCONN_SERVER|SIGAR_NETCONN_TCP); - - if (status != SIGAR_OK) { - return status; - } - } - - if (sigar_cache_find(sigar->net_listen, port)) { - void *value = sigar_cache_get(sigar->net_listen, port)->value; - memcpy(address, value, sizeof(*address)); - return SIGAR_OK; - } - else { - return ENOENT; - } -} - -typedef struct { - sigar_net_stat_t *netstat; - sigar_net_connection_list_t *connlist; -} net_stat_getter_t; - -static int net_stat_walker(sigar_net_connection_walker_t *walker, - sigar_net_connection_t *conn) -{ - int state = conn->state; - sigar_cache_t *listen_ports = walker->sigar->net_listen; - net_stat_getter_t *getter = - (net_stat_getter_t *)walker->data; - - if (conn->type == SIGAR_NETCONN_TCP) { - getter->netstat->tcp_states[state]++; - - /* XXX listen_ports may get stale */ - if (state == SIGAR_TCP_LISTEN) { - sigar_net_listen_address_add(walker->sigar, conn); - } - else { - if (sigar_cache_find(listen_ports, - conn->local_port)) - { - getter->netstat->tcp_inbound_total++; - } - else { - getter->netstat->tcp_outbound_total++; - } - } - } - else if (conn->type == SIGAR_NETCONN_UDP) { - /*XXX*/ - } - - getter->netstat->all_inbound_total = - getter->netstat->tcp_inbound_total; - - getter->netstat->all_outbound_total = - getter->netstat->tcp_outbound_total; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_net_stat_get(sigar_t *sigar, - sigar_net_stat_t *netstat, - int flags) -{ - sigar_net_connection_walker_t walker; - net_stat_getter_t getter; - - if (!sigar->net_listen) { - sigar->net_listen = sigar_cache_new(32); - } - - SIGAR_ZERO(netstat); - - getter.netstat = netstat; - - walker.sigar = sigar; - walker.data = &getter; - walker.add_connection = net_stat_walker; - - walker.flags = flags; - - return sigar_net_connection_walk(&walker); -} - -typedef struct { - sigar_net_stat_t *netstat; - sigar_net_address_t *address; - unsigned long port; -} net_stat_port_getter_t; - -static int net_stat_port_walker(sigar_net_connection_walker_t *walker, - sigar_net_connection_t *conn) -{ - net_stat_port_getter_t *getter = - (net_stat_port_getter_t *)walker->data; - sigar_net_stat_t *netstat = getter->netstat; - - if (conn->type == SIGAR_NETCONN_TCP) { - if (conn->local_port == getter->port) { - netstat->all_inbound_total++; - - if (sigar_net_address_equals(getter->address, - &conn->local_address) == SIGAR_OK) - { - netstat->tcp_inbound_total++; - } - } - else if (conn->remote_port == getter->port) { - netstat->all_outbound_total++; - - if (sigar_net_address_equals(getter->address, - &conn->remote_address) == SIGAR_OK) - { - netstat->tcp_outbound_total++; - } - } - else { - return SIGAR_OK; - } - - netstat->tcp_states[conn->state]++; - } - else if (conn->type == SIGAR_NETCONN_UDP) { - /*XXX*/ - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) -sigar_net_stat_port_get(sigar_t *sigar, - sigar_net_stat_t *netstat, - int flags, - sigar_net_address_t *address, - unsigned long port) -{ - sigar_net_connection_walker_t walker; - net_stat_port_getter_t getter; - - SIGAR_ZERO(netstat); - - getter.netstat = netstat; - getter.address = address; - getter.port = port; - - walker.sigar = sigar; - walker.data = &getter; - walker.add_connection = net_stat_port_walker; - - walker.flags = flags; - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - char name[SIGAR_FQDN_LEN]; - sigar_net_address_to_string(sigar, address, name); - - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[net_stat_port] using address '%s:%d'", - name, port); - } - - return sigar_net_connection_walk(&walker); -} - -static int tcp_curr_estab_count(sigar_net_connection_walker_t *walker, - sigar_net_connection_t *conn) -{ - if ((conn->state == SIGAR_TCP_ESTABLISHED) || - (conn->state == SIGAR_TCP_CLOSE_WAIT)) - { - ((sigar_tcp_t *)walker->data)->curr_estab++; - } - - return SIGAR_OK; -} - -/* TCP-MIB::tcpCurrEstab */ -int sigar_tcp_curr_estab(sigar_t *sigar, sigar_tcp_t *tcp) -{ - sigar_net_connection_walker_t walker; - - walker.sigar = sigar; - walker.data = tcp; - walker.add_connection = tcp_curr_estab_count; - walker.flags = SIGAR_NETCONN_CLIENT|SIGAR_NETCONN_TCP; - - tcp->curr_estab = 0; - - return sigar_net_connection_walk(&walker); -} - -int sigar_arp_list_create(sigar_arp_list_t *arplist) -{ - arplist->number = 0; - arplist->size = SIGAR_ARP_LIST_MAX; - arplist->data = malloc(sizeof(*(arplist->data)) * - arplist->size); - return SIGAR_OK; -} - -int sigar_arp_list_grow(sigar_arp_list_t *arplist) -{ - arplist->data = realloc(arplist->data, - sizeof(*(arplist->data)) * - (arplist->size + SIGAR_ARP_LIST_MAX)); - arplist->size += SIGAR_ARP_LIST_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_arp_list_destroy(sigar_t *sigar, - sigar_arp_list_t *arplist) -{ - if (arplist->size) { - free(arplist->data); - arplist->number = arplist->size = 0; - } - - return SIGAR_OK; -} - -int sigar_who_list_create(sigar_who_list_t *wholist) -{ - wholist->number = 0; - wholist->size = SIGAR_WHO_LIST_MAX; - wholist->data = malloc(sizeof(*(wholist->data)) * - wholist->size); - return SIGAR_OK; -} - -int sigar_who_list_grow(sigar_who_list_t *wholist) -{ - wholist->data = realloc(wholist->data, - sizeof(*(wholist->data)) * - (wholist->size + SIGAR_WHO_LIST_MAX)); - wholist->size += SIGAR_WHO_LIST_MAX; - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_who_list_destroy(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - if (wholist->size) { - free(wholist->data); - wholist->number = wholist->size = 0; - } - - return SIGAR_OK; -} - -#ifdef DARWIN -#include -#endif -#ifdef MAC_OS_X_VERSION_10_5 -# if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 -# define SIGAR_NO_UTMP -# endif -/* else 10.4 and earlier or compiled with -mmacosx-version-min=10.3 */ -#endif - -#if defined(__sun) -# include -# define SIGAR_UTMP_FILE _UTMPX_FILE -# define ut_time ut_tv.tv_sec -#elif defined(WIN32) -/* XXX may not be the default */ -#define SIGAR_UTMP_FILE "C:\\cygwin\\var\\run\\utmp" -#define UT_LINESIZE 16 -#define UT_NAMESIZE 16 -#define UT_HOSTSIZE 256 -#define UT_IDLEN 2 -#define ut_name ut_user - -struct utmp { - short ut_type; - int ut_pid; - char ut_line[UT_LINESIZE]; - char ut_id[UT_IDLEN]; - time_t ut_time; - char ut_user[UT_NAMESIZE]; - char ut_host[UT_HOSTSIZE]; - long ut_addr; -}; -#elif defined(NETWARE) -static char *getpass(const char *prompt) -{ - static char password[BUFSIZ]; - - fputs(prompt, stderr); - fgets((char *)&password, sizeof(password), stdin); - - return (char *)&password; -} -#elif !defined(SIGAR_NO_UTMP) -# include -# ifdef UTMP_FILE -# define SIGAR_UTMP_FILE UTMP_FILE -# else -# define SIGAR_UTMP_FILE _PATH_UTMP -# endif -#endif - -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(DARWIN) -# define ut_user ut_name -#endif - -#ifdef DARWIN -/* XXX from utmpx.h; sizeof changed in 10.5 */ -/* additionally, utmpx does not work on 10.4 */ -#define SIGAR_HAS_UTMPX -#define _PATH_UTMPX "/var/run/utmpx" -#define _UTX_USERSIZE 256 /* matches MAXLOGNAME */ -#define _UTX_LINESIZE 32 -#define _UTX_IDSIZE 4 -#define _UTX_HOSTSIZE 256 -struct utmpx { - char ut_user[_UTX_USERSIZE]; /* login name */ - char ut_id[_UTX_IDSIZE]; /* id */ - char ut_line[_UTX_LINESIZE]; /* tty name */ - pid_t ut_pid; /* process id creating the entry */ - short ut_type; /* type of this entry */ - struct timeval ut_tv; /* time entry was created */ - char ut_host[_UTX_HOSTSIZE]; /* host name */ - __uint32_t ut_pad[16]; /* reserved for future use */ -}; -#define ut_xtime ut_tv.tv_sec -#define UTMPX_USER_PROCESS 7 -/* end utmpx.h */ -#define SIGAR_UTMPX_FILE _PATH_UTMPX -#endif - -#if !defined(NETWARE) && !defined(_AIX) - -#define WHOCPY(dest, src) \ - SIGAR_SSTRCPY(dest, src); \ - if (sizeof(src) < sizeof(dest)) \ - dest[sizeof(src)] = '\0' - -#ifdef SIGAR_HAS_UTMPX -static int sigar_who_utmpx(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - FILE *fp; - struct utmpx ut; - - if (!(fp = fopen(SIGAR_UTMPX_FILE, "r"))) { - return errno; - } - - while (fread(&ut, sizeof(ut), 1, fp) == 1) { - sigar_who_t *who; - - if (*ut.ut_user == '\0') { - continue; - } - -#ifdef UTMPX_USER_PROCESS - if (ut.ut_type != UTMPX_USER_PROCESS) { - continue; - } -#endif - - SIGAR_WHO_LIST_GROW(wholist); - who = &wholist->data[wholist->number++]; - - WHOCPY(who->user, ut.ut_user); - WHOCPY(who->device, ut.ut_line); - WHOCPY(who->host, ut.ut_host); - - who->time = ut.ut_xtime; - } - - fclose(fp); - - return SIGAR_OK; -} -#endif - -#if defined(SIGAR_NO_UTMP) && defined(SIGAR_HAS_UTMPX) -#define sigar_who_utmp sigar_who_utmpx -#else -static int sigar_who_utmp(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - FILE *fp; -#ifdef __sun - /* use futmpx w/ pid32_t for sparc64 */ - struct futmpx ut; -#else - struct utmp ut; -#endif - if (!(fp = fopen(SIGAR_UTMP_FILE, "r"))) { -#ifdef SIGAR_HAS_UTMPX - /* Darwin 10.5 */ - return sigar_who_utmpx(sigar, wholist); -#endif - return errno; - } - - while (fread(&ut, sizeof(ut), 1, fp) == 1) { - sigar_who_t *who; - - if (*ut.ut_name == '\0') { - continue; - } - -#ifdef USER_PROCESS - if (ut.ut_type != USER_PROCESS) { - continue; - } -#endif - - SIGAR_WHO_LIST_GROW(wholist); - who = &wholist->data[wholist->number++]; - - WHOCPY(who->user, ut.ut_user); - WHOCPY(who->device, ut.ut_line); - WHOCPY(who->host, ut.ut_host); - - who->time = ut.ut_time; - } - - fclose(fp); - - return SIGAR_OK; -} -#endif /* SIGAR_NO_UTMP */ -#endif /* NETWARE */ - -#if defined(WIN32) - -int sigar_who_list_get_win32(sigar_t *sigar, - sigar_who_list_t *wholist); - -SIGAR_DECLARE(int) sigar_who_list_get(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - sigar_who_list_create(wholist); - - /* cygwin ssh */ - sigar_who_utmp(sigar, wholist); - - sigar_who_list_get_win32(sigar, wholist); - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_resource_limit_get(sigar_t *sigar, - sigar_resource_limit_t *rlimit) -{ - MEMORY_BASIC_INFORMATION meminfo; - memset(rlimit, 0x7fffffff, sizeof(*rlimit)); - - if (VirtualQuery((LPCVOID)&meminfo, &meminfo, sizeof(meminfo))) { - rlimit->stack_cur = - (DWORD)&meminfo - (DWORD)meminfo.AllocationBase; - rlimit->stack_max = - ((DWORD)meminfo.BaseAddress + meminfo.RegionSize) - - (DWORD)meminfo.AllocationBase; - } - - rlimit->virtual_memory_max = rlimit->virtual_memory_cur = - 0x80000000UL; - - return SIGAR_OK; -} - -#elif defined(NETWARE) -int sigar_resource_limit_get(sigar_t *sigar, - sigar_resource_limit_t *rlimit) -{ - return SIGAR_ENOTIMPL; -} - -int sigar_who_list_get(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - return SIGAR_ENOTIMPL; -} -#else - -#ifndef _AIX -int sigar_who_list_get(sigar_t *sigar, - sigar_who_list_t *wholist) -{ - int status; - - sigar_who_list_create(wholist); - - status = sigar_who_utmp(sigar, wholist); - if (status != SIGAR_OK) { - sigar_who_list_destroy(sigar, wholist); - return status; - } - - return SIGAR_OK; -} -#endif - -static int sigar_get_default_gateway(sigar_t *sigar, - sigar_net_info_t *netinfo) -{ - int status, i; - sigar_net_route_list_t routelist; - - status = sigar_net_route_list_get(sigar, &routelist); - if (status != SIGAR_OK) { - return status; - } - - for (i=0; idefault_gateway); - - SIGAR_STRNCPY(netinfo->default_gateway_interface, - routelist.data[i].ifname, - sizeof(netinfo->default_gateway_interface)); - break; - } - } - - sigar_net_route_list_destroy(sigar, &routelist); - - return SIGAR_OK; -} - -int sigar_net_info_get(sigar_t *sigar, - sigar_net_info_t *netinfo) -{ - int size; - char buffer[BUFSIZ], *ptr; - FILE *fp; - - SIGAR_ZERO(netinfo); - - if ((fp = fopen("/etc/resolv.conf", "r"))) { - while ((ptr = fgets(buffer, sizeof(buffer), fp))) { - int len; - - SIGAR_SKIP_SPACE(ptr); - if ((*ptr == '#') || - !(ptr = strstr(ptr, "nameserver"))) - { - continue; - } - ptr += 10; - SIGAR_SKIP_SPACE(ptr); - - len = strlen(ptr); - ptr[len-1] = '\0'; /* chop \n */ - - if (!netinfo->primary_dns[0]) { - SIGAR_SSTRCPY(netinfo->primary_dns, ptr); - } - else if (!netinfo->secondary_dns[0]) { - SIGAR_SSTRCPY(netinfo->secondary_dns, ptr); - } - else { - break; - } - } - fclose(fp); - } /* else /etc/resolv.conf may not exist if unplugged (MacOSX) */ - - size = sizeof(netinfo->host_name)-1; - if (gethostname(netinfo->host_name, size) == 0) { - netinfo->host_name[size] = '\0'; - } - else { - netinfo->host_name[0] = '\0'; - } - - size = sizeof(netinfo->domain_name)-1; - if (getdomainname(netinfo->domain_name, size) == 0) { - netinfo->domain_name[size] = '\0'; - } - else { - netinfo->domain_name[0] = '\0'; - } - - sigar_get_default_gateway(sigar, netinfo); - - return SIGAR_OK; -} - -#include - -#define OffsetOf(structure, field) \ - (size_t)(&((structure *)NULL)->field) - -#define RlimitOffsets(field) \ - OffsetOf(sigar_resource_limit_t, field##_cur), \ - OffsetOf(sigar_resource_limit_t, field##_max) - -#define RlimitSet(structure, ptr, val) \ - *(sigar_uint64_t *)((char *)structure + (int)(long)ptr) = val - -typedef struct { - int resource; - int factor; - size_t cur; - size_t max; -} rlimit_field_t; - -#ifndef RLIMIT_RSS -#define RLIMIT_RSS (RLIM_NLIMITS+1) -#endif - -#ifndef RLIMIT_NPROC -#define RLIMIT_NPROC (RLIM_NLIMITS+2) -#endif - -#define RLIMIT_PSIZE (RLIM_NLIMITS+3) - -#ifndef RLIMIT_AS -# if defined(RLIMIT_VMEM) -# define RLIMIT_AS RLIMIT_VMEM -# elif defined(RLIMIT_RSS) -# define RLIMIT_AS RLIMIT_RSS -# endif -#endif - -static rlimit_field_t sigar_rlimits[] = { - { RLIMIT_CPU, 1, RlimitOffsets(cpu) }, - { RLIMIT_FSIZE, 1024, RlimitOffsets(file_size) }, - { RLIMIT_DATA, 1024, RlimitOffsets(data) }, - { RLIMIT_STACK, 1024, RlimitOffsets(stack) }, - { RLIMIT_PSIZE, 512, RlimitOffsets(pipe_size) }, - { RLIMIT_CORE, 1024, RlimitOffsets(core) }, - { RLIMIT_RSS, 1024, RlimitOffsets(memory) }, - { RLIMIT_NPROC, 1, RlimitOffsets(processes) }, - { RLIMIT_NOFILE, 1, RlimitOffsets(open_files) }, - { RLIMIT_AS, 1024, RlimitOffsets(virtual_memory) }, - { -1 } -}; - -#define RlimitScale(val) \ - if (val != RLIM_INFINITY) val /= r->factor - -#define RlimitHS(val) \ - rl.rlim_cur = rl.rlim_max = (val) - -int sigar_resource_limit_get(sigar_t *sigar, - sigar_resource_limit_t *rlimit) -{ - int i; - - for (i=0; sigar_rlimits[i].resource != -1; i++) { - struct rlimit rl; - rlimit_field_t *r = &sigar_rlimits[i]; - - if (r->resource > RLIM_NLIMITS) { - switch (r->resource) { - case RLIMIT_NPROC: - RlimitHS(sysconf(_SC_CHILD_MAX)); - break; - case RLIMIT_PSIZE: - RlimitHS(PIPE_BUF/512); - break; - default: - RlimitHS(RLIM_INFINITY); - break; - } - } - else if (getrlimit(r->resource, &rl) != 0) { - RlimitHS(RLIM_INFINITY); - } - else { - RlimitScale(rl.rlim_cur); - RlimitScale(rl.rlim_max); - } - - RlimitSet(rlimit, r->cur, rl.rlim_cur); - RlimitSet(rlimit, r->max, rl.rlim_max); - } - - return SIGAR_OK; -} -#endif - -#if !defined(WIN32) && !defined(NETWARE) && !defined(DARWIN) && \ - !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) - -/* XXX: prolly will be moving these stuffs into os_net.c */ -#include -#include - -#ifndef SIOCGIFCONF -#include -#endif - -#if defined(_AIX) || defined(__osf__) /* good buddies */ - -#include - -static void hwaddr_aix_lookup(sigar_t *sigar, sigar_net_interface_config_t *ifconfig) -{ - char *ent, *end; - struct ifreq *ifr; - - /* XXX: assumes sigar_net_interface_list_get has been called */ - end = sigar->ifconf_buf + sigar->ifconf_len; - - for (ent = sigar->ifconf_buf; - ent < end; - ent += sizeof(*ifr)) - { - ifr = (struct ifreq *)ent; - - if (ifr->ifr_addr.sa_family != AF_LINK) { - continue; - } - - if (strEQ(ifr->ifr_name, ifconfig->name)) { - struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr; - - sigar_net_address_mac_set(ifconfig->hwaddr, - LLADDR(sdl), - sdl->sdl_alen); - return; - } - } - - sigar_hwaddr_set_null(ifconfig); -} - -#elif !defined(SIOCGIFHWADDR) - -#include - -static void hwaddr_arp_lookup(sigar_net_interface_config_t *ifconfig, int sock) -{ - struct arpreq areq; - struct sockaddr_in *sa; - - memset(&areq, 0, sizeof(areq)); - sa = (struct sockaddr_in *)&areq.arp_pa; - sa->sin_family = AF_INET; - sa->sin_addr.s_addr = ifconfig->address.addr.in; - - if (ioctl(sock, SIOCGARP, &areq) < 0) { - /* ho-hum */ - sigar_hwaddr_set_null(ifconfig); - } - else { - sigar_net_address_mac_set(ifconfig->hwaddr, - areq.arp_ha.sa_data, - SIGAR_IFHWADDRLEN); - } -} - -#endif - -#ifdef __linux__ - -#include - -#ifndef ARPHRD_CISCO /* not in 2.2 kernel headers */ -#define ARPHRD_CISCO 513 /* Cisco HDLC. */ -#endif - -static void get_interface_type(sigar_net_interface_config_t *ifconfig, - int family) -{ - char *type; - - switch (family) { - case ARPHRD_SLIP: - type = SIGAR_NIC_SLIP; - break; - case ARPHRD_CSLIP: - type = SIGAR_NIC_CSLIP; - break; - case ARPHRD_SLIP6: - type = SIGAR_NIC_SLIP6; - break; - case ARPHRD_CSLIP6: - type = SIGAR_NIC_CSLIP6; - break; - case ARPHRD_ADAPT: - type = SIGAR_NIC_ADAPTIVE; - break; - case ARPHRD_ETHER: - type = SIGAR_NIC_ETHERNET; - break; - case ARPHRD_ASH: - type = SIGAR_NIC_ASH; - break; - case ARPHRD_FDDI: - type = SIGAR_NIC_FDDI; - break; - case ARPHRD_HIPPI: - type = SIGAR_NIC_HIPPI; - break; - case ARPHRD_AX25: - type = SIGAR_NIC_AX25; - break; - case ARPHRD_ROSE: - type = SIGAR_NIC_ROSE; - break; - case ARPHRD_NETROM: - type = SIGAR_NIC_NETROM; - break; - case ARPHRD_X25: - type = SIGAR_NIC_X25; - break; - case ARPHRD_TUNNEL: - type = SIGAR_NIC_TUNNEL; - break; - case ARPHRD_PPP: - type = SIGAR_NIC_PPP; - break; - case ARPHRD_CISCO: - type = SIGAR_NIC_HDLC; - break; - case ARPHRD_LAPB: - type = SIGAR_NIC_LAPB; - break; - case ARPHRD_ARCNET: - type = SIGAR_NIC_ARCNET; - break; - case ARPHRD_DLCI: - type = SIGAR_NIC_DLCI; - break; - case ARPHRD_FRAD: - type = SIGAR_NIC_FRAD; - break; - case ARPHRD_SIT: - type = SIGAR_NIC_SIT; - break; - case ARPHRD_IRDA: - type = SIGAR_NIC_IRDA; - break; - case ARPHRD_ECONET: - type = SIGAR_NIC_EC; - break; - default: - type = SIGAR_NIC_UNSPEC; - break; - } - - SIGAR_SSTRCPY(ifconfig->type, type); -} - -#endif - -int sigar_net_interface_config_get(sigar_t *sigar, const char *name, - sigar_net_interface_config_t *ifconfig) -{ - int sock; - struct ifreq ifr; - - if (!name) { - return sigar_net_interface_config_primary_get(sigar, ifconfig); - } - - SIGAR_ZERO(ifconfig); - - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - return errno; - } - - SIGAR_SSTRCPY(ifconfig->name, name); - SIGAR_SSTRCPY(ifr.ifr_name, name); - -#define ifr_s_addr(ifr) \ - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr - - if (!ioctl(sock, SIOCGIFADDR, &ifr)) { - sigar_net_address_set(ifconfig->address, - ifr_s_addr(ifr)); - } - - if (!ioctl(sock, SIOCGIFNETMASK, &ifr)) { - sigar_net_address_set(ifconfig->netmask, - ifr_s_addr(ifr)); - } - - if (!ioctl(sock, SIOCGIFFLAGS, &ifr)) { - sigar_uint64_t flags = ifr.ifr_flags; -#ifdef __linux__ -# ifndef IFF_DYNAMIC -# define IFF_DYNAMIC 0x8000 /* not in 2.2 kernel */ -# endif /* IFF_DYNAMIC */ - int is_mcast = flags & IFF_MULTICAST; - int is_slave = flags & IFF_SLAVE; - int is_master = flags & IFF_MASTER; - int is_dynamic = flags & IFF_DYNAMIC; - /* - * XXX: should just define SIGAR_IFF_* - * and test IFF_* bits on given platform. - * this is the only diff between solaris/hpux/linux - * for the flags we care about. - * - */ - flags &= ~(IFF_MULTICAST|IFF_SLAVE|IFF_MASTER); - if (is_mcast) { - flags |= SIGAR_IFF_MULTICAST; - } - if (is_slave) { - flags |= SIGAR_IFF_SLAVE; - } - if (is_master) { - flags |= SIGAR_IFF_MASTER; - } - if (is_dynamic) { - flags |= SIGAR_IFF_DYNAMIC; - } -#endif - ifconfig->flags = flags; - } - else { - /* should always be able to get flags for existing device */ - /* other ioctls may fail if device is not enabled: ok */ - close(sock); - return errno; - } - - if (ifconfig->flags & IFF_LOOPBACK) { - sigar_net_address_set(ifconfig->destination, - ifconfig->address.addr.in); - sigar_net_address_set(ifconfig->broadcast, 0); - sigar_hwaddr_set_null(ifconfig); - SIGAR_SSTRCPY(ifconfig->type, - SIGAR_NIC_LOOPBACK); - } - else { - if (!ioctl(sock, SIOCGIFDSTADDR, &ifr)) { - sigar_net_address_set(ifconfig->destination, - ifr_s_addr(ifr)); - } - - if (!ioctl(sock, SIOCGIFBRDADDR, &ifr)) { - sigar_net_address_set(ifconfig->broadcast, - ifr_s_addr(ifr)); - } - -#if defined(SIOCGIFHWADDR) - if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) { - get_interface_type(ifconfig, - ifr.ifr_hwaddr.sa_family); - sigar_net_address_mac_set(ifconfig->hwaddr, - ifr.ifr_hwaddr.sa_data, - IFHWADDRLEN); - } -#elif defined(_AIX) || defined(__osf__) - hwaddr_aix_lookup(sigar, ifconfig); - SIGAR_SSTRCPY(ifconfig->type, - SIGAR_NIC_ETHERNET); -#else - hwaddr_arp_lookup(ifconfig, sock); - SIGAR_SSTRCPY(ifconfig->type, - SIGAR_NIC_ETHERNET); -#endif - } - -#if defined(SIOCGLIFMTU) && !defined(__hpux) - { - struct lifreq lifr; - SIGAR_SSTRCPY(lifr.lifr_name, name); - if(!ioctl(sock, SIOCGLIFMTU, &lifr)) { - ifconfig->mtu = lifr.lifr_mtu; - } - } -#elif defined(SIOCGIFMTU) - if (!ioctl(sock, SIOCGIFMTU, &ifr)) { -# if defined(__hpux) - ifconfig->mtu = ifr.ifr_metric; -# else - ifconfig->mtu = ifr.ifr_mtu; -#endif - } -#else - ifconfig->mtu = 0; /*XXX*/ -#endif - - if (!ioctl(sock, SIOCGIFMETRIC, &ifr)) { - ifconfig->metric = ifr.ifr_metric ? ifr.ifr_metric : 1; - } - -#if defined(SIOCGIFTXQLEN) - if (!ioctl(sock, SIOCGIFTXQLEN, &ifr)) { - ifconfig->tx_queue_len = ifr.ifr_qlen; - } - else { - ifconfig->tx_queue_len = -1; /* net-tools behaviour */ - } -#else - ifconfig->tx_queue_len = -1; -#endif - - close(sock); - - /* XXX can we get a better description like win32? */ - SIGAR_SSTRCPY(ifconfig->description, - ifconfig->name); - - sigar_net_interface_ipv6_config_init(ifconfig); - sigar_net_interface_ipv6_config_get(sigar, name, ifconfig); - - return SIGAR_OK; -} - -#ifdef _AIX -# define MY_SIOCGIFCONF CSIOCGIFCONF -#else -# define MY_SIOCGIFCONF SIOCGIFCONF -#endif - -#ifdef __osf__ -static int sigar_netif_configured(sigar_t *sigar, char *name) -{ - int status; - sigar_net_interface_config_t ifconfig; - - status = sigar_net_interface_config_get(sigar, name, &ifconfig); - - return status == SIGAR_OK; -} -#endif - -#ifdef __linux__ -static SIGAR_INLINE int has_interface(sigar_net_interface_list_t *iflist, - char *name) -{ - register int i; - register int num = iflist->number; - register char **data = iflist->data; - for (i=0; idata[iflist->number++] = - sigar_strdup(dev); - } - - fclose(fp); - - return SIGAR_OK; -} -#endif - -int sigar_net_interface_list_get(sigar_t *sigar, - sigar_net_interface_list_t *iflist) -{ - int n, lastlen=0; - struct ifreq *ifr; - struct ifconf ifc; - int sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (sock < 0) { - return errno; - } - - for (;;) { - if (!sigar->ifconf_buf || lastlen) { - sigar->ifconf_len += sizeof(struct ifreq) * SIGAR_NET_IFLIST_MAX; - sigar->ifconf_buf = realloc(sigar->ifconf_buf, sigar->ifconf_len); - } - - ifc.ifc_len = sigar->ifconf_len; - ifc.ifc_buf = sigar->ifconf_buf; - - if (ioctl(sock, MY_SIOCGIFCONF, &ifc) < 0) { - /* EINVAL should mean num_interfaces > ifc.ifc_len */ - if ((errno != EINVAL) || - (lastlen == ifc.ifc_len)) - { - free(ifc.ifc_buf); - return errno; - } - } - - if (ifc.ifc_len < sigar->ifconf_len) { - break; /* got em all */ - } - - if (ifc.ifc_len != lastlen) { - /* might be more */ - lastlen = ifc.ifc_len; - continue; - } - - break; - } - - close(sock); - - iflist->number = 0; - iflist->size = ifc.ifc_len; - iflist->data = malloc(sizeof(*(iflist->data)) * - iflist->size); - - ifr = ifc.ifc_req; - for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq), ifr++) { -#if defined(_AIX) || defined(__osf__) /* pass the bourbon */ - if (ifr->ifr_addr.sa_family != AF_LINK) { - /* XXX: dunno if this is right. - * otherwise end up with two 'en0' and three 'lo0' - * with the same ip address. - */ - continue; - } -# ifdef __osf__ - /* weed out "sl0", "tun0" and the like */ - /* XXX must be a better way to check this */ - if (!sigar_netif_configured(sigar, ifr->ifr_name)) { - continue; - } -# endif -#endif - iflist->data[iflist->number++] = - sigar_strdup(ifr->ifr_name); - } - -#ifdef __linux__ - proc_net_interface_list_get(sigar, iflist); -#endif - - return SIGAR_OK; -} - -#endif /* WIN32 */ - -SIGAR_DECLARE(int) -sigar_net_interface_config_primary_get(sigar_t *sigar, - sigar_net_interface_config_t *ifconfig) -{ - int i, status, found=0; - sigar_net_interface_list_t iflist; - sigar_net_interface_config_t possible_config; - - possible_config.flags = 0; - - if ((status = sigar_net_interface_list_get(sigar, &iflist)) != SIGAR_OK) { - return status; - } - - for (i=0; iflags & SIGAR_IFF_LOOPBACK) || - !ifconfig->hwaddr.addr.in) /* no mac address */ - { - continue; - } - - if (!possible_config.flags) { - /* save for later for use if we're not connected to the net - * or all interfaces are aliases (e.g. solaris zone) - */ - memcpy(&possible_config, ifconfig, sizeof(*ifconfig)); - } - if (!ifconfig->address.addr.in) { - continue; /* no ip address */ - } - if (strchr(iflist.data[i], ':')) { - continue; /* alias */ - } - - found = 1; - break; - } - - sigar_net_interface_list_destroy(sigar, &iflist); - - if (found) { - return SIGAR_OK; - } - else if (possible_config.flags) { - memcpy(ifconfig, &possible_config, sizeof(*ifconfig)); - return SIGAR_OK; - } - else { - return SIGAR_ENXIO; - } -} - -static int fqdn_ip_get(sigar_t *sigar, char *name) -{ - sigar_net_interface_config_t ifconfig; - int status; - - status = sigar_net_interface_config_primary_get(sigar, &ifconfig); - - if (status != SIGAR_OK) { - return status; - } - if (!ifconfig.address.addr.in) { - return SIGAR_ENXIO; - } - - sigar_net_address_to_string(sigar, &ifconfig.address, name); - - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] using ip address '%s' for fqdn", - name); - - return SIGAR_OK; -} - -struct hostent *sigar_gethostbyname(const char *name, - sigar_hostent_t *data) -{ - struct hostent *hp = NULL; - -#if defined(__linux__) - gethostbyname_r(name, &data->hs, - data->buffer, sizeof(data->buffer), - &hp, &data->error); -#elif defined(__sun) - hp = gethostbyname_r(name, &data->hs, - data->buffer, sizeof(data->buffer), - &data->error); -#elif defined(SIGAR_HAS_HOSTENT_DATA) - if (gethostbyname_r(name, &data->hs, &data->hd) == 0) { - hp = &data->hs; - } - else { - data->error = h_errno; - } -#else - hp = gethostbyname(name); -#endif - - return hp; -} - -static struct hostent *sigar_gethostbyaddr(const char *addr, - int len, int type, - sigar_hostent_t *data) -{ - struct hostent *hp = NULL; - -#if defined(__linux__) - gethostbyaddr_r(addr, len, type, - &data->hs, - data->buffer, sizeof(data->buffer), - &hp, &data->error); -#elif defined(__sun) - hp = gethostbyaddr_r(addr, len, type, - &data->hs, - data->buffer, sizeof(data->buffer), - &data->error); -#elif defined(SIGAR_HAS_HOSTENT_DATA) - if (gethostbyaddr_r((char *)addr, len, type, - &data->hs, &data->hd) == 0) - { - hp = &data->hs; - } - else { - data->error = h_errno; - } -#else - if (!(hp = gethostbyaddr(addr, len, type))) { - data->error = h_errno; - } -#endif - - return hp; -} -#define IS_FQDN(name) \ - (name && strchr(name, '.')) - -#define IS_FQDN_MATCH(lookup, name) \ - (IS_FQDN(lookup) && strnEQ(lookup, name, strlen(name))) - -#define FQDN_SET(fqdn) \ - SIGAR_STRNCPY(name, fqdn, namelen) - -SIGAR_DECLARE(int) sigar_fqdn_get(sigar_t *sigar, char *name, int namelen) -{ - register int is_debug = SIGAR_LOG_IS_DEBUG(sigar); - sigar_hostent_t data; - struct hostent *p; - char domain[SIGAR_FQDN_LEN + 1]; -#ifdef WIN32 - int status = sigar_wsa_init(sigar); - - if (status != SIGAR_OK) { - return status; - } -#endif - - if (gethostname(name, namelen - 1) != 0) { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "[fqdn] gethostname failed: %s", - sigar_strerror(sigar, errno)); - return errno; - } - else { - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] gethostname()=='%s'", - name); - } - } - - if (!(p = sigar_gethostbyname(name, &data))) { - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] gethostbyname(%s) failed: %s", - name, sigar_strerror(sigar, errno)); - } - - if (!IS_FQDN(name)) { - fqdn_ip_get(sigar, name); - } - - return SIGAR_OK; - } - - if (IS_FQDN_MATCH(p->h_name, name)) { - FQDN_SET(p->h_name); - - sigar_log(sigar, SIGAR_LOG_DEBUG, - "[fqdn] resolved using gethostbyname.h_name"); - - return SIGAR_OK; - } - else { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] unresolved using gethostbyname.h_name"); - } - - if (p->h_aliases) { - int i; - - for (i=0; p->h_aliases[i]; i++) { - if (IS_FQDN_MATCH(p->h_aliases[i], name)) { - FQDN_SET(p->h_aliases[i]); - - sigar_log(sigar, SIGAR_LOG_DEBUG, - "[fqdn] resolved using gethostbyname.h_aliases"); - - return SIGAR_OK; - } - else if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] gethostbyname(%s).alias[%d]=='%s'", - name, i, p->h_aliases[i]); - } - } - } - - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] unresolved using gethostbyname.h_aliases"); - - if (p->h_addr_list) { - int i,j; - - for (i=0; p->h_addr_list[i]; i++) { - char addr[SIGAR_INET6_ADDRSTRLEN]; - struct in_addr *in = - (struct in_addr *)p->h_addr_list[i]; - - struct hostent *q = - sigar_gethostbyaddr(p->h_addr_list[i], - p->h_length, - p->h_addrtype, - &data); - - if (is_debug) { - sigar_inet_ntoa(sigar, in->s_addr, addr); - } - - if (!q) { - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] gethostbyaddr(%s) failed: %s", - addr, - sigar_strerror(sigar, errno)); - } - continue; - } - - if (IS_FQDN_MATCH(q->h_name, name)) { - FQDN_SET(q->h_name); - - sigar_log(sigar, SIGAR_LOG_DEBUG, - "[fqdn] resolved using gethostbyaddr.h_name"); - - return SIGAR_OK; - } - else { - if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] gethostbyaddr(%s)=='%s'", - addr, q->h_name); - } - - for (j=0; q->h_aliases[j]; j++) { - if (IS_FQDN_MATCH(q->h_aliases[j], name)) { - FQDN_SET(q->h_aliases[j]); - - sigar_log(sigar, SIGAR_LOG_DEBUG, - "[fqdn] resolved using " - "gethostbyaddr.h_aliases"); - - return SIGAR_OK; - } - else if (is_debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[fqdn] gethostbyaddr(%s).alias[%d]=='%s'", - addr, j, q->h_aliases[j]); - } - } - } - } - } - - sigar_log(sigar, SIGAR_LOG_DEBUG, - "[fqdn] unresolved using gethostbyname.h_addr_list"); - -#if !defined(WIN32) && !defined(NETWARE) - if (!IS_FQDN(name) && /* e.g. aix gethostname is already fqdn */ - (getdomainname(domain, sizeof(domain) - 1) == 0) && - (domain[0] != '\0') && - (domain[0] != '(')) /* linux default is "(none)" */ - { - /* sprintf(name, "%s.%s", name, domain); */ - char *ptr = name; - int len = strlen(name); - ptr += len; - *ptr++ = '.'; - namelen -= (len+1); - SIGAR_STRNCPY(ptr, domain, namelen); - - sigar_log(sigar, SIGAR_LOG_DEBUG, - "[fqdn] resolved using getdomainname"); - } - else { - sigar_log(sigar, SIGAR_LOG_DEBUG, - "[fqdn] getdomainname failed"); - } -#endif - - if (!IS_FQDN(name)) { - fqdn_ip_get(sigar, name); - } - - return SIGAR_OK; -} - -#ifndef MAX_STRING_LEN -#define MAX_STRING_LEN 8192 -#endif - -#ifdef WIN32 -/* The windows version of getPasswordNative was lifted from apr */ -SIGAR_DECLARE(char *) sigar_password_get(const char *prompt) -{ - static char password[MAX_STRING_LEN]; - int n = 0; - int ch; - - fputs(prompt, stderr); - fflush(stderr); - - while ((ch = _getch()) != '\r') { - if (ch == EOF) /* EOF */ { - return NULL; - } - else if (ch == 0 || ch == 0xE0) { - /* FN Keys (0 or E0) are a sentinal for a FN code */ - ch = (ch << 4) | _getch(); - /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */ - if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) { - password[--n] = '\0'; - fputs("\b \b", stderr); - fflush(stderr); - } - else { - fputc('\a', stderr); - fflush(stderr); - } - } - else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ { - password[--n] = '\0'; - fputs("\b \b", stderr); - fflush(stderr); - } - else if (ch == 3) /* CTRL+C */ { - /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */ - fputs("^C\n", stderr); - fflush(stderr); - exit(-1); - } - else if (ch == 26) /* CTRL+Z */ { - fputs("^Z\n", stderr); - fflush(stderr); - return NULL; - } - else if (ch == 27) /* ESC */ { - fputc('\n', stderr); - fputs(prompt, stderr); - fflush(stderr); - n = 0; - } - else if ((n < sizeof(password) - 1) && !iscntrl(ch)) { - password[n++] = ch; - fputc(' ', stderr); - fflush(stderr); - } - else { - fputc('\a', stderr); - fflush(stderr); - } - } - - fputc('\n', stderr); - fflush(stderr); - password[n] = '\0'; - - return password; -} - -#else - -/* linux/hpux/solaris getpass() prototype lives here */ -#include - -#include - -/* from apr_getpass.c */ - -#if defined(SIGAR_HPUX) -# define getpass termios_getpass -#elif defined(SIGAR_SOLARIS) -# define getpass getpassphrase -#endif - -#ifdef SIGAR_HPUX -static char *termios_getpass(const char *prompt) -{ - struct termios attr; - static char password[MAX_STRING_LEN]; - unsigned int n=0; - - fputs(prompt, stderr); - fflush(stderr); - - if (tcgetattr(STDIN_FILENO, &attr) != 0) { - return NULL; - } - - attr.c_lflag &= ~(ECHO); - - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0) { - return NULL; - } - - while ((password[n] = getchar()) != '\n') { - if (n < (sizeof(password) - 1) && - (password[n] >= ' ') && - (password[n] <= '~')) - { - n++; - } - else { - fprintf(stderr, "\n"); - fputs(prompt, stderr); - fflush(stderr); - n = 0; - } - } - - password[n] = '\0'; - printf("\n"); - - if (n > (MAX_STRING_LEN - 1)) { - password[MAX_STRING_LEN - 1] = '\0'; - } - - attr.c_lflag |= ECHO; - tcsetattr(STDIN_FILENO, TCSANOW, &attr); - - return (char *)&password; -} -#endif - -SIGAR_DECLARE(char *) sigar_password_get(const char *prompt) -{ - char *buf = NULL; - - /* the linux version of getpass prints the prompt to the tty; ok. - * the solaris version prints the prompt to stderr; not ok. - * so print the prompt to /dev/tty ourselves if possible (always should be) - */ - - FILE *tty = NULL; - - if ((tty = fopen("/dev/tty", "w"))) { - fprintf(tty, "%s", prompt); - fflush(tty); - - buf = getpass(tty ? "" : prompt); - fclose(tty); - } - - return buf; -} - -#endif /* WIN32 */ diff --git a/vendor/sigar/src/sigar_cache.c b/vendor/sigar/src/sigar_cache.c deleted file mode 100644 index 8d64016..0000000 --- a/vendor/sigar/src/sigar_cache.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2004-2006 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include -/* - * hash table to cache values where key is a unique number - * such as: - * pid -> some process data - * uid -> user name - * gid -> group name - */ - -#define ENTRIES_SIZE(n) \ - (sizeof(sigar_cache_entry_t *) * (n)) - -/* wrap free() for use w/ dmalloc */ -static void free_value(void *ptr) -{ - free(ptr); -} - -sigar_cache_t *sigar_cache_new(int size) -{ - sigar_cache_t *table = malloc(sizeof(*table)); - table->count = 0; - table->size = size; - table->entries = malloc(ENTRIES_SIZE(size)); - memset(table->entries, '\0', ENTRIES_SIZE(size)); - table->free_value = free_value; - return table; -} - -#ifdef DEBUG_CACHE -/* see how well entries are distributed */ -static void sigar_cache_dump(sigar_cache_t *table) -{ - int i; - sigar_cache_entry_t **entries = table->entries; - - for (i=0; isize; i++) { - sigar_cache_entry_t *entry = *entries++; - - printf("|"); - while (entry) { - printf("%lld", entry->id); - if (entry->next) { - printf(","); - } - entry = entry->next; - } - } - printf("\n"); - fflush(stdout); -} -#endif - -static void sigar_cache_rehash(sigar_cache_t *table) -{ - int i; - unsigned int new_size = table->size * 2 + 1; - sigar_cache_entry_t **entries = table->entries; - sigar_cache_entry_t **new_entries = - malloc(ENTRIES_SIZE(new_size)); - - memset(new_entries, '\0', ENTRIES_SIZE(new_size)); - - for (i=0; isize; i++) { - sigar_cache_entry_t *entry = *entries++; - - while (entry) { - sigar_cache_entry_t *next = entry->next; - sigar_uint64_t hash = entry->id % new_size; - - entry->next = new_entries[hash]; - new_entries[hash] = entry; - entry = next; - } - } - - free(table->entries); - table->entries = new_entries; - table->size = new_size; -} - -#define SIGAR_CACHE_IX(t, k) \ - t->entries + (k % t->size) - -sigar_cache_entry_t *sigar_cache_find(sigar_cache_t *table, - sigar_uint64_t key) -{ - sigar_cache_entry_t *entry, **ptr; - - for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr; - entry; - ptr = &entry->next, entry = *ptr) - { - if (entry->id == key) { - return entry; - } - } - - return NULL; -} - -/* create entry if it does not exist */ -sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table, - sigar_uint64_t key) -{ - sigar_cache_entry_t *entry, **ptr; - - for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr; - entry; - ptr = &entry->next, entry = *ptr) - { - if (entry->id == key) { - return entry; - } - } - - if (table->count++ > table->size) { - sigar_cache_rehash(table); - - for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr; - entry; - ptr = &entry->next, entry = *ptr) - { - } - } - - *ptr = entry = malloc(sizeof(*entry)); - entry->id = key; - entry->value = NULL; - entry->next = NULL; - - return entry; -} - -void sigar_cache_destroy(sigar_cache_t *table) -{ - int i; - sigar_cache_entry_t **entries = table->entries; - -#ifdef DEBUG_CACHE - sigar_cache_dump(table); -#endif - - for (i=0; isize; i++) { - sigar_cache_entry_t *entry, *ptr; - entry = *entries++; - - while (entry) { - if (entry->value) { - table->free_value(entry->value); - } - ptr = entry->next; - free(entry); - entry = ptr; - } - } - - free(table->entries); - free(table); -} diff --git a/vendor/sigar/src/sigar_fileinfo.c b/vendor/sigar/src/sigar_fileinfo.c deleted file mode 100644 index adde8c0..0000000 --- a/vendor/sigar/src/sigar_fileinfo.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - * Copyright (c) 2004-2005, 2007-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2003 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR - * ITS 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 consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - */ - -#ifndef WIN32 -# ifdef _AIX -# define _LARGE_FILES -# else -# define _FILE_OFFSET_BITS 64 -# define _LARGEFILE64_SOURCE -# endif -#endif - -#include "sigar.h" - -#ifndef WIN32 -#if defined(__FreeBSD__) || defined(__OpenBSD__) -# include -# include -#else -# include -# define HAVE_STATVFS -#endif -#include - -#define SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) ((val * bsize) >> 1) - -int sigar_statvfs(sigar_t *sigar, - const char *dirname, - sigar_file_system_usage_t *fsusage) -{ - sigar_uint64_t val, bsize; -#ifdef HAVE_STATVFS - struct statvfs buf; - int status = -# if defined(__sun) && !defined(_LP64) - /* http://bugs.opensolaris.org/view_bug.do?bug_id=4462986 */ - statvfs(dirname, (void *)&buf); -# else - statvfs(dirname, &buf); -# endif -#else - struct statfs buf; - int status = statfs(dirname, &buf); -#endif - - if (status != 0) { - return errno; - } - -#ifdef HAVE_STATVFS - bsize = buf.f_frsize / 512; -#else - bsize = buf.f_bsize / 512; -#endif - val = buf.f_blocks; - fsusage->total = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize); - val = buf.f_bfree; - fsusage->free = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize); - val = buf.f_bavail; - fsusage->avail = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize); - fsusage->used = fsusage->total - fsusage->free; - fsusage->files = buf.f_files; - fsusage->free_files = buf.f_ffree; - - return SIGAR_OK; -} -#endif - -/* - * whittled down version of apr/file_info/{unix,win32}/filestat.c - * to fillin sigar_fileattrs_t - */ -#include "sigar_fileinfo.h" -#include "sigar_log.h" - -#ifndef SIGAR_ZERO -#define SIGAR_ZERO(s) \ - memset(s, '\0', sizeof(*(s))) -#endif - -#ifdef WIN32 -#include -sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft); -#else -#include -#endif - -static const char* types[] = { - "none", - "regular", - "directory", - "character device", - "block device", - "pipe", - "symbolic link", - "socket", - "unknown" -}; - -SIGAR_DECLARE(const char *) -sigar_file_attrs_type_string_get(sigar_file_type_e type) -{ - if ((type < SIGAR_FILETYPE_NOFILE) || - (type > SIGAR_FILETYPE_UNKFILE)) - { - type = SIGAR_FILETYPE_UNKFILE; - } - - return types[type]; -} - -static const sigar_uint64_t perm_modes[] = { - SIGAR_UREAD, SIGAR_UWRITE, SIGAR_UEXECUTE, - SIGAR_GREAD, SIGAR_GWRITE, SIGAR_GEXECUTE, - SIGAR_WREAD, SIGAR_WWRITE, SIGAR_WEXECUTE -}; - -static const char perm_chars[] = "rwx"; - -SIGAR_DECLARE(char *) -sigar_file_attrs_permissions_string_get(sigar_uint64_t permissions, - char *str) -{ - char *ptr = str; - int i=0, j=0; - - for (i=0; i<9; i+=3) { - for (j=0; j<3; j++) { - if (permissions & perm_modes[i+j]) { - *ptr = perm_chars[j]; - } - else { - *ptr = '-'; - } - ptr++; - } - } - - *ptr = '\0'; - return str; -} - -static const int perm_int[] = { - 400, 200, 100, - 40, 20, 10, - 4, 2, 1 -}; - -SIGAR_DECLARE(int)sigar_file_attrs_mode_get(sigar_uint64_t permissions) -{ - int i=0; - int perms = 0; - - /* no doubt there is some fancy bitshifting - * to convert, but this works fine. - */ - for (i=0; i<9; i++) { - if (permissions & perm_modes[i]) { - perms += perm_int[i]; - } - } - - return perms; -} - -#define IS_DOTDIR(dir) \ - ((dir[0] == '.') && (!dir[1] || ((dir[1] == '.') && !dir[2]))) - -#define DIR_STAT_WARN() \ - sigar_log_printf(sigar, SIGAR_LOG_WARN, \ - "dir_stat: cannot stat `%s': %s", \ - name, \ - sigar_strerror(sigar, status)) - -#if defined(NETWARE) - -int sigar_dir_stat_get(sigar_t *sigar, - const char *dir, - sigar_dir_stat_t *dirstats) -{ - return SIGAR_ENOTIMPL; -} - -int sigar_file_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs) -{ - return SIGAR_ENOTIMPL; -} - -int sigar_link_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs) -{ - return SIGAR_ENOTIMPL; -} - -#elif defined(WIN32) - -#include -#include - -static void fillin_fileattrs(sigar_file_attrs_t *finfo, - WIN32_FILE_ATTRIBUTE_DATA *wininfo, - int linkinfo) -{ - DWORD *sizes = &wininfo->nFileSizeHigh; - - finfo->atime = sigar_FileTimeToTime(&wininfo->ftLastAccessTime) / 1000; - finfo->ctime = sigar_FileTimeToTime(&wininfo->ftCreationTime) / 1000; - finfo->mtime = sigar_FileTimeToTime(&wininfo->ftLastWriteTime) / 1000; - - finfo->size = - (sigar_uint64_t)sizes[1] | ((sigar_uint64_t)sizes[0] << 32); - - if (linkinfo && - (wininfo->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { - finfo->type = SIGAR_FILETYPE_LNK; - } - else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - finfo->type = SIGAR_FILETYPE_DIR; - } - else { - finfo->type = SIGAR_FILETYPE_REG; - } -} - -static sigar_uint64_t convert_perms(ACCESS_MASK acc, sigar_uint64_t scope) -{ - sigar_uint64_t perms = 0; - if (acc & FILE_EXECUTE) { - perms |= SIGAR_WEXECUTE; - } - if (acc & FILE_WRITE_DATA) { - perms |= SIGAR_WWRITE; - } - if (acc & FILE_READ_DATA) { - perms |= SIGAR_WREAD; - } - - return (perms << scope); -} - -static int get_security_info(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs) -{ - DWORD retval; - PSID user = NULL, group = NULL, world = NULL; - PACL dacl = NULL; - PSECURITY_DESCRIPTOR pdesc = NULL; - SECURITY_INFORMATION sinfo = - OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION; - TRUSTEE ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID}; - ACCESS_MASK acc; - SID_IDENTIFIER_AUTHORITY auth = SECURITY_WORLD_SID_AUTHORITY; - - retval = GetNamedSecurityInfo((char *)file, - SE_FILE_OBJECT, - sinfo, - &user, - &group, - &dacl, - NULL, - &pdesc); - - if (retval != ERROR_SUCCESS) { - return retval; - } - - if (!AllocateAndInitializeSid(&auth, 1, SECURITY_WORLD_RID, - 0, 0, 0, 0, 0, 0, 0, &world)) - { - world = NULL; - } - - ident.TrusteeType = TRUSTEE_IS_USER; - ident.ptstrName = user; - if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) { - fileattrs->permissions |= convert_perms(acc, 8); - } - - ident.TrusteeType = TRUSTEE_IS_GROUP; - ident.ptstrName = group; - if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) { - fileattrs->permissions |= convert_perms(acc, 4); - } - - if (world) { - ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - ident.ptstrName = world; - if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) { - fileattrs->permissions |= convert_perms(acc, 0); - } - } - - if (world) { - FreeSid(world); - } - - LocalFree(pdesc); - - return SIGAR_OK; -} - -static int fileattrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs, - int linkinfo) -{ - BY_HANDLE_FILE_INFORMATION info; - WIN32_FILE_ATTRIBUTE_DATA attrs; - HANDLE handle; - DWORD flags; - - SIGAR_ZERO(fileattrs); - - if (!GetFileAttributesExA(file, - GetFileExInfoStandard, - &attrs)) - { - return GetLastError(); - } - - fillin_fileattrs(fileattrs, &attrs, linkinfo); - - flags = fileattrs->type == SIGAR_FILETYPE_DIR ? - FILE_FLAG_BACKUP_SEMANTICS : - FILE_ATTRIBUTE_NORMAL; - - /** - * We need to set dwDesiredAccess to 0 to work in cases where GENERIC_READ can fail. - * - * see: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx - */ - handle = CreateFile(file, - 0, - 0, - NULL, - OPEN_EXISTING, - flags, - NULL); - - if (handle != INVALID_HANDLE_VALUE) { - if (GetFileInformationByHandle(handle, &info)) { - fileattrs->inode = - info.nFileIndexLow | - (info.nFileIndexHigh << 32); - fileattrs->device = info.dwVolumeSerialNumber; - fileattrs->nlink = info.nNumberOfLinks; - } - CloseHandle(handle); - } - - get_security_info(sigar, file, fileattrs); - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_file_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs) -{ - return fileattrs_get(sigar, file, fileattrs, 0); -} - -SIGAR_DECLARE(int) sigar_link_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs) -{ - return fileattrs_get(sigar, file, fileattrs, 1); -} - -static __inline int file_type(char *file) -{ - WIN32_FILE_ATTRIBUTE_DATA attrs; - - if (!GetFileAttributesExA(file, - GetFileExInfoStandard, - &attrs)) - { - return -1; - } - - if (attrs.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - return SIGAR_FILETYPE_LNK; - } - else if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - return SIGAR_FILETYPE_DIR; - } - else { - return SIGAR_FILETYPE_REG; - } -} - -static int dir_stat_get(sigar_t *sigar, - const char *dir, - sigar_dir_stat_t *dirstats, - int recurse) -{ - int status; - char name[SIGAR_PATH_MAX+1]; - int len = strlen(dir); - int max = sizeof(name)-len-1; - char *ptr = name; - WIN32_FIND_DATA data; - HANDLE handle; - DWORD error; - char delim; - - if (file_type((char *)dir) != SIGAR_FILETYPE_DIR) { - return ERROR_NO_MORE_FILES; - } - - strncpy(name, dir, sizeof(name)); - ptr += len; - if (strchr(dir, '/')) { - delim = '/'; - } - else { - delim = '\\'; - } - if (name[len] != delim) { - *ptr++ = delim; - len++; - max--; - } - - /* e.g. "C:\sigar\*" */ - name[len] = '*'; - name[len+1] = '\0'; - - handle = FindFirstFile(name, &data); - if (handle == INVALID_HANDLE_VALUE) { - return GetLastError(); - } - - do { - /* skip '.' and '..' */ - if (IS_DOTDIR(data.cFileName)) { - continue; - } - - dirstats->disk_usage += - (data.nFileSizeHigh * (MAXDWORD+1)) + - data.nFileSizeLow; - - /* e.g. "C:\sigar\lib" */ - strncpy(ptr, data.cFileName, max); - ptr[max] = '\0'; - - switch (file_type(name)) { - case -1: - break; - case SIGAR_FILETYPE_REG: - ++dirstats->files; - break; - case SIGAR_FILETYPE_DIR: - ++dirstats->subdirs; - if (recurse) { - status = - dir_stat_get(sigar, name, - dirstats, recurse); - if (status != SIGAR_OK) { - DIR_STAT_WARN(); - } - } - break; - case SIGAR_FILETYPE_LNK: - ++dirstats->symlinks; - break; - case SIGAR_FILETYPE_CHR: - ++dirstats->chrdevs; - break; - case SIGAR_FILETYPE_BLK: - ++dirstats->blkdevs; - break; - case SIGAR_FILETYPE_SOCK: - ++dirstats->sockets; - break; - default: - ++dirstats->total; - } - } while (FindNextFile(handle, &data)); - - error = GetLastError(); - - FindClose(handle); - - if (error != ERROR_NO_MORE_FILES) { - return error; - } - - dirstats->total = - dirstats->files + - dirstats->subdirs + - dirstats->symlinks + - dirstats->chrdevs + - dirstats->blkdevs + - dirstats->sockets; - - return SIGAR_OK; -} - -#else - -#include -#include -#include -#include - -static sigar_file_type_e filetype_from_mode(mode_t mode) -{ - sigar_file_type_e type; - - switch (mode & S_IFMT) { - case S_IFREG: - type = SIGAR_FILETYPE_REG; break; - case S_IFDIR: - type = SIGAR_FILETYPE_DIR; break; - case S_IFLNK: - type = SIGAR_FILETYPE_LNK; break; - case S_IFCHR: - type = SIGAR_FILETYPE_CHR; break; - case S_IFBLK: - type = SIGAR_FILETYPE_BLK; break; -#if defined(S_IFFIFO) - case S_IFFIFO: - type = SIGAR_FILETYPE_PIPE; break; -#endif -#if !defined(BEOS) && defined(S_IFSOCK) - case S_IFSOCK: - type = SIGAR_FILETYPE_SOCK; break; -#endif - - default: - /* Work around missing S_IFxxx values above - * for Linux et al. - */ -#if !defined(S_IFFIFO) && defined(S_ISFIFO) - if (S_ISFIFO(mode)) { - type = SIGAR_FILETYPE_PIPE; - } else -#endif -#if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK) - if (S_ISSOCK(mode)) { - type = SIGAR_FILETYPE_SOCK; - } else -#endif - type = SIGAR_FILETYPE_UNKFILE; - } - return type; -} - -static sigar_uint64_t sigar_unix_mode2perms(mode_t mode) -{ - sigar_uint64_t perms = 0; - - if (mode & S_IRUSR) - perms |= SIGAR_UREAD; - if (mode & S_IWUSR) - perms |= SIGAR_UWRITE; - if (mode & S_IXUSR) - perms |= SIGAR_UEXECUTE; - - if (mode & S_IRGRP) - perms |= SIGAR_GREAD; - if (mode & S_IWGRP) - perms |= SIGAR_GWRITE; - if (mode & S_IXGRP) - perms |= SIGAR_GEXECUTE; - - if (mode & S_IROTH) - perms |= SIGAR_WREAD; - if (mode & S_IWOTH) - perms |= SIGAR_WWRITE; - if (mode & S_IXOTH) - perms |= SIGAR_WEXECUTE; - - return perms; -} - -static void copy_stat_info(sigar_file_attrs_t *fileattrs, - struct stat *info) -{ - fileattrs->permissions = sigar_unix_mode2perms(info->st_mode); - fileattrs->type = filetype_from_mode(info->st_mode); - fileattrs->uid = info->st_uid; - fileattrs->gid = info->st_gid; - fileattrs->size = info->st_size; - fileattrs->inode = info->st_ino; - fileattrs->device = info->st_dev; - fileattrs->nlink = info->st_nlink; - fileattrs->atime = info->st_atime; - fileattrs->mtime = info->st_mtime; - fileattrs->ctime = info->st_ctime; - fileattrs->atime *= 1000; - fileattrs->mtime *= 1000; - fileattrs->ctime *= 1000; -} - -int sigar_file_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs) -{ - struct stat info; - - if (stat(file, &info) == 0) { - copy_stat_info(fileattrs, &info); - return SIGAR_OK; - } - else { - return errno; - } -} - -int sigar_link_attrs_get(sigar_t *sigar, - const char *file, - sigar_file_attrs_t *fileattrs) -{ - struct stat info; - - if (lstat(file, &info) == 0) { - copy_stat_info(fileattrs, &info); - return SIGAR_OK; - } - else { - return errno; - } -} - -static int dir_stat_get(sigar_t *sigar, - const char *dir, - sigar_dir_stat_t *dirstats, - int recurse) -{ - int status; - char name[SIGAR_PATH_MAX+1]; - int len = strlen(dir); - int max = sizeof(name)-len-1; - char *ptr = name; - DIR *dirp = opendir(dir); - struct dirent *ent; - struct stat info; -#ifdef HAVE_READDIR_R - struct dirent dbuf; -#endif - - if (!dirp) { - return errno; - } - - strncpy(name, dir, sizeof(name)); - ptr += len; - if (name[len] != '/') { - *ptr++ = '/'; - len++; - max--; - } - -#ifdef HAVE_READDIR_R - while (readdir_r(dirp, &dbuf, &ent) == 0) { - if (ent == NULL) { - break; - } -#else - while ((ent = readdir(dirp))) { -#endif - /* skip '.' and '..' */ - if (IS_DOTDIR(ent->d_name)) { - continue; - } - - strncpy(ptr, ent->d_name, max); - ptr[max] = '\0'; - - if (lstat(name, &info) != 0) { - continue; - } - - dirstats->disk_usage += info.st_size; - - switch (filetype_from_mode(info.st_mode)) { - case SIGAR_FILETYPE_REG: - ++dirstats->files; - break; - case SIGAR_FILETYPE_DIR: - ++dirstats->subdirs; - if (recurse) { - status = - dir_stat_get(sigar, name, - dirstats, recurse); - if (status != SIGAR_OK) { - DIR_STAT_WARN(); - } - } - break; - case SIGAR_FILETYPE_LNK: - ++dirstats->symlinks; - break; - case SIGAR_FILETYPE_CHR: - ++dirstats->chrdevs; - break; - case SIGAR_FILETYPE_BLK: - ++dirstats->blkdevs; - break; - case SIGAR_FILETYPE_SOCK: - ++dirstats->sockets; - break; - default: - ++dirstats->total; - } - } - - dirstats->total = - dirstats->files + - dirstats->subdirs + - dirstats->symlinks + - dirstats->chrdevs + - dirstats->blkdevs + - dirstats->sockets; - - closedir(dirp); - - return SIGAR_OK; -} - -#endif - -SIGAR_DECLARE(int) sigar_dir_stat_get(sigar_t *sigar, - const char *dir, - sigar_dir_stat_t *dirstats) -{ - SIGAR_ZERO(dirstats); - return dir_stat_get(sigar, dir, dirstats, 0); -} - -SIGAR_DECLARE(int) sigar_dir_usage_get(sigar_t *sigar, - const char *dir, - sigar_dir_usage_t *dirusage) -{ - SIGAR_ZERO(dirusage); - return dir_stat_get(sigar, dir, dirusage, 1); -} diff --git a/vendor/sigar/src/sigar_format.c b/vendor/sigar/src/sigar_format.c deleted file mode 100644 index 8062ddd..0000000 --- a/vendor/sigar/src/sigar_format.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2007-2008 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * Copyright (c) 2010 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Utility functions to provide string formatting of SIGAR data */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" -#include "sigar_format.h" - -#include -#include - -#ifndef WIN32 -#include -#include -#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(_AIX) -#include -#endif -#include -#include - -/* sysconf(_SC_GET{PW,GR}_R_SIZE_MAX) */ -#define R_SIZE_MAX 2048 - -int sigar_user_name_get(sigar_t *sigar, int uid, char *buf, int buflen) -{ - struct passwd *pw = NULL; - /* XXX cache lookup */ - -# ifdef HAVE_GETPWUID_R - struct passwd pwbuf; - char buffer[R_SIZE_MAX]; - - if (getpwuid_r(uid, &pwbuf, buffer, sizeof(buffer), &pw) != 0) { - return errno; - } - if (!pw) { - return ENOENT; - } -# else - if ((pw = getpwuid(uid)) == NULL) { - return errno; - } -# endif - - strncpy(buf, pw->pw_name, buflen); - buf[buflen-1] = '\0'; - - return SIGAR_OK; -} - -int sigar_group_name_get(sigar_t *sigar, int gid, char *buf, int buflen) -{ - struct group *gr; - /* XXX cache lookup */ - -# ifdef HAVE_GETGRGID_R - struct group grbuf; - char buffer[R_SIZE_MAX]; - - if (getgrgid_r(gid, &grbuf, buffer, sizeof(buffer), &gr) != 0) { - return errno; - } -# else - if ((gr = getgrgid(gid)) == NULL) { - return errno; - } -# endif - - if (gr && gr->gr_name) { - strncpy(buf, gr->gr_name, buflen); - } - else { - /* seen on linux.. apache httpd.conf has: - * Group #-1 - * results in uid == -1 and gr == NULL. - * wtf getgrgid_r doesnt fail instead? - */ - sprintf(buf, "%d", gid); - } - buf[buflen-1] = '\0'; - - return SIGAR_OK; -} - -int sigar_user_id_get(sigar_t *sigar, const char *name, int *uid) -{ - /* XXX cache lookup */ - struct passwd *pw; - -# ifdef HAVE_GETPWNAM_R - struct passwd pwbuf; - char buf[R_SIZE_MAX]; - - if (getpwnam_r(name, &pwbuf, buf, sizeof(buf), &pw) != 0) { - return errno; - } -# else - if (!(pw = getpwnam(name))) { - return errno; - } -# endif - - *uid = (int)pw->pw_uid; - return SIGAR_OK; -} - -#endif /* WIN32 */ - -static char *sigar_error_string(int err) -{ - switch (err) { - case SIGAR_ENOTIMPL: - return "This function has not been implemented on this platform"; - default: - return "Error string not specified yet"; - } -} - -SIGAR_DECLARE(char *) sigar_strerror(sigar_t *sigar, int err) -{ - char *buf; - - if (err < 0) { - return sigar->errbuf; - } - - if (err > SIGAR_OS_START_ERROR) { - if ((buf = sigar_os_error_string(sigar, err)) != NULL) { - return buf; - } - return "Unknown OS Error"; /* should never happen */ - } - - if (err > SIGAR_START_ERROR) { - return sigar_error_string(err); - } - - return sigar_strerror_get(err, sigar->errbuf, sizeof(sigar->errbuf)); -} - -char *sigar_strerror_get(int err, char *errbuf, int buflen) -{ - char *buf = NULL; -#ifdef WIN32 - DWORD len; - - len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), /* force english */ - (LPTSTR)errbuf, - (DWORD)buflen, - NULL); -#else - -#if defined(HAVE_STRERROR_R) && defined(HAVE_STRERROR_R_GLIBC) - /* - * strerror_r man page says: - * "The GNU version may, but need not, use the user supplied buffer" - */ - buf = strerror_r(err, errbuf, buflen); -#elif defined(HAVE_STRERROR_R) - if (strerror_r(err, errbuf, buflen) < 0) { - buf = "Unknown Error"; - } -#else - /* strerror() is thread safe on solaris and hpux */ - buf = strerror(err); -#endif - - if (buf != NULL) { - SIGAR_STRNCPY(errbuf, buf, buflen); - } - -#endif - return errbuf; -} - -void sigar_strerror_set(sigar_t *sigar, char *msg) -{ - SIGAR_SSTRCPY(sigar->errbuf, msg); -} - -#ifdef WIN32 -#define vsnprintf _vsnprintf -#endif - -void sigar_strerror_printf(sigar_t *sigar, const char *format, ...) -{ - va_list args; - - va_start(args, format); - vsnprintf(sigar->errbuf, sizeof(sigar->errbuf), format, args); - va_end(args); -} - -/* copy apr_strfsize */ -SIGAR_DECLARE(char *) sigar_format_size(sigar_uint64_t size, char *buf) -{ - const char ord[] = "KMGTPE"; - const char *o = ord; - int remain; - - if (size == SIGAR_FIELD_NOTIMPL) { - buf[0] = '-'; - buf[1] = '\0'; - return buf; - } - - if (size < 973) { - sprintf(buf, "%3d ", (int) size); - return buf; - } - - do { - remain = (int)(size & 1023); - size >>= 10; - - if (size >= 973) { - ++o; - continue; - } - - if (size < 9 || (size == 9 && remain < 973)) { - if ((remain = ((remain * 5) + 256) / 512) >= 10) { - ++size; - remain = 0; - } - sprintf(buf, "%d.%d%c", (int) size, remain, *o); - return buf; - } - - if (remain >= 512) { - ++size; - } - - sprintf(buf, "%3d%c", (int) size, *o); - - return buf; - } while (1); -} - - -SIGAR_DECLARE(int) sigar_uptime_string(sigar_t *sigar, - sigar_uptime_t *uptime, - char *buffer, - int buflen) -{ - char *ptr = buffer; - int time = (int)uptime->uptime; - int minutes, hours, days, offset = 0; - - /* XXX: get rid of sprintf and/or check for overflow */ - days = time / (60*60*24); - - if (days) { - offset += sprintf(ptr + offset, "%d day%s, ", - days, (days > 1) ? "s" : ""); - } - - minutes = time / 60; - hours = minutes / 60; - hours = hours % 24; - minutes = minutes % 60; - - if (hours) { - offset += sprintf(ptr + offset, "%2d:%02d", - hours, minutes); - } - else { - offset += sprintf(ptr + offset, "%d min", minutes); - } - - return SIGAR_OK; -} - -/* threadsafe alternative to inet_ntoa (inet_ntop4 from apr) */ -int sigar_inet_ntoa(sigar_t *sigar, - sigar_uint32_t address, - char *addr_str) -{ - char *next=addr_str; - int n=0; - const unsigned char *src = - (const unsigned char *)&address; - - do { - unsigned char u = *src++; - if (u > 99) { - *next++ = '0' + u/100; - u %= 100; - *next++ = '0' + u/10; - u %= 10; - } - else if (u > 9) { - *next++ = '0' + u/10; - u %= 10; - } - *next++ = '0' + u; - *next++ = '.'; - n++; - } while (n < 4); - - *--next = 0; - - return SIGAR_OK; -} - -static int sigar_ether_ntoa(char *buff, unsigned char *ptr) -{ - sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X", - (ptr[0] & 0xff), (ptr[1] & 0xff), (ptr[2] & 0xff), - (ptr[3] & 0xff), (ptr[4] & 0xff), (ptr[5] & 0xff)); - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_net_address_equals(sigar_net_address_t *addr1, - sigar_net_address_t *addr2) - -{ - if (addr1->family != addr2->family) { - return EINVAL; - } - - switch (addr1->family) { - case SIGAR_AF_INET: - return memcmp(&addr1->addr.in, &addr2->addr.in, sizeof(addr1->addr.in)); - case SIGAR_AF_INET6: - return memcmp(&addr1->addr.in6, &addr2->addr.in6, sizeof(addr1->addr.in6)); - case SIGAR_AF_LINK: - return memcmp(&addr1->addr.mac, &addr2->addr.mac, sizeof(addr1->addr.mac)); - default: - return EINVAL; - } -} - -#if defined(SIGAR_USING_MSC6) -#define sigar_inet_ntop(af, src, dst, size) NULL -#define sigar_inet_ntop_errno SIGAR_ENOTIMPL -#elif defined(WIN32) -static char *sigar_inet_ntop(int af, const void *src, char *dst, int cnt) -{ - struct sockaddr_in6 sa; /* note only using this for AF_INET6 */ - - memset(&sa, '\0', sizeof(sa)); - sa.sin6_family = af; - memcpy(&sa.sin6_addr, src, sizeof(sa.sin6_addr)); - - if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), - dst, cnt, NULL, 0, NI_NUMERICHOST)) - { - return NULL; - } - else { - return dst; - } -} -#define sigar_inet_ntop_errno GetLastError() -#else -#define sigar_inet_ntop inet_ntop -#define sigar_inet_ntop_errno errno -#endif - -SIGAR_DECLARE(int) sigar_net_address_to_string(sigar_t *sigar, - sigar_net_address_t *address, - char *addr_str) -{ - *addr_str = '\0'; - switch (address->family) { - case SIGAR_AF_INET6: - if (sigar_inet_ntop(AF_INET6, (const void *)&address->addr.in6, - addr_str, SIGAR_INET6_ADDRSTRLEN)) - { - return SIGAR_OK; - } - else { - return sigar_inet_ntop_errno; - } - case SIGAR_AF_INET: - return sigar_inet_ntoa(sigar, address->addr.in, addr_str); - case SIGAR_AF_UNSPEC: - return sigar_inet_ntoa(sigar, 0, addr_str); /*XXX*/ - case SIGAR_AF_LINK: - return sigar_ether_ntoa(addr_str, &address->addr.mac[0]); - default: - return EINVAL; - } -} - -SIGAR_DECLARE(const char *)sigar_net_scope_to_string(int type) -{ - switch (type) { - case SIGAR_IPV6_ADDR_ANY: - return "Global"; - case SIGAR_IPV6_ADDR_LOOPBACK: - return "Host"; - case SIGAR_IPV6_ADDR_LINKLOCAL: - return "Link"; - case SIGAR_IPV6_ADDR_SITELOCAL: - return "Site"; - case SIGAR_IPV6_ADDR_COMPATv4: - return "Compat"; - default: - return "Unknown"; - } -} - -SIGAR_DECLARE(sigar_uint32_t) sigar_net_address_hash(sigar_net_address_t *address) -{ - sigar_uint32_t hash = 0; - unsigned char *data; - int i=0, size, elts; - - switch (address->family) { - case SIGAR_AF_UNSPEC: - case SIGAR_AF_INET: - return address->addr.in; - case SIGAR_AF_INET6: - data = (unsigned char *)&address->addr.in6; - size = sizeof(address->addr.in6); - elts = 4; - break; - case SIGAR_AF_LINK: - data = (unsigned char *)&address->addr.mac; - size = sizeof(address->addr.mac); - elts = 2; - break; - default: - return -1; - } - - while (ivalue) { - entry->value = strdup(name); - } - } - - fclose(fp); - return SIGAR_OK; -} - -SIGAR_DECLARE(char *)sigar_net_services_name_get(sigar_t *sigar, - int protocol, unsigned long port) -{ - sigar_cache_entry_t *entry; - sigar_cache_t **names; - char *pname; - - switch (protocol) { - case SIGAR_NETCONN_TCP: - names = &sigar->net_services_tcp; - pname = "tcp"; - break; - case SIGAR_NETCONN_UDP: - names = &sigar->net_services_udp; - pname = "udp"; - break; - default: - return NULL; - } - - if (*names == NULL) { - *names = sigar_cache_new(1024); - net_services_parse(*names, pname); - } - - if ((entry = sigar_cache_find(*names, port))) { - return (char *)entry->value; - } - else { - return NULL; - } -} - -SIGAR_DECLARE(int) sigar_cpu_perc_calculate(sigar_cpu_t *prev, - sigar_cpu_t *curr, - sigar_cpu_perc_t *perc) -{ - double diff_user, diff_sys, diff_nice, diff_idle; - double diff_wait, diff_irq, diff_soft_irq, diff_stolen; - double diff_total; - - diff_user = curr->user - prev->user; - diff_sys = curr->sys - prev->sys; - diff_nice = curr->nice - prev->nice; - diff_idle = curr->idle - prev->idle; - diff_wait = curr->wait - prev->wait; - diff_irq = curr->irq - prev->irq; - diff_soft_irq = curr->soft_irq - prev->soft_irq; - diff_stolen = curr->stolen - prev->stolen; - - diff_user = diff_user < 0 ? 0 : diff_user; - diff_sys = diff_sys < 0 ? 0 : diff_sys; - diff_nice = diff_nice < 0 ? 0 : diff_nice; - diff_idle = diff_idle < 0 ? 0 : diff_idle; - diff_wait = diff_wait < 0 ? 0 : diff_wait; - diff_irq = diff_irq < 0 ? 0 : diff_irq; - diff_soft_irq = diff_soft_irq < 0 ? 0 : diff_soft_irq; - diff_stolen = diff_stolen < 0 ? 0 : diff_stolen; - - diff_total = - diff_user + diff_sys + diff_nice + diff_idle + - diff_wait + diff_irq + diff_soft_irq + - diff_stolen; - - perc->user = diff_user / diff_total; - perc->sys = diff_sys / diff_total; - perc->nice = diff_nice / diff_total; - perc->idle = diff_idle / diff_total; - perc->wait = diff_wait / diff_total; - perc->irq = diff_irq / diff_total; - perc->soft_irq = diff_soft_irq / diff_total; - perc->stolen = diff_stolen / diff_total; - - perc->combined = - perc->user + perc->sys + perc->nice + perc->wait; - - return SIGAR_OK; -} diff --git a/vendor/sigar/src/sigar_getline.c b/vendor/sigar/src/sigar_getline.c deleted file mode 100644 index 0a8946b..0000000 --- a/vendor/sigar/src/sigar_getline.c +++ /dev/null @@ -1,1849 +0,0 @@ -/* - * Copyright (C) 1991, 1992 by Chris Thewalt (thewalt@ce.berkeley.edu) - * - * Permission to use, copy, modify, and distribute this software - * for any purpose and without fee is hereby granted, provided - * that the above copyright notices appear in all copies and that both the - * copyright notice and this permission notice appear in supporting - * documentation. This software is provided "as is" without express or - * implied warranty. - */ -/* -*************************** Motivation ********************************** - -Many interactive programs read input line by line, but would like to -provide line editing and history functionality to the end-user that -runs the program. - -The input-edit package provides that functionality. As far as the -programmer is concerned, the program only asks for the next line -of input. However, until the user presses the RETURN key they can use -emacs-style line editing commands and can traverse the history of lines -previously typed. - -Other packages, such as GNU's readline, have greater capability but are -also substantially larger. Input-edit is small, since it uses neither -stdio nor any termcap features, and is also quite portable. It only uses -\b to backspace and \007 to ring the bell on errors. Since it cannot -edit multiple lines it scrolls long lines left and right on the same line. - -Input edit uses classic (not ANSI) C, and should run on any Unix -system (BSD or SYSV), PC's with the MSC compiler, or Vax/VMS (untested by me). -Porting the package to new systems basicaly requires code to read a -character when it is typed without echoing it, everything else should be OK. - -I have run the package on: - - DECstation 5000, Ultrix 4.2 with cc and gcc - Sun Sparc 2, SunOS 4.1.1, with cc - SGI Iris, IRIX System V.3, with cc - PC, DRDOS 5.0, with MSC 6.0 - -The description below is broken into two parts, the end-user (editing) -interface and the programmer interface. Send bug reports, fixes and -enhancements to: - -Chris Thewalt (thewalt@ce.berkeley.edu) -2/4/92 - -PS: I don't have, and don't want to add, a vi mode, sorry. - -************************** End-User Interface *************************** - -Entering printable keys generally inserts new text into the buffer (unless -in overwrite mode, see below). Other special keys can be used to modify -the text in the buffer. In the description of the keys below, ^n means -Control-n, or holding the CONTROL key down while pressing "n". M-B means -Meta-B (or Alt-B). Errors will ring the terminal bell. - -^A/^E : Move cursor to beginning/end of the line. -^F/^B : Move cursor forward/backward one character. -^D : Delete the character under the cursor. -^H, DEL : Delete the character to the left of the cursor. -^K : Kill from the cursor to the end of line. -^L : Redraw current line. -^O : Toggle overwrite/insert mode. Initially in insert mode. Text - added in overwrite mode (including yanks) overwrite - existing text, while insert mode does not overwrite. -^P/^N : Move to previous/next item on history list. -^R/^S : Perform incremental reverse/forward search for string on - the history list. Typing normal characters adds to the current - search string and searches for a match. Typing ^R/^S marks - the start of a new search, and moves on to the next match. - Typing ^H or DEL deletes the last character from the search - string, and searches from the starting location of the last search. - Therefore, repeated DEL's appear to unwind to the match nearest - the point at which the last ^R or ^S was typed. If DEL is - repeated until the search string is empty the search location - begins from the start of the history list. Typing ESC or - any other editing character accepts the current match and - loads it into the buffer, terminating the search. -^T : Toggle the characters under and to the left of the cursor. -^U : Kill from beginning to the end of the line. -^Y : Yank previously killed text back at current location. Note that - this will overwrite or insert, depending on the current mode. -M-F/M-B : Move cursor forward/backward one word. -M-D : Delete the word under the cursor. -^SPC : Set mark. -^W : Kill from mark to point. -^X : Exchange mark and point. -TAB : By default adds spaces to buffer to get to next TAB stop - (just after every 8th column), although this may be rebound by the - programmer, as described below. -NL, CR : returns current buffer to the program. - -DOS and ANSI terminal arrow key sequences are recognized, and act like: - - up : same as ^P - down : same as ^N - left : same as ^B - right : same as ^F - -************************** Programmer Interface *************************** - -The programmer accesses input-edit through five functions, and optionally -through three additional function pointer hooks. The five functions are: - -char *Getline(char *prompt) - - Prints the prompt and allows the user to edit the current line. A - pointer to the line is returned when the user finishes by - typing a newline or a return. Unlike GNU readline, the returned - pointer points to a static buffer, so it should not be free'd, and - the buffer contains the newline character. The user enters an - end-of-file by typing ^D on an empty line, in which case the - first character of the returned buffer is '\0'. Getline never - returns a NULL pointer. The getline function sets terminal modes - needed to make it work, and resets them before returning to the - caller. The getline function also looks for characters that would - generate a signal, and resets the terminal modes before raising the - signal condition. If the signal handler returns to getline, - the screen is automatically redrawn and editing can continue. - Getline now requires both the input and output stream be connected - to the terminal (not redirected) so the main program should check - to make sure this is true. If input or output have been redirected - the main program should use buffered IO (stdio) rather than - the slow 1 character read()s that getline uses (note: this limitation - has been removed). - -char *Getlinem(int mode, char *prompt) - - mode: -1 = init, 0 = line mode, 1 = one char at a time mode, 2 = cleanup - - More specialized version of the previous function. Depending on - the mode, it behaves differently. Its main use is to allow - character by character input from the input stream (useful when - in an X eventloop). It will return NULL as long as no newline - has been received. Its use is typically as follows: - 1) In the program initialization part one calls: Getlinem(-1,"prompt>") - 2) In the X inputhandler: if ((line = Getlinem(1,NULL))) { - 3) In the termination routine: Getlinem(2,NULL) - With mode=0 the function behaves exactly like the previous function. - -void Gl_config(const char *which, int value) - - Set some config options. Which can be: - "noecho": do not echo characters (used for passwd input) - "erase": do erase line after return (used for text scrollers) - -void Gl_setwidth(int width) - - Set the width of the terminal to the specified width. The default - width is 80 characters, so this function need only be called if the - width of the terminal is not 80. Since horizontal scrolling is - controlled by this parameter it is important to get it right. - -void Gl_histinit(char *file) - - This function reads a history list from file. So lines from a - previous session can be used again. - -void Gl_histadd(char *buf) - - The Gl_histadd function checks to see if the buf is not empty or - whitespace, and also checks to make sure it is different than - the last saved buffer to avoid repeats on the history list. - If the buf is a new non-blank string a copy is made and saved on - the history list, so the caller can re-use the specified buf. - -The main loop in testgl.c, included in this directory, shows how the -input-edit package can be used: - -extern char *Getline(); -extern void Gl_histadd(); -main() -{ - char *p; - Gl_histinit(".hist"); - do { - p = Getline("PROMPT>>>> "); - Gl_histadd(p); - fputs(p, stdout); - } while (*p != 0); -} - -In order to allow the main program to have additional access to the buffer, -to implement things such as completion or auto-indent modes, three -function pointers can be bound to user functions to modify the buffer as -described below. By default gl_in_hook and gl_out_hook are set to NULL, -and gl_tab_hook is bound to a function that inserts spaces until the next -logical tab stop is reached. The user can reassign any of these pointers -to other functions. Each of the functions bound to these hooks receives -the current buffer as the first argument, and must return the location of -the leftmost change made in the buffer. If the buffer isn't modified the -functions should return -1. When the hook function returns the screen is -updated to reflect any changes made by the user function. - -int (*gl_in_hook)(char *buf) - - If gl_in_hook is non-NULL the function is called each time a new - buffer is loaded. It is called when getline is entered, with an - empty buffer, it is called each time a new buffer is loaded from - the history with ^P or ^N, and it is called when an incremental - search string is accepted (when the search is terminated). The - buffer can be modified and will be redrawn upon return to Getline(). - -int (*gl_out_hook)(char *buf) - - If gl_out_hook is non-NULL it is called when a line has been - completed by the user entering a newline or return. The buffer - handed to the hook does not yet have the newline appended. If the - buffer is modified the screen is redrawn before getline returns the - buffer to the caller. - -int (*gl_tab_hook)(char *buf, int prompt_width, int *cursor_loc) - - If gl_tab_hook is non-NULL, it is called whenever a tab is typed. - In addition to receiving the buffer, the current prompt width is - given (needed to do tabbing right) and a pointer to the cursor - offset is given, where a 0 offset means the first character in the - line. Not only does the cursor_loc tell the programmer where the - TAB was received, but it can be reset so that the cursor will end - up at the specified location after the screen is redrawn. -*/ - -/* forward reference needed for gl_tab_hook */ -static int gl_tab(char *buf, int offset, int *loc); - -/********************* exported interface ********************************/ - -static int (*gl_in_hook)(char *buf) = 0; -static int (*gl_out_hook)(char *buf) = 0; -static int (*gl_tab_hook)(char *buf, int prompt_width, int *loc) = gl_tab; - -/******************** imported interface *********************************/ -#ifdef DMALLOC -/* reports leaks, which is the history buffer. dont care */ -#undef DMALLOC -#endif -#include "sigar_getline.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include -#include -#include -#include -#include -#include - -/******************** internal interface *********************************/ - -static char *sigar_getlinem(int mode, char *prompt); /* allows reading char by char */ - -static void sigar_getline_config(const char *which, int value); /* set some options */ - -static void sigar_getline_clear_screen(void); - -#define BUF_SIZE 8096 - -static int gl_init_done = -1; /* terminal mode flag */ -static int gl_notty = 0; /* 1 when not a tty */ -static int gl_eof = 0; /* 1 when not a tty and read() == -1 */ -static int gl_termw = 80; /* actual terminal width */ -static int gl_scroll = 27; /* width of EOL scrolling region */ -static int gl_width = 0; /* net size available for input */ -static int gl_extent = 0; /* how far to redraw, 0 means all */ -static int gl_overwrite = 0; /* overwrite mode */ -static int gl_no_echo = 0; /* do not echo input characters */ -static int gl_passwd = 0; /* do not echo input characters */ -static int gl_erase_line = 0; /* erase line before returning */ -static int gl_pos, gl_cnt = 0; /* position and size of input */ -static char gl_buf[BUF_SIZE]; /* input buffer */ -static char gl_killbuf[BUF_SIZE]=""; /* killed text */ -static char *gl_prompt; /* to save the prompt string */ -static char gl_intrc = 0; /* keyboard SIGINT char */ -static char gl_quitc = 0; /* keyboard SIGQUIT char */ -static char gl_suspc = 0; /* keyboard SIGTSTP char */ -static char gl_dsuspc = 0; /* delayed SIGTSTP char */ -static int gl_search_mode = 0; /* search mode flag */ -static int gl_bell_enabled = 0; /* bell mode */ -static int gl_savehist = 0; /* # of lines to save in hist file */ -static char gl_histfile[256]; /* name of history file */ - -static void gl_init(); /* prepare to edit a line */ -static void gl_bell(); /* ring bell */ -static void gl_cleanup(); /* to undo gl_init */ -static void gl_char_init(); /* get ready for no echo input */ -static void gl_char_cleanup(); /* undo gl_char_init */ - -static void gl_addchar(int c); /* install specified char */ -static void gl_del(int loc); /* del, either left (-1) or cur (0) */ -static void gl_error(char *buf); /* write error msg and die */ -static void gl_fixup(char *p, int c, int cur); /* fixup state variables and screen */ -static int gl_getc(); /* read one char from terminal */ -static void gl_kill(); /* delete to EOL */ -static void gl_newline(); /* handle \n or \r */ -static void gl_putc(int c); /* write one char to terminal */ -static void gl_puts(char *buf); /* write a line to terminal */ -static void gl_transpose(); /* transpose two chars */ -static void gl_yank(); /* yank killed text */ - -static int is_whitespace(char c); /* "whitespace" very loosely interpreted */ -static void gl_back_1_word(); /* move cursor back one word */ -static void gl_kill_1_word(); /* kill to end of word */ -static void gl_kill_region(int i, int j); /* kills from i to j */ -static void gl_fwd_1_word(); /* move cursor forward one word */ -static void gl_set_mark(); /* sets mark to be at point */ -static void gl_exch(); /* exchanges point and mark */ -static void gl_wipe(); /* kills from mark to point */ -static int gl_mark = -1; /* position of mark. gl_mark<0 if not set */ - -static void hist_init(); /* initializes hist pointers */ -static char *hist_next(); /* return ptr to next item */ -static char *hist_prev(); /* return ptr to prev item */ -static char *hist_save(char *p); /* makes copy of a string, without NL */ - -static void search_addchar(int c); /* increment search string */ -static void search_term(); /* reset with current contents */ -static void search_back(int s); /* look back for current string */ -static void search_forw(int s); /* look forw for current string */ - -/************************ nonportable part *********************************/ - -#ifdef MSDOS -#include -#endif - -#ifdef WIN32 -# define MSDOS -# include -# include -#endif /* WIN32 */ - -#ifdef __MWERKS__ -#define R__MWERKS -#endif - -#ifdef R__MWERKS -# include -#endif - -#if defined(_AIX) || defined(__Lynx__) || defined(__APPLE__) -#define unix -#endif - -#if defined(__hpux) || defined(__osf__) /* W.Karig@gsi.de */ -#ifndef unix -#define unix -#endif -#endif - -#ifdef unix -#include -#if !defined(__osf__) && !defined(_AIX) /* W.Karig@gsi.de */ -#include -#endif - -#if defined(__linux__) && defined(__powerpc__) -# define R__MKLINUX // = linux on PowerMac -#endif -#if defined(__linux__) && defined(__alpha__) -# define R__ALPHALINUX // = linux on Alpha -#endif - -#if defined(TIOCGETP) && !defined(__sgi) && !defined(R__MKLINUX) && \ - !defined(R__ALPHALINUX) /* use BSD interface if possible */ -#include -static struct sgttyb new_tty, old_tty; -static struct tchars tch; -static struct ltchars ltch; -#else -#ifdef SIGTSTP /* need POSIX interface to handle SUSP */ -#include -#if defined(__sun) || defined(__sgi) || defined(R__MKLINUX) || \ - defined(R__ALPHALINUX) -#undef TIOCGETP /* Solaris and SGI define TIOCGETP in */ -#undef TIOCSETP -#endif -static struct termios new_termios, old_termios; -#else /* use SYSV interface */ -#include -static struct termio new_termio, old_termio; -#endif -#endif -#endif /* unix */ - -#ifdef VMS -#include -#include -#include -#include -#include -#include unixio - -static int setbuff[2]; /* buffer to set terminal attributes */ -static short chan = -1; /* channel to terminal */ -struct dsc$descriptor_s descrip; /* VMS descriptor */ -#endif - -static void -sigar_getline_config(const char *which, int value) -{ - if (strcmp(which, "noecho") == 0) - gl_no_echo = value; - else if (strcmp(which, "erase") == 0) - gl_erase_line = value; - else - printf("gl_config: %s ?\n", which); -} - -static void -gl_char_init() /* turn off input echo */ -{ - if (gl_notty) return; -#ifdef unix -#ifdef TIOCGETP /* BSD */ - ioctl(0, TIOCGETC, &tch); - ioctl(0, TIOCGLTC, <ch); - gl_intrc = tch.t_intrc; - gl_quitc = tch.t_quitc; - gl_suspc = ltch.t_suspc; - gl_dsuspc = ltch.t_dsuspc; - ioctl(0, TIOCGETP, &old_tty); - new_tty = old_tty; - new_tty.sg_flags |= RAW; - new_tty.sg_flags &= ~ECHO; - ioctl(0, TIOCSETP, &new_tty); -#else -#ifdef SIGTSTP /* POSIX */ - tcgetattr(0, &old_termios); - gl_intrc = old_termios.c_cc[VINTR]; - gl_quitc = old_termios.c_cc[VQUIT]; -#ifdef VSUSP - gl_suspc = old_termios.c_cc[VSUSP]; -#endif -#ifdef VDSUSP - gl_dsuspc = old_termios.c_cc[VDSUSP]; -#endif - new_termios = old_termios; - new_termios.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF); - new_termios.c_iflag |= (IGNBRK|IGNPAR); - new_termios.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO); - new_termios.c_cc[VMIN] = 1; - new_termios.c_cc[VTIME] = 0; - tcsetattr(0, TCSANOW, &new_termios); -#else /* SYSV */ - ioctl(0, TCGETA, &old_termio); - gl_intrc = old_termio.c_cc[VINTR]; - gl_quitc = old_termio.c_cc[VQUIT]; - new_termio = old_termio; - new_termio.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF); - new_termio.c_iflag |= (IGNBRK|IGNPAR); - new_termio.c_lflag &= ~(ICANON|ISIG|ECHO); - new_termio.c_cc[VMIN] = 1; - new_termio.c_cc[VTIME] = 0; - ioctl(0, TCSETA, &new_termio); -#endif -#endif -#endif /* unix */ - -#ifdef MSDOS - gl_intrc = 'C' - '@'; - gl_quitc = 'Q' - '@'; -// gl_suspc = ltch.t_suspc; -#endif /* MSDOS */ - -#ifdef R__MWERKS - gl_intrc = 'C' - '@'; - gl_quitc = 'Q' - '@'; -#endif - -#ifdef vms - descrip.dsc$w_length = strlen("tt:"); - descrip.dsc$b_dtype = DSC$K_DTYPE_T; - descrip.dsc$b_class = DSC$K_CLASS_S; - descrip.dsc$a_pointer = "tt:"; - (void)sys$assign(&descrip,&chan,0,0); - (void)sys$qiow(0,chan,IO$_SENSEMODE,0,0,0,setbuff,8,0,0,0,0); - setbuff[1] |= TT$M_NOECHO; - (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0); -#endif /* vms */ -} - -static void -gl_char_cleanup() /* undo effects of gl_char_init */ -{ - if (gl_notty) return; -#ifdef unix -#ifdef TIOCSETP /* BSD */ - ioctl(0, TIOCSETP, &old_tty); -#else -#ifdef SIGTSTP /* POSIX */ - tcsetattr(0, TCSANOW, &old_termios); -#else /* SYSV */ - ioctl(0, TCSETA, &old_termio); -#endif -#endif -#endif /* unix */ - -#ifdef vms - setbuff[1] &= ~TT$M_NOECHO; - (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0); - sys$dassgn(chan); - chan = -1; -#endif -} - -#if defined(MSDOS) && !defined(WIN32) -// +DECK, PAUSE, T=XCC, IF=WINNT. (from KERNDOS.CAR ) -# include - int pause_() - { - int first_char; - first_char = _getch(); - if (first_char == 0 || first_char == 0xE0) first_char = -_getch(); - return first_char; - } -#endif - -#if defined(MSDOS) && defined(WIN32) -//______________________________________________________________________________ -int pause_() -{ - static HANDLE hConsoleInput = NULL; - static iCharCount = 0; - static int chLastChar = 0; - - DWORD cRead; - - INPUT_RECORD pirBuffer; - KEY_EVENT_RECORD *KeyEvent= (KEY_EVENT_RECORD *)&(pirBuffer.Event); - - if (!hConsoleInput) hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); - - if (iCharCount) iCharCount--; // Whether several symbols had been read - else { - chLastChar = 0; - while (chLastChar == 0) { - if (!ReadConsoleInput(hConsoleInput, // handle of a console input buffer - &pirBuffer, // address of the buffer for read data - 1, // number of records to read - &cRead // address of number of records read - )) return 0; - - if (pirBuffer.EventType == KEY_EVENT && KeyEvent->bKeyDown == TRUE){ - iCharCount = KeyEvent->wRepeatCount - 1; - chLastChar = ((int) (KeyEvent->uChar).AsciiChar & 0xffff); - if (chLastChar) - OemToCharBuff((char const *)&chLastChar,(char *)&chLastChar,1); - else - chLastChar = - (KeyEvent->wVirtualScanCode); -// chLastChar = - (KeyEvent->wVirtualKeyCode); - } - } - } - return chLastChar; - -} -#endif - -static int -gl_getc() -/* get a character without echoing it to screen */ -{ -#ifdef MSDOS -# define k_ctrl_C 3 -# define k_ctrl_Z 26 -# define k_ctrl_Q 17 -# define k_ctrl_K 11 -# define k_rt_arr -77 -# define k_lt_arr -75 -# define k_up_arr -72 -# define k_dn_arr -80 -# define k_PGUP -73 -# define k_PGDW -81 -# define k_HOME -71 -# define k_END -79 -# define k_INS -82 -# define k_DEL -83 -# define k_ENTER 13 -# define k_CR 13 -# define k_BS 8 -# define k_ESC 27 -# define k_alt_H -35 -# define k_beep 7 -# ifndef WIN32 - int get_cursor__(int *,int *); - int display_off__(int *); - int display_on__(); - int locate_(int *,int *); - int ixc, iyc; -# endif - int pause_(); -#endif - - int c; - -#if defined(unix) - unsigned char ch; - while ((c = (read(0, &ch, 1) > 0) ? ch : -1) == -1 && errno == EINTR) - errno = 0; -#endif - -#if defined(R__MWERKS) - c = getchar(); -#endif - -#ifdef MSDOS - c = pause_(); - if (c < 0) { - switch (c) { - case k_up_arr: c = 'P' - '@'; /* up -> ^P = 16 */ - break; - case k_dn_arr: c = 'N' - '@'; /* down -> ^N = 14 */ - break; - case k_lt_arr: c = 'B' - '@'; /* left -> ^B =2 */ - break; - case k_rt_arr: c = 'F' - '@'; /* right -> ^F = 6*/ - break; - case k_INS: c = 'O' - '@'; /* right -> ^O = 15*/ - break; - case k_DEL: c = 'D' - '@'; /* Delete character under cursor = 4*/ - break; - case k_END: c = 'E' - '@'; /* Moves cursor to end of line * = 5 */ - break; - case k_HOME: c = 'A' - '@'; /* Moves cursor to beginning of line = 1*/ - break; - default: c = 0; /* make it garbage */ - } - } - else { - switch(c) { - case k_ESC: c = 'U' - '@'; /* Clear full line -> ^U */ - break; - default: - break; - } - } -#endif - -#ifdef vms - if(chan < 0) { - c='\0'; - } - (void)sys$qiow(0,chan,IO$_TTYREADALL,0,0,0,&c,1,0,0,0,0); - c &= 0177; /* get a char */ -#endif - return c; -} - -static void -gl_putc(int c) -{ - char ch = c; - - if (gl_notty) return; - - if ( !gl_passwd || !isgraph(c)) - { -#ifdef WIN32 - CharToOemBuff((char const *)&c,&ch,1); -#endif - - sigar_write(1, &ch, 1); - } -#if defined(unix) || defined(MSDOS) || defined(WIN32) || defined(R__MWERKS) -#ifdef TIOCSETP /* BSD in RAW mode, map NL to NL,CR */ - if (ch == '\n') { - ch = '\r'; - sigar_write(1, &ch, 1); - } -#endif -#endif -} - -/******************** fairly portable part *********************************/ - -static void -gl_puts(char *buf) -{ - int len = strlen(buf); - - if (gl_notty) return; -#ifdef WIN32 - { - char *OemBuf = (char *)malloc(2*len); - CharToOemBuff(buf,OemBuf,len); - sigar_write(1, OemBuf, len); - free(OemBuf); - } -#else - sigar_write(1, buf, len); -#endif -} - -static void -gl_error(char *buf) -{ - int len = strlen(buf); - - gl_cleanup(); -#ifdef WIN32 - { - char *OemBuf = (char *)malloc(2*len); - CharToOemBuff(buf,OemBuf,len); - sigar_write(2, OemBuf, len); - free(OemBuf); - } -#else - sigar_write(2, buf, len); -#endif - exit(1); -} - -static void -gl_init() -/* set up variables and terminal */ -{ - if (gl_init_done < 0) { /* -1 only on startup */ - hist_init(); - } - if (sigar_isatty(0) == 0 || sigar_isatty(1) == 0) - gl_notty = 1; - gl_char_init(); - gl_init_done = 1; -} - -static void -gl_bell() -{ - if (gl_bell_enabled) { - gl_putc('\007'); - } -} - -static void -gl_cleanup() -/* undo effects of gl_init, as necessary */ -{ - if (gl_init_done > 0) - gl_char_cleanup(); - gl_init_done = 0; -} - -SIGAR_DECLARE(void) -sigar_getline_setwidth(int w) -{ - if (w > 20) { - gl_termw = w; - gl_scroll = w / 3; - } else { - gl_error("\n*** Error: minimum screen width is 21\n"); - } -} - -SIGAR_DECLARE(void) -sigar_getline_windowchanged() -{ -#ifdef TIOCGWINSZ - if (sigar_isatty(0)) { - static char lenv[32], cenv[32]; - struct winsize wins; - ioctl(0, TIOCGWINSZ, &wins); - - if (wins.ws_col == 0) wins.ws_col = 80; - if (wins.ws_row == 0) wins.ws_row = 24; - - sigar_getline_setwidth(wins.ws_col); - - sprintf(lenv, "LINES=%d", wins.ws_row); - putenv(lenv); - sprintf(cenv, "COLUMNS=%d", wins.ws_col); - putenv(cenv); - } -#endif -} - -/* -1 = init, 0 = line mode, 1 = one char at a time mode, 2 = cleanup */ - -static char * -sigar_getlinem(int mode, char *prompt) -{ - int c, loc, tmp; - int sig; - - if (mode == 2) { - gl_cleanup(); - return NULL; - } - - if (mode < 1) { - if (mode == -1) { - sigar_getline_config("noecho", 0); - sigar_getline_config("erase", 0); - } - gl_init(); - gl_prompt = (prompt)? prompt : (char*)""; - gl_buf[0] = 0; - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, -2, BUF_SIZE); - if (mode == -1) return NULL; - } - while ((c = gl_getc()) >= 0) { - gl_extent = 0; /* reset to full extent */ -#ifndef WIN32 - if (isprint(c)) { -#else - if (c >= ' ') { -#endif - if (gl_search_mode) - search_addchar(c); - else - gl_addchar(c); - } else { - if (gl_search_mode) { - if (c == '\033' || c == '\016' || c == '\020') { - search_term(); - c = 0; /* ignore the character */ - } else if (c == '\010' || c == '\177') { - search_addchar(-1); /* unwind search string */ - c = 0; - } else if (c != '\022' && c != '\023') { - search_term(); /* terminate and handle char */ - } - } - /* NOTE: - * sometimes M-x turns on bit 8 ( M-x --> 'x' + 128 ) - * sometimes M-x prepends an escape character ( M-x --> '\033','x' ) - * both cases are handled ... - */ - switch (c) - { - case 'b'+128: /* M-b */ - case 'B'+128: /* M-B */ - gl_back_1_word(); - break; - case 'd'+128: /* M-d */ - case 'D'+128: /* M-D */ - gl_kill_1_word(); - break; - case 'f'+128: /* M-f */ - case 'F'+128: /* M-F */ - gl_fwd_1_word(); - break; - case '\000': /* ^SPC */ - gl_set_mark(); - break; - case '\027': /* ^W */ - gl_wipe(); - break; - case '\030': /* ^X */ - gl_exch(); - break; - case '\n': /* newline */ - case '\r': - gl_newline(); - gl_cleanup(); - return gl_buf; - /*NOTREACHED*/ - break; - case '\001': gl_fixup(gl_prompt, -1, 0); /* ^A */ - break; - case '\002': gl_fixup(gl_prompt, -1, gl_pos-1); /* ^B */ - break; - case '\004': /* ^D */ - if (gl_cnt == 0) { - gl_buf[0] = 0; - gl_cleanup(); - gl_putc('\n'); - return gl_buf; - } else { - gl_del(0); - } - break; - case '\005': gl_fixup(gl_prompt, -1, gl_cnt); /* ^E */ - break; - case '\006': gl_fixup(gl_prompt, -1, gl_pos+1); /* ^F */ - break; - case '\010': case '\177': gl_del(-1); /* ^H and DEL */ - break; - case '\t': /* TAB */ - if (gl_tab_hook) { - tmp = gl_pos; - loc = gl_tab_hook(gl_buf, strlen(gl_prompt), &tmp); - if (loc >= 0 || tmp != gl_pos || loc == -2) - gl_fixup(gl_prompt, loc, tmp); - } - break; - case '\013': gl_kill(); /* ^K */ - break; - case '\014': sigar_getline_clear_screen(); /* ^L */ - break; - case '\016': /* ^N */ - strcpy(gl_buf, hist_next()); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, BUF_SIZE); - break; - case '\017': gl_overwrite = !gl_overwrite; /* ^O */ - break; - case '\020': /* ^P */ - strcpy(gl_buf, hist_prev()); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, BUF_SIZE); - break; - case '\022': search_back(1); /* ^R */ - break; - case '\023': search_forw(1); /* ^S */ - break; - case '\024': gl_transpose(); /* ^T */ - break; - case '\025': gl_fixup(gl_prompt,-1,0); gl_kill(); /* ^U */ - break; - case '\031': gl_yank(); /* ^Y */ - break; - case '\033': - switch(c = gl_getc()) - { - case 'b': /* M-b */ - case 'B': /* M-B */ - gl_back_1_word(); - break; - case 'd': /* M-d */ - case 'D': /* M-D */ - gl_kill_1_word(); - break; - case 'f': /* M-f */ - case 'F': /* M-F */ - gl_fwd_1_word(); - break; - case '[': /* ansi arrow keys */ - case 'O': /* xterm arrow keys */ - switch(c = gl_getc()) - { - case 'A': /* up */ - strcpy(gl_buf, hist_prev()); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, BUF_SIZE); - break; - case 'B': /* down */ - strcpy(gl_buf, hist_next()); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, BUF_SIZE); - break; - case 'C': gl_fixup(gl_prompt, -1, gl_pos+1); /* right */ - break; - case 'D': gl_fixup(gl_prompt, -1, gl_pos-1); /* left */ - break; - default: /* who knows */ - gl_bell(); - break; - } - break; - default: - gl_bell(); - } - break; - default: /* check for a terminal signal */ - -#if defined(unix) || defined(WIN32) || defined(R__MWERKS) - if (c > 0) { /* ignore 0 (reset above) */ - sig = 0; -#ifdef SIGINT - if (c == gl_intrc) - sig = SIGINT; -#endif -#ifdef SIGQUIT - if (c == gl_quitc) - sig = SIGQUIT; -#endif -#ifdef SIGTSTP - if (c == gl_suspc || c == gl_dsuspc) - sig = SIGTSTP; -#endif - if (sig != 0) { - gl_cleanup(); -#if !defined(WIN32) - raise(sig); -#endif -#ifdef WIN32 - if (sig == SIGINT) GenerateConsoleCtrlEvent(CTRL_C_EVENT,0); - else raise(sig); -#endif - gl_init(); - sigar_getline_redraw(); - c = 0; - } - } -#endif /* unix */ - if (c > 0) - gl_bell(); - break; - } - } - if (mode == 1) return NULL; - } - if (c == -1 && gl_notty) - gl_eof = 1; - else - gl_eof = 0; - - gl_cleanup(); - gl_buf[0] = 0; - return gl_buf; -} - -SIGAR_DECLARE(int) -sigar_getline_eof() -{ - return gl_eof; -} - -SIGAR_DECLARE(char *) -sigar_getline(char *prompt) -{ - return sigar_getlinem(0, prompt); -} - -static void -gl_addchar(int c) -/* adds the character c to the input buffer at current location */ -{ - int i; - - if (gl_cnt >= BUF_SIZE - 1) - gl_error("\n*** Error: sigar_getline(): input buffer overflow\n"); - if (gl_overwrite == 0 || gl_pos == gl_cnt) { - for (i=gl_cnt; i >= gl_pos; i--) - gl_buf[i+1] = gl_buf[i]; - gl_buf[gl_pos] = c; - gl_fixup(gl_prompt, gl_pos, gl_pos+1); - } else { - gl_buf[gl_pos] = c; - gl_extent = 1; - gl_fixup(gl_prompt, gl_pos, gl_pos+1); - } -} - -static void -gl_yank() -/* adds the kill buffer to the input buffer at current location */ -{ - int i, len; - - len = strlen(gl_killbuf); - if (len > 0) { - gl_mark = gl_pos; - if (gl_overwrite == 0) { - if (gl_cnt + len >= BUF_SIZE - 1) - gl_error("\n*** Error: sigar_getline(): input buffer overflow\n"); - for (i=gl_cnt; i >= gl_pos; i--) - gl_buf[i+len] = gl_buf[i]; - for (i=0; i < len; i++) - gl_buf[gl_pos+i] = gl_killbuf[i]; - gl_fixup(gl_prompt, gl_pos, gl_pos+len); - } else { - if (gl_pos + len > gl_cnt) { - if (gl_pos + len >= BUF_SIZE - 1) - gl_error("\n*** Error: sigar_getline(): input buffer overflow\n"); - gl_buf[gl_pos + len] = 0; - } - for (i=0; i < len; i++) - gl_buf[gl_pos+i] = gl_killbuf[i]; - gl_extent = len; - gl_fixup(gl_prompt, gl_pos, gl_pos+len); - } - } else - gl_bell(); -} - -static void -gl_transpose() -/* switch character under cursor and to left of cursor */ -{ - int c; - - if (gl_pos > 0 && gl_cnt > gl_pos) { - c = gl_buf[gl_pos-1]; - gl_buf[gl_pos-1] = gl_buf[gl_pos]; - gl_buf[gl_pos] = c; - gl_extent = 2; - gl_fixup(gl_prompt, gl_pos-1, gl_pos); - } else - gl_bell(); -} - -static void -gl_newline() -/* - * Cleans up entire line before returning to caller. A \n is appended. - * If line longer than screen, we redraw starting at beginning - */ -{ - int change = gl_cnt; - int len = gl_cnt; - int loc = gl_width - 5; /* shifts line back to start position */ - - if (gl_cnt >= BUF_SIZE - 1) - gl_error("\n*** Error: sigar_getline(): input buffer overflow\n"); - if (gl_out_hook) { - change = gl_out_hook(gl_buf); - len = strlen(gl_buf); - } - if (gl_erase_line) { - char gl_buf0 = gl_buf[0]; - gl_buf[0] = '\0'; - gl_fixup("", 0, 0); - gl_buf[0] = gl_buf0; - } - else { - if (loc > len) - loc = len; - gl_fixup(gl_prompt, change, loc); /* must do this before appending \n */ - gl_putc('\n'); - } -#if 0 - gl_buf[len] = '\n'; - gl_buf[len+1] = '\0'; -#endif - gl_mark = -1; -} - -static void -gl_del(int loc) -/* - * Delete a character. The loc variable can be: - * -1 : delete character to left of cursor - * 0 : delete character under cursor - */ -{ - int i; - - if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) { - for (i=gl_pos+loc; i < gl_cnt; i++) - gl_buf[i] = gl_buf[i+1]; - gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc); - } else - gl_bell(); -} - -static void -gl_kill() -/* delete from current position to the end of line */ -{ - if (gl_pos < gl_cnt) { - strcpy(gl_killbuf, gl_buf + gl_pos); - gl_buf[gl_pos] = '\0'; - gl_fixup(gl_prompt, gl_pos, gl_pos); - } else - gl_bell(); -} - -SIGAR_DECLARE(void) sigar_getline_redraw(void) -/* emit a newline, reset and redraw prompt and current input line */ -{ - if (gl_init_done > 0) { - gl_putc('\n'); - gl_fixup(gl_prompt, -2, gl_pos); - } -} - -#define CLEAR_SCREEN "\033[2J" - -static void sigar_getline_clear_screen(void) -{ - if (gl_init_done > 0) { - gl_putc('\n'); - /* XXX what to do for non-ansi term? */ - gl_puts(CLEAR_SCREEN); - gl_fixup(gl_prompt, -2, gl_pos); - } -} - -SIGAR_DECLARE(void) sigar_getline_reset(void) -{ - gl_fixup(gl_prompt,-1,0); - gl_kill(); -} - -static void -gl_fixup(char *prompt, int change, int cursor) -/* - * This function is used both for redrawing when input changes or for - * moving within the input line. The parameters are: - * prompt: compared to last_prompt[] for changes; - * change : the index of the start of changes in the input buffer, - * with -1 indicating no changes, -2 indicating we're on - * a new line, redraw everything. - * cursor : the desired location of the cursor after the call. - * A value of BUF_SIZE can be used to indicate the cursor should - * move just past the end of the input line. - */ -{ - static int gl_shift; /* index of first on screen character */ - static int off_right; /* true if more text right of screen */ - static int off_left; /* true if more text left of screen */ - static char last_prompt[BUF_SIZE] = ""; - int left = 0, right = -1; /* bounds for redraw */ - int padl; /* how much to erase at end of line */ - int backup; /* how far to backup before fixing */ - int new_shift; /* value of shift based on cursor */ - int extra; /* adjusts when shift (scroll) happens */ - int i; - int new_right = -1; /* alternate right bound, using gl_extent */ - int l1, l2; - - if (change == -2) { /* reset */ - gl_pos = gl_cnt = gl_shift = off_right = off_left = 0; - gl_passwd = 0; - gl_puts(prompt); - gl_passwd = gl_no_echo; - strcpy(last_prompt, prompt); - change = 0; - gl_width = gl_termw - strlen(prompt); - } else if (strcmp(prompt, last_prompt) != 0) { - l1 = strlen(last_prompt); - l2 = strlen(prompt); - gl_cnt = gl_cnt + l1 - l2; - strcpy(last_prompt, prompt); - backup = gl_pos - gl_shift + l1; - for (i=0; i < backup; i++) - gl_putc('\b'); - gl_passwd = 0; - gl_puts(prompt); - gl_passwd = gl_no_echo; - gl_pos = gl_shift; - gl_width = gl_termw - l2; - change = 0; - } - padl = (off_right)? gl_width - 1 : gl_cnt - gl_shift; /* old length */ - backup = gl_pos - gl_shift; - if (change >= 0) { - gl_cnt = strlen(gl_buf); - if (change > gl_cnt) - change = gl_cnt; - } - if (cursor > gl_cnt) { - if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */ - gl_bell(); - cursor = gl_cnt; - } - if (cursor < 0) { - gl_bell(); - cursor = 0; - } - if (off_right || (off_left && cursor < gl_shift + gl_width - gl_scroll / 2)) - extra = 2; /* shift the scrolling boundary */ - else - extra = 0; - new_shift = cursor + extra + gl_scroll - gl_width; - if (new_shift > 0) { - new_shift /= gl_scroll; - new_shift *= gl_scroll; - } else - new_shift = 0; - if (new_shift != gl_shift) { /* scroll occurs */ - gl_shift = new_shift; - off_left = (gl_shift)? 1 : 0; - off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0; - left = gl_shift; - new_right = right = (off_right)? gl_shift + gl_width - 2 : gl_cnt; - } else if (change >= 0) { /* no scroll, but text changed */ - if (change < gl_shift + off_left) { - left = gl_shift; - } else { - left = change; - backup = gl_pos - change; - } - off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0; - right = (off_right)? gl_shift + gl_width - 2 : gl_cnt; - new_right = (gl_extent && (right > left + gl_extent))? - left + gl_extent : right; - } - padl -= (off_right)? gl_width - 1 : gl_cnt - gl_shift; - padl = (padl < 0)? 0 : padl; - if (left <= right) { /* clean up screen */ - for (i=0; i < backup; i++) - gl_putc('\b'); - if (left == gl_shift && off_left) { - gl_putc('$'); - left++; - } - for (i=left; i < new_right; i++) - gl_putc(gl_buf[i]); - gl_pos = new_right; - if (off_right && new_right == right) { - gl_putc('$'); - gl_pos++; - } else { - for (i=0; i < padl; i++) /* erase remains of prev line */ - gl_putc(' '); - gl_pos += padl; - } - } - i = gl_pos - cursor; /* move to final cursor location */ - if (i > 0) { - while (i--) - gl_putc('\b'); - } else { - for (i=gl_pos; i < cursor; i++) - gl_putc(gl_buf[i]); - } - gl_pos = cursor; -} - -static int -gl_tab(char *buf, int offset, int *loc) -/* default tab handler, acts like tabstops every 8 cols */ -{ - int i, count, len; - - len = strlen(buf); - count = 8 - (offset + *loc) % 8; - for (i=len; i >= *loc; i--) - buf[i+count] = buf[i]; - for (i=0; i < count; i++) - buf[*loc+i] = ' '; - i = *loc; - *loc = i + count; - return i; -} - -/******************* History stuff **************************************/ - -#ifndef HIST_SIZE -#define HIST_SIZE 100 -#endif - -static int hist_pos = 0, hist_last = 0; -static char *hist_buf[HIST_SIZE]; - -static void -hist_init() -{ - int i; - - if (gl_savehist) return; - - hist_buf[0] = ""; - for (i=1; i < HIST_SIZE; i++) - hist_buf[i] = (char *)0; -} - -SIGAR_DECLARE(void) sigar_getline_completer_set(sigar_getline_completer_t func) -{ - if (func) { - gl_tab_hook = func; - } - else { - gl_tab_hook = gl_tab; - } -} - -SIGAR_DECLARE(void) -sigar_getline_histinit(char *file) -{ - char line[256]; - FILE *fp; - int nline = 1; /* prevent from becoming 0 */ - - gl_savehist = 0; - - hist_init(); - - if (!strcmp(file, "-")) return; - - sprintf(gl_histfile, "%s", file); - - fp = fopen(gl_histfile, "r"); - if (fp) - while (fgets(line, 256, fp)) { - nline++; - sigar_getline_histadd(line); - } - else - fp = fopen(gl_histfile, "w"); - - if (fp) fclose(fp); - - gl_savehist = nline; -} - -SIGAR_DECLARE(void) -sigar_getline_histadd(char *buf) -{ - static char *prev = 0; - char *p = buf; - int len; - - while (*p == ' ' || *p == '\t' || *p == '\n') - p++; - if (*p) { - len = strlen(buf); - if (strchr(p, '\n')) /* previously line already has NL stripped */ - len--; - if (prev == 0 || strlen(prev) != len || - strncmp(prev, buf, len) != 0) { - hist_buf[hist_last] = hist_save(buf); - prev = hist_buf[hist_last]; - hist_last = (hist_last + 1) % HIST_SIZE; - if (hist_buf[hist_last] && *hist_buf[hist_last]) { - free(hist_buf[hist_last]); - } - hist_buf[hist_last] = ""; - - /* append command to history file */ - if (gl_savehist) { - FILE *fp; - fp = fopen(gl_histfile, "a+"); - if (fp) { - fprintf(fp, "%s\n", prev); - gl_savehist++; - fclose(fp); - } - - /* if more than HIST_SIZE lines, safe last 60 command and delete rest */ - if (gl_savehist > HIST_SIZE) { - FILE *ftmp; - char tname[L_tmpnam]; - char line[BUFSIZ]; - - fp = fopen(gl_histfile, "r"); - tmpnam(tname); - ftmp = fopen(tname, "w"); - if (fp && ftmp) { - int nline = 0; - while (fgets(line, BUFSIZ, fp)) { - nline++; - gl_savehist = 1; /* prevent from becoming 0 */ - if (nline > HIST_SIZE-60) { - gl_savehist++; - fprintf(ftmp, "%s", line); - } - } - } - if (fp) fclose(fp); - if (ftmp) fclose(ftmp); - - /* copy back to history file */ - fp = fopen(gl_histfile, "w"); - ftmp = fopen(tname, "r"); - if (fp && ftmp) - while (fgets(line, BUFSIZ, ftmp)) - fprintf(fp, "%s", line); - - if (fp) fclose(fp); - if (ftmp) fclose(ftmp); - remove(tname); - } - } - } - } - hist_pos = hist_last; -} - -static char * -hist_prev() -/* loads previous hist entry into input buffer, sticks on first */ -{ - char *p = 0; - int next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE; - - if (hist_buf[hist_pos] != 0 && next != hist_last) { - hist_pos = next; - p = hist_buf[hist_pos]; - } - if (p == 0) { - p = ""; - gl_bell(); - } - return p; -} - -static char * -hist_next() -/* loads next hist entry into input buffer, clears on last */ -{ - char *p = 0; - - if (hist_pos != hist_last) { - hist_pos = (hist_pos+1) % HIST_SIZE; - p = hist_buf[hist_pos]; - } - if (p == 0) { - p = ""; - gl_bell(); - } - return p; -} - -static char * -hist_save(char *p) -/* makes a copy of the string */ -{ - char *s = 0; - int len = strlen(p); - char *nl = strchr(p, '\n'); - - if (nl) { - if ((s = (char *)malloc(len)) != 0) { - strncpy(s, p, len-1); - s[len-1] = 0; - } - } else { - if ((s = (char *)malloc(len+1)) != 0) { - strcpy(s, p); - } - } - if (s == 0) - gl_error("\n*** Error: hist_save() failed on malloc\n"); - return s; -} - -/******************* Search stuff **************************************/ - -static char search_prompt[101]; /* prompt includes search string */ -static char search_string[100]; -static int search_pos = 0; /* current location in search_string */ -static int search_forw_flg = 0; /* search direction flag */ -static int search_last = 0; /* last match found */ - -static void -search_update(int c) -{ - if (c == 0) { - search_pos = 0; - search_string[0] = 0; - search_prompt[0] = '?'; - search_prompt[1] = ' '; - search_prompt[2] = 0; - } else if (c > 0) { - search_string[search_pos] = c; - search_string[search_pos+1] = 0; - search_prompt[search_pos] = c; - search_prompt[search_pos+1] = '?'; - search_prompt[search_pos+2] = ' '; - search_prompt[search_pos+3] = 0; - search_pos++; - } else { - if (search_pos > 0) { - search_pos--; - search_string[search_pos] = 0; - search_prompt[search_pos] = '?'; - search_prompt[search_pos+1] = ' '; - search_prompt[search_pos+2] = 0; - } else { - gl_bell(); - hist_pos = hist_last; - } - } -} - -static void -search_addchar(int c) -{ - char *loc; - - search_update(c); - if (c < 0) { - if (search_pos > 0) { - hist_pos = search_last; - } else { - gl_buf[0] = 0; - hist_pos = hist_last; - } - strcpy(gl_buf, hist_buf[hist_pos]); - } - if ((loc = strstr(gl_buf, search_string)) != 0) { - gl_fixup(search_prompt, 0, loc - gl_buf); - } else if (search_pos > 0) { - if (search_forw_flg) { - search_forw(0); - } else { - search_back(0); - } - } else { - gl_fixup(search_prompt, 0, 0); - } -} - -static void -search_term() -{ - gl_search_mode = 0; - if (gl_buf[0] == 0) /* not found, reset hist list */ - hist_pos = hist_last; - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, gl_pos); -} - -static void -search_back(int new_search) -{ - int found = 0; - char *p, *loc; - - search_forw_flg = 0; - if (gl_search_mode == 0) { - search_last = hist_pos = hist_last; - search_update(0); - gl_search_mode = 1; - gl_buf[0] = 0; - gl_fixup(search_prompt, 0, 0); - } else if (search_pos > 0) { - while (!found) { - p = hist_prev(); - if (*p == 0) { /* not found, done looking */ - gl_buf[0] = 0; - gl_fixup(search_prompt, 0, 0); - found = 1; - } else if ((loc = strstr(p, search_string)) != 0) { - strcpy(gl_buf, p); - gl_fixup(search_prompt, 0, loc - p); - if (new_search) - search_last = hist_pos; - found = 1; - } - } - } else { - gl_bell(); - } -} - -static void -search_forw(int new_search) -{ - int found = 0; - char *p, *loc; - - search_forw_flg = 1; - if (gl_search_mode == 0) { - search_last = hist_pos = hist_last; - search_update(0); - gl_search_mode = 1; - gl_buf[0] = 0; - gl_fixup(search_prompt, 0, 0); - } else if (search_pos > 0) { - while (!found) { - p = hist_next(); - if (*p == 0) { /* not found, done looking */ - gl_buf[0] = 0; - gl_fixup(search_prompt, 0, 0); - found = 1; - } else if ((loc = strstr(p, search_string)) != 0) { - strcpy(gl_buf, p); - gl_fixup(search_prompt, 0, loc - p); - if (new_search) - search_last = hist_pos; - found = 1; - } - } - } else { - gl_bell(); - } -} -#if 0 -/*********************************************************************** - * * - * Strip blanks from both sides of a string. Space for the new * - * string is allocated and a pointer to it is returned. * - * * - ***********************************************************************/ -char *strip(char *s) -{ - char *r, *t1, *t2; - int l; - - l = strlen(s); - r = (char *)calloc(l+1, 1); - - if (l == 0) { - *r = '\0'; - return r; - } - - /* get rid of leading blanks */ - t1 = s; - while (*t1 == ' ') - t1++; - - t2 = s + l - 1; - while (*t2 == ' ' && t2 > s) - t2--; - - if (t1 > t2) { - *r = '\0'; - return r; - } - strncpy(r, t1, (size_t) (t2-t1+1)); - - return r; -} -#endif -/*****************************************************************************/ -/* Extra routine provided by Christian Lacunza */ -/*****************************************************************************/ - -/* move cursor back to beginning of _current_ word */ -/* unless it's already at the beginning, */ -/* in which case it moves back to the beginning */ -/* of the _previous_ word. */ -static void gl_back_1_word( void ) -{ - int i = gl_pos; - - /* if we're at the beginning of a word, */ - /* slip back into the preceeding whitespace */ - if( i>0 && is_whitespace(gl_buf[i-1]) ) { - i-=1; - } - - /* now move back over all consecutive whitespace */ - while( i>0 && is_whitespace(gl_buf[i]) ) { - i-=1; - } - - /* now keep moving back over all consecutive non-whitespace */ - /* until we find the beginning of this word. */ - /* ie. stop just before more whitespace shows up. */ - while( i>0 && !is_whitespace(gl_buf[i-1]) ) { - i-=1; - } - - /* move the cursor here */ - gl_fixup(gl_prompt, -1, i); -} - -/* kills from current position to end of word */ -static void gl_kill_1_word( void ) -{ - int i = gl_pos; - int j = gl_pos; - -/* delete this: */ -#if 0 - /* not sure what to do with "punctuation" */ - if( is_whitespace(gl_buf[j]) && gl_buf[j]!=' ' ) { - return; - } - /* first find a word */ - while( j - -#ifdef SIGAR_HAS_PCRE -#include "pcre.h" -#endif - -/* See http://gcc.gnu.org/ml/libstdc++/2002-03/msg00164.html */ -#if defined(WIN32) || (defined(__hpux) && defined(SIGAR_64BIT)) -#define strtoull strtoul -#elif (defined(__hpux) && !defined(SIGAR_64BIT)) -#define strtoull __strtoull -#else -#include -#endif - -#define SIGAR_CLEAR_ERRNO() errno = 0 - -#define strtonum_failed(src, ptr) \ - ((src == ptr) || (errno == ERANGE) || (*ptr != '\0')) - -typedef struct ptql_parse_branch_t ptql_parse_branch_t; -typedef struct ptql_branch_t ptql_branch_t; - -/* adhere to calling convention, else risk stack corruption */ -#ifdef WIN32 -#define SIGAPI WINAPI -#else -#define SIGAPI -#endif - -typedef int (SIGAPI *ptql_get_t)(sigar_t *sigar, sigar_pid_t pid, void *data); -typedef int (*ptql_branch_init_t)(ptql_parse_branch_t *parsed, ptql_branch_t *branch, - sigar_ptql_error_t *error); - -typedef int (*ptql_op_ui64_t)(ptql_branch_t *branch, - sigar_uint64_t haystack, - sigar_uint64_t needle); - -typedef int (*ptql_op_ui32_t)(ptql_branch_t *branch, - sigar_uint32_t haystack, - sigar_uint32_t needle); - -typedef int (*ptql_op_dbl_t)(ptql_branch_t *branch, - double haystack, - double needle); - -typedef int (*ptql_op_str_t)(ptql_branch_t *branch, - char *haystack, - char *needle); - -typedef int (*ptql_op_chr_t)(ptql_branch_t *branch, - char haystack, - char needle); - -typedef enum { - PTQL_VALUE_TYPE_UI64, - PTQL_VALUE_TYPE_UI32, - PTQL_VALUE_TYPE_DBL, - PTQL_VALUE_TYPE_CHR, - PTQL_VALUE_TYPE_STR, - PTQL_VALUE_TYPE_ANY -} ptql_value_type_t; - -typedef enum { - PTQL_OP_EQ, - PTQL_OP_NE, - PTQL_OP_GT, - PTQL_OP_GE, - PTQL_OP_LT, - PTQL_OP_LE, -#define PTQL_OP_MAX_NSTR PTQL_OP_LE - PTQL_OP_EW, /* rest are string only */ - PTQL_OP_SW, - PTQL_OP_RE, - PTQL_OP_CT, - PTQL_OP_MAX -} ptql_op_name_t; - -#define PTQL_OP_FLAG_PARENT 1 -#define PTQL_OP_FLAG_REF 2 -#define PTQL_OP_FLAG_GLOB 4 -#define PTQL_OP_FLAG_PID 8 -#define PTQL_OP_FLAG_ICASE 16 - -struct ptql_parse_branch_t { - char *name; - char *attr; - char *op; - char *value; - unsigned int op_flags; -}; - -typedef struct { - char *name; - ptql_get_t get; - size_t offset; - unsigned int data_size; - ptql_value_type_t type; - ptql_branch_init_t init; -} ptql_lookup_t; - -#define DATA_PTR(branch) \ - ((char *)branch->data.ptr + branch->lookup->offset) - -#define IS_ICASE(branch) \ - (branch->op_flags & PTQL_OP_FLAG_ICASE) - -#define branch_strcmp(branch, s1, s2) \ - (IS_ICASE(branch) ? strcasecmp(s1, s2) : strcmp(s1, s2)) - -#define branch_strncmp(branch, s1, s2, n) \ - (IS_ICASE(branch) ? strncasecmp(s1, s2, n) : strncmp(s1, s2, n)) - -#define branch_strEQ(branch, s1, s2) \ - (branch_strcmp(branch, s1, s2) == 0) - -#define branch_strnEQ(branch, s1, s2, n) \ - (branch_strncmp(branch, s1, s2, n) == 0) - -#define branch_strstr(branch, s1, s2) \ - (IS_ICASE(branch) ? sigar_strcasestr(s1, s2) : strstr(s1, s2)) - -#define IS_PID_SERVICE_QUERY(branch) \ - (branch->flags >= PTQL_PID_SERVICE_NAME) - -static void data_free(void *data) -{ - free(data); -} - -typedef union { - sigar_pid_t pid; - sigar_uint64_t ui64; - sigar_uint32_t ui32; - double dbl; - char chr[4]; - char *str; - void *ptr; -} any_value_t; - -struct ptql_branch_t { - ptql_lookup_t *lookup; - any_value_t data; - unsigned int data_size; - void (*data_free)(void *); - unsigned int flags; - unsigned int op_flags; - ptql_op_name_t op_name; - union { - ptql_op_ui64_t ui64; - ptql_op_ui32_t ui32; - ptql_op_dbl_t dbl; - ptql_op_chr_t chr; - ptql_op_str_t str; - } match; - any_value_t value; - void (*value_free)(void *); -}; - -typedef struct { - char *name; - ptql_lookup_t *members; -} ptql_entry_t; - -typedef struct { - unsigned long number; - unsigned long size; - ptql_branch_t *data; -} ptql_branch_list_t; - -struct sigar_ptql_query_t { - ptql_branch_list_t branches; -#ifdef PTQL_DEBUG - char *ptql; -#endif -}; - -/* XXX optimize */ -static ptql_op_name_t ptql_op_code_get(char *op) -{ - if (strEQ(op, "eq")) { - return PTQL_OP_EQ; - } - else if (strEQ(op, "ne")) { - return PTQL_OP_NE; - } - else if (strEQ(op, "gt")) { - return PTQL_OP_GT; - } - else if (strEQ(op, "ge")) { - return PTQL_OP_GE; - } - else if (strEQ(op, "lt")) { - return PTQL_OP_LT; - } - else if (strEQ(op, "le")) { - return PTQL_OP_LE; - } - else if (strEQ(op, "ew")) { - return PTQL_OP_EW; - } - else if (strEQ(op, "sw")) { - return PTQL_OP_SW; - } - else if (strEQ(op, "re")) { - return PTQL_OP_RE; - } - else if (strEQ(op, "ct")) { - return PTQL_OP_CT; - } - else { - return PTQL_OP_MAX; - } -} - -static int ptql_op_ui64_eq(ptql_branch_t *branch, - sigar_uint64_t haystack, sigar_uint64_t needle) -{ - return haystack == needle; -} - -static int ptql_op_ui64_ne(ptql_branch_t *branch, - sigar_uint64_t haystack, sigar_uint64_t needle) -{ - return haystack != needle; -} - -static int ptql_op_ui64_gt(ptql_branch_t *branch, - sigar_uint64_t haystack, sigar_uint64_t needle) -{ - return haystack > needle; -} - -static int ptql_op_ui64_ge(ptql_branch_t *branch, - sigar_uint64_t haystack, sigar_uint64_t needle) -{ - return haystack >= needle; -} - -static int ptql_op_ui64_lt(ptql_branch_t *branch, - sigar_uint64_t haystack, sigar_uint64_t needle) -{ - return haystack < needle; -} - -static int ptql_op_ui64_le(ptql_branch_t *branch, - sigar_uint64_t haystack, sigar_uint64_t needle) -{ - return haystack <= needle; -} - -static ptql_op_ui64_t ptql_op_ui64[] = { - ptql_op_ui64_eq, - ptql_op_ui64_ne, - ptql_op_ui64_gt, - ptql_op_ui64_ge, - ptql_op_ui64_lt, - ptql_op_ui64_le -}; - -static int ptql_op_ui32_eq(ptql_branch_t *branch, - sigar_uint32_t haystack, sigar_uint32_t needle) -{ - return haystack == needle; -} - -static int ptql_op_ui32_ne(ptql_branch_t *branch, - sigar_uint32_t haystack, sigar_uint32_t needle) -{ - return haystack != needle; -} - -static int ptql_op_ui32_gt(ptql_branch_t *branch, - sigar_uint32_t haystack, sigar_uint32_t needle) -{ - return haystack > needle; -} - -static int ptql_op_ui32_ge(ptql_branch_t *branch, - sigar_uint32_t haystack, sigar_uint32_t needle) -{ - return haystack >= needle; -} - -static int ptql_op_ui32_lt(ptql_branch_t *branch, - sigar_uint32_t haystack, sigar_uint32_t needle) -{ - return haystack < needle; -} - -static int ptql_op_ui32_le(ptql_branch_t *branch, - sigar_uint32_t haystack, sigar_uint32_t needle) -{ - return haystack <= needle; -} - -static ptql_op_ui32_t ptql_op_ui32[] = { - ptql_op_ui32_eq, - ptql_op_ui32_ne, - ptql_op_ui32_gt, - ptql_op_ui32_ge, - ptql_op_ui32_lt, - ptql_op_ui32_le -}; - -static int ptql_op_dbl_eq(ptql_branch_t *branch, - double haystack, double needle) -{ - return haystack == needle; -} - -static int ptql_op_dbl_ne(ptql_branch_t *branch, - double haystack, double needle) -{ - return haystack != needle; -} - -static int ptql_op_dbl_gt(ptql_branch_t *branch, - double haystack, double needle) -{ - return haystack > needle; -} - -static int ptql_op_dbl_ge(ptql_branch_t *branch, - double haystack, double needle) -{ - return haystack >= needle; -} - -static int ptql_op_dbl_lt(ptql_branch_t *branch, - double haystack, double needle) -{ - return haystack < needle; -} - -static int ptql_op_dbl_le(ptql_branch_t *branch, - double haystack, double needle) -{ - return haystack <= needle; -} - -static ptql_op_dbl_t ptql_op_dbl[] = { - ptql_op_dbl_eq, - ptql_op_dbl_ne, - ptql_op_dbl_gt, - ptql_op_dbl_ge, - ptql_op_dbl_lt, - ptql_op_dbl_le -}; - -static int ptql_op_str_eq(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return branch_strEQ(branch, haystack, needle); -} - -static int ptql_op_str_ne(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return !branch_strEQ(branch, haystack, needle); -} - -static int ptql_op_str_gt(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return branch_strcmp(branch, haystack, needle) > 0; -} - -static int ptql_op_str_ge(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return branch_strcmp(branch, haystack, needle) >= 0; -} - -static int ptql_op_str_lt(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return branch_strcmp(branch, haystack, needle) < 0; -} - -static int ptql_op_str_le(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return branch_strcmp(branch, haystack, needle) <= 0; -} - -static int ptql_op_str_ew(ptql_branch_t *branch, - char *haystack, char *needle) -{ - int nlen = strlen(needle); - int hlen = strlen(haystack); - int diff = hlen - nlen; - if (diff < 0) { - return 0; - } - return branch_strnEQ(branch, haystack + diff, needle, nlen); -} - -static int ptql_op_str_sw(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return branch_strnEQ(branch, haystack, needle, strlen(needle)); -} - -static int ptql_op_str_re(ptql_branch_t *branch, - char *haystack, char *needle) -{ -#ifdef SIGAR_HAS_PCRE - pcre *re = (pcre *)branch->value.ptr; - int len = strlen(haystack); - int rc = - pcre_exec(re, NULL, haystack, len, 0, 0, NULL, 0); - return rc >= 0; -#else - return 0; -#endif -} - -static int ptql_op_str_ct(ptql_branch_t *branch, - char *haystack, char *needle) -{ - return branch_strstr(branch, haystack, needle) != NULL; -} - -static ptql_op_str_t ptql_op_str[] = { - ptql_op_str_eq, - ptql_op_str_ne, - ptql_op_str_gt, - ptql_op_str_ge, - ptql_op_str_lt, - ptql_op_str_le, - ptql_op_str_ew, - ptql_op_str_sw, - ptql_op_str_re, - ptql_op_str_ct -}; - -static int ptql_op_chr_eq(ptql_branch_t *branch, - char haystack, char needle) -{ - return haystack == needle; -} - -static int ptql_op_chr_ne(ptql_branch_t *branch, - char haystack, char needle) -{ - return haystack != needle; -} - -static int ptql_op_chr_gt(ptql_branch_t *branch, - char haystack, char needle) -{ - return haystack > needle; -} - -static int ptql_op_chr_ge(ptql_branch_t *branch, - char haystack, char needle) -{ - return haystack >= needle; -} - -static int ptql_op_chr_lt(ptql_branch_t *branch, - char haystack, char needle) -{ - return haystack < needle; -} - -static int ptql_op_chr_le(ptql_branch_t *branch, - char haystack, char needle) -{ - return haystack <= needle; -} - -static ptql_op_chr_t ptql_op_chr[] = { - ptql_op_chr_eq, - ptql_op_chr_ne, - ptql_op_chr_gt, - ptql_op_chr_ge, - ptql_op_chr_lt, - ptql_op_chr_le -}; - -#define PTQL_BRANCH_LIST_MAX 3 - -#define PTQL_BRANCH_LIST_GROW(branches) \ - if ((branches)->number >= (branches)->size) { \ - ptql_branch_list_grow(branches); \ - } - -static int ptql_branch_list_create(ptql_branch_list_t *branches) -{ - branches->number = 0; - branches->size = PTQL_BRANCH_LIST_MAX; - branches->data = malloc(sizeof(*(branches->data)) * - branches->size); - - return SIGAR_OK; -} - -static int ptql_branch_list_grow(ptql_branch_list_t *branches) -{ - branches->data = - realloc(branches->data, - sizeof(*(branches->data)) * - (branches->size + PTQL_BRANCH_LIST_MAX)); - branches->size += PTQL_BRANCH_LIST_MAX; - - return SIGAR_OK; -} - -static int ptql_branch_list_destroy(ptql_branch_list_t *branches) -{ - if (branches->size) { - int i; - - for (i=0; inumber; i++) { - ptql_branch_t *branch = - &branches->data[i]; - - if (branch->data_size && branch->data.ptr) { - branch->data_free(branch->data.ptr); - } - - if (branch->lookup && - ((branch->lookup->type == PTQL_VALUE_TYPE_STR) || - (branch->lookup->type == PTQL_VALUE_TYPE_ANY)) && - !(branch->op_flags & PTQL_OP_FLAG_REF)) - { - if (branch->value.str) { - branch->value_free(branch->value.str); - } - } - } - - free(branches->data); - branches->number = branches->size = 0; - } - - return SIGAR_OK; -} - -#ifdef WIN32 -#define vsnprintf _vsnprintf -#endif - -#define PTQL_ERRNAN \ - ptql_error(error, "Query value '%s' is not a number", parsed->value) - -static int ptql_error(sigar_ptql_error_t *error, const char *format, ...) -{ - va_list args; - - if (error != NULL) { - va_start(args, format); - vsnprintf(error->message, sizeof(error->message), format, args); - va_end(args); - } - - return SIGAR_PTQL_MALFORMED_QUERY; -} - -static int ptql_branch_init_any(ptql_parse_branch_t *parsed, - ptql_branch_t *branch, - sigar_ptql_error_t *error) -{ - branch->data.str = sigar_strdup(parsed->attr); - branch->data_size = strlen(parsed->attr); - return SIGAR_OK; -} - -static int ptql_str_match(sigar_t *sigar, ptql_branch_t *branch, char *value) -{ - if (!branch->value.str) { - return 0; - } -#ifndef SIGAR_HAS_PCRE - if (branch->op_name == PTQL_OP_RE) { - if (sigar->ptql_re_impl) { - return sigar->ptql_re_impl(sigar->ptql_re_data, - value, - branch->value.str); - } - else { - return 0; - } - } -#endif - return branch->match.str(branch, - value, - branch->value.str); -} - -static int ptql_branch_match(ptql_branch_t *branch) -{ - switch (branch->lookup->type) { - case PTQL_VALUE_TYPE_UI64: - return branch->match.ui64(branch, - *(sigar_uint64_t *)DATA_PTR(branch), - branch->value.ui64); - case PTQL_VALUE_TYPE_UI32: - return branch->match.ui32(branch, - *(sigar_uint32_t *)DATA_PTR(branch), - branch->value.ui32); - case PTQL_VALUE_TYPE_DBL: - return branch->match.dbl(branch, - *(double *)DATA_PTR(branch), - branch->value.dbl); - case PTQL_VALUE_TYPE_CHR: - return branch->match.chr(branch, - *(char *)DATA_PTR(branch), - branch->value.chr[0]); - case PTQL_VALUE_TYPE_STR: - case PTQL_VALUE_TYPE_ANY: - if (!branch->value.str) { - return 0; - } - return branch->match.str(branch, - (char *)DATA_PTR(branch), - branch->value.str); - default: - return 0; - } -} - -static int ptql_branch_match_ref(ptql_branch_t *branch, ptql_branch_t *ref) -{ - switch (branch->lookup->type) { - case PTQL_VALUE_TYPE_UI64: - return branch->match.ui64(branch, - *(sigar_uint64_t *)DATA_PTR(branch), - *(sigar_uint64_t *)DATA_PTR(ref)); - case PTQL_VALUE_TYPE_UI32: - return branch->match.ui32(branch, - *(sigar_uint32_t *)DATA_PTR(branch), - *(sigar_uint32_t *)DATA_PTR(ref)); - case PTQL_VALUE_TYPE_DBL: - return branch->match.dbl(branch, - *(double *)DATA_PTR(branch), - *(double *)DATA_PTR(ref)); - case PTQL_VALUE_TYPE_CHR: - return branch->match.chr(branch, - *(char *)DATA_PTR(branch), - *(char *)DATA_PTR(ref)); - case PTQL_VALUE_TYPE_STR: - case PTQL_VALUE_TYPE_ANY: - return branch->match.str(branch, - (char *)DATA_PTR(branch), - (char *)DATA_PTR(ref)); - default: - return 0; - } -} - -enum { - PTQL_PID_PID, - PTQL_PID_FILE, - PTQL_PID_SUDO_FILE, - PTQL_PID_TCP_PORT, - PTQL_PID_UDP_PORT, - PTQL_PID_SERVICE_NAME, - PTQL_PID_SERVICE_DISPLAY, - PTQL_PID_SERVICE_PATH, - PTQL_PID_SERVICE_EXE, - PTQL_PID_SERVICE_PID -}; - -#ifdef SIGAR_64BIT - -#define str2pid(value, ptr) strtoull(value, &ptr, 10) - -#define pid_branch_match(branch, pid, match_pid) \ - ptql_op_ui64[branch->op_name](branch, pid, match_pid) - -#else - -#define str2pid(value, ptr) strtoul(value, &ptr, 10) - -#define pid_branch_match(branch, pid, match_pid) \ - ptql_op_ui32[branch->op_name](branch, pid, match_pid) - -#endif - -#ifndef WIN32 -#include -int sigar_sudo_file2str(const char *fname, char *buffer, int buflen) -{ - FILE *fp; - struct stat sb; - - if (stat(fname, &sb) < 0) { - return errno; - } - if (sb.st_size > buflen) { - return ENOMEM; - } - snprintf(buffer, buflen, "sudo cat %s", fname); - if (!(fp = popen(buffer, "r"))) { - return errno; - } - (void)fgets(buffer, buflen, fp); - pclose(fp); - - return SIGAR_OK; -} -#endif - -static int ptql_branch_init_service(ptql_parse_branch_t *parsed, - ptql_branch_t *branch, - sigar_ptql_error_t *error) -{ - branch->op_flags |= PTQL_OP_FLAG_PID; - - if (strEQ(parsed->attr, "Name")) { - branch->flags = PTQL_PID_SERVICE_NAME; - } - else if (strEQ(parsed->attr, "DisplayName")) { - branch->flags = PTQL_PID_SERVICE_DISPLAY; - } - else if (strEQ(parsed->attr, "Path")) { - branch->flags = PTQL_PID_SERVICE_PATH; - } - else if (strEQ(parsed->attr, "Exe")) { - /* basename of Path */ - branch->flags = PTQL_PID_SERVICE_EXE; - } - else if (strEQ(parsed->attr, "Pid")) { - branch->flags = PTQL_PID_SERVICE_PID; - } - else { - return ptql_error(error, "Unsupported %s attribute: %s", - parsed->name, parsed->attr); - } - -#ifdef WIN32 - branch->data.str = sigar_strdup(parsed->value); - branch->data_size = strlen(parsed->value); -#endif - return SIGAR_OK; -} - -static int ptql_branch_init_pid(ptql_parse_branch_t *parsed, - ptql_branch_t *branch, - sigar_ptql_error_t *error) -{ - int use_sudo = 0; - branch->op_flags |= PTQL_OP_FLAG_PID; - - if (strEQ(parsed->attr, "Pid")) { - branch->flags = PTQL_PID_PID; - if (strEQ(parsed->value, "$$")) { - branch->data.pid = getpid(); - } - else { - char *ptr; - SIGAR_CLEAR_ERRNO(); - branch->data.pid = str2pid(parsed->value, ptr); - if (strtonum_failed(parsed->value, ptr)) { - return PTQL_ERRNAN; - } - } - return SIGAR_OK; - } - else if (strEQ(parsed->attr, "PidFile") || - (use_sudo = strEQ(parsed->attr, "SudoPidFile"))) - { - branch->flags = use_sudo ? PTQL_PID_SUDO_FILE : PTQL_PID_FILE; - branch->data.str = sigar_strdup(parsed->value); - branch->data_size = strlen(parsed->value); - return SIGAR_OK; - } - - return ptql_error(error, "Unsupported %s attribute: %s", - parsed->name, parsed->attr); -} - -#ifdef WIN32 -#define QUERY_SC_SIZE 8192 - -static int ptql_service_query_config(SC_HANDLE scm_handle, - char *name, - LPQUERY_SERVICE_CONFIG config) -{ - int status; - DWORD bytes; - SC_HANDLE handle = - OpenService(scm_handle, name, SERVICE_QUERY_CONFIG); - - if (!handle) { - return GetLastError(); - } - - if (QueryServiceConfig(handle, config, QUERY_SC_SIZE, &bytes)) { - status = SIGAR_OK; - } - else { - status = GetLastError(); - } - - CloseServiceHandle(handle); - return status; -} - -static int sigar_services_walk(sigar_services_walker_t *walker, - ptql_branch_t *branch) -{ - sigar_services_status_t ss; - char buffer[QUERY_SC_SIZE]; - char exe[SIGAR_CMDLINE_MAX]; - LPQUERY_SERVICE_CONFIG config = (LPQUERY_SERVICE_CONFIG)buffer; - DWORD i, status; - - SIGAR_ZERO(&ss); - status = sigar_services_status_get(&ss, walker->flags); - if (status != SIGAR_OK) { - return status; - } - for (i=0; iadd_service(walker, name) != SIGAR_OK) { - break; - } - continue; - } - - switch (branch->flags) { - case PTQL_PID_SERVICE_DISPLAY: - value = ss.services[i].lpDisplayName; - break; - case PTQL_PID_SERVICE_PATH: - case PTQL_PID_SERVICE_EXE: - status = ptql_service_query_config(ss.handle, name, config); - if (status == SIGAR_OK) { - if (branch->flags == PTQL_PID_SERVICE_EXE) { - value = - sigar_service_exe_get(config->lpBinaryPathName, - exe, 1); - } - else { - value = config->lpBinaryPathName; - } - } - else { - continue; - } - break; - case PTQL_PID_SERVICE_PID: - sigar_service_pid_get(walker->sigar, - name, - &service_pid); - break; - case PTQL_PID_SERVICE_NAME: - default: - value = name; - break; - } - - if ((value && ptql_str_match(walker->sigar, branch, value)) || - (service_pid && - pid_branch_match(branch, service_pid, atoi(branch->data.str)))) - { - if (walker->add_service(walker, name) != SIGAR_OK) { - break; - } - } - } - - sigar_services_status_close(&ss); - - return SIGAR_OK; -} - -static int ptql_pid_service_add(sigar_services_walker_t *walker, - char *name) -{ - sigar_pid_t service_pid; - sigar_proc_list_t *proclist = - (sigar_proc_list_t *)walker->data; - int status = - sigar_service_pid_get(walker->sigar, - name, - &service_pid); - - if (status == SIGAR_OK) { - SIGAR_PROC_LIST_GROW(proclist); - proclist->data[proclist->number++] = service_pid; - } - - return SIGAR_OK; -} - -static int ptql_pid_service_list_get(sigar_t *sigar, - ptql_branch_t *branch, - sigar_proc_list_t *proclist) -{ - sigar_services_walker_t walker; - walker.sigar = sigar; - walker.flags = SERVICE_ACTIVE; - walker.data = proclist; - walker.add_service = ptql_pid_service_add; - - return sigar_services_walk(&walker, branch); -} - -int sigar_services_query(char *ptql, - sigar_ptql_error_t *error, - sigar_services_walker_t *walker) -{ - int status; - sigar_ptql_query_t *query; - - if (ptql == NULL) { - return sigar_services_walk(walker, NULL); - } - - status = sigar_ptql_query_create(&query, (char *)ptql, error); - if (status != SIGAR_OK) { - return status; - } - - if (query->branches.number == 1) { - ptql_branch_t *branch = &query->branches.data[0]; - - if (IS_PID_SERVICE_QUERY(branch)) { - status = sigar_services_walk(walker, branch); - } - else { - ptql_error(error, "Invalid Service query: %s", ptql); - status = SIGAR_PTQL_MALFORMED_QUERY; - } - } - else { - ptql_error(error, "Too many queries (%d), must be (1)", - query->branches.number); - status = SIGAR_PTQL_MALFORMED_QUERY; - } - - sigar_ptql_query_destroy(query); - - return status; -} -#endif - -static int ptql_pid_port_get(sigar_t *sigar, - ptql_branch_t *branch, - sigar_pid_t *pid) -{ - unsigned long port = - branch->data.ui32; - int status; - int proto = - branch->flags == PTQL_PID_UDP_PORT ? - SIGAR_NETCONN_UDP : SIGAR_NETCONN_TCP; - - status = - sigar_proc_port_get(sigar, proto, port, pid); - - return status; -} - -static int ptql_pid_get(sigar_t *sigar, - ptql_branch_t *branch, - sigar_pid_t *pid) -{ - if ((branch->flags == PTQL_PID_FILE) || - (branch->flags == PTQL_PID_SUDO_FILE)) - { - char *ptr, buffer[SIGAR_PATH_MAX+1]; - const char *fname = (const char *)branch->data.str; - int status, len = sizeof(buffer)-1; - - if (branch->flags == PTQL_PID_FILE) { - status = sigar_file2str(fname, buffer, len); - } - else { -#ifdef WIN32 - return SIGAR_ENOTIMPL; -#else - status = sigar_sudo_file2str(fname, buffer, len); -#endif - } - if (status != SIGAR_OK) { - return status; - } - SIGAR_CLEAR_ERRNO(); - *pid = str2pid(buffer, ptr); - if ((buffer == ptr) || (errno == ERANGE)) { - return errno; - } - } - else if (branch->flags == PTQL_PID_SERVICE_NAME) { -#ifdef WIN32 - int status = - sigar_service_pid_get(sigar, - branch->data.str, pid); - if (status != SIGAR_OK) { - return status; - } -#else - return SIGAR_ENOTIMPL; -#endif - } - else if ((branch->flags == PTQL_PID_UDP_PORT) || - (branch->flags == PTQL_PID_TCP_PORT)) - { - int status = ptql_pid_port_get(sigar, branch, pid); - if (status != SIGAR_OK) { - return status; - } - } - else { - *pid = branch->data.pid; - } - - return SIGAR_OK; -} - -static int ptql_pid_list_get(sigar_t *sigar, - ptql_branch_t *branch, - sigar_proc_list_t *proclist) -{ - int status, i; - sigar_pid_t match_pid; - - if (IS_PID_SERVICE_QUERY(branch)) { - if ((branch->flags > PTQL_PID_SERVICE_NAME) || - (branch->op_name != PTQL_OP_EQ)) - { -#ifdef WIN32 - return ptql_pid_service_list_get(sigar, branch, proclist); -#else - return SIGAR_OK; /* no matches */ -#endif - } - } - - status = ptql_pid_get(sigar, branch, &match_pid); - - if (status != SIGAR_OK) { - /* XXX treated as non-match but would be nice to propagate */ - return SIGAR_OK; - } - - status = sigar_proc_list_get(sigar, NULL); - if (status != SIGAR_OK) { - return status; - } - for (i=0; ipids->number; i++) { - sigar_pid_t pid = sigar->pids->data[i]; - if (pid_branch_match(branch, pid, match_pid)) { - SIGAR_PROC_LIST_GROW(proclist); - proclist->data[proclist->number++] = pid; - } - } - - return SIGAR_OK; -} - -static int SIGAPI ptql_pid_match(sigar_t *sigar, - sigar_pid_t pid, - void *data) -{ - /* query already used to filter proc_list */ - return SIGAR_OK; -} - -static int ptql_args_branch_init(ptql_parse_branch_t *parsed, - ptql_branch_t *branch, - sigar_ptql_error_t *error) -{ - if (strEQ(parsed->attr, "*")) { - branch->op_flags |= PTQL_OP_FLAG_GLOB; - } - else { - char *end; - - SIGAR_CLEAR_ERRNO(); - branch->data.ui32 = - strtol(parsed->attr, &end, 10); - - if (strtonum_failed(parsed->attr, end)) { - /* conversion failed */ - return ptql_error(error, "%s is not a number", parsed->attr); - } - } - return SIGAR_OK; -} - -static int SIGAPI ptql_args_match(sigar_t *sigar, - sigar_pid_t pid, - void *data) -{ - ptql_branch_t *branch = - (ptql_branch_t *)data; - int status, matched=0; - sigar_proc_args_t args; - - status = sigar_proc_args_get(sigar, pid, &args); - if (status != SIGAR_OK) { - return status; - } - - if (branch->op_flags & PTQL_OP_FLAG_GLOB) { - int i; - for (i=0; idata.ui32; - - /* e.g. find last element of args: Args.-1.eq=weblogic.Server */ - if (num < 0) { - num += args.number; - } - if ((num >= 0) && (num < args.number)) { - matched = - ptql_str_match(sigar, branch, args.data[num]); - } - } - - sigar_proc_args_destroy(sigar, &args); - - return matched ? SIGAR_OK : !SIGAR_OK; -} - -typedef struct { - sigar_t *sigar; - ptql_branch_t *branch; - sigar_uint32_t ix; - int matched; -} proc_modules_match_t; - -static int proc_modules_match(void *data, char *name, int len) -{ - proc_modules_match_t *matcher = - (proc_modules_match_t *)data; - ptql_branch_t *branch = matcher->branch; - - if (branch->op_flags & PTQL_OP_FLAG_GLOB) { /* Modules.*.ct=libc */ - matcher->matched = - ptql_str_match(matcher->sigar, branch, name); - - if (matcher->matched) { - return !SIGAR_OK; /* stop iterating */ - } - } - else { - if (matcher->ix++ == branch->data.ui32) { /* Modules.3.ct=libc */ - matcher->matched = - ptql_str_match(matcher->sigar, branch, name); - return !SIGAR_OK; /* stop iterating */ - } - } - - return SIGAR_OK; -} - -static int SIGAPI ptql_modules_match(sigar_t *sigar, - sigar_pid_t pid, - void *data) -{ - ptql_branch_t *branch = - (ptql_branch_t *)data; - int status; - sigar_proc_modules_t procmods; - proc_modules_match_t matcher; - - matcher.sigar = sigar; - matcher.branch = branch; - matcher.ix = 0; - matcher.matched = 0; - - procmods.module_getter = proc_modules_match; - procmods.data = &matcher; - - status = sigar_proc_modules_get(sigar, pid, &procmods); - - if (status != SIGAR_OK) { - return status; - } - - return matcher.matched ? SIGAR_OK : !SIGAR_OK; -} - -typedef struct { - const char *key; - int klen; - char *val; - int vlen; -} sigar_proc_env_entry_t; - -static int sigar_proc_env_get_key(void *data, - const char *key, int klen, - char *val, int vlen) -{ - sigar_proc_env_entry_t *entry = - (sigar_proc_env_entry_t *)data; - - if ((entry->klen == klen) && - (strcmp(entry->key, key) == 0)) - { - entry->val = val; - entry->vlen = vlen; - return !SIGAR_OK; /* foundit; stop iterating */ - } - - return SIGAR_OK; -} - -static int SIGAPI ptql_env_match(sigar_t *sigar, - sigar_pid_t pid, - void *data) -{ - ptql_branch_t *branch = - (ptql_branch_t *)data; - int status, matched=0; - sigar_proc_env_t procenv; - sigar_proc_env_entry_t entry; - - /* XXX ugh this is klunky */ - entry.key = branch->data.str; - entry.klen = branch->data_size; - entry.val = NULL; - - procenv.type = SIGAR_PROC_ENV_KEY; - procenv.key = branch->data.str; - procenv.klen = branch->data_size; - procenv.env_getter = sigar_proc_env_get_key; - procenv.data = &entry; - - status = sigar_proc_env_get(sigar, pid, &procenv); - if (status != SIGAR_OK) { - return status; - } - else { - if (entry.val) { - matched = - ptql_str_match(sigar, branch, entry.val); - } - } - - return matched ? SIGAR_OK : !SIGAR_OK; -} - -static int ptql_branch_init_port(ptql_parse_branch_t *parsed, - ptql_branch_t *branch, - sigar_ptql_error_t *error) -{ - char *ptr; - - /* only 'eq' is supported here */ - if (branch->op_name != PTQL_OP_EQ) { - return ptql_error(error, "%s requires 'eq' operator", - parsed->name); - } - - if (strEQ(parsed->attr, "tcp")) { - branch->flags = PTQL_PID_TCP_PORT; - } - else if (strEQ(parsed->attr, "udp")) { - branch->flags = PTQL_PID_TCP_PORT; - } - else { - return ptql_error(error, "Unsupported %s protocol: %s", - parsed->name, parsed->attr); - } - - branch->op_flags |= PTQL_OP_FLAG_PID; - SIGAR_CLEAR_ERRNO(); - branch->data.ui32 = strtoul(parsed->value, &ptr, 10); - if (strtonum_failed(parsed->value, ptr)) { - return PTQL_ERRNAN; - } - - return SIGAR_OK; -} - -#define PTQL_LOOKUP_ENTRY(cname, member, type) \ - (ptql_get_t)sigar_##cname##_get, \ - sigar_offsetof(sigar_##cname##_t, member), \ - sizeof(sigar_##cname##_t), \ - PTQL_VALUE_TYPE_##type, \ - NULL - -/* XXX uid/pid can be larger w/ 64bit mode */ -#define PTQL_VALUE_TYPE_PID PTQL_VALUE_TYPE_UI32 -#define PTQL_VALUE_TYPE_UID PTQL_VALUE_TYPE_UI32 - -static ptql_lookup_t PTQL_Time[] = { - { "StartTime", PTQL_LOOKUP_ENTRY(proc_time, start_time, UI64) }, - { "User", PTQL_LOOKUP_ENTRY(proc_time, user, UI64) }, - { "Sys", PTQL_LOOKUP_ENTRY(proc_time, sys, UI64) }, - { "Total", PTQL_LOOKUP_ENTRY(proc_time, total, UI64) }, - { NULL } -}; - -static ptql_lookup_t PTQL_Cpu[] = { - { "StartTime", PTQL_LOOKUP_ENTRY(proc_cpu, start_time, UI64) }, - { "User", PTQL_LOOKUP_ENTRY(proc_cpu, user, UI64) }, - { "Sys", PTQL_LOOKUP_ENTRY(proc_cpu, sys, UI64) }, - { "Total", PTQL_LOOKUP_ENTRY(proc_cpu, total, UI64) }, - { "Percent", PTQL_LOOKUP_ENTRY(proc_cpu, percent, DBL) }, - { NULL } -}; - -static ptql_lookup_t PTQL_CredName[] = { - { "User", PTQL_LOOKUP_ENTRY(proc_cred_name, user, STR) }, - { "Group", PTQL_LOOKUP_ENTRY(proc_cred_name, group, STR) }, - { NULL } -}; - -static ptql_lookup_t PTQL_Mem[] = { - { "Size", PTQL_LOOKUP_ENTRY(proc_mem, size, UI64) }, - { "Resident", PTQL_LOOKUP_ENTRY(proc_mem, resident, UI64) }, - { "Share", PTQL_LOOKUP_ENTRY(proc_mem, share, UI64) }, - { "MinorFaults", PTQL_LOOKUP_ENTRY(proc_mem, minor_faults, UI64) }, - { "MajorFaults", PTQL_LOOKUP_ENTRY(proc_mem, major_faults, UI64) }, - { "PageFaults", PTQL_LOOKUP_ENTRY(proc_mem, page_faults, UI64) }, - { NULL } -}; - -static ptql_lookup_t PTQL_Exe[] = { - { "Name", PTQL_LOOKUP_ENTRY(proc_exe, name, STR) }, - { "Cwd", PTQL_LOOKUP_ENTRY(proc_exe, cwd, STR) }, - { NULL } -}; - -static ptql_lookup_t PTQL_Cred[] = { - { "Uid", PTQL_LOOKUP_ENTRY(proc_cred, uid, UID) }, - { "Gid", PTQL_LOOKUP_ENTRY(proc_cred, gid, UID) }, - { "Euid", PTQL_LOOKUP_ENTRY(proc_cred, euid, UID) }, - { "Egid", PTQL_LOOKUP_ENTRY(proc_cred, egid, UID) }, - { NULL } -}; - -static ptql_lookup_t PTQL_State[] = { - { "State", PTQL_LOOKUP_ENTRY(proc_state, state, CHR) }, - { "Name", PTQL_LOOKUP_ENTRY(proc_state, name, STR) }, - { "Ppid", PTQL_LOOKUP_ENTRY(proc_state, ppid, PID) }, - { "Tty", PTQL_LOOKUP_ENTRY(proc_state, tty, UI32) }, - { "Nice", PTQL_LOOKUP_ENTRY(proc_state, nice, UI32) }, - { "Priority", PTQL_LOOKUP_ENTRY(proc_state, priority, UI32) }, - { "Threads", PTQL_LOOKUP_ENTRY(proc_state, threads, UI64) }, - { "Processor", PTQL_LOOKUP_ENTRY(proc_state, processor, UI32) }, - { NULL } -}; - -static ptql_lookup_t PTQL_Fd[] = { - { "Total", PTQL_LOOKUP_ENTRY(proc_fd, total, UI64) }, - { NULL } -}; - -static ptql_lookup_t PTQL_Args[] = { - { NULL, ptql_args_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_args_branch_init } -}; - -static ptql_lookup_t PTQL_Modules[] = { - { NULL, ptql_modules_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_args_branch_init } -}; - -static ptql_lookup_t PTQL_Env[] = { - { NULL, ptql_env_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_any } -}; - -static ptql_lookup_t PTQL_Port[] = { - { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_port } -}; - -static ptql_lookup_t PTQL_Pid[] = { - { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_pid } -}; - -static ptql_lookup_t PTQL_Service[] = { - { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_service } -}; - -static ptql_entry_t ptql_map[] = { - { "Time", PTQL_Time }, - { "Cpu", PTQL_Cpu }, - { "CredName", PTQL_CredName }, - { "Mem", PTQL_Mem }, - { "Exe", PTQL_Exe }, - { "Cred", PTQL_Cred }, - { "State", PTQL_State }, - { "Fd", PTQL_Fd }, - { "Args", PTQL_Args }, - { "Modules", PTQL_Modules }, - { "Env", PTQL_Env }, - { "Port", PTQL_Port }, - { "Pid", PTQL_Pid }, - { "Service", PTQL_Service }, - { NULL } -}; - -static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch, - sigar_ptql_error_t *error) -{ - char *ptr = strchr(query, '='); - if (!ptr) { - return ptql_error(error, "Missing '='"); - } - - branch->op_flags = 0; - - *ptr = '\0'; - branch->value = ++ptr; - - if ((ptr = strchr(query, '.'))) { - *ptr = '\0'; - branch->name = query; - query = ++ptr; - } - else { - return ptql_error(error, "Missing '.'"); - } - - if ((ptr = strchr(query, '.'))) { - *ptr = '\0'; - branch->attr = query; - query = ++ptr; - } - else { - return ptql_error(error, "Missing '.'"); - } - - if (*query) { - char flag; - - while (sigar_isupper((flag = *query))) { - switch (flag) { - case 'P': - branch->op_flags |= PTQL_OP_FLAG_PARENT; - break; - case 'I': - branch->op_flags |= PTQL_OP_FLAG_ICASE; - break; - default: - return ptql_error(error, "Unsupported modifier: %c", flag); - } - - ++query; - } - - branch->op = query; - } - else { - return ptql_error(error, "Missing query"); - } - - /* Pid.Service -> Service.Name */ - if (strEQ(branch->attr, "Service")) { - branch->name = branch->attr; - branch->attr = "Name"; - } - - return SIGAR_OK; -} - -static int ptql_branch_add(ptql_parse_branch_t *parsed, - ptql_branch_list_t *branches, - sigar_ptql_error_t *error) -{ - ptql_branch_t *branch; - ptql_entry_t *entry = NULL; - ptql_lookup_t *lookup = NULL; - int i, is_set=0; - char *ptr; - - PTQL_BRANCH_LIST_GROW(branches); - - branch = &branches->data[branches->number++]; - SIGAR_ZERO(branch); - branch->data_free = data_free; - branch->value_free = data_free; - branch->op_flags = parsed->op_flags; - - branch->op_name = ptql_op_code_get(parsed->op); - if (branch->op_name == PTQL_OP_MAX) { - return ptql_error(error, "Unsupported operator: %s", parsed->op); - } - - for (i=0; ptql_map[i].name; i++) { - if (strEQ(ptql_map[i].name, parsed->name)) { - entry = &ptql_map[i]; - break; - } - } - - if (!entry) { - return ptql_error(error, "Unsupported method: %s", parsed->name); - } - - for (i=0; entry->members[i].name; i++) { - if (strEQ(entry->members[i].name, parsed->attr)) { - lookup = &entry->members[i]; - break; - } - } - - if (!lookup) { - if (entry->members[0].type == PTQL_VALUE_TYPE_ANY) { - /* Args, Env, etc. */ - lookup = &entry->members[0]; - } - else { - return ptql_error(error, "Unsupported %s attribute: %s", - parsed->name, parsed->attr); - } - } - - if (lookup->init) { - int status = lookup->init(parsed, branch, error); - if (status != SIGAR_OK) { - return status; - } - } - - branch->lookup = lookup; - - if ((lookup->type < PTQL_VALUE_TYPE_STR) && - (branch->op_name > PTQL_OP_MAX_NSTR)) - { - return ptql_error(error, "Unsupported operator '%s' for %s.%s", - parsed->op, parsed->name, parsed->attr); - } - - if (*parsed->value == '$') { - is_set = 1; - - if (branch->op_name == PTQL_OP_RE) { - /* not for use with .re */ - return ptql_error(error, "Unsupported operator '%s' with variable %s", - parsed->op, parsed->value); - } - - if (sigar_isdigit(*(parsed->value+1))) { - branch->op_flags |= PTQL_OP_FLAG_REF; - parsed->op_flags = branch->op_flags; /* for use by caller */ - branch->value.ui32 = atoi(parsed->value+1) - 1; - - if (branch->value.ui32 >= branches->number) { - /* out-of-range */ - return ptql_error(error, "Variable %s out of range (%d)", - parsed->value, branches->number); - } - else if (branch->value.ui32 == branches->number-1) { - /* self reference */ - return ptql_error(error, "Variable %s self reference", - parsed->value); - } - } - else { - if ((ptr = getenv(parsed->value+1))) { - branch->value.str = sigar_strdup(ptr); - } - else { - branch->value.str = NULL; - } - } - } - else if (branch->op_name == PTQL_OP_RE) { -#ifdef SIGAR_HAS_PCRE - const char *error; - int offset; - pcre *re = - pcre_compile(parsed->value, 0, - &error, &offset, NULL); - if (!re) { - /* XXX pcre_error ? */ - return ptql_error(error, "Invalid regex"); - } - is_set = 1; - branch->value.ptr = re; - branch->value_free = pcre_free; -#endif - } - - switch (lookup->type) { - case PTQL_VALUE_TYPE_UI64: - branch->match.ui64 = ptql_op_ui64[branch->op_name]; - if (!is_set) { - SIGAR_CLEAR_ERRNO(); - branch->value.ui64 = strtoull(parsed->value, &ptr, 10); - if (strtonum_failed(parsed->value, ptr)) { - return PTQL_ERRNAN; - } - } - break; - case PTQL_VALUE_TYPE_UI32: - branch->match.ui32 = ptql_op_ui32[branch->op_name]; - if (!is_set) { - SIGAR_CLEAR_ERRNO(); - branch->value.ui32 = strtoul(parsed->value, &ptr, 10); - if (strtonum_failed(parsed->value, ptr)) { - return PTQL_ERRNAN; - } - } - break; - case PTQL_VALUE_TYPE_DBL: - branch->match.dbl = ptql_op_dbl[branch->op_name]; - if (!is_set) { - SIGAR_CLEAR_ERRNO(); - branch->value.dbl = strtod(parsed->value, &ptr); - if (strtonum_failed(parsed->value, ptr)) { - return PTQL_ERRNAN; - } - } - break; - case PTQL_VALUE_TYPE_CHR: - branch->match.chr = ptql_op_chr[branch->op_name]; - if (!is_set) { - if (strlen(parsed->value) != 1) { - return ptql_error(error, "%s is not a char", parsed->value); - } - branch->value.chr[0] = parsed->value[0]; - } - break; - case PTQL_VALUE_TYPE_STR: - case PTQL_VALUE_TYPE_ANY: - branch->match.str = ptql_op_str[branch->op_name]; - if (!is_set) { - branch->value.str = sigar_strdup(parsed->value); - } - break; - } - - return SIGAR_OK; -} - -static int ptql_branch_compare(const void *b1, const void *b2) -{ - /* XXX can do better */ - ptql_branch_t *branch1 = (ptql_branch_t *)b1; - ptql_branch_t *branch2 = (ptql_branch_t *)b2; - return - branch1->lookup->type - - branch2->lookup->type; -} - -SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp, - char *ptql, - sigar_ptql_error_t *error) -{ - char *ptr, *ptql_copy = sigar_strdup(ptql); - int status = SIGAR_OK; - int has_ref = 0; - sigar_ptql_query_t *query = - *queryp = malloc(sizeof(*query)); - - (void)ptql_error(error, "Malformed query"); - -#ifdef PTQL_DEBUG - query->ptql = sigar_strdup(ptql); -#endif - - ptql = ptql_copy; - - ptql_branch_list_create(&query->branches); - - do { - ptql_parse_branch_t parsed; - - if ((ptr = strchr(ptql, ','))) { - *ptr = '\0'; - } - - status = ptql_branch_parse(ptql, &parsed, error); - if (status == SIGAR_OK) { - status = - ptql_branch_add(&parsed, &query->branches, error); - - if (status != SIGAR_OK) { - break; - } - if (parsed.op_flags & PTQL_OP_FLAG_REF) { - has_ref = 1; - } - } - else { - break; - } - - if (ptr) { - ptql = ++ptr; - } - else { - break; - } - } while (*ptql); - - free(ptql_copy); - - if (status != SIGAR_OK) { - sigar_ptql_query_destroy(query); - *queryp = NULL; - } - else if (!has_ref && (query->branches.number > 1)) { - qsort(query->branches.data, - query->branches.number, - sizeof(query->branches.data[0]), - ptql_branch_compare); - } - - if (status == SIGAR_OK) { - (void)ptql_error(error, "OK"); - } - return status; -} - -SIGAR_DECLARE(int) sigar_ptql_query_destroy(sigar_ptql_query_t *query) -{ -#ifdef PTQL_DEBUG - free(query->ptql); -#endif - ptql_branch_list_destroy(&query->branches); - free(query); - return SIGAR_OK; -} - -SIGAR_DECLARE(void) sigar_ptql_re_impl_set(sigar_t *sigar, void *data, - sigar_ptql_re_impl_t impl) -{ - sigar->ptql_re_data = data; - sigar->ptql_re_impl = impl; -} - -SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar, - sigar_ptql_query_t *query, - sigar_pid_t query_pid) -{ - int i; - - for (i=0; ibranches.number; i++) { - sigar_pid_t pid = query_pid; - int status, matched=0; - ptql_branch_t *branch = &query->branches.data[i]; - ptql_lookup_t *lookup = branch->lookup; - - if (branch->op_flags & PTQL_OP_FLAG_PARENT) { - sigar_proc_state_t state; - - status = sigar_proc_state_get(sigar, pid, &state); - if (status != SIGAR_OK) { - return status; - } - - pid = state.ppid; - } - - if (lookup->type == PTQL_VALUE_TYPE_ANY) { - /* Args, Env, etc. */ - status = lookup->get(sigar, pid, branch); - if (status == SIGAR_OK) { - matched = 1; - } - } - else { - /* standard sigar_proc_*_get / structptr + offset */ - if (!branch->data.ptr) { - branch->data_size = lookup->data_size; - branch->data.ptr = malloc(branch->data_size); - } - status = lookup->get(sigar, pid, branch->data.ptr); - if (status != SIGAR_OK) { - return status; - } - - if (branch->op_flags & PTQL_OP_FLAG_REF) { - ptql_branch_t *ref = - &query->branches.data[branch->value.ui32]; - - matched = ptql_branch_match_ref(branch, ref); - } -#ifndef SIGAR_HAS_PCRE - else if (branch->lookup->type == PTQL_VALUE_TYPE_STR) { - matched = ptql_str_match(sigar, branch, (char *)DATA_PTR(branch)); - } -#endif - else { - matched = ptql_branch_match(branch); - } - } - - if (!matched) { - return 1; - } - } - - return SIGAR_OK; -} - -static int ptql_proc_list_get(sigar_t *sigar, - sigar_ptql_query_t *query, - sigar_proc_list_t **proclist) -{ - int status; - int i; - - *proclist = NULL; - - for (i=0; ibranches.number; i++) { - ptql_branch_t *branch = &query->branches.data[i]; - - if (branch->op_flags & PTQL_OP_FLAG_PID) { - /* pre-filter pid list for Pid.* queries */ - /* XXX multiple Pid.* may result in dups */ - if (*proclist == NULL) { - *proclist = malloc(sizeof(**proclist)); - SIGAR_ZERO(*proclist); - sigar_proc_list_create(*proclist); - } - status = ptql_pid_list_get(sigar, branch, *proclist); - if (status != SIGAR_OK) { - sigar_proc_list_destroy(sigar, *proclist); - free(*proclist); - return status; - } - } - } - - if (*proclist) { - return SIGAR_OK; - } - - status = sigar_proc_list_get(sigar, NULL); - if (status != SIGAR_OK) { - return status; - } - *proclist = sigar->pids; - return SIGAR_OK; -} - -static int ptql_proc_list_destroy(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - if (proclist != sigar->pids) { - sigar_proc_list_destroy(sigar, proclist); - free(proclist); - } - - return SIGAR_OK; -} - -SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar, - sigar_ptql_query_t *query, - sigar_pid_t *pid) -{ - int status; - int i, matches=0; - sigar_proc_list_t *pids; - - status = ptql_proc_list_get(sigar, query, &pids); - if (status != SIGAR_OK) { - return status; - } - - for (i=0; inumber; i++) { - int query_status = - sigar_ptql_query_match(sigar, query, pids->data[i]); - - if (query_status == SIGAR_OK) { - *pid = pids->data[i]; - matches++; - } - else if (query_status == SIGAR_ENOTIMPL) { - /* let caller know query is invalid. */ - status = query_status; - break; - } /* else ok, e.g. permission denied */ - } - - ptql_proc_list_destroy(sigar, pids); - - if (status != SIGAR_OK) { - return status; - } - - if (matches == 1) { - return SIGAR_OK; - } - else if (matches == 0) { - sigar_strerror_set(sigar, - "Query did not match any processes"); - } - else { - sigar_strerror_printf(sigar, - "Query matched multiple processes (%d)", - matches); - } - - return -1; -} - -SIGAR_DECLARE(int) sigar_ptql_query_find(sigar_t *sigar, - sigar_ptql_query_t *query, - sigar_proc_list_t *proclist) -{ - int status; - int i; - sigar_proc_list_t *pids; - - status = ptql_proc_list_get(sigar, query, &pids); - if (status != SIGAR_OK) { - return status; - } - - sigar_proc_list_create(proclist); - - for (i=0; inumber; i++) { - int query_status = - sigar_ptql_query_match(sigar, query, pids->data[i]); - - if (query_status == SIGAR_OK) { - SIGAR_PROC_LIST_GROW(proclist); - proclist->data[proclist->number++] = pids->data[i]; - } - else if (query_status == SIGAR_ENOTIMPL) { - /* let caller know query is invalid. */ - status = query_status; - break; - } - } - - ptql_proc_list_destroy(sigar, pids); - - if (status != SIGAR_OK) { - sigar_proc_list_destroy(sigar, proclist); - return status; - } - - return SIGAR_OK; -} diff --git a/vendor/sigar/src/sigar_signal.c b/vendor/sigar/src/sigar_signal.c deleted file mode 100644 index e32d231..0000000 --- a/vendor/sigar/src/sigar_signal.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2007 Hyperic, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" - -#ifdef WIN32 -#include -#endif - -#include -#include - -SIGAR_DECLARE(int) sigar_proc_kill(sigar_pid_t pid, int signum) -{ -#ifdef WIN32 - int status = -1; - HANDLE proc = - OpenProcess(PROCESS_ALL_ACCESS, - TRUE, (DWORD)pid); - - if (proc) { - switch (signum) { - case 0: - status = SIGAR_OK; - break; - default: - if (TerminateProcess(proc, signum)) { - status = SIGAR_OK; - } - break; - } - - CloseHandle(proc); - - if (status == SIGAR_OK) { - return SIGAR_OK; - } - } - return GetLastError(); -#else - if (kill(pid, signum) == -1) { - return errno; - } - return SIGAR_OK; -#endif -} - -SIGAR_DECLARE(int) sigar_signum_get(char *name) -{ - if (strnEQ(name, "SIG", 3)) { - name += 3; - } - - switch (*name) { - case 'A': -#ifdef SIGABRT - if (strEQ(name, "ABRT")) return SIGABRT; -#endif -#ifdef SIGALRM - if (strEQ(name, "ALRM")) return SIGALRM; -#endif - break; - case 'B': -#ifdef SIGBUS - if (strEQ(name, "BUS")) return SIGBUS; -#endif - break; - case 'C': -#ifdef SIGCONT - if (strEQ(name, "CONT")) return SIGCONT; -#endif -#ifdef SIGCHLD - if (strEQ(name, "CHLD")) return SIGCHLD; -#endif -#ifdef SIGCLD - if (strEQ(name, "CLD")) return SIGCLD; -#endif - break; - case 'E': -#ifdef SIGEMT - if (strEQ(name, "EMT")) return SIGEMT; -#endif - break; - case 'F': -#ifdef SIGFPE - if (strEQ(name, "FPE")) return SIGFPE; -#endif - break; - case 'H': -#ifdef SIGHUP - if (strEQ(name, "HUP")) return SIGHUP; -#endif - break; - case 'I': -#ifdef SIGINT - if (strEQ(name, "INT")) return SIGINT; -#endif -#ifdef SIGILL - if (strEQ(name, "ILL")) return SIGILL; -#endif -#ifdef SIGIOT - if (strEQ(name, "IOT")) return SIGIOT; -#endif -#ifdef SIGIO - if (strEQ(name, "IO")) return SIGIO; -#endif -#ifdef SIGINFO - if (strEQ(name, "INFO")) return SIGINFO; -#endif - break; - case 'K': -#ifdef SIGKILL - if (strEQ(name, "KILL")) return SIGKILL; -#endif - break; - case 'P': -#ifdef SIGPOLL - if (strEQ(name, "POLL")) return SIGPOLL; -#endif -#ifdef SIGPIPE - if (strEQ(name, "PIPE")) return SIGPIPE; -#endif -#ifdef SIGPROF - if (strEQ(name, "PROF")) return SIGPROF; -#endif -#ifdef SIGPWR - if (strEQ(name, "PWR")) return SIGPWR; -#endif - break; - case 'Q': -#ifdef SIGQUIT - if (strEQ(name, "QUIT")) return SIGQUIT; -#endif - break; - case 'S': -#ifdef SIGSEGV - if (strEQ(name, "SEGV")) return SIGSEGV; -#endif -#ifdef SIGSYS - if (strEQ(name, "SYS")) return SIGSYS; -#endif -#ifdef SIGSTOP - if (strEQ(name, "STOP")) return SIGSTOP; -#endif -#ifdef SIGSTKFLT - if (strEQ(name, "STKFLT")) return SIGSTKFLT; -#endif - break; - case 'T': -#ifdef SIGTRAP - if (strEQ(name, "TRAP")) return SIGTRAP; -#endif -#ifdef SIGTERM - if (strEQ(name, "TERM")) return SIGTERM; -#endif -#ifdef SIGTSTP - if (strEQ(name, "TSTP")) return SIGTSTP; -#endif -#ifdef SIGTTIN - if (strEQ(name, "TTIN")) return SIGTTIN; -#endif -#ifdef SIGTTOU - if (strEQ(name, "TTOU")) return SIGTTOU; -#endif - break; - case 'U': -#ifdef SIGURG - if (strEQ(name, "URG")) return SIGURG; -#endif -#ifdef SIGUSR1 - if (strEQ(name, "USR1")) return SIGUSR1; -#endif -#ifdef SIGUSR2 - if (strEQ(name, "USR2")) return SIGUSR2; -#endif - break; - case 'V': -#ifdef SIGVTALRM - if (strEQ(name, "VTALRM")) return SIGVTALRM; -#endif - break; - case 'W': -#ifdef SIGWINCH - if (strEQ(name, "WINCH")) return SIGWINCH; -#endif - break; - case 'X': -#ifdef SIGXCPU - if (strEQ(name, "XCPU")) return SIGXCPU; -#endif -#ifdef SIGXFSZ - if (strEQ(name, "XFSZ")) return SIGXFSZ; -#endif - break; - default: - break; - } - - return -1; -} - diff --git a/vendor/sigar/src/sigar_util.c b/vendor/sigar/src/sigar_util.c deleted file mode 100644 index 3c668fc..0000000 --- a/vendor/sigar/src/sigar_util.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * Copyright (c) 2004-2009 Hyperic, Inc. - * Copyright (c) 2009 SpringSource, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include "sigar.h" -#include "sigar_private.h" -#include "sigar_util.h" -#include "sigar_os.h" - -#ifndef WIN32 - -#include -#include - -SIGAR_INLINE char *sigar_uitoa(char *buf, unsigned int n, int *len) -{ - char *start = buf + UITOA_BUFFER_SIZE - 1; - - *start = 0; - - do { - *--start = '0' + (n % 10); - ++*len; - n /= 10; - } while (n); - - return start; -} - -SIGAR_INLINE char *sigar_skip_line(char *buffer, int buflen) -{ - char *ptr = buflen ? - (char *)memchr(buffer, '\n', buflen) : /* bleh */ - strchr(buffer, '\n'); - return ++ptr; -} - -SIGAR_INLINE char *sigar_skip_token(char *p) -{ - while (sigar_isspace(*p)) p++; - while (*p && !sigar_isspace(*p)) p++; - return p; -} - -SIGAR_INLINE char *sigar_skip_multiple_token(char *p, int count) -{ - int i; - - for (i = 0; i < count; i++) { - p = sigar_skip_token(p); - } - - return p; -} - -char *sigar_getword(char **line, char stop) -{ - char *pos = *line; - int len; - char *res; - - while ((*pos != stop) && *pos) { - ++pos; - } - - len = pos - *line; - res = malloc(len + 1); - memcpy(res, *line, len); - res[len] = 0; - - if (stop) { - while (*pos == stop) { - ++pos; - } - } - - *line = pos; - - return res; -} - -/* avoiding sprintf */ - -char *sigar_proc_filename(char *buffer, int buflen, - sigar_pid_t bigpid, - const char *fname, int fname_len) -{ - int len = 0; - char *ptr = buffer; - unsigned int pid = (unsigned int)bigpid; /* XXX -- This isn't correct */ - char pid_buf[UITOA_BUFFER_SIZE]; - char *pid_str = sigar_uitoa(pid_buf, pid, &len); - - assert((unsigned int)buflen >= - (SSTRLEN(PROCP_FS_ROOT) + UITOA_BUFFER_SIZE + fname_len + 1)); - - memcpy(ptr, PROCP_FS_ROOT, SSTRLEN(PROCP_FS_ROOT)); - ptr += SSTRLEN(PROCP_FS_ROOT); - - memcpy(ptr, pid_str, len); - ptr += len; - - memcpy(ptr, fname, fname_len); - ptr += fname_len; - *ptr = '\0'; - - return buffer; -} - -int sigar_proc_file2str(char *buffer, int buflen, - sigar_pid_t pid, - const char *fname, - int fname_len) -{ - int retval; - - buffer = sigar_proc_filename(buffer, buflen, pid, - fname, fname_len); - - retval = sigar_file2str(buffer, buffer, buflen); - - if (retval != SIGAR_OK) { - switch (retval) { - case ENOENT: - retval = ESRCH; /* no such process */ - default: - break; - } - } - - return retval; -} - -int sigar_proc_list_procfs_get(sigar_t *sigar, - sigar_proc_list_t *proclist) -{ - DIR *dirp = opendir("/proc"); - struct dirent *ent; -#ifdef HAVE_READDIR_R - struct dirent dbuf; -#endif - - if (!dirp) { - return errno; - } - -#ifdef HAVE_READDIR_R - while (readdir_r(dirp, &dbuf, &ent) == 0) { - if (ent == NULL) { - break; - } -#else - while ((ent = readdir(dirp))) { -#endif - if (!sigar_isdigit(*ent->d_name)) { - continue; - } - - /* XXX: more sanity checking */ - - SIGAR_PROC_LIST_GROW(proclist); - - proclist->data[proclist->number++] = - strtoul(ent->d_name, NULL, 10); - } - - closedir(dirp); - - return SIGAR_OK; -} - -int sigar_proc_fd_count(sigar_t *sigar, sigar_pid_t pid, - sigar_uint64_t *total) -{ - DIR *dirp; - struct dirent *ent; -#ifdef HAVE_READDIR_R - struct dirent dbuf; -#endif - char name[BUFSIZ]; - - (void)SIGAR_PROC_FILENAME(name, pid, "/fd"); - - *total = 0; - - if (!(dirp = opendir(name))) { - return errno; - } - -#ifdef HAVE_READDIR_R - while (readdir_r(dirp, &dbuf, &ent) == 0) { - if (ent == NULL) { - break; - } -#else - while ((ent = readdir(dirp))) { -#endif - if (!sigar_isdigit(*ent->d_name)) { - continue; - } - - (*total)++; - } - - closedir(dirp); - - return SIGAR_OK; -} - -int sigar_procfs_args_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_args_t *procargs) -{ - char buffer[9086], *buf=NULL, *ptr; - int fd, len, total=0; - - (void)SIGAR_PROC_FILENAME(buffer, pid, "/cmdline"); - - if ((fd = open(buffer, O_RDONLY)) < 0) { - if (errno == ENOENT) { - return ESRCH; - } - return errno; - } - - buffer[0] = '\0'; - - /* XXX: possible to get rid of some mallocs here. - * but, unlikely this will be called often so it - * might not even matter much. - */ - while ((len = read(fd, buffer, sizeof(buffer)-1)) > 0) { - if (len == 0) { - break; - } - buf = realloc(buf, total+len+1); - memcpy(buf+total, buffer, len); - total += len; - } - - close(fd); - - /* e.g. /proc/2/cmdline */ - if (total == 0) { - procargs->number = 0; - return SIGAR_OK; - } - - buf[total] = '\0'; - ptr = buf; - - while (total > 0) { - int alen = strlen(ptr)+1; - char *arg = malloc(alen); - - SIGAR_PROC_ARGS_GROW(procargs); - memcpy(arg, ptr, alen); - - procargs->data[procargs->number++] = arg; - - total -= alen; - if (total > 0) { - ptr += alen; - } - } - - free(buf); - - return SIGAR_OK; -} - -#endif /* WIN32 */ - -/* from httpd/server/util.c */ -char *sigar_strcasestr(const char *s1, const char *s2) -{ - char *p1, *p2; - if (*s2 == '\0') { - /* an empty s2 */ - return((char *)s1); - } - while(1) { - for ( ; (*s1 != '\0') && (sigar_tolower(*s1) != sigar_tolower(*s2)); s1++); - if (*s1 == '\0') { - return(NULL); - } - /* found first character of s2, see if the rest matches */ - p1 = (char *)s1; - p2 = (char *)s2; - for (++p1, ++p2; sigar_tolower(*p1) == sigar_tolower(*p2); ++p1, ++p2) { - if (*p1 == '\0') { - /* both strings ended together */ - return((char *)s1); - } - } - if (*p2 == '\0') { - /* second string ended, a match */ - break; - } - /* didn't find a match here, try starting at next character in s1 */ - s1++; - } - return((char *)s1); -} - -int sigar_mem_calc_ram(sigar_t *sigar, sigar_mem_t *mem) -{ - sigar_int64_t total = mem->total / 1024, diff; - sigar_uint64_t lram = (mem->total / (1024 * 1024)); - int ram = (int)lram; /* must cast after division */ - int remainder = ram % 8; - - if (remainder > 0) { - ram += (8 - remainder); - } - - mem->ram = ram; - - diff = total - (mem->actual_free / 1024); - mem->used_percent = - (double)(diff * 100) / total; - - diff = total - (mem->actual_used / 1024); - mem->free_percent = - (double)(diff * 100) / total; - - return ram; -} - -#ifndef WIN32 - -sigar_iodev_t *sigar_iodev_get(sigar_t *sigar, - const char *dirname) -{ - sigar_cache_entry_t *entry; - struct stat sb; - sigar_uint64_t id; - sigar_file_system_list_t fslist; - int i, status, is_dev=0; - int debug = SIGAR_LOG_IS_DEBUG(sigar); - char dev_name[SIGAR_FS_NAME_LEN]; - - if (!sigar->fsdev) { - sigar->fsdev = sigar_cache_new(15); - } - - if (*dirname != '/') { - snprintf(dev_name, sizeof(dev_name), - SIGAR_DEV_PREFIX "%s", dirname); - dirname = dev_name; - is_dev = 1; - } - else if (SIGAR_NAME_IS_DEV(dirname)) { - is_dev = 1; - } - - if (stat(dirname, &sb) < 0) { - if (debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[iodev] stat(%s) failed", - dirname); - } - return NULL; - } - - id = SIGAR_FSDEV_ID(sb); - - entry = sigar_cache_get(sigar->fsdev, id); - - if (entry->value != NULL) { - return (sigar_iodev_t *)entry->value; - } - - if (is_dev) { - sigar_iodev_t *iodev; - entry->value = iodev = malloc(sizeof(*iodev)); - SIGAR_ZERO(iodev); - SIGAR_SSTRCPY(iodev->name, dirname); - if (debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[iodev] %s is_dev=true", dirname); - } - return iodev; - } - - status = sigar_file_system_list_get(sigar, &fslist); - - if (status != SIGAR_OK) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[iodev] file_system_list failed: %s", - sigar_strerror(sigar, status)); - return NULL; - } - - for (i=0; itype == SIGAR_FSTYPE_LOCAL_DISK) { - int retval = stat(fsp->dir_name, &sb); - sigar_cache_entry_t *ent; - - if (retval < 0) { - if (debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[iodev] inode stat(%s) failed", - fsp->dir_name); - } - continue; /* cant cache w/o inode */ - } - - ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb)); - if (ent->value) { - continue; /* already cached */ - } - - if (SIGAR_NAME_IS_DEV(fsp->dev_name)) { - sigar_iodev_t *iodev; - ent->value = iodev = malloc(sizeof(*iodev)); - SIGAR_ZERO(iodev); - iodev->is_partition = 1; - SIGAR_SSTRCPY(iodev->name, fsp->dev_name); - - if (debug) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[iodev] map %s -> %s", - fsp->dir_name, iodev->name); - } - } - } - } - - sigar_file_system_list_destroy(sigar, &fslist); - - if (entry->value && - (((sigar_iodev_t *)entry->value)->name[0] != '\0')) - { - return (sigar_iodev_t *)entry->value; - } - else { - return NULL; - } -} -#endif - -double sigar_file_system_usage_calc_used(sigar_t *sigar, - sigar_file_system_usage_t *fsusage) -{ - /* - * win32 will not convert __uint64 to double. - * convert to KB then do unsigned long -> double. - */ - sigar_uint64_t b_used = (fsusage->total - fsusage->free) / 1024; - sigar_uint64_t b_avail = fsusage->avail / 1024; - unsigned long utotal = b_used + b_avail; - unsigned long used = b_used; - - if (utotal != 0) { - unsigned long u100 = used * 100; - double pct = u100 / utotal + - ((u100 % utotal != 0) ? 1 : 0); - return pct / 100; - } - - return 0; -} - -typedef struct { - sigar_uint32_t eax; - sigar_uint32_t ebx; - sigar_uint32_t ecx; - sigar_uint32_t edx; -} sigar_cpuid_t; - -#if defined(__GNUC__) && !defined(__sun) - -# if defined(__i386__) -# define SIGAR_HAS_CPUID -static void sigar_cpuid(sigar_uint32_t request, sigar_cpuid_t *id) -{ - /* derived from: */ - /* http://svn.red-bean.com/repos/minor/trunk/gc/barriers-ia-32.c */ - asm volatile ("mov %%ebx, %%esi\n\t" - "cpuid\n\t" - "xchgl %%ebx, %%esi" - : "=a" (id->eax), - "=S" (id->ebx), - "=c" (id->ecx), - "=d" (id->edx) - : "0" (request) - : "memory"); -} -# elif defined(__amd64__) -# define SIGAR_HAS_CPUID -static void sigar_cpuid(sigar_uint32_t request, - sigar_cpuid_t *id) -{ - /* http://svn.red-bean.com/repos/minor/trunk/gc/barriers-amd64.c */ - asm volatile ("cpuid\n\t" - : "=a" (id->eax), - "=b" (id->ebx), - "=c" (id->ecx), - "=d" (id->edx) - : "0" (request) - : "memory"); -} -# endif -#elif defined(WIN32) -# ifdef _M_X64 -# include -# define SIGAR_HAS_CPUID -static void sigar_cpuid(sigar_uint32_t request, - sigar_cpuid_t *id) -{ - sigar_uint32_t info[4]; - __cpuid(info, request); /* as of MSVC 7 */ - memcpy(id, &info[0], sizeof(info)); -} -# else -# define SIGAR_HAS_CPUID -static void sigar_cpuid(sigar_uint32_t request, - sigar_cpuid_t *id) -{ - __asm { - mov edi, id - mov eax, [edi].eax - mov ecx, [edi].ecx - cpuid - mov [edi].eax, eax - mov [edi].ebx, ebx - mov [edi].ecx, ecx - mov [edi].edx, edx - } -} -# endif -#endif - -#define INTEL_ID 0x756e6547 -#define AMD_ID 0x68747541 - -int sigar_cpu_core_count(sigar_t *sigar) -{ -#if defined(SIGAR_HAS_CPUID) - sigar_cpuid_t id; - - if (sigar->lcpu == -1) { - sigar->lcpu = 1; - - sigar_cpuid(0, &id); - - if ((id.ebx == INTEL_ID) || (id.ebx == AMD_ID)) { - sigar_cpuid(1, &id); - - if (id.edx & (1<<28)) { - sigar->lcpu = (id.ebx & 0x00FF0000) >> 16; - } - } - - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[cpu] %d cores per socket", sigar->lcpu); - } - - return sigar->lcpu; -#elif defined(__sun) || defined(__hpux) || defined(_AIX) - return 1; -#else - sigar->lcpu = 1; - return sigar->lcpu; -#endif -} - -int sigar_cpu_core_rollup(sigar_t *sigar) -{ -#ifdef SIGAR_HAS_CPUID - int log_rollup = - SIGAR_LOG_IS_DEBUG(sigar) && - (sigar->lcpu == -1); - - (void)sigar_cpu_core_count(sigar); - - if (sigar->cpu_list_cores) { - if (log_rollup && (sigar->lcpu > 1)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[cpu] treating cores as-is"); - } - } - else { - if (log_rollup && (sigar->lcpu > 1)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "[cpu] rolling up cores to sockets"); - return 1; - } - } -#endif - return 0; -} - -#define IS_CPU_R(p) \ - ((*p == '(') && (*(p+1) == 'R') && (*(p+2) == ')')) - -typedef struct { - char *name; /* search */ - int len; - char *rname; /* replace */ - int rlen; -} cpu_model_str_t; - -/* to later replace 's' with 'r' */ -#define CPU_MODEL_ENT_R(s, r) \ - { s, sizeof(s)-1, r, sizeof(r) } - -#define CPU_MODEL_ENT(s) \ - CPU_MODEL_ENT_R(s, s) - -/* after the vendor part of the string is removed, - * looking for startsWith the entries below - * to remove the crap after the model name, see - * ../exp/intel_amd_cpu_models.txt - */ -static const cpu_model_str_t cpu_models[] = { - /* intel */ - CPU_MODEL_ENT("Xeon"), - CPU_MODEL_ENT_R("XEON", "Xeon"), - CPU_MODEL_ENT("Pentium III"), - CPU_MODEL_ENT("Pentium II"), - CPU_MODEL_ENT_R("Pentium(R) III", "Pentium III"), - CPU_MODEL_ENT_R("Pentium(R) 4", "Pentium 4"), - CPU_MODEL_ENT_R("Pentium(R) M", "Pentium M"), - CPU_MODEL_ENT("Pentium Pro"), - CPU_MODEL_ENT("Celeron"), - - /* amd */ - CPU_MODEL_ENT("Opteron"), - CPU_MODEL_ENT("Athlon"), - CPU_MODEL_ENT("Duron"), - CPU_MODEL_ENT_R("K6(tm)-III", "K6 III"), - CPU_MODEL_ENT_R("K6(tm) 3D+", "K6 3D+"), - { NULL } -}; - -/* common to win32 and linux */ -void sigar_cpu_model_adjust(sigar_t *sigar, sigar_cpu_info_t *info) -{ - int len, i; - char model[128], *ptr=model, *end; - - memcpy(model, info->model, sizeof(model)); - - /* trim leading and trailing spaces */ - len = strlen(model); - end = &model[len-1]; - while (*ptr == ' ') ++ptr; - while (*end == ' ') *end-- = '\0'; - - /* remove vendor from model name */ - len = strlen(info->vendor); - if (strnEQ(ptr, info->vendor, len)) { - ptr += len; - if (IS_CPU_R(ptr)) { - ptr += 3; /* remove (R) */ - } - while (*ptr == ' ') ++ptr; - } - - if (*ptr == '-') { - ++ptr; /* e.g. was AMD-K6... */ - } - - for (i=0; cpu_models[i].name; i++) { - const cpu_model_str_t *cpu_model = &cpu_models[i]; - - if (strnEQ(ptr, cpu_model->name, cpu_model->len)) { - memcpy(info->model, cpu_model->rname, cpu_model->rlen); - return; - } - } - - strcpy(info->model, ptr); -} - -/* attempt to derive MHz from model name - * currently works for certain intel strings - * see exp/intel_amd_cpu_models.txt - */ -int sigar_cpu_mhz_from_model(char *model) -{ - int mhz = SIGAR_FIELD_NOTIMPL; - char *ptr = model; - - while (*ptr && (ptr = strchr(ptr, ' '))) { - while(*ptr && !sigar_isdigit(*ptr)) { - ptr++; - } - mhz = sigar_strtoul(ptr); - - if (*ptr == '.') { - /* e.g. "2.40GHz" */ - ++ptr; - mhz *= 100; - mhz += sigar_strtoul(ptr); - break; - } - else if (strnEQ(ptr, "GHz", 3) || - strnEQ(ptr, "MHz", 3)) - { - /* e.g. "1500MHz" */ - break; - } - else { - mhz = SIGAR_FIELD_NOTIMPL; - } - } - - if (mhz != SIGAR_FIELD_NOTIMPL) { - if (strnEQ(ptr, "GHz", 3)) { - mhz *= 10; - } - } - - return mhz; -} - -#if !defined(WIN32) && !defined(NETWARE) -#include -#include -#include -#include -#ifdef SIGAR_HPUX -#include -#endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun) || defined(DARWIN) -#include -#endif -#if defined(__sun) || defined(SIGAR_HPUX) -#include -#endif -#if defined(_AIX) || defined(SIGAR_HPUX) || defined(__OpenBSD__) || defined(__NetBSD__) -#include -#endif - -static enum clnt_stat get_sockaddr(struct sockaddr_in *addr, char *host) -{ - register struct hostent *hp; - sigar_hostent_t data; - - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; - - if ((addr->sin_addr.s_addr = inet_addr(host)) == -1) { - if (!(hp = sigar_gethostbyname(host, &data))) { - return RPC_UNKNOWNHOST; - } - memcpy(&addr->sin_addr, hp->h_addr, hp->h_length); - } - - return RPC_SUCCESS; -} - -char *sigar_rpc_strerror(int err) -{ - return (char *)clnt_sperrno(err); -} - -SIGAR_DECLARE(int) sigar_rpc_ping(char *host, - int protocol, - unsigned long program, - unsigned long version) -{ - CLIENT *client; - struct sockaddr_in addr; - int sock; - struct timeval timeout; - unsigned short port = 0; - enum clnt_stat rpc_stat; - - rpc_stat = get_sockaddr(&addr, host); - if (rpc_stat != RPC_SUCCESS) { - return rpc_stat; - } - - timeout.tv_sec = 2; - timeout.tv_usec = 0; - addr.sin_port = htons(port); - sock = RPC_ANYSOCK; - - if (protocol == SIGAR_NETCONN_UDP) { - client = - clntudp_create(&addr, program, version, - timeout, &sock); - } - else if (protocol == SIGAR_NETCONN_TCP) { - client = - clnttcp_create(&addr, program, version, - &sock, 0, 0); - } - else { - return RPC_UNKNOWNPROTO; - } - - if (!client) { - return rpc_createerr.cf_stat; - } - - timeout.tv_sec = 10; - timeout.tv_usec = 0; - rpc_stat = clnt_call(client, NULLPROC, (xdrproc_t)xdr_void, NULL, - (xdrproc_t)xdr_void, NULL, timeout); - - clnt_destroy(client); - - return rpc_stat; -} -#endif - -int sigar_file2str(const char *fname, char *buffer, int buflen) -{ - int len, status; - int fd = open(fname, O_RDONLY); - - if (fd < 0) { - return ENOENT; - } - - if ((len = read(fd, buffer, buflen)) < 0) { - status = errno; - } - else { - status = SIGAR_OK; - buffer[len] = '\0'; - } - close(fd); - - return status; -} - -#ifdef WIN32 -#define vsnprintf _vsnprintf -#endif - -#ifdef WIN32 -# define rindex strrchr -#endif - -static int proc_module_get_self(void *data, char *name, int len) -{ - sigar_t *sigar = (sigar_t *)data; - char *ptr = rindex(name, '/'); - - if (!ptr) { - return SIGAR_OK; - } - - if (strnEQ(ptr+1, "libsigar-", 9)) { - int offset = ptr - name; - - sigar->self_path = sigar_strdup(name); - *(sigar->self_path + offset) = '\0'; /* chop libsigar-*.so */ - - if (SIGAR_LOG_IS_DEBUG(sigar)) { - sigar_log_printf(sigar, SIGAR_LOG_DEBUG, - "detected sigar-lib='%s'", - sigar->self_path); - } - - return !SIGAR_OK; /* break loop */ - } - - return SIGAR_OK; -} - -char *sigar_get_self_path(sigar_t *sigar) -{ - if (!sigar->self_path) { - sigar_proc_modules_t procmods; - char *self_path = getenv("SIGAR_PATH"); - - if (self_path) { - sigar->self_path = sigar_strdup(self_path); - return sigar->self_path; - } - - procmods.module_getter = proc_module_get_self; - procmods.data = sigar; - - sigar_proc_modules_get(sigar, - sigar_pid_get(sigar), - &procmods); - - if (!sigar->self_path) { - /* dont try again */ - sigar->self_path = sigar_strdup("."); - } - } - - return sigar->self_path; -} - -#ifdef SIGAR_HAS_DLINFO_MODULES - -static int sigar_dlinfo_get(sigar_t *sigar, const char *func, - void **handle, Link_map **map) -{ - Dl_info dli; - - if (!dladdr((void *)((uintptr_t)sigar_dlinfo_get), &dli)) { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "[%s] dladdr(%s) = %s", - func, SIGAR_FUNC, dlerror()); - return ESRCH; - } - - if (!(*handle = dlopen(dli.dli_fname, RTLD_LAZY))) { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "[%s] dlopen(%s) = %s", - func, dli.dli_fname, dlerror()); - return ESRCH; - } - - dlinfo(*handle, RTLD_DI_LINKMAP, map); - - if (!map) { - sigar_log_printf(sigar, SIGAR_LOG_ERROR, - "[%s] dlinfo = %s", - func, dlerror()); - return ESRCH; - } - - return SIGAR_OK; -} - -int sigar_dlinfo_modules(sigar_t *sigar, sigar_proc_modules_t *procmods) -{ - int status; - void *handle; - Link_map *map; - - status = sigar_dlinfo_get(sigar, SIGAR_FUNC, &handle, &map); - if (status != SIGAR_OK) { - return status; - } - - while (map->l_prev != NULL) { - map = map->l_prev; - } - - do { - int status = - procmods->module_getter(procmods->data, - (char *)map->l_name, - strlen(map->l_name)); - - if (status != SIGAR_OK) { - /* not an error; just stop iterating */ - break; - } - } while ((map = map->l_next)); - - dlclose(handle); - - return SIGAR_OK; -} -#endif - -SIGAR_DECLARE(void) sigar_log_printf(sigar_t *sigar, int level, - const char *format, ...) -{ - va_list args; - char buffer[8192]; - - if (level > sigar->log_level) { - return; - } - - if (!sigar->log_impl) { - return; - } - - va_start(args, format); - vsnprintf(buffer, sizeof(buffer), format, args); - va_end(args); - - sigar->log_impl(sigar, sigar->log_data, level, buffer); -} - -SIGAR_DECLARE(void) sigar_log(sigar_t *sigar, int level, char *message) -{ - if (level > sigar->log_level) { - return; - } - - if (!sigar->log_impl) { - return; - } - - sigar->log_impl(sigar, sigar->log_data, level, message); -} - -SIGAR_DECLARE(void) sigar_log_impl_set(sigar_t *sigar, void *data, - sigar_log_impl_t impl) -{ - sigar->log_data = data; - sigar->log_impl = impl; -} - -SIGAR_DECLARE(int) sigar_log_level_get(sigar_t *sigar) -{ - return sigar->log_level; -} - -static const char *log_levels[] = { - "FATAL", - "ERROR", - "WARN", - "INFO", - "DEBUG", - "TRACE" -}; - -SIGAR_DECLARE(const char *) sigar_log_level_string_get(sigar_t *sigar) -{ - return log_levels[sigar->log_level]; -} - -SIGAR_DECLARE(void) sigar_log_level_set(sigar_t *sigar, int level) -{ - sigar->log_level = level; -} - -SIGAR_DECLARE(void) sigar_log_impl_file(sigar_t *sigar, void *data, - int level, char *message) -{ - FILE *fp = (FILE*)data; - fprintf(fp, "[%s] %s\n", log_levels[level], message); -} - -#ifndef WIN32 -sigar_int64_t sigar_time_now_millis(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return ((tv.tv_sec * SIGAR_USEC) + tv.tv_usec) / SIGAR_MSEC; -} -#endif diff --git a/vendor/sigar/src/sigar_version_autoconf.c b/vendor/sigar/src/sigar_version_autoconf.c deleted file mode 100644 index 7b1f865..0000000 --- a/vendor/sigar/src/sigar_version_autoconf.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "sigar.h" - -static sigar_version_t sigar_version = { - __DATE__, - "@SCM_REVISION@", - "libsigar 1.6.2", - "x86_64-apple-darwin11.4.0", - "darwin11.4.0", - "x86_64", - "SIGAR-1.6.2, " - "SCM revision @SCM_REVISION@, " - "built "__DATE__" as x86_64", - 1, - 6, - 2, - 0 -}; - -SIGAR_DECLARE(sigar_version_t *) sigar_version_get(void) -{ - return &sigar_version; -}