various updates for arm
This commit is contained in:
commit
0114f6e3e7
169 changed files with 60409 additions and 272 deletions
|
|
@ -41,9 +41,8 @@ option( UNITY_BUILD OFF )
|
|||
|
||||
FIND_PACKAGE( OpenSSL )
|
||||
|
||||
include_directories( vendor/boost/process/include )
|
||||
include_directories( vendor/libssh2-1.4.2/include )
|
||||
include_directories( vendor/zlib-1.2.7/)
|
||||
include_directories( vendor/libssh2-1.4.2/include )
|
||||
include_directories( ${Boost_INCLUDE_DIR} )
|
||||
include_directories( ${OPENSSL_INCLUDE_DIR} )
|
||||
include_directories( include )
|
||||
|
|
@ -95,13 +94,12 @@ set( sources
|
|||
# src/program_options.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(vendor/libssh2-1.4.2)
|
||||
add_subdirectory( vendor/zlib-1.2.7/)
|
||||
add_subdirectory(vendor)
|
||||
|
||||
setup_library( fc SOURCES ${sources} )
|
||||
|
||||
setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES zlibstatic fc ${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 zlibstatic ${OPENSSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_DATE_TIME_LIBRARY})
|
||||
#setup_executable( json_rpc_test SOURCES tests/json_rpc_test.cpp LIBRARIES fc ${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})
|
||||
|
||||
#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} )
|
||||
|
|
|
|||
25
include/boost/process.hpp
Normal file
25
include/boost/process.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process.hpp
|
||||
*
|
||||
* Convenience header that includes all public Boost.Process header files.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_HPP
|
||||
#define BOOST_PROCESS_HPP
|
||||
|
||||
#include <boost/process/all.hpp>
|
||||
|
||||
#endif
|
||||
40
include/boost/process/all.hpp
Normal file
40
include/boost/process/all.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/all.hpp
|
||||
*
|
||||
* Convenience header that includes all public Boost.Process header files.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_ALL_HPP
|
||||
#define BOOST_PROCESS_ALL_HPP
|
||||
|
||||
#include <boost/process/child.hpp>
|
||||
#include <boost/process/context.hpp>
|
||||
#include <boost/process/environment.hpp>
|
||||
#include <boost/process/handle.hpp>
|
||||
#include <boost/process/operations.hpp>
|
||||
#include <boost/process/pid_type.hpp>
|
||||
#include <boost/process/pipe.hpp>
|
||||
#include <boost/process/pistream.hpp>
|
||||
#include <boost/process/postream.hpp>
|
||||
#include <boost/process/process.hpp>
|
||||
#include <boost/process/self.hpp>
|
||||
#include <boost/process/status.hpp>
|
||||
#include <boost/process/stream_behavior.hpp>
|
||||
#include <boost/process/stream_ends.hpp>
|
||||
#include <boost/process/stream_id.hpp>
|
||||
#include <boost/process/stream_type.hpp>
|
||||
|
||||
#endif
|
||||
92
include/boost/process/child.hpp
Normal file
92
include/boost/process/child.hpp
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/child.hpp
|
||||
*
|
||||
* Includes the declaration of the child class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_CHILD_HPP
|
||||
#define BOOST_PROCESS_CHILD_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/process/process.hpp>
|
||||
#include <boost/process/pid_type.hpp>
|
||||
#include <boost/process/stream_id.hpp>
|
||||
#include <boost/process/handle.hpp>
|
||||
#include <map>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* The child class provides access to a child process.
|
||||
*/
|
||||
class child : public process
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a new child object that represents the just spawned child
|
||||
* process \a id.
|
||||
*/
|
||||
child(pid_type id, std::map<stream_id, handle> handles)
|
||||
: process(id),
|
||||
handles_(handles)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
/**
|
||||
* Creates a new child object that represents the just spawned child
|
||||
* process \a id.
|
||||
*
|
||||
* This operation is only available on Windows systems.
|
||||
*/
|
||||
child(handle hprocess, std::map<stream_id, handle> handles)
|
||||
: process(hprocess),
|
||||
handles_(handles)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gets a handle to a stream attached to the child.
|
||||
*
|
||||
* If the handle doesn't exist an invalid handle is returned.
|
||||
*/
|
||||
handle get_handle(stream_id id) const
|
||||
{
|
||||
std::map<stream_id, handle>::const_iterator it = handles_.find(id);
|
||||
return (it != handles_.end()) ? it->second : handle();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Handles providing access to streams attached to the child process.
|
||||
*/
|
||||
std::map<stream_id, handle> handles_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
74
include/boost/process/config.hpp
Normal file
74
include/boost/process/config.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/config.hpp
|
||||
*
|
||||
* Defines macros that are used by the library to determine the operating
|
||||
* system it is running under and the features it supports.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_CONFIG_HPP
|
||||
#define BOOST_PROCESS_CONFIG_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/system/config.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <errno.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
|
||||
# if !defined(BOOST_PROCESS_POSIX_PATH_MAX) || defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* Specifies the system's maximal supported path length.
|
||||
*
|
||||
* The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer
|
||||
* value which specifies the system's maximal supported path length. It is
|
||||
* only used if neither PATH_MAX nor _PC_PATH_MAX and HAVE_PATHCONF are defined.
|
||||
* The maximal supported path length is required by
|
||||
* boost::process::self::get_work_dir(). Please note that this function is
|
||||
* also called by the constructor of boost::process::context.
|
||||
*/
|
||||
# define BOOST_PROCESS_POSIX_PATH_MAX 259
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** \cond */
|
||||
#define BOOST_PROCESS_SOURCE_LOCATION \
|
||||
"in file '" __FILE__ "', line " BOOST_STRINGIZE(__LINE__) ": "
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# define BOOST_PROCESS_LAST_ERROR errno
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# define BOOST_PROCESS_LAST_ERROR GetLastError()
|
||||
#endif
|
||||
|
||||
#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \
|
||||
boost::throw_exception(boost::system::system_error( \
|
||||
boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
|
||||
boost::system::get_system_category()), \
|
||||
BOOST_PROCESS_SOURCE_LOCATION what))
|
||||
|
||||
#define BOOST_PROCESS_THROW_ERROR(error, what) \
|
||||
boost::throw_exception(boost::system::system_error( \
|
||||
boost::system::error_code(error, \
|
||||
boost::system::get_system_category()), \
|
||||
BOOST_PROCESS_SOURCE_LOCATION what))
|
||||
/** \endcond */
|
||||
|
||||
#endif
|
||||
133
include/boost/process/context.hpp
Normal file
133
include/boost/process/context.hpp
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/context.hpp
|
||||
*
|
||||
* Includes the declaration of the context class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_CONTEXT_HPP
|
||||
#define BOOST_PROCESS_CONTEXT_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <unistd.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <boost/process/stream_id.hpp>
|
||||
#include <boost/process/stream_ends.hpp>
|
||||
#include <boost/process/stream_type.hpp>
|
||||
#include <boost/process/environment.hpp>
|
||||
#include <boost/process/self.hpp>
|
||||
#include <boost/process/stream_behavior.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Context class to define how a child process is created.
|
||||
*
|
||||
* The context class is used to configure streams, to set the work directory
|
||||
* and define environment variables. It is also used to change a process
|
||||
* name (the variable commonly known as argv[0]).
|
||||
*/
|
||||
struct context
|
||||
{
|
||||
typedef std::map<stream_id, boost::function<stream_ends (stream_type)> >
|
||||
streams_t;
|
||||
|
||||
/**
|
||||
* Streams.
|
||||
*
|
||||
* Streams of a child process can be configured through factory functions
|
||||
* which return a pair of handles - one handle to use as a stream end
|
||||
* in the child process and possibly another handle to use as a stream end
|
||||
* in the parent process (if a pipe is setup both processes can communicate
|
||||
* with each other).
|
||||
*/
|
||||
streams_t streams;
|
||||
|
||||
/**
|
||||
* Process name.
|
||||
*
|
||||
* The child process can access the process name via a variable
|
||||
* commonly known as argv[0].
|
||||
*/
|
||||
std::string process_name;
|
||||
|
||||
/**
|
||||
* Work directory.
|
||||
*/
|
||||
std::string work_dir;
|
||||
|
||||
/**
|
||||
* Environment variables.
|
||||
*/
|
||||
environment env;
|
||||
|
||||
/**
|
||||
* Constructs a process context.
|
||||
*
|
||||
* The default behavior of standard streams is to inherit them. The current
|
||||
* work directory is also the work directory of the child process. The child
|
||||
* process also inherits all environment variables.
|
||||
*/
|
||||
context()
|
||||
: work_dir(self::get_work_dir()),
|
||||
env(self::get_environment())
|
||||
{
|
||||
#if 0 // this default behavior will throw in non-console apps
|
||||
#if defined(BOOST_POSIX_API)
|
||||
streams[stdin_id] = behavior::inherit(STDIN_FILENO);
|
||||
streams[stdout_id] = behavior::inherit(STDOUT_FILENO);
|
||||
streams[stderr_id] = behavior::inherit(STDERR_FILENO);
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
streams[stdin_id] = behavior::inherit(GetStdHandle(STD_INPUT_HANDLE));
|
||||
streams[stdout_id] = behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||
streams[stderr_id] = behavior::inherit(GetStdHandle(STD_ERROR_HANDLE));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* Setups a child process.
|
||||
*
|
||||
* This is an extension point to support more configuration options for
|
||||
* child processes. You can initialize \a setup with a user-defined function
|
||||
* which is called when a child process is created.
|
||||
*
|
||||
* On POSIX platforms setup() is called in the child process. That's why in
|
||||
* a multithreaded application only async-signal-safe functions must be
|
||||
* called in the function \a setup is bound to.
|
||||
*
|
||||
* On Windows platforms setup() is called in the parent process. A
|
||||
* reference to a STARTUPINFOA structure is passed as parameter.
|
||||
*/
|
||||
boost::function<void ()> setup;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
boost::function<void (STARTUPINFOA&)> setup;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
69
include/boost/process/detail/basic_status.hpp
Normal file
69
include/boost/process/detail/basic_status.hpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/detail/basic_status.hpp
|
||||
*
|
||||
* Includes the declaration of the basic status class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP
|
||||
#define BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
#include <boost/process/pid_type.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* The basic_status class to wait for processes to exit.
|
||||
*
|
||||
* The basic_status class is a Boost.Asio I/O object and supports synchronous
|
||||
* and asynchronous wait operations. It must be instantiated with a Service.
|
||||
*/
|
||||
template <typename Service>
|
||||
class basic_status
|
||||
: public boost::asio::basic_io_object<Service>
|
||||
{
|
||||
public:
|
||||
explicit basic_status(boost::asio::io_service &io_service)
|
||||
: boost::asio::basic_io_object<Service>(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits synchronously for a process to exit.
|
||||
*/
|
||||
int wait(pid_type pid)
|
||||
{
|
||||
return this->service.wait(this->implementation, pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits asynchronously for a process to exit.
|
||||
*/
|
||||
template <typename Handler>
|
||||
void async_wait(pid_type pid, Handler handler)
|
||||
{
|
||||
this->service.async_wait(this->implementation, pid, handler);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
318
include/boost/process/detail/basic_status_service.hpp
Normal file
318
include/boost/process/detail/basic_status_service.hpp
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/detail/basic_status_service.hpp
|
||||
*
|
||||
* Includes the declaration of the basic status service class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP
|
||||
#define BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <boost/process/operations.hpp>
|
||||
# include <string>
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/process/pid_type.hpp>
|
||||
#include <boost/process/detail/status_impl.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* The basic_status_service class provides the service to wait for processes
|
||||
* synchronously and asynchronously.
|
||||
*/
|
||||
template <typename StatusImplementation = status_impl>
|
||||
class basic_status_service
|
||||
: public boost::asio::detail::service_base<StatusImplementation>
|
||||
{
|
||||
public:
|
||||
explicit basic_status_service(boost::asio::io_service &io_service)
|
||||
: boost::asio::detail::service_base<StatusImplementation>(io_service),
|
||||
#if defined(BOOST_POSIX_API)
|
||||
interrupt_pid_(-1),
|
||||
pids_(0)
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
run_(true)
|
||||
#endif
|
||||
{
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
handles_.push_back(CreateEvent(NULL, FALSE, FALSE, NULL));
|
||||
if (handles_[0] == NULL)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateEvent() failed");
|
||||
work_thread_ = boost::thread(
|
||||
&basic_status_service<StatusImplementation>::work_thread, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
~basic_status_service()
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
bool worker_thread_active = (pids_ != 0);
|
||||
lock.unlock();
|
||||
if (worker_thread_active)
|
||||
{
|
||||
stop_work_thread();
|
||||
work_thread_.join();
|
||||
}
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
stop_work_thread();
|
||||
work_thread_.join();
|
||||
CloseHandle(handles_[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef boost::shared_ptr<StatusImplementation> implementation_type;
|
||||
|
||||
void construct(implementation_type &impl)
|
||||
{
|
||||
impl = boost::make_shared<StatusImplementation>();
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
impls_.push_back(impl);
|
||||
}
|
||||
|
||||
void destroy(implementation_type &impl)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
typename std::vector<implementation_type>::iterator it =
|
||||
std::find(impls_.begin(), impls_.end(), impl);
|
||||
if (it != impls_.end())
|
||||
impls_.erase(it);
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
interrupt_work_thread();
|
||||
work_thread_cond_.wait(work_thread_mutex_);
|
||||
impl->clear(handles_);
|
||||
work_thread_cond_.notify_all();
|
||||
#endif
|
||||
impl.reset();
|
||||
}
|
||||
|
||||
int wait(implementation_type &impl, pid_type pid)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
int status = impl->wait(pid, ec);
|
||||
#if defined(BOOST_POSIX_API)
|
||||
if (ec.value() == ECHILD)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
boost::unordered_map<pid_t, int>::iterator it = statuses_.find(pid);
|
||||
if (it == statuses_.end())
|
||||
{
|
||||
work_thread_cond_.wait(work_thread_mutex_);
|
||||
it = statuses_.find(pid);
|
||||
}
|
||||
if (it != statuses_.end())
|
||||
{
|
||||
status = it->second;
|
||||
statuses_.erase(it);
|
||||
ec.clear();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
boost::asio::detail::throw_error(ec);
|
||||
return status;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void async_wait(implementation_type &impl, pid_type pid, Handler handler)
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
if (++pids_ == 1)
|
||||
{
|
||||
work_.reset(new boost::asio::io_service::work(
|
||||
this->get_io_service()));
|
||||
work_thread_ = boost::thread(
|
||||
&basic_status_service<StatusImplementation>::work_thread,
|
||||
this);
|
||||
}
|
||||
impl->async_wait(pid, this->get_io_service().wrap(handler));
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
|
||||
FALSE, pid);
|
||||
if (handle == NULL)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
if (!work_)
|
||||
work_.reset(new boost::asio::io_service::work(
|
||||
this->get_io_service()));
|
||||
interrupt_work_thread();
|
||||
work_thread_cond_.wait(work_thread_mutex_);
|
||||
handles_.push_back(handle);
|
||||
impl->async_wait(handle, this->get_io_service().wrap(handler));
|
||||
work_thread_cond_.notify_all();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
void shutdown_service()
|
||||
{
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
work_.reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
void work_thread()
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
for (;;)
|
||||
{
|
||||
int status;
|
||||
pid_t pid = ::wait(&status);
|
||||
if (pid == -1)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("wait(2) failed");
|
||||
}
|
||||
else if (interrupted(pid))
|
||||
{
|
||||
// On POSIX the only reason to interrupt is to break out.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
bool regchild = false;
|
||||
for (typename std::vector<implementation_type>::iterator it =
|
||||
impls_.begin(); it != impls_.end(); ++it)
|
||||
regchild |= (*it)->complete(pid, status);
|
||||
if (regchild && --pids_ == 0)
|
||||
{
|
||||
work_.reset();
|
||||
break;
|
||||
}
|
||||
else if (!regchild)
|
||||
{
|
||||
statuses_.insert(boost::unordered_map<pid_t, int>::
|
||||
value_type(pid, status));
|
||||
work_thread_cond_.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
for (;;)
|
||||
{
|
||||
DWORD res = WaitForMultipleObjects(handles_.size(), &handles_[0],
|
||||
FALSE, INFINITE);
|
||||
if (res == WAIT_FAILED)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"WaitForMultipleObjects() failed");
|
||||
else if (res - WAIT_OBJECT_0 == 0)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
if (!run_)
|
||||
break;
|
||||
work_thread_cond_.notify_all();
|
||||
work_thread_cond_.wait(work_thread_mutex_);
|
||||
}
|
||||
else if (res - WAIT_OBJECT_0 > 0)
|
||||
{
|
||||
HANDLE handle = handles_[res - WAIT_OBJECT_0];
|
||||
DWORD exit_code;
|
||||
if (!GetExitCodeProcess(handle, &exit_code))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"GetExitCodeProcess() failed");
|
||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
||||
for (typename std::vector<implementation_type>::iterator it =
|
||||
impls_.begin(); it != impls_.end(); ++it)
|
||||
(*it)->complete(handle, exit_code);
|
||||
std::vector<HANDLE>::iterator it = handles_.begin();
|
||||
std::advance(it, res - WAIT_OBJECT_0);
|
||||
handles_.erase(it);
|
||||
if (handles_.size() == 1)
|
||||
work_.reset();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void interrupt_work_thread()
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
// By creating a child process which immediately exits
|
||||
// we interrupt wait().
|
||||
std::vector<std::string> args;
|
||||
args.push_back("-c");
|
||||
args.push_back("'exit'");
|
||||
interrupt_pid_ = create_child("/bin/sh", args).get_id();
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
// By signaling the event in the first slot WaitForMultipleObjects()
|
||||
// will return. The work thread won't do anything except checking if
|
||||
// it should continue to run.
|
||||
if (!SetEvent(handles_[0]))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetEvent() failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
bool interrupted(pid_t pid)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(work_thread_mutex_);
|
||||
return interrupt_pid_ == pid;
|
||||
}
|
||||
#endif
|
||||
|
||||
void stop_work_thread()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(work_thread_mutex_);
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
// Access to run_ must be sychronized with running().
|
||||
run_ = false;
|
||||
#endif
|
||||
// Access to interrupt_pid_ must be sychronized with interrupted().
|
||||
interrupt_work_thread();
|
||||
}
|
||||
|
||||
boost::scoped_ptr<boost::asio::io_service::work> work_;
|
||||
std::vector<implementation_type> impls_;
|
||||
boost::mutex work_thread_mutex_;
|
||||
boost::thread work_thread_;
|
||||
boost::condition_variable_any work_thread_cond_;
|
||||
#if defined(BOOST_POSIX_API)
|
||||
pid_t interrupt_pid_;
|
||||
int pids_;
|
||||
boost::unordered_map<pid_t, int> statuses_;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
bool run_;
|
||||
std::vector<HANDLE> handles_;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
106
include/boost/process/detail/posix_helpers.hpp
Normal file
106
include/boost/process/detail/posix_helpers.hpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/detail/posix_helpers.hpp
|
||||
*
|
||||
* Includes the declaration of helper functions for POSIX systems.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_POSIX_HELPERS_HPP
|
||||
#define BOOST_PROCESS_POSIX_HELPERS_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
#include <boost/process/environment.hpp>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Converts an environment to a char** table as used by execve().
|
||||
*
|
||||
* Converts the environment's contents to the format used by the
|
||||
* execve() system call. The returned char** array is allocated
|
||||
* in dynamic memory; the caller must free it when not used any
|
||||
* more. Each entry is also allocated in dynamic memory and is a
|
||||
* NULL-terminated string of the form var=value; these must also be
|
||||
* released by the caller.
|
||||
*
|
||||
* This operation is only available on POSIX systems.
|
||||
*
|
||||
* \return The first argument of the pair is an integer that indicates
|
||||
* how many strings are stored in the second argument. The
|
||||
* second argument is a NULL-terminated, dynamically allocated
|
||||
* array of dynamically allocated strings representing the
|
||||
* enviroment's content. Each array entry is a NULL-terminated
|
||||
* string of the form var=value. The caller is responsible for
|
||||
* freeing them.
|
||||
*/
|
||||
inline std::pair<std::size_t, char**> environment_to_envp(const environment
|
||||
&env)
|
||||
{
|
||||
std::size_t nargs = env.size();
|
||||
char **envp = new char*[nargs + 1];
|
||||
environment::size_type i = 0;
|
||||
for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
|
||||
{
|
||||
std::string s = it->first + "=" + it->second;
|
||||
envp[i] = new char[s.size() + 1];
|
||||
std::strncpy(envp[i], s.c_str(), s.size() + 1);
|
||||
++i;
|
||||
}
|
||||
envp[i] = 0;
|
||||
return std::pair<std::size_t, char**>(nargs, envp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the command line to an array of C strings.
|
||||
*
|
||||
* Converts the command line's list of arguments to the format expected
|
||||
* by the \a argv parameter in the POSIX execve() system call.
|
||||
*
|
||||
* This operation is only available on POSIX systems.
|
||||
*
|
||||
* \return The first argument of the pair is an integer that indicates
|
||||
* how many strings are stored in the second argument. The
|
||||
* second argument is a NULL-terminated, dynamically allocated
|
||||
* array of dynamically allocated strings holding the arguments
|
||||
* to the executable. The caller is responsible for freeing them.
|
||||
*/
|
||||
template <class Arguments>
|
||||
inline std::pair<std::size_t, char**> collection_to_argv(const Arguments &args)
|
||||
{
|
||||
std::size_t nargs = args.size();
|
||||
char **argv = new char*[nargs + 1];
|
||||
typename Arguments::size_type i = 0;
|
||||
for (typename Arguments::const_iterator it = args.begin(); it != args.end();
|
||||
++it)
|
||||
{
|
||||
argv[i] = new char[it->size() + 1];
|
||||
std::strncpy(argv[i], it->c_str(), it->size() + 1);
|
||||
++i;
|
||||
}
|
||||
argv[nargs] = 0;
|
||||
return std::pair<std::size_t, char**>(nargs, argv);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
190
include/boost/process/detail/status_impl.hpp
Normal file
190
include/boost/process/detail/status_impl.hpp
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/detail/status_impl.hpp
|
||||
*
|
||||
* Includes the declaration of the status implementation class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
|
||||
#define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <sys/types.h>
|
||||
# include <signal.h>
|
||||
# include <sys/wait.h>
|
||||
# include <errno.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/process/pid_type.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/ptr_container/ptr_unordered_map.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
namespace detail {
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
typedef pid_t phandle;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
typedef HANDLE phandle;
|
||||
#endif
|
||||
|
||||
struct operation
|
||||
{
|
||||
virtual ~operation(){}
|
||||
virtual void operator()(int exit_code)
|
||||
{
|
||||
#if defined(BOOST_MSVC)
|
||||
exit_code;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
class wrapped_handler : public operation
|
||||
{
|
||||
public:
|
||||
wrapped_handler(Handler handler)
|
||||
: handler_(handler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(int exit_code)
|
||||
{
|
||||
handler_(boost::system::error_code(), exit_code);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The status_impl class saves internal data of every status I/O object.
|
||||
*/
|
||||
class status_impl
|
||||
{
|
||||
public:
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
template <typename Container>
|
||||
void clear(Container &handles)
|
||||
{
|
||||
for (operations_type::iterator it = ops_.begin(); it != ops_.end();
|
||||
++it)
|
||||
{
|
||||
for (typename Container::iterator it2 = handles.begin(); it2 !=
|
||||
handles.end(); ++it2)
|
||||
{
|
||||
if (*it2 == it->first)
|
||||
{
|
||||
handles.erase(it2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(it->first);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int wait(pid_type pid, boost::system::error_code &ec)
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
pid_t p;
|
||||
int status;
|
||||
do
|
||||
{
|
||||
p = waitpid(pid, &status, 0);
|
||||
} while (p == -1 && errno == EINTR);
|
||||
if (p == -1)
|
||||
{
|
||||
ec = boost::system::error_code(errno,
|
||||
boost::system::get_system_category());
|
||||
return -1;
|
||||
}
|
||||
return status;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
|
||||
pid);
|
||||
if (h == NULL)
|
||||
{
|
||||
ec = boost::system::error_code(GetLastError(),
|
||||
boost::system::get_system_category());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
CloseHandle(h);
|
||||
ec = boost::system::error_code(GetLastError(),
|
||||
boost::system::get_system_category());
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD exit_code;
|
||||
if (!GetExitCodeProcess(h, &exit_code))
|
||||
{
|
||||
CloseHandle(h);
|
||||
ec = boost::system::error_code(GetLastError(),
|
||||
boost::system::get_system_category());
|
||||
return -1;
|
||||
}
|
||||
if (!CloseHandle(h))
|
||||
{
|
||||
ec = boost::system::error_code(GetLastError(),
|
||||
boost::system::get_system_category());
|
||||
return -1;
|
||||
}
|
||||
return exit_code;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void async_wait(phandle ph, Handler handler)
|
||||
{
|
||||
ops_.insert(ph, new wrapped_handler<Handler>(handler));
|
||||
}
|
||||
|
||||
bool complete(phandle ph, int exit_code)
|
||||
{
|
||||
boost::iterator_range<operations_type::iterator> r =
|
||||
ops_.equal_range(ph);
|
||||
if (r.empty())
|
||||
return false;
|
||||
for (operations_type::iterator it = r.begin(); it != r.end(); ++it)
|
||||
(*it->second)(exit_code);
|
||||
ops_.erase(r.begin(), r.end());
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (!CloseHandle(ph))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef boost::ptr_unordered_multimap<phandle, operation> operations_type;
|
||||
operations_type ops_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
228
include/boost/process/detail/systembuf.hpp
Normal file
228
include/boost/process/detail/systembuf.hpp
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/detail/systembuf.hpp
|
||||
*
|
||||
* Includes the declaration of the systembuf class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
|
||||
#define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <streambuf>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
class postream;
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* std::streambuf implementation for handles.
|
||||
*
|
||||
* systembuf provides a std::streambuf implementation for handles.
|
||||
* Contrarywise to the handle class, this class does \b not take
|
||||
* ownership of the native handle; this should be taken care of
|
||||
* somewhere else.
|
||||
*
|
||||
* This class follows the expected semantics of a std::streambuf object.
|
||||
* However, it is not copyable to avoid introducing inconsistences with
|
||||
* the on-disk file and the in-memory buffers.
|
||||
*/
|
||||
class systembuf : public std::streambuf, public boost::noncopyable
|
||||
{
|
||||
friend class boost::process::postream;
|
||||
|
||||
public:
|
||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* Opaque name for the native handle type.
|
||||
*/
|
||||
typedef NativeHandleType handle_type;
|
||||
#elif defined(BOOST_POSIX_API)
|
||||
typedef int handle_type;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
typedef HANDLE handle_type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructs a new systembuf for the given handle.
|
||||
*
|
||||
* This constructor creates a new systembuf object that reads or
|
||||
* writes data from/to the \a h native handle. This handle
|
||||
* is \b not owned by the created systembuf object; the code
|
||||
* should take care of it externally.
|
||||
*
|
||||
* This class buffers input and output; the buffer size may be
|
||||
* tuned through the \a bufsize parameter, which defaults to 8192
|
||||
* bytes.
|
||||
*
|
||||
* \see pistream and postream
|
||||
*/
|
||||
explicit systembuf(handle_type h, std::size_t bufsize = 8192)
|
||||
: handle_(h),
|
||||
bufsize_(bufsize),
|
||||
read_buf_(new char[bufsize]),
|
||||
write_buf_(new char[bufsize])
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
BOOST_ASSERT(handle_ >= 0);
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE);
|
||||
#endif
|
||||
BOOST_ASSERT(bufsize_ > 0);
|
||||
setp(write_buf_.get(), write_buf_.get() + bufsize_);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Reads new data from the native handle.
|
||||
*
|
||||
* This operation is called by input methods when there is no more
|
||||
* data in the input buffer. The function fills the buffer with new
|
||||
* data, if available.
|
||||
*
|
||||
* \pre All input positions are exhausted (gptr() >= egptr()).
|
||||
* \post The input buffer has new data, if available.
|
||||
* \returns traits_type::eof() if a read error occurrs or there are
|
||||
* no more data to be read. Otherwise returns
|
||||
* traits_type::to_int_type(*gptr()).
|
||||
*/
|
||||
virtual int_type underflow()
|
||||
{
|
||||
BOOST_ASSERT(gptr() >= egptr());
|
||||
|
||||
bool ok;
|
||||
#if defined(BOOST_POSIX_API)
|
||||
ssize_t cnt = read(handle_, read_buf_.get(), bufsize_);
|
||||
ok = (cnt != -1 && cnt != 0);
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
DWORD cnt;
|
||||
BOOL res = ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL);
|
||||
ok = (res && cnt > 0);
|
||||
#endif
|
||||
|
||||
if (!ok)
|
||||
return traits_type::eof();
|
||||
else
|
||||
{
|
||||
setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt);
|
||||
return traits_type::to_int_type(*gptr());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes room in the write buffer for additional data.
|
||||
*
|
||||
* This operation is called by output methods when there is no more
|
||||
* space in the output buffer to hold a new element. The function
|
||||
* first flushes the buffer's contents to disk and then clears it to
|
||||
* leave room for more characters. The given \a c character is
|
||||
* stored at the beginning of the new space.
|
||||
*
|
||||
* \pre All output positions are exhausted (pptr() >= epptr()).
|
||||
* \post The output buffer has more space if no errors occurred
|
||||
* during the write to disk.
|
||||
* \post *(pptr() - 1) is \a c.
|
||||
* \returns traits_type::eof() if a write error occurrs. Otherwise
|
||||
* returns traits_type::not_eof(c).
|
||||
*/
|
||||
virtual int_type overflow(int c)
|
||||
{
|
||||
BOOST_ASSERT(pptr() >= epptr());
|
||||
|
||||
if (sync() == -1)
|
||||
return traits_type::eof();
|
||||
|
||||
if (!traits_type::eq_int_type(c, traits_type::eof()))
|
||||
{
|
||||
traits_type::assign(*pptr(), static_cast<traits_type::char_type>(
|
||||
c));
|
||||
pbump(1);
|
||||
}
|
||||
|
||||
return traits_type::not_eof(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the output buffer to disk.
|
||||
*
|
||||
* Synchronizes the systembuf buffers with the contents of the file
|
||||
* associated to this object through the native handle. The output buffer
|
||||
* is flushed to disk and cleared to leave new room for more data.
|
||||
*
|
||||
* \returns 0 on success, -1 if an error occurred.
|
||||
*/
|
||||
virtual int sync()
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
ssize_t cnt = pptr() - pbase();
|
||||
bool ok = (write(handle_, pbase(), cnt) == cnt);
|
||||
if (ok)
|
||||
pbump(-cnt);
|
||||
return ok ? 0 : -1;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
long cnt = pptr() - pbase();
|
||||
DWORD rcnt;
|
||||
BOOL res = WriteFile(handle_, pbase(), cnt, &rcnt, NULL);
|
||||
bool ok = (res && static_cast<long>(rcnt) == cnt);
|
||||
if (ok)
|
||||
pbump(-cnt);
|
||||
return ok ? 0 : -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Native handle used by the systembuf object.
|
||||
*/
|
||||
handle_type handle_;
|
||||
|
||||
/**
|
||||
* Internal buffer size used during read and write operations.
|
||||
*/
|
||||
std::size_t bufsize_;
|
||||
|
||||
/**
|
||||
* Internal buffer used during read operations.
|
||||
*/
|
||||
boost::scoped_array<char> read_buf_;
|
||||
|
||||
/**
|
||||
* Internal buffer used during write operations.
|
||||
*/
|
||||
boost::scoped_array<char> write_buf_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
138
include/boost/process/detail/windows_helpers.hpp
Normal file
138
include/boost/process/detail/windows_helpers.hpp
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/detail/windows_helpers.hpp
|
||||
*
|
||||
* Includes the declaration of helper functions for Windows systems.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_WINDOWS_HELPERS_HPP
|
||||
#define BOOST_PROCESS_WINDOWS_HELPERS_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
#include <boost/process/environment.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Converts an environment to a string used by CreateProcess().
|
||||
*
|
||||
* Converts the environment's contents to the format used by the
|
||||
* CreateProcess() system call. The returned char* string is
|
||||
* allocated in dynamic memory; the caller must free it when not
|
||||
* used any more. This is enforced by the use of a shared pointer.
|
||||
*
|
||||
* This operation is only available on Windows systems.
|
||||
*
|
||||
* \return A dynamically allocated char* string that represents
|
||||
* the environment's content. This string is of the form
|
||||
* var1=value1\\0var2=value2\\0\\0.
|
||||
*/
|
||||
inline boost::shared_array<char> environment_to_windows_strings(environment
|
||||
&env)
|
||||
{
|
||||
boost::shared_array<char> envp;
|
||||
|
||||
if (env.empty())
|
||||
{
|
||||
envp.reset(new char[2]);
|
||||
ZeroMemory(envp.get(), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string s;
|
||||
for (environment::const_iterator it = env.begin(); it != env.end();
|
||||
++it)
|
||||
{
|
||||
s += it->first + "=" + it->second;
|
||||
s.push_back(0);
|
||||
}
|
||||
envp.reset(new char[s.size() + 1]);
|
||||
#if (BOOST_MSVC >= 1400)
|
||||
memcpy_s(envp.get(), s.size() + 1, s.c_str(), s.size() + 1);
|
||||
#else
|
||||
memcpy(envp.get(), s.c_str(), s.size() + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return envp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the command line to a plain string.
|
||||
*
|
||||
* Converts the command line's list of arguments to the format expected by the
|
||||
* \a lpCommandLine parameter in the CreateProcess() system call.
|
||||
*
|
||||
* This operation is only available on Windows systems.
|
||||
*
|
||||
* \return A dynamically allocated string holding the command line
|
||||
* to be passed to the executable. It is returned in a
|
||||
* shared_array object to ensure its release at some point.
|
||||
*/
|
||||
template <class Arguments>
|
||||
inline boost::shared_array<char> collection_to_windows_cmdline(const Arguments
|
||||
&args)
|
||||
{
|
||||
typedef std::vector<std::string> arguments_t;
|
||||
arguments_t args2;
|
||||
typename Arguments::size_type i = 0;
|
||||
std::size_t size = 0;
|
||||
for (typename Arguments::const_iterator it = args.begin(); it != args.end();
|
||||
++it)
|
||||
{
|
||||
std::string arg = *it;
|
||||
|
||||
std::string::size_type pos = 0;
|
||||
while ( (pos = arg.find('"', pos)) != std::string::npos)
|
||||
{
|
||||
arg.replace(pos, 1, "\\\"");
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
if (arg.find(' ') != std::string::npos)
|
||||
arg = '\"' + arg + '\"';
|
||||
|
||||
if (i++ != args.size() - 1)
|
||||
arg += ' ';
|
||||
|
||||
args2.push_back(arg);
|
||||
size += arg.size() + 1;
|
||||
}
|
||||
|
||||
boost::shared_array<char> cmdline(new char[size]);
|
||||
cmdline.get()[0] = '\0';
|
||||
for (arguments_t::size_type i = 0; i < args.size(); ++i)
|
||||
#if (BOOST_MSVC >= 1400)
|
||||
strcat_s(cmdline.get(), size, args2[i].c_str());
|
||||
#else
|
||||
strncat(cmdline.get(), args2[i].c_str(), args2[i].size());
|
||||
#endif
|
||||
|
||||
return cmdline;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
52
include/boost/process/environment.hpp
Normal file
52
include/boost/process/environment.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/environment.hpp
|
||||
*
|
||||
* Includes the declaration of the environment class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_ENVIRONMENT_HPP
|
||||
#define BOOST_PROCESS_ENVIRONMENT_HPP
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Representation of a process' environment variables.
|
||||
*
|
||||
* The environment is a map that establishes an unidirectional
|
||||
* association between variable names and their values and is
|
||||
* represented by a string to string map.
|
||||
*
|
||||
* Variables may be defined to the empty string. Be aware that doing so
|
||||
* is not portable: POSIX systems will treat such variables as being
|
||||
* defined to the empty value, but Windows systems are not able to
|
||||
* distinguish them from undefined variables.
|
||||
*
|
||||
* Neither POSIX nor Windows systems support a variable with no name.
|
||||
*
|
||||
* It is worthy to note that the environment is sorted alphabetically.
|
||||
* This is provided for-free by the map container used to implement this
|
||||
* type, and this behavior is required by Windows systems.
|
||||
*/
|
||||
typedef std::map<std::string, std::string> environment;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
231
include/boost/process/handle.hpp
Normal file
231
include/boost/process/handle.hpp
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/handle.hpp
|
||||
*
|
||||
* Includes the declaration of the handle class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_HANDLE_HPP
|
||||
#define BOOST_PROCESS_HANDLE_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <unistd.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* RAII model for handles.
|
||||
*
|
||||
* The \a handle class is a RAII model for native handles. This class wraps
|
||||
* one of such handles grabbing its ownership, and automaticaly closes it
|
||||
* upon destruction. It is used to avoid leaking open handles, shall an
|
||||
* unexpected execution trace occur.
|
||||
*/
|
||||
class handle
|
||||
{
|
||||
public:
|
||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* Opaque name for the native handle type.
|
||||
*
|
||||
* On POSIX systems \a NativeSystemHandle is an integer type while it is
|
||||
* a \a HANDLE on Windows systems.
|
||||
*/
|
||||
typedef NativeSystemHandle native_type;
|
||||
#elif defined(BOOST_POSIX_API)
|
||||
typedef int native_type;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
typedef HANDLE native_type;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructs an invalid handle.
|
||||
*
|
||||
* \see valid()
|
||||
*/
|
||||
handle()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* RAII settings to specify if handle should be automatically closed.
|
||||
*/
|
||||
enum close_type { do_close, dont_close };
|
||||
|
||||
/**
|
||||
* Constructs a handle from a native handle.
|
||||
*
|
||||
* This constructor creates a new \a handle object that takes
|
||||
* ownership of the given \a native handle. If \a close is set to
|
||||
* handle::dont_close the \a native handle is not closed upon destruction.
|
||||
* The user must not close \a native if it is owned by a \a handle object.
|
||||
* Ownership can be reclaimed using release().
|
||||
*
|
||||
* \see release()
|
||||
*/
|
||||
handle(native_type native, close_type close = handle::do_close)
|
||||
: impl_(boost::make_shared<impl>(native, close))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the handle is valid or not.
|
||||
*
|
||||
* \return true if the handle is valid; false otherwise.
|
||||
*/
|
||||
bool valid() const
|
||||
{
|
||||
return impl_ && impl_->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the handle.
|
||||
*
|
||||
* \post The handle is invalid.
|
||||
* \post The native handle is closed.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
if (impl_)
|
||||
impl_->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the native handle.
|
||||
*
|
||||
* The caller can issue any operation on it except closing it.
|
||||
* If closing is required, release() shall be used.
|
||||
*
|
||||
* \return The native handle.
|
||||
*/
|
||||
native_type native() const
|
||||
{
|
||||
return impl_ ? impl_->native() : invalid_handle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reclaims ownership of the native handle.
|
||||
*
|
||||
* The caller is responsible of closing the native handle.
|
||||
*
|
||||
* \post The handle is invalid.
|
||||
* \return The native handle.
|
||||
*/
|
||||
native_type release()
|
||||
{
|
||||
return impl_ ? impl_->release() : invalid_handle();
|
||||
}
|
||||
|
||||
private:
|
||||
class impl
|
||||
{
|
||||
public:
|
||||
typedef handle::native_type native_type;
|
||||
|
||||
impl(native_type native, close_type close)
|
||||
: native_(native),
|
||||
close_(close)
|
||||
{
|
||||
}
|
||||
|
||||
~impl()
|
||||
{
|
||||
if (valid() && close_ == handle::do_close)
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
::close(native_);
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
CloseHandle(native_);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return native_ != handle::invalid_handle();
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (valid())
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
::close(native_);
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
CloseHandle(native_);
|
||||
#endif
|
||||
native_ = handle::invalid_handle();
|
||||
}
|
||||
}
|
||||
|
||||
native_type native() const
|
||||
{
|
||||
return native_;
|
||||
}
|
||||
|
||||
native_type release()
|
||||
{
|
||||
native_type native = native_;
|
||||
native_ = handle::invalid_handle();
|
||||
return native;
|
||||
}
|
||||
|
||||
private:
|
||||
native_type native_;
|
||||
close_type close_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of handle to store native handle value.
|
||||
*
|
||||
* A shared pointer is used as handles represent system resources. If a
|
||||
* handle is closed and becomes invalid the state of copies of the handle
|
||||
* object will be updated as they all share the handle implementation.
|
||||
*/
|
||||
boost::shared_ptr<impl> impl_;
|
||||
|
||||
/**
|
||||
* Constant function representing an invalid handle value.
|
||||
*
|
||||
* Returns the platform-specific handle value that represents an
|
||||
* invalid handle. This is a constant function rather than a regular
|
||||
* constant because, in the latter case, we cannot define it under
|
||||
* Windows due to the value being of a complex type.
|
||||
*/
|
||||
static const native_type invalid_handle()
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
return -1;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
433
include/boost/process/operations.hpp
Normal file
433
include/boost/process/operations.hpp
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/operations.hpp
|
||||
*
|
||||
* Provides miscellaneous free functions.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_OPERATIONS_HPP
|
||||
#define BOOST_PROCESS_OPERATIONS_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <boost/process/detail/posix_helpers.hpp>
|
||||
# include <utility>
|
||||
# include <cstddef>
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# if defined(__CYGWIN__)
|
||||
# include <boost/scoped_array.hpp>
|
||||
# include <sys/cygwin.h>
|
||||
# endif
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <boost/process/detail/windows_helpers.hpp>
|
||||
# include <boost/scoped_array.hpp>
|
||||
# include <boost/shared_array.hpp>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/process/child.hpp>
|
||||
#include <boost/process/context.hpp>
|
||||
#include <boost/process/stream_id.hpp>
|
||||
#include <boost/process/stream_ends.hpp>
|
||||
#include <boost/process/handle.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Locates the executable program \a file in all the directory components
|
||||
* specified in \a path. If \a path is empty, the value of the PATH
|
||||
* environment variable is used.
|
||||
*
|
||||
* The path variable is interpreted following the same conventions used
|
||||
* to parse the PATH environment variable in the underlying platform.
|
||||
*
|
||||
* \throw boost::filesystem::filesystem_error If the file cannot be found
|
||||
* in the path.
|
||||
*/
|
||||
inline std::string find_executable_in_path(const std::string &file,
|
||||
std::string path = "")
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
BOOST_ASSERT(file.find('/') == std::string::npos);
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
BOOST_ASSERT(file.find_first_of("\\/") == std::string::npos);
|
||||
#endif
|
||||
|
||||
std::string result;
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
if (path.empty())
|
||||
{
|
||||
const char *envpath = getenv("PATH");
|
||||
if (!envpath)
|
||||
boost::throw_exception(boost::filesystem::filesystem_error(
|
||||
BOOST_PROCESS_SOURCE_LOCATION "file not found", file,
|
||||
boost::system::errc::make_error_code(
|
||||
boost::system::errc::no_such_file_or_directory)));
|
||||
path = envpath;
|
||||
}
|
||||
BOOST_ASSERT(!path.empty());
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
if (!cygwin_posix_path_list_p(path.c_str()))
|
||||
{
|
||||
int size = cygwin_win32_to_posix_path_list_buf_size(path.c_str());
|
||||
boost::scoped_array<char> cygpath(new char[size]);
|
||||
cygwin_win32_to_posix_path_list(path.c_str(), cygpath.get());
|
||||
path = cygpath.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string::size_type pos1 = 0, pos2;
|
||||
do
|
||||
{
|
||||
pos2 = path.find(':', pos1);
|
||||
std::string dir = (pos2 != std::string::npos) ?
|
||||
path.substr(pos1, pos2 - pos1) : path.substr(pos1);
|
||||
std::string f = dir +
|
||||
(boost::algorithm::ends_with(dir, "/") ? "" : "/") + file;
|
||||
if (!access(f.c_str(), X_OK))
|
||||
result = f;
|
||||
pos1 = pos2 + 1;
|
||||
} while (pos2 != std::string::npos && result.empty());
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
const char *exts[] = { "", ".exe", ".com", ".bat", NULL };
|
||||
const char **ext = exts;
|
||||
while (*ext)
|
||||
{
|
||||
char buf[MAX_PATH];
|
||||
char *dummy;
|
||||
DWORD size = SearchPathA(path.empty() ? NULL : path.c_str(),
|
||||
file.c_str(), *ext, MAX_PATH, buf, &dummy);
|
||||
BOOST_ASSERT(size < MAX_PATH);
|
||||
if (size > 0)
|
||||
{
|
||||
result = buf;
|
||||
break;
|
||||
}
|
||||
++ext;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (result.empty())
|
||||
boost::throw_exception(boost::filesystem::filesystem_error(
|
||||
BOOST_PROCESS_SOURCE_LOCATION "file not found", file,
|
||||
boost::system::errc::make_error_code(
|
||||
boost::system::errc::no_such_file_or_directory)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the program name from a given executable.
|
||||
*
|
||||
* \return The program name. On Windows the program name
|
||||
* is returned without a file extension.
|
||||
*/
|
||||
inline std::string executable_to_progname(const std::string &exe)
|
||||
{
|
||||
std::string::size_type begin = 0;
|
||||
std::string::size_type end = std::string::npos;
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
std::string::size_type slash = exe.rfind('/');
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
std::string::size_type slash = exe.find_last_of("/\\");
|
||||
#endif
|
||||
if (slash != std::string::npos)
|
||||
begin = slash + 1;
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (exe.size() > 4 && (boost::algorithm::iends_with(exe, ".exe") ||
|
||||
boost::algorithm::iends_with(exe, ".com") ||
|
||||
boost::algorithm::iends_with(exe, ".bat")))
|
||||
end = exe.size() - 4;
|
||||
#endif
|
||||
|
||||
return exe.substr(begin, end - begin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new child process.
|
||||
*
|
||||
* Launches a new process based on the binary image specified by the
|
||||
* executable, the set of arguments passed to it and the execution context.
|
||||
*
|
||||
* \remark Blocking remarks: This function may block if the device holding the
|
||||
* executable blocks when loading the image. This might happen if, e.g.,
|
||||
* the binary is being loaded from a network share.
|
||||
*
|
||||
* \return A handle to the new child process.
|
||||
*/
|
||||
template <typename Arguments, typename Context>
|
||||
inline child create_child(const std::string &executable, Arguments args,
|
||||
Context ctx)
|
||||
{
|
||||
typedef std::map<stream_id, stream_ends> handles_t;
|
||||
handles_t handles;
|
||||
typename Context::streams_t::iterator it = ctx.streams.begin();
|
||||
for (; it != ctx.streams.end(); ++it)
|
||||
{
|
||||
if (it->first == stdin_id)
|
||||
handles[it->first] = it->second(input_stream);
|
||||
else if (it->first == stdout_id)
|
||||
handles[it->first] = it->second(output_stream);
|
||||
else if (it->first == stderr_id)
|
||||
handles[it->first] = it->second(output_stream);
|
||||
#if defined(BOOST_POSIX_API)
|
||||
else
|
||||
handles[it->first] = it->second(unknown_stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string p_name = ctx.process_name.empty() ?
|
||||
executable_to_progname(executable) : ctx.process_name;
|
||||
args.insert(args.begin(), p_name);
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
// Between fork() and execve() only async-signal-safe functions
|
||||
// must be called if multithreaded applications should be supported.
|
||||
// That's why the following code is executed before fork() is called.
|
||||
#if defined(F_MAXFD)
|
||||
int maxdescs = fcntl(-1, F_MAXFD, 0);
|
||||
if (maxdescs == -1)
|
||||
maxdescs = sysconf(_SC_OPEN_MAX);
|
||||
#else
|
||||
int maxdescs = sysconf(_SC_OPEN_MAX);
|
||||
#endif
|
||||
if (maxdescs == -1)
|
||||
maxdescs = 1024;
|
||||
std::vector<bool> closeflags(maxdescs, true);
|
||||
std::pair<std::size_t, char**> argv = detail::collection_to_argv(args);
|
||||
std::pair<std::size_t, char**> envp =
|
||||
detail::environment_to_envp(ctx.env);
|
||||
|
||||
const char *work_dir = ctx.work_dir.c_str();
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed");
|
||||
else if (pid == 0)
|
||||
{
|
||||
if (chdir(work_dir) == -1)
|
||||
{
|
||||
write(STDERR_FILENO, "chdir() failed\n", 15);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
for (handles_t::iterator it = handles.begin(); it != handles.end();
|
||||
++it)
|
||||
{
|
||||
if (it->second.child.valid())
|
||||
{
|
||||
handles_t::iterator it2 = it;
|
||||
++it2;
|
||||
for (; it2 != handles.end(); ++it2)
|
||||
{
|
||||
if (it2->second.child.native() == it->first)
|
||||
{
|
||||
int fd = fcntl(it2->second.child.native(), F_DUPFD,
|
||||
it->first + 1);
|
||||
if (fd == -1)
|
||||
{
|
||||
write(STDERR_FILENO, "fcntl() failed\n", 15);
|
||||
_exit(127);
|
||||
}
|
||||
it2->second.child = fd;
|
||||
}
|
||||
}
|
||||
|
||||
if (dup2(it->second.child.native(), it->first) == -1)
|
||||
{
|
||||
write(STDERR_FILENO, "dup2() failed\n", 14);
|
||||
_exit(127);
|
||||
}
|
||||
closeflags[it->first] = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.setup)
|
||||
ctx.setup();
|
||||
|
||||
for (std::size_t i = 0; i < closeflags.size(); ++i)
|
||||
{
|
||||
if (closeflags[i])
|
||||
close(i);
|
||||
}
|
||||
|
||||
execve(executable.c_str(), argv.second, envp.second);
|
||||
|
||||
// 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);
|
||||
_exit(127);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(pid > 0);
|
||||
|
||||
for (std::size_t i = 0; i < argv.first; ++i)
|
||||
delete[] argv.second[i];
|
||||
delete[] argv.second;
|
||||
|
||||
for (std::size_t i = 0; i < envp.first; ++i)
|
||||
delete[] envp.second[i];
|
||||
delete[] envp.second;
|
||||
|
||||
std::map<stream_id, handle> parent_ends;
|
||||
for (handles_t::iterator it = handles.begin(); it != handles.end();
|
||||
++it)
|
||||
parent_ends[it->first] = it->second.parent;
|
||||
|
||||
return child(pid, parent_ends);
|
||||
}
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
STARTUPINFOA startup_info;
|
||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
startup_info.dwFlags |= STARTF_USESTDHANDLES;
|
||||
startup_info.hStdInput = handles[stdin_id].child.native();
|
||||
startup_info.hStdOutput = handles[stdout_id].child.native();
|
||||
startup_info.hStdError = handles[stderr_id].child.native();
|
||||
|
||||
if (ctx.setup)
|
||||
ctx.setup(startup_info);
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
boost::shared_array<char> cmdline =
|
||||
detail::collection_to_windows_cmdline(args);
|
||||
|
||||
boost::scoped_array<char> exe(new char[executable.size() + 1]);
|
||||
#if (BOOST_MSVC >= 1400)
|
||||
strcpy_s(exe.get(), executable.size() + 1, executable.c_str());
|
||||
#else
|
||||
strcpy(exe.get(), executable.c_str());
|
||||
#endif
|
||||
|
||||
boost::scoped_array<char> workdir(new char[ctx.work_dir.size() + 1]);
|
||||
#if (BOOST_MSVC >= 1400)
|
||||
strcpy_s(workdir.get(), ctx.work_dir.size() + 1, ctx.work_dir.c_str());
|
||||
#else
|
||||
strcpy(workdir.get(), ctx.work_dir.c_str());
|
||||
#endif
|
||||
|
||||
boost::shared_array<char> envstrs =
|
||||
detail::environment_to_windows_strings(ctx.env);
|
||||
|
||||
if (CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0,
|
||||
envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed");
|
||||
|
||||
handle hprocess(pi.hProcess);
|
||||
|
||||
if (!CloseHandle(pi.hThread))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
||||
|
||||
std::map<stream_id, handle> parent_ends;
|
||||
parent_ends[stdin_id] = handles[stdin_id].parent;
|
||||
parent_ends[stdout_id] = handles[stdout_id].parent;
|
||||
parent_ends[stderr_id] = handles[stderr_id].parent;
|
||||
|
||||
return child(hprocess, parent_ends);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
inline child create_child(const std::string &executable)
|
||||
{
|
||||
return create_child(executable, std::vector<std::string>(), context());
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
template <typename Arguments>
|
||||
inline child create_child(const std::string &executable, Arguments args)
|
||||
{
|
||||
return create_child(executable, args, context());
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a shell-based command.
|
||||
*
|
||||
* Executes the given command through the default system shell. The
|
||||
* command is subject to pattern expansion, redirection and pipelining.
|
||||
* The shell is launched as described by the parameters in the context.
|
||||
*
|
||||
* This function behaves similarly to the system(3) system call. In a
|
||||
* POSIX system, the command is fed to /bin/sh whereas under a Windows
|
||||
* system, it is fed to cmd.exe. It is difficult to write portable
|
||||
* commands, but this function comes in handy in multiple situations.
|
||||
*
|
||||
* \remark Blocking remarks: This function may block if the device holding the
|
||||
* executable blocks when loading the image. This might happen if, e.g.,
|
||||
* the binary is being loaded from a network share.
|
||||
*
|
||||
* \return A handle to the new child process.
|
||||
*/
|
||||
template <typename Context>
|
||||
inline child shell(const std::string &command, Context ctx)
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
std::string executable = "/bin/sh";
|
||||
std::vector<std::string> args;
|
||||
args.push_back("-c");
|
||||
args.push_back(command);
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
char sysdir[MAX_PATH];
|
||||
UINT size = GetSystemDirectoryA(sysdir, sizeof(sysdir));
|
||||
if (!size)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetSystemDirectory() failed");
|
||||
std::string executable = std::string(sysdir) +
|
||||
(sysdir[size - 1] != '\\' ? "\\cmd.exe" : "cmd.exe");
|
||||
std::vector<std::string> args;
|
||||
args.push_back("/c");
|
||||
args.push_back(command);
|
||||
#endif
|
||||
return create_child(executable, args, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
inline child shell(const std::string &command)
|
||||
{
|
||||
return shell(command, context());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
56
include/boost/process/pid_type.hpp
Normal file
56
include/boost/process/pid_type.hpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/pid_type.hpp
|
||||
*
|
||||
* Includes the declaration of the pid type.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_PID_TYPE_HPP
|
||||
#define BOOST_PROCESS_PID_TYPE_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <sys/types.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* Opaque name for the process identifier type.
|
||||
*
|
||||
* Each operating system identifies processes using a specific type.
|
||||
* The \a pid_type type is used to transparently refer to a process
|
||||
* regardless of the operating system.
|
||||
*
|
||||
* This type is guaranteed to be an integral type on all supported
|
||||
* platforms. On POSIX systems it is defined as pid_t, on Windows systems as
|
||||
* DWORD.
|
||||
*/
|
||||
typedef NativeProcessId pid_type;
|
||||
#elif defined(BOOST_POSIX_API)
|
||||
typedef pid_t pid_type;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
typedef DWORD pid_type;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
49
include/boost/process/pipe.hpp
Normal file
49
include/boost/process/pipe.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/pipe.hpp
|
||||
*
|
||||
* Includes the declaration of the pipe class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_PIPE_HPP
|
||||
#define BOOST_PROCESS_PIPE_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* The pipe class is a type definition for stream-based classes defined by
|
||||
* Boost.Asio.
|
||||
*
|
||||
* The type definition is provided for convenience. You can also use Boost.Asio
|
||||
* classes directly for asynchronous I/O operations.
|
||||
*/
|
||||
typedef BoostAsioPipe pipe;
|
||||
#elif defined(BOOST_POSIX_API)
|
||||
typedef boost::asio::posix::stream_descriptor pipe;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
typedef boost::asio::windows::stream_handle pipe;
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
114
include/boost/process/pistream.hpp
Normal file
114
include/boost/process/pistream.hpp
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/pistream.hpp
|
||||
*
|
||||
* Includes the declaration of the pistream class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_PISTREAM_HPP
|
||||
#define BOOST_PROCESS_PISTREAM_HPP
|
||||
|
||||
#include <boost/process/handle.hpp>
|
||||
#include <boost/process/detail/systembuf.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <istream>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Child process' output stream.
|
||||
*
|
||||
* The pistream class represents an output communication channel with the
|
||||
* child process. The child process writes data to this stream and the
|
||||
* parent process can read it through the pistream object. In other
|
||||
* words, from the child's point of view, the communication channel is an
|
||||
* output one, but from the parent's point of view it is an input one;
|
||||
* hence the confusing pistream name.
|
||||
*
|
||||
* pistream objects cannot be copied because they buffer data
|
||||
* that flows through the communication channel.
|
||||
*
|
||||
* A pistream object behaves as a std::istream stream in all senses.
|
||||
* The class is only provided because it must provide a method to let
|
||||
* the caller explicitly close the communication channel.
|
||||
*
|
||||
* \remark Blocking remarks: Functions that read data from this
|
||||
* stream can block if the associated handle blocks during
|
||||
* the read. As this class is used to communicate with child
|
||||
* processes through anonymous pipes, the most typical blocking
|
||||
* condition happens when the child has no more data to send to
|
||||
* the pipe's system buffer. When this happens, the buffer
|
||||
* eventually empties and the system blocks until the writer
|
||||
* generates some data.
|
||||
*/
|
||||
class pistream : public std::istream, public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a new process' output stream.
|
||||
*/
|
||||
explicit pistream(boost::process::handle h)
|
||||
: std::istream(0),
|
||||
handle_(h),
|
||||
systembuf_(handle_.native())
|
||||
{
|
||||
rdbuf(&systembuf_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handle managed by this stream.
|
||||
*/
|
||||
const boost::process::handle &handle() const
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handle managed by this stream.
|
||||
*/
|
||||
boost::process::handle &handle()
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the handle managed by this stream.
|
||||
*
|
||||
* Explicitly closes the handle managed by this stream. This
|
||||
* function can be used by the user to tell the child process it's
|
||||
* not willing to receive more data.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
handle_.close();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The handle managed by this stream.
|
||||
*/
|
||||
boost::process::handle handle_;
|
||||
|
||||
/**
|
||||
* The systembuf object used to manage this stream's data.
|
||||
*/
|
||||
detail::systembuf systembuf_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
115
include/boost/process/postream.hpp
Normal file
115
include/boost/process/postream.hpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/postream.hpp
|
||||
*
|
||||
* Includes the declaration of the postream class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_POSTREAM_HPP
|
||||
#define BOOST_PROCESS_POSTREAM_HPP
|
||||
|
||||
#include <boost/process/handle.hpp>
|
||||
#include <boost/process/detail/systembuf.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Child process' input stream.
|
||||
*
|
||||
* The postream class represents an input communication channel with the
|
||||
* child process. The child process reads data from this stream and the
|
||||
* parent process can write to it through the postream object. In other
|
||||
* words, from the child's point of view, the communication channel is an
|
||||
* input one, but from the parent's point of view it is an output one;
|
||||
* hence the confusing postream name.
|
||||
*
|
||||
* postream objects cannot be copied because they buffer data that flows
|
||||
* through the communication channel.
|
||||
*
|
||||
* A postream object behaves as a std::ostream stream in all senses.
|
||||
* The class is only provided because it must provide a method to let
|
||||
* the caller explicitly close the communication channel.
|
||||
*
|
||||
* \remark Blocking remarks: Functions that write data to this
|
||||
* stream can block if the associated handle blocks during
|
||||
* the write. As this class is used to communicate with child
|
||||
* processes through anonymous pipes, the most typical blocking
|
||||
* condition happens when the child is not processing the data
|
||||
* in the pipe's system buffer. When this happens, the buffer
|
||||
* eventually fills up and the system blocks until the reader
|
||||
* consumes some data, leaving some new room.
|
||||
*/
|
||||
class postream : public std::ostream, public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a new process' input stream.
|
||||
*/
|
||||
explicit postream(boost::process::handle h)
|
||||
: std::ostream(0),
|
||||
handle_(h),
|
||||
systembuf_(handle_.native())
|
||||
{
|
||||
rdbuf(&systembuf_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handle managed by this stream.
|
||||
*/
|
||||
const boost::process::handle &handle() const
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handle managed by this stream.
|
||||
*/
|
||||
boost::process::handle &handle()
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the handle managed by this stream.
|
||||
*
|
||||
* Explicitly closes the handle managed by this stream. This
|
||||
* function can be used by the user to tell the child process there
|
||||
* is no more data to send.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
systembuf_.sync();
|
||||
handle_.close();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The handle managed by this stream.
|
||||
*/
|
||||
boost::process::handle handle_;
|
||||
|
||||
/**
|
||||
* The systembuf object used to manage this stream's data.
|
||||
*/
|
||||
detail::systembuf systembuf_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
212
include/boost/process/process.hpp
Normal file
212
include/boost/process/process.hpp
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/process.hpp
|
||||
*
|
||||
* Includes the declaration of the process class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_PROCESS_HPP
|
||||
#define BOOST_PROCESS_PROCESS_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <unistd.h>
|
||||
# include <sys/types.h>
|
||||
# include <signal.h>
|
||||
# include <sys/wait.h>
|
||||
# include <errno.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <boost/process/handle.hpp>
|
||||
# include <cstdlib>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/process/pid_type.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Process class to represent any running process.
|
||||
*/
|
||||
class process
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a new process object.
|
||||
*
|
||||
* Creates a new process object that represents a running process
|
||||
* within the system.
|
||||
*
|
||||
* On Windows the process is opened and a handle saved. This is required
|
||||
* to avoid the operating system removing process resources when the
|
||||
* process exits. The handle is closed when the process instance (and all
|
||||
* of its copies) is destroyed.
|
||||
*/
|
||||
process(pid_type id)
|
||||
: id_(id)
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
, handle_(open_process(id))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* Constructs a new process object.
|
||||
*
|
||||
* Creates a new process object that represents a running process
|
||||
* within the system.
|
||||
*
|
||||
* This operation is only available on Windows systems. The handle is
|
||||
* closed when the process instance (and all of its copies) is destroyed.
|
||||
*/
|
||||
process(handle h)
|
||||
: id_(GetProcessId(h.native())),
|
||||
handle_(h)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the process identifier.
|
||||
*/
|
||||
pid_type get_id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the process execution.
|
||||
*
|
||||
* Forces the termination of the process execution. Some platforms
|
||||
* allow processes to ignore some external termination notifications
|
||||
* or to capture them for a proper exit cleanup. You can set the
|
||||
* \a force flag to true to force their termination regardless
|
||||
* of any exit handler.
|
||||
*
|
||||
* After this call, accessing this object can be dangerous because the
|
||||
* process identifier may have been reused by a different process. It
|
||||
* might still be valid, though, if the process has refused to die.
|
||||
*
|
||||
* \throw boost::system::system_error If system calls used to terminate the
|
||||
* process fail.
|
||||
*/
|
||||
void terminate(bool force = false) const
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
if (kill(id_, force ? SIGKILL : SIGTERM) == -1)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed");
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
#if defined(BOOST_MSVC)
|
||||
force;
|
||||
#endif
|
||||
HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, id_);
|
||||
if (h == NULL)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
||||
if (!TerminateProcess(h, EXIT_FAILURE))
|
||||
{
|
||||
CloseHandle(h);
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed");
|
||||
}
|
||||
if (!CloseHandle(h))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks and waits for the process to terminate.
|
||||
*
|
||||
* Returns an exit code. The process object ceases to be valid after this
|
||||
* call.
|
||||
*
|
||||
* \remark Blocking remarks: This call blocks if the process has not
|
||||
* finalized execution and waits until it terminates.
|
||||
*
|
||||
* \throw boost::system::system_error If system calls used to wait for the
|
||||
* process fail.
|
||||
*/
|
||||
int wait() const
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
pid_t p;
|
||||
int status;
|
||||
do
|
||||
{
|
||||
p = waitpid(id_, &status, 0);
|
||||
} while (p == -1 && errno == EINTR);
|
||||
if (p == -1)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed");
|
||||
return status;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
|
||||
id_);
|
||||
if (h == NULL)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
||||
if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
CloseHandle(h);
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"WaitForSingleObject() failed");
|
||||
}
|
||||
DWORD exit_code;
|
||||
if (!GetExitCodeProcess(h, &exit_code))
|
||||
{
|
||||
CloseHandle(h);
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"GetExitCodeProcess() failed");
|
||||
}
|
||||
if (!CloseHandle(h))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
||||
return exit_code;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The process identifier.
|
||||
*/
|
||||
pid_type id_;
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
/**
|
||||
* Opens a process and returns a handle.
|
||||
*
|
||||
* OpenProcess() returns NULL and not INVALID_HANDLE_VALUE on failure.
|
||||
* That's why the return value is manually checked in this helper function
|
||||
* instead of simply passing it to the constructor of the handle class.
|
||||
*/
|
||||
HANDLE open_process(pid_type id)
|
||||
{
|
||||
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, id);
|
||||
if (h == NULL)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* The process handle.
|
||||
*/
|
||||
handle handle_;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
188
include/boost/process/self.hpp
Normal file
188
include/boost/process/self.hpp
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/self.hpp
|
||||
*
|
||||
* Includes the declaration of the self class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_SELF_HPP
|
||||
#define BOOST_PROCESS_SELF_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <boost/scoped_array.hpp>
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
# include <limits.h>
|
||||
# if defined(__APPLE__)
|
||||
# include <crt_externs.h>
|
||||
# endif
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
#include <boost/process/process.hpp>
|
||||
#include <boost/process/environment.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
extern "C"
|
||||
{
|
||||
extern char **environ;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* The self class provides access to the process itself.
|
||||
*/
|
||||
class self : public process, public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Returns the self instance representing the caller's process.
|
||||
*/
|
||||
static self &get_instance()
|
||||
{
|
||||
static self *instance = 0;
|
||||
if (!instance)
|
||||
instance = new self;
|
||||
return *instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current environment.
|
||||
*
|
||||
* Returns the current process environment variables. Modifying the
|
||||
* returned object has no effect on the current environment.
|
||||
*/
|
||||
static environment get_environment()
|
||||
{
|
||||
environment e;
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# if defined(__APPLE__)
|
||||
char **env = *_NSGetEnviron();
|
||||
# else
|
||||
char **env = environ;
|
||||
# endif
|
||||
|
||||
while (*env)
|
||||
{
|
||||
std::string s = *env;
|
||||
std::string::size_type pos = s.find('=');
|
||||
e.insert(environment::value_type(s.substr(0, pos),
|
||||
s.substr(pos + 1)));
|
||||
++env;
|
||||
}
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# ifdef GetEnvironmentStrings
|
||||
# undef GetEnvironmentStrings
|
||||
# endif
|
||||
|
||||
char *ms_environ = GetEnvironmentStrings();
|
||||
if (!ms_environ)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"GetEnvironmentStrings() failed");
|
||||
try
|
||||
{
|
||||
char *env = ms_environ;
|
||||
while (*env)
|
||||
{
|
||||
std::string s = env;
|
||||
std::string::size_type pos = s.find('=');
|
||||
e.insert(environment::value_type(s.substr(0, pos),
|
||||
s.substr(pos + 1)));
|
||||
env += s.size() + 1;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FreeEnvironmentStringsA(ms_environ);
|
||||
throw;
|
||||
}
|
||||
FreeEnvironmentStringsA(ms_environ);
|
||||
#endif
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current work directory.
|
||||
*/
|
||||
static std::string get_work_dir()
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
#if defined(PATH_MAX)
|
||||
char buffer[PATH_MAX];
|
||||
char *cwd = buffer;
|
||||
long size = PATH_MAX;
|
||||
#elif defined(_PC_PATH_MAX)
|
||||
errno = 0;
|
||||
long size = pathconf("/", _PC_PATH_MAX);
|
||||
if (size == -1 && errno)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pathconf(2) failed");
|
||||
else if (size == -1)
|
||||
size = BOOST_PROCESS_POSIX_PATH_MAX;
|
||||
BOOST_ASSERT(size > 0);
|
||||
boost::scoped_array<char> buffer(new char[size]);
|
||||
char *cwd = buffer.get();
|
||||
#else
|
||||
char buffer[BOOST_PROCESS_POSIX_PATH_MAX];
|
||||
char *cwd = buffer;
|
||||
long size = BOOST_PROCESS_POSIX_PATH_MAX;
|
||||
#endif
|
||||
if (!getcwd(cwd, size))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("getcwd(2) failed");
|
||||
BOOST_ASSERT(cwd[0] != '\0');
|
||||
return cwd;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
BOOST_ASSERT(MAX_PATH > 0);
|
||||
char cwd[MAX_PATH];
|
||||
if (!GetCurrentDirectoryA(sizeof(cwd), cwd))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"GetCurrentDirectory() failed");
|
||||
BOOST_ASSERT(cwd[0] != '\0');
|
||||
return cwd;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Constructs a new self object.
|
||||
*
|
||||
* Creates a new self object that represents the current process.
|
||||
*/
|
||||
self() :
|
||||
#if defined(BOOST_POSIX_API)
|
||||
process(getpid())
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
process(GetCurrentProcessId())
|
||||
#endif
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
41
include/boost/process/status.hpp
Normal file
41
include/boost/process/status.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/status.hpp
|
||||
*
|
||||
* Includes the declaration of the status class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_STATUS_HPP
|
||||
#define BOOST_PROCESS_STATUS_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
#include <boost/process/detail/basic_status.hpp>
|
||||
#include <boost/process/detail/basic_status_service.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* The status class to wait for processes to exit.
|
||||
*
|
||||
* The status class is a Boost.Asio I/O object and supports synchronous
|
||||
* and asynchronous wait operations.
|
||||
*/
|
||||
typedef detail::basic_status<detail::basic_status_service<> > status;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
326
include/boost/process/stream_behavior.hpp
Normal file
326
include/boost/process/stream_behavior.hpp
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/stream_behavior.hpp
|
||||
*
|
||||
* Includes the declaration of stream behavior classes.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_STREAM_BEHAVIOR_HPP
|
||||
#define BOOST_PROCESS_STREAM_BEHAVIOR_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
# include <rpc.h>
|
||||
#endif
|
||||
|
||||
#include <boost/process/stream_ends.hpp>
|
||||
#include <boost/process/stream_type.hpp>
|
||||
#include <boost/process/handle.hpp>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
namespace behavior {
|
||||
|
||||
/**
|
||||
* Stream behavior to close streams of a child process.
|
||||
*
|
||||
* A child process will not be able to use the stream.
|
||||
*/
|
||||
class close
|
||||
{
|
||||
public:
|
||||
stream_ends operator()(stream_type) const
|
||||
{
|
||||
return stream_ends();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stream behavior to make a child process inherit streams.
|
||||
*
|
||||
* A child process will use the very same stream of its parent process.
|
||||
*/
|
||||
class inherit
|
||||
{
|
||||
public:
|
||||
inherit(handle::native_type h)
|
||||
: h_(h, handle::dont_close)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!SetHandleInformation(h_.native(), HANDLE_FLAG_INHERIT,
|
||||
HANDLE_FLAG_INHERIT))
|
||||
{
|
||||
HANDLE proc = GetCurrentProcess();
|
||||
HANDLE dup;
|
||||
if (!DuplicateHandle(proc, h_.native(), proc, &dup, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"DuplicateHandle() failed");
|
||||
}
|
||||
h_ = dup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
stream_ends operator()(stream_type) const
|
||||
{
|
||||
return stream_ends(h_, handle());
|
||||
}
|
||||
|
||||
private:
|
||||
handle h_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stream behavior to redirect streams with a pipe.
|
||||
*
|
||||
* A child process will be able to communicate with its parent process.
|
||||
*/
|
||||
class pipe
|
||||
{
|
||||
public:
|
||||
#if defined(BOOST_POSIX_API)
|
||||
pipe()
|
||||
: stype_(unknown_stream)
|
||||
{
|
||||
}
|
||||
|
||||
pipe(stream_type stype)
|
||||
: stype_(stype)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
stream_ends operator()(stream_type stype) const
|
||||
{
|
||||
handle::native_type ends[2];
|
||||
#if defined(BOOST_POSIX_API)
|
||||
if (::pipe(ends) == -1)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed");
|
||||
if (stype_ != unknown_stream)
|
||||
stype = stype_;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
ZeroMemory(&sa, sizeof(sa));
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = FALSE;
|
||||
if (!CreatePipe(&ends[0], &ends[1], &sa, 0))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
|
||||
#endif
|
||||
handle child_end = ends[stype == input_stream ? 0 : 1];
|
||||
handle parent_end = ends[stype == input_stream ? 1 : 0];
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
|
||||
HANDLE_FLAG_INHERIT))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"SetHandleInformation() failed");
|
||||
#endif
|
||||
return stream_ends(child_end, parent_end);
|
||||
}
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
private:
|
||||
stream_type stype_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Stream behavior to redirect streams with a named pipe.
|
||||
*
|
||||
* A child process will be able to communicate with its parent process.
|
||||
*/
|
||||
class named_pipe
|
||||
{
|
||||
public:
|
||||
named_pipe(const std::string &name)
|
||||
: name_(name)
|
||||
#if defined(BOOST_POSIX_API)
|
||||
, stype_(unknown_stream)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
named_pipe(const std::string &name, stream_type stype)
|
||||
: name_(name),
|
||||
stype_(stype)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
stream_ends operator()(stream_type stype) const
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
if (mkfifo(name_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed");
|
||||
handle child_end = open(name_.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (!child_end.valid())
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
|
||||
int opts = fcntl(child_end.native(), F_GETFL);
|
||||
if (opts == -1)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
|
||||
opts ^= O_NONBLOCK;
|
||||
if (fcntl(child_end.native(), F_SETFL, opts) == -1)
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
|
||||
handle parent_end = open(name_.c_str(), O_WRONLY);
|
||||
if (!parent_end.valid())
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
|
||||
if (stype_ != unknown_stream)
|
||||
stype = stype_;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
ZeroMemory(&sa, sizeof(sa));
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
handle child_end = CreateNamedPipeA(name_.c_str(), PIPE_ACCESS_INBOUND |
|
||||
FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
|
||||
if (!child_end.valid())
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed");
|
||||
handle parent_end = CreateFileA(name_.c_str(), GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
if (!parent_end.valid())
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
|
||||
#endif
|
||||
if (stype == output_stream)
|
||||
std::swap(child_end, parent_end);
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
|
||||
HANDLE_FLAG_INHERIT))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"SetHandleInformation() failed");
|
||||
#endif
|
||||
return stream_ends(child_end, parent_end);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
stream_type stype_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Stream behavior to redirect streams with a pipe which supports asynchronous
|
||||
* I/O.
|
||||
*
|
||||
* As platforms require different types of pipes for asynchronous I/O this
|
||||
* stream behavior is provided for convenience. It uses the minimum required
|
||||
* pipe type on a platform in order to be able to use asynchronous I/O.
|
||||
*/
|
||||
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
|
||||
typedef pipe async_pipe;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
class async_pipe
|
||||
{
|
||||
public:
|
||||
stream_ends operator()(stream_type stype) const
|
||||
{
|
||||
UUID uuid;
|
||||
RPC_STATUS s = UuidCreateSequential(&uuid);
|
||||
if (s != RPC_S_OK && s != RPC_S_UUID_LOCAL_ONLY)
|
||||
BOOST_PROCESS_THROW_ERROR(s, "UuidCreateSequential() failed");
|
||||
unsigned char *c;
|
||||
s = UuidToStringA(&uuid, &c);
|
||||
if (s != RPC_S_OK)
|
||||
BOOST_PROCESS_THROW_ERROR(s, "UuidToString() failed");
|
||||
std::string name;
|
||||
try
|
||||
{
|
||||
name = reinterpret_cast<char*>(c);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
RpcStringFreeA(&c);
|
||||
throw;
|
||||
}
|
||||
RpcStringFreeA(&c);
|
||||
named_pipe p("\\\\.\\pipe\\boost_process_" + name);
|
||||
return p(stype);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Stream behavior to mute streams.
|
||||
*
|
||||
* A child process will be able to use streams. But data written to an
|
||||
* output stream is discarded and data read from an input stream is 0.
|
||||
*/
|
||||
class null
|
||||
{
|
||||
public:
|
||||
#if defined(BOOST_POSIX_API)
|
||||
null()
|
||||
: stype_(unknown_stream)
|
||||
{
|
||||
}
|
||||
|
||||
null(stream_type stype)
|
||||
: stype_(stype)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
stream_ends operator()(stream_type stype) const
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
if (stype_ != unknown_stream)
|
||||
stype = stype_;
|
||||
std::string filename = (stype == input_stream) ? "/dev/zero" :
|
||||
"/dev/null";
|
||||
int flag = (stype == input_stream) ? O_RDONLY : O_WRONLY;
|
||||
handle child_end = open(filename.c_str(), flag);
|
||||
if (!child_end.valid())
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
DWORD access = (stype == input_stream) ? GENERIC_READ : GENERIC_WRITE;
|
||||
handle child_end = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (!child_end.valid())
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
|
||||
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
|
||||
HANDLE_FLAG_INHERIT))
|
||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
||||
"SetHandleInformation() failed");
|
||||
#endif
|
||||
return stream_ends(child_end, handle());
|
||||
}
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
private:
|
||||
stream_type stype_;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
68
include/boost/process/stream_ends.hpp
Normal file
68
include/boost/process/stream_ends.hpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/stream_ends.hpp
|
||||
*
|
||||
* Includes the declaration of the stream_ends class.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_STREAM_ENDS_HPP
|
||||
#define BOOST_PROCESS_STREAM_ENDS_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
#include <boost/process/handle.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* A pair of handles to configure streams.
|
||||
*
|
||||
* Stream behaviors return a pair of handles to specify how a child's stream
|
||||
* should be configured and possibly the opposite end of a child's end. This
|
||||
* is the end remaining in the parent process and which can be used for example
|
||||
* to communicate with a child process through its standard streams.
|
||||
*/
|
||||
struct stream_ends {
|
||||
/**
|
||||
* The child's end.
|
||||
*/
|
||||
handle child;
|
||||
|
||||
/**
|
||||
* The parent's end.
|
||||
*/
|
||||
handle parent;
|
||||
|
||||
/**
|
||||
* Standard constructor creating two invalid handles.
|
||||
*/
|
||||
stream_ends()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper constructor to easily initialize handles.
|
||||
*/
|
||||
stream_ends(handle c, handle p)
|
||||
: child(c),
|
||||
parent(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
50
include/boost/process/stream_id.hpp
Normal file
50
include/boost/process/stream_id.hpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/stream_id.hpp
|
||||
*
|
||||
* Includes the declaration of the stream_id type.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_STREAM_ID_HPP
|
||||
#define BOOST_PROCESS_STREAM_ID_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Standard stream id to refer to standard streams in a cross-platform manner.
|
||||
*/
|
||||
enum std_stream_id { stdin_id, stdout_id, stderr_id };
|
||||
|
||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
||||
/**
|
||||
* Stream id type.
|
||||
*
|
||||
* Depending on the platform the stream id type is defined to refer to standard
|
||||
* streams only or to support more streams.
|
||||
*/
|
||||
typedef NativeStreamId stream_id;
|
||||
#elif defined(BOOST_POSIX_API)
|
||||
typedef int stream_id;
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
typedef std_stream_id stream_id;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
45
include/boost/process/stream_type.hpp
Normal file
45
include/boost/process/stream_type.hpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// Boost.Process
|
||||
// ~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
/**
|
||||
* \file boost/process/stream_type.hpp
|
||||
*
|
||||
* Includes the declaration of the stream_type enumeration.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_STREAM_TYPE_HPP
|
||||
#define BOOST_PROCESS_STREAM_TYPE_HPP
|
||||
|
||||
#include <boost/process/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace process {
|
||||
|
||||
/**
|
||||
* Stream type to differentiate between input and output streams.
|
||||
*
|
||||
* On POSIX systems another value unknown_stream is defined. It is passed
|
||||
* to stream behaviors for file descriptors greater than 2.
|
||||
*/
|
||||
enum stream_type {
|
||||
input_stream,
|
||||
output_stream
|
||||
#if defined(BOOST_POSIX_API)
|
||||
, unknown_stream
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
#ifndef _FC_BASE58_HPP_
|
||||
#define _FC_BASE58_HPP_
|
||||
#pragma once
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
fc::string to_base58( const char* d, uint32_t s );
|
||||
fc::string to_base58( const char* d, size_t s );
|
||||
fc::vector<char> from_base58( const fc::string& base58_str );
|
||||
size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len );
|
||||
}
|
||||
#endif // _FC_BASE58_HPP_
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _FC_DATASTREAM_HPP_
|
||||
#define _FC_DATASTREAM_HPP_
|
||||
#pragma once
|
||||
#include <fc/utility.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
#include <string.h>
|
||||
|
|
@ -16,26 +15,13 @@ namespace fc {
|
|||
*/
|
||||
template<typename T>
|
||||
struct datastream {
|
||||
datastream( T start, uint32_t s )
|
||||
datastream( T start, size_t s )
|
||||
:m_start(start),m_pos(start),m_end(start+s){};
|
||||
|
||||
template<typename DATA>
|
||||
inline datastream& operator<<(const DATA& d) {
|
||||
static_assert( !fc::is_class<DATA>::type::value, "no serialization defined" );
|
||||
write( (const char*)&d, sizeof(d) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename DATA>
|
||||
inline datastream& operator>>(DATA& d) {
|
||||
static_assert( !fc::is_class<DATA>::type::value, "no serialization defined" );
|
||||
read((char*)&d, sizeof(d) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void skip( uint32_t s ){ m_pos += s; }
|
||||
inline bool read( char* d, uint32_t s ) {
|
||||
if( m_end - m_pos >= (int32_t)s ) {
|
||||
inline void skip( size_t s ){ m_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;
|
||||
return true;
|
||||
|
|
@ -45,7 +31,7 @@ struct datastream {
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool write( const char* d, uint32_t s ) {
|
||||
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;
|
||||
|
|
@ -82,9 +68,9 @@ struct datastream {
|
|||
|
||||
T pos()const { return m_pos; }
|
||||
inline bool valid()const { return m_pos <= m_end && m_pos >= m_start; }
|
||||
inline bool seekp(uint32_t p) { m_pos = m_start + p; return m_pos <= m_end; }
|
||||
inline uint32_t tellp()const { return m_pos - m_start; }
|
||||
inline uint32_t remaining()const { return m_end - m_pos; }
|
||||
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; }
|
||||
private:
|
||||
T m_start;
|
||||
T m_pos;
|
||||
|
|
@ -94,24 +80,117 @@ struct datastream {
|
|||
template<>
|
||||
struct datastream<size_t> {
|
||||
datastream( size_t init_size = 0):m_size(init_size){};
|
||||
template<typename DATA>
|
||||
inline datastream& operator<<(const DATA& d) {
|
||||
static_assert( !fc::is_class<DATA>::type::value, "no serialzation defined" );
|
||||
m_size += sizeof(d);
|
||||
return *this;
|
||||
}
|
||||
inline bool skip( uint32_t s ) { m_size += s; return true; }
|
||||
inline bool write( const char* d, uint32_t s ) { m_size += s; return true; }
|
||||
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(uint32_t p) { m_size = p; return true; }
|
||||
inline uint32_t tellp()const { return m_size; }
|
||||
inline uint32_t remaining()const { return 0; }
|
||||
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:
|
||||
uint32_t m_size;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
/*
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const size_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return *this;
|
||||
}
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, size_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const int32_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, int32_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint32_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, uint32_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const int64_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, int64_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint64_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, uint64_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const int16_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, int16_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint16_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, uint16_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const int8_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, int8_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
template<typename ST>
|
||||
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint8_t& d) {
|
||||
ds.write( (const char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename ST, typename DATA>
|
||||
inline datastream<ST>& operator>>(datastream<ST>& ds, uint8_t& d) {
|
||||
ds.read((char*)&d, sizeof(d) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
|
||||
} // namespace fc
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _FC_FILESYSTEM_HPP_
|
||||
#define _FC_FILESYSTEM_HPP_
|
||||
#pragma once
|
||||
#include <fc/string.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
|
||||
|
|
@ -7,6 +6,7 @@ namespace boost {
|
|||
namespace filesystem {
|
||||
class path;
|
||||
class directory_iterator;
|
||||
class recursive_directory_iterator;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,12 +32,15 @@ namespace fc {
|
|||
operator boost::filesystem::path& ();
|
||||
operator const boost::filesystem::path& ()const;
|
||||
|
||||
void replace_extension( const fc::path& e );
|
||||
fc::path stem()const;
|
||||
fc::path extension()const;
|
||||
fc::path filename()const;
|
||||
fc::path parent_path()const;
|
||||
fc::string string()const;
|
||||
fc::string generic_string()const;
|
||||
bool is_relative()const;
|
||||
bool is_absolute()const;
|
||||
private:
|
||||
fwd<boost::filesystem::path,32> _p;
|
||||
};
|
||||
|
|
@ -57,19 +60,39 @@ namespace fc {
|
|||
private:
|
||||
fwd<boost::filesystem::directory_iterator,16> _p;
|
||||
};
|
||||
class recursive_directory_iterator {
|
||||
public:
|
||||
recursive_directory_iterator( const fc::path& p );
|
||||
recursive_directory_iterator();
|
||||
~recursive_directory_iterator();
|
||||
|
||||
fc::path operator*()const;
|
||||
recursive_directory_iterator& operator++(int);
|
||||
recursive_directory_iterator& operator++();
|
||||
|
||||
friend bool operator==( const recursive_directory_iterator&, const recursive_directory_iterator& );
|
||||
friend bool operator!=( const recursive_directory_iterator&, const recursive_directory_iterator& );
|
||||
private:
|
||||
fwd<boost::filesystem::recursive_directory_iterator,16> _p;
|
||||
};
|
||||
|
||||
bool exists( const path& p );
|
||||
bool is_directory( const path& p );
|
||||
bool is_regular_file( const path& p );
|
||||
void create_directories( const path& p );
|
||||
void remove_all( const path& p );
|
||||
path absolute( const path& p );
|
||||
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 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& );
|
||||
}
|
||||
|
||||
#endif // _FC_FILESYSTEM_HPP_
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ namespace fc {
|
|||
template<typename T,unsigned int S,typename A>
|
||||
fwd<T,S,A>::fwd() {
|
||||
check_size<sizeof(T),sizeof(_store)>();
|
||||
new (this) T();
|
||||
new (this) T;
|
||||
}
|
||||
template<typename T,unsigned int S,typename A>
|
||||
fwd<T,S,A>::fwd( const fwd<T,S,A>& f ){
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ namespace fc {
|
|||
};
|
||||
|
||||
struct request {
|
||||
fc::string get_header( const fc::string& key )const;
|
||||
fc::string method;
|
||||
fc::string domain;
|
||||
fc::string path;
|
||||
|
|
@ -39,6 +40,8 @@ namespace fc {
|
|||
fc::vector<char> body;
|
||||
};
|
||||
|
||||
fc::vector<header> parse_urlencoded_params( const fc::string& f );
|
||||
|
||||
/**
|
||||
* Connections have reference semantics, all copies refer to the same
|
||||
* underlying socket.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
#include <fc/utility.hpp>
|
||||
#include <fc/lexical_cast.hpp>
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
class string;
|
||||
|
||||
class istream {
|
||||
public:
|
||||
|
|
@ -44,6 +44,7 @@ namespace fc {
|
|||
};
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ namespace fc {
|
|||
struct impl : public impl_base {
|
||||
impl(T& i):st(i){}
|
||||
|
||||
virtual size_t readsome( char* buf, size_t len ) { return st.readsome(buf,len); }
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _FC_IP_HPP_
|
||||
#define _FC_IP_HPP_
|
||||
#pragma once
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
|
@ -36,7 +35,6 @@ namespace fc {
|
|||
friend bool operator==( const endpoint& a, const endpoint& b );
|
||||
|
||||
private:
|
||||
address _ip;
|
||||
/**
|
||||
* The compiler pads endpoint to a full 8 bytes, so while
|
||||
* a port number is limited in range to 16 bits, we specify
|
||||
|
|
@ -45,7 +43,10 @@ namespace fc {
|
|||
* where they are stored.
|
||||
*/
|
||||
uint32_t _port;
|
||||
address _ip;
|
||||
};
|
||||
}
|
||||
class value;
|
||||
void pack( fc::value& , const fc::ip::endpoint& );
|
||||
void unpack( const fc::value& , fc::ip::endpoint& );
|
||||
}
|
||||
#endif // _FC_ENDPOINT_HPP_
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ namespace fc {
|
|||
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 );
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _FC_LOG_HPP_
|
||||
#define _FC_LOG_HPP_
|
||||
#pragma once
|
||||
#include <fc/utility.hpp>
|
||||
|
||||
namespace boost { class mutex; }
|
||||
|
|
@ -30,4 +29,3 @@ namespace fc {
|
|||
#define elog(...) do { fc::log( CONSOLE_RED, __FILE__, __LINE__, __func__, __VA_ARGS__ ); }while(false)
|
||||
|
||||
|
||||
#endif // _FC_LOG_HPP_
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef FC_MUTEX_HPP_
|
||||
#define FC_MUTEX_HPP_
|
||||
#pragma once
|
||||
#include <fc/time.hpp>
|
||||
#include <fc/spin_yield_lock.hpp>
|
||||
|
||||
|
|
@ -107,4 +106,3 @@ namespace fc {
|
|||
|
||||
} // namespace fc
|
||||
|
||||
#endif // MACE_CMT_MUTEX_HPP_
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ namespace fc {
|
|||
|
||||
template<typename U>
|
||||
optional& operator=( U&& u ) {
|
||||
if( &u == &**this ) return *this;
|
||||
if( !_valid ) {
|
||||
new (&**this) T( fc::forward<U>(u) );
|
||||
_valid = true;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef FC_PKE_HPP_
|
||||
#define FC_PKE_HPP_
|
||||
#pragma once
|
||||
#include <fc/sha1.hpp>
|
||||
#include <fc/vector.hpp>
|
||||
#include <fc/reflect.hpp>
|
||||
|
||||
/**
|
||||
* Define common crypto methods and data types to abstract underlying implementation.
|
||||
|
|
@ -143,7 +143,13 @@ namespace fc {
|
|||
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
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
#pragma once
|
||||
#include <fc/shared_impl.hpp>
|
||||
#include <fc/future.hpp>
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
class istream;
|
||||
class ostream;
|
||||
class path;
|
||||
class string;
|
||||
template<typename> class vector;
|
||||
|
||||
fc::path find_executable_in_path( const fc::string name );
|
||||
|
||||
/**
|
||||
* @brief start and manage an external process
|
||||
*
|
||||
|
|
@ -23,6 +25,7 @@ namespace fc {
|
|||
open_stderr = 0x04,
|
||||
open_all = open_stdin|open_stdout|open_stderr,
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a new process executing the specified exe with the specified args.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _TORNET_RPC_RAW_HPP_
|
||||
#define _TORNET_RPC_RAW_HPP_
|
||||
#pragma once
|
||||
#include <fc/reflect.hpp>
|
||||
#include <fc/datastream.hpp>
|
||||
#include <fc/varint.hpp>
|
||||
|
|
@ -7,7 +6,6 @@
|
|||
#include <fc/vector.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
#include <fc/array.hpp>
|
||||
//#include <fc/value.hpp>
|
||||
|
||||
namespace fc {
|
||||
class value;
|
||||
|
|
@ -248,7 +246,7 @@ namespace fc {
|
|||
raw::pack(ps,v );
|
||||
fc::vector<char> vec(ps.tellp());
|
||||
if( vec.size() ) {
|
||||
datastream<char*> ds( vec.data(), vec.size() );
|
||||
datastream<char*> ds( vec.data(), size_t(vec.size()) );
|
||||
raw::pack(ds,v);
|
||||
}
|
||||
return vec;
|
||||
|
|
@ -258,7 +256,7 @@ namespace fc {
|
|||
inline T unpack( const fc::vector<char>& s ) {
|
||||
T tmp;
|
||||
if( s.size() ) {
|
||||
datastream<const char*> ds( s.data(), s.size() );
|
||||
datastream<const char*> ds( s.data(), size_t(s.size()) );
|
||||
raw::unpack(ds,tmp);
|
||||
}
|
||||
return tmp;
|
||||
|
|
@ -280,4 +278,3 @@ namespace fc {
|
|||
|
||||
} } // namespace fc::raw
|
||||
|
||||
#endif // BOOST_RPC_RAW_HPP
|
||||
|
|
|
|||
|
|
@ -78,9 +78,11 @@ struct reflector{
|
|||
#else
|
||||
#define TEMPLATE
|
||||
#endif
|
||||
//#include <boost/typeof/typeof.hpp>
|
||||
|
||||
#define FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \
|
||||
visitor.TEMPLATE operator()<decltype(((type*)0)->elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) );
|
||||
{ typedef decltype(((type*)nullptr)->elem) member_type; \
|
||||
visitor.TEMPLATE operator()<member_type,type,&type::elem>( BOOST_PP_STRINGIZE(elem) ); \
|
||||
}
|
||||
|
||||
|
||||
#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
|
||||
|
|
|
|||
11
include/fc/scoped_lock.hpp
Normal file
11
include/fc/scoped_lock.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace fc {
|
||||
template<typename T>
|
||||
class scoped_lock {
|
||||
public:
|
||||
scoped_lock( T& l ):_lock(l) { _lock.lock(); }
|
||||
~scoped_lock() { _lock.unlock(); }
|
||||
T& _lock;
|
||||
};
|
||||
}
|
||||
|
|
@ -14,8 +14,8 @@ shared_impl<T>::shared_impl( U&& u ):_impl(fc::forward<U>(u)){}
|
|||
|
||||
template<typename T>
|
||||
shared_impl<T>::shared_impl( const shared_impl<T>& u ):_impl(u._impl){}
|
||||
template<typename T>
|
||||
shared_impl<T>::shared_impl( shared_impl<T>& u ):_impl(u._impl){}
|
||||
//template<typename T>
|
||||
//shared_impl<T>::shared_impl( shared_impl<T>& u ):_impl(u._impl){}
|
||||
|
||||
template<typename T>
|
||||
shared_impl<T>::shared_impl( shared_impl<T>&& u ):_impl(fc::move(u._impl)){}
|
||||
|
|
@ -57,8 +57,6 @@ TYPE::TYPE( TYPE&& c )\
|
|||
:my(fc::move(c.my)){}\
|
||||
TYPE::TYPE( const TYPE& c )\
|
||||
:my(c.my){}\
|
||||
TYPE::TYPE( TYPE& c )\
|
||||
:my(c.my){}\
|
||||
TYPE::TYPE() \
|
||||
:my( new fc::shared_impl<TYPE>::impl( ) ){}\
|
||||
TYPE::~TYPE(){}\
|
||||
|
|
|
|||
|
|
@ -110,10 +110,10 @@ namespace fc {
|
|||
bool operator !()const;
|
||||
|
||||
template<typename U>
|
||||
shared_impl( U&& u );
|
||||
explicit shared_impl( U&& u );
|
||||
|
||||
shared_impl( const shared_impl& u );
|
||||
shared_impl( 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 );
|
||||
|
|
@ -132,7 +132,6 @@ namespace fc {
|
|||
TYPE( TYPE* ); \
|
||||
TYPE( TYPE&& ); \
|
||||
TYPE( const TYPE& ); \
|
||||
TYPE( TYPE& ); \
|
||||
template<typename A1> \
|
||||
TYPE( A1&& ); \
|
||||
template<typename A1,typename A2> \
|
||||
|
|
@ -155,7 +154,8 @@ namespace fc {
|
|||
#define FC_START_SHARED_IMPL( SCOPED_TYPE ) \
|
||||
namespace fc { \
|
||||
template<> \
|
||||
struct fc::shared_impl<SCOPED_TYPE>::impl : public fc::retainable { \
|
||||
class fc::shared_impl<SCOPED_TYPE>::impl : public fc::retainable { \
|
||||
public:\
|
||||
SCOPED_TYPE self() { return SCOPED_TYPE(this); } \
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <fc/utility.hpp>
|
||||
#include <fc/log.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
|
|
@ -28,39 +29,37 @@ namespace fc {
|
|||
template<typename Other>
|
||||
shared_ptr( const shared_ptr<Other>& o )
|
||||
:_ptr(o.get()) {
|
||||
if(_ptr) _ptr->retain();
|
||||
if(_ptr != nullptr ) _ptr->retain();
|
||||
}
|
||||
shared_ptr( const shared_ptr& o )
|
||||
:_ptr(o.get()) {
|
||||
if(_ptr != nullptr ) _ptr->retain();
|
||||
}
|
||||
|
||||
shared_ptr( T* t, bool inc = false )
|
||||
:_ptr(t) { if( inc ) t->retain(); }
|
||||
:_ptr(t) { if( inc && t != nullptr) t->retain(); }
|
||||
|
||||
shared_ptr():_ptr(nullptr){}
|
||||
|
||||
shared_ptr( const shared_ptr& p ) {
|
||||
_ptr = p._ptr;
|
||||
if( _ptr ) _ptr->retain();
|
||||
}
|
||||
shared_ptr( shared_ptr& p ) {
|
||||
_ptr = p._ptr;
|
||||
if( _ptr ) _ptr->retain();
|
||||
}
|
||||
shared_ptr( shared_ptr&& p ) {
|
||||
_ptr = p._ptr;
|
||||
p._ptr = nullptr;
|
||||
}
|
||||
~shared_ptr() { if( _ptr ) { _ptr->release(); } }
|
||||
|
||||
shared_ptr( shared_ptr&& p )
|
||||
:_ptr(p._ptr){ p._ptr = nullptr; }
|
||||
|
||||
shared_ptr& reset( T* v = 0, bool inc = false ) {
|
||||
~shared_ptr() { if( nullptr != _ptr ) { _ptr->release(); } }
|
||||
|
||||
shared_ptr& reset( T* v = nullptr, bool inc = false ) {
|
||||
if( v == _ptr ) return *this;
|
||||
if( _ptr ) _ptr->release();
|
||||
if( inc && nullptr != v ) v->retain();
|
||||
if( nullptr != _ptr ) _ptr->release();
|
||||
_ptr = v;
|
||||
if( _ptr && inc ) _ptr->retain();
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_ptr& operator=(const shared_ptr& p ) {
|
||||
shared_ptr tmp(p);
|
||||
fc_swap(tmp._ptr,_ptr);
|
||||
if( _ptr == p._ptr ) return *this;
|
||||
if( p._ptr != nullptr ) p._ptr->retain();
|
||||
if( _ptr != nullptr ) _ptr->release();
|
||||
_ptr = p._ptr;
|
||||
return *this;
|
||||
}
|
||||
shared_ptr& operator=(shared_ptr&& p ) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _FC_SPIN_YIELD_LOCK_HPP_
|
||||
#define _FC_SPIN_YIELD_LOCK_HPP_
|
||||
#pragma once
|
||||
|
||||
namespace boost {
|
||||
template<typename T> class atomic;
|
||||
|
|
@ -38,4 +37,3 @@ namespace fc {
|
|||
|
||||
} // namespace fc
|
||||
|
||||
#endif // _FC_SPIN_YIELD_LOCK_HPP_
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace fc {
|
|||
struct file_attrib {
|
||||
file_attrib();
|
||||
|
||||
size_t size;
|
||||
uint64_t size;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t permissions;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ namespace fc {
|
|||
|
||||
class istream;
|
||||
class ostream;
|
||||
class string;
|
||||
|
||||
namespace ssh {
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace std {
|
|||
}
|
||||
|
||||
namespace fc {
|
||||
// typedef std::string string;
|
||||
/**
|
||||
* Including <string> results in 4000 lines of code
|
||||
* that must be included to build your header. This
|
||||
|
|
@ -55,17 +56,19 @@ namespace fc {
|
|||
const_iterator begin()const;
|
||||
const_iterator end()const;
|
||||
|
||||
char& operator[](uint64_t idx);
|
||||
const char& operator[](uint64_t idx)const;
|
||||
char& operator[](size_t idx);
|
||||
const char& operator[](size_t idx)const;
|
||||
|
||||
string& operator =( const string& c );
|
||||
string& operator =( string&& c );
|
||||
|
||||
void reserve( uint64_t );
|
||||
uint64_t size()const;
|
||||
uint64_t find( char c, uint64_t pos = 0 )const;
|
||||
void reserve( size_t );
|
||||
size_t size()const;
|
||||
size_t find( char c, size_t pos = 0 )const;
|
||||
size_t rfind( char c, size_t pos = 0 )const;
|
||||
size_t rfind( const fc::string& c, size_t pos = 0 )const;
|
||||
|
||||
void resize( uint64_t s );
|
||||
void resize( size_t s );
|
||||
void clear();
|
||||
|
||||
const char* c_str()const;
|
||||
|
|
@ -82,11 +85,11 @@ namespace fc {
|
|||
friend string operator + ( const string&, const string& );
|
||||
friend string operator + ( const string&, char c );
|
||||
|
||||
fc::string substr( int32_t start, int32_t len = 0x7fffffff )const;
|
||||
fc::string substr( size_t start, size_t len = fc::string::npos )const;
|
||||
|
||||
private:
|
||||
fc::fwd<std::string,32> my;
|
||||
};
|
||||
|
||||
} // namespace FC
|
||||
} // namespace fc
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
#ifndef _FC_SUPER_FAST_HASH_HPP_
|
||||
#define _FC_SUPER_FAST_HASH_HPP_
|
||||
#pragma once
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
class string;
|
||||
uint32_t super_fast_hash (const char * data, int len);
|
||||
uint32_t super_fast_hash (const fc::string& str );
|
||||
}
|
||||
|
||||
|
||||
#endif // _FC_SUPER_FAST_HASH_HPP_
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
#define _FC_THREAD_HPP_
|
||||
#include <fc/task.hpp>
|
||||
#include <fc/vector.hpp>
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
class string;
|
||||
class time_point;
|
||||
class microseconds;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _FC_TIME_HPP_
|
||||
#define _FC_TIME_HPP_
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <fc/string.hpp>
|
||||
#include <fc/raw.hpp>
|
||||
|
||||
namespace fc {
|
||||
class microseconds {
|
||||
|
|
@ -41,5 +41,16 @@ namespace fc {
|
|||
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<typename Stream, typename T>
|
||||
void unpack( Stream& s, fc::time_point& v );
|
||||
template<typename Stream, typename T>
|
||||
void pack( Stream& s, const fc::time_point& v );
|
||||
}
|
||||
}
|
||||
#endif // _FC_TIME_HPP_
|
||||
|
|
|
|||
18
include/fc/time_io.hpp
Normal file
18
include/fc/time_io.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include <fc/time_point.hpp>
|
||||
#include <fc/raw.hpp>
|
||||
|
||||
namespace fc {
|
||||
namespace raw {
|
||||
template<typename Stream, typename T>
|
||||
void unpack( Stream& s, fc::time_point& v ) {
|
||||
int64_t micro;
|
||||
fc::raw::unpack(s, micro );
|
||||
v = fc::time_point( fc::microseconds(micro);
|
||||
}
|
||||
template<typename Stream, typename T>
|
||||
void pack( Stream& s, const fc::time_point& v ) {
|
||||
fc::raw::pack( s, v.time_since_epoch().count() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,9 +85,8 @@ namespace fc {
|
|||
struct tuple<BOOST_PP_ENUM_PARAMS(n,A)> { \
|
||||
enum size_enum { size = n }; \
|
||||
template<BOOST_PP_ENUM_PARAMS( n, typename AA)> \
|
||||
tuple( BOOST_PP_ENUM(n, RREF_PARAMS, unused ) )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS,unused){} \
|
||||
explicit tuple( BOOST_PP_ENUM(n, RREF_PARAMS, unused ) )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS,unused){} \
|
||||
tuple( const tuple& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
|
||||
tuple( tuple& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
|
||||
tuple( tuple&& t )BOOST_PP_IF(n,:,BOOST_PP_EMPTY())BOOST_PP_ENUM( n, ILIST_PARAMS_COPY,unused){} \
|
||||
tuple(){}\
|
||||
template<typename V>\
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <fc/string.hpp>
|
||||
namespace fc {
|
||||
class string;
|
||||
class value;
|
||||
template<typename T> class get_typename{};
|
||||
template<> struct get_typename<int32_t> { static const char* name() { return "int32_t"; } };
|
||||
template<> struct get_typename<int64_t> { static const char* name() { return "int64_t"; } };
|
||||
|
|
@ -16,4 +17,5 @@ namespace fc {
|
|||
template<> struct get_typename<char> { static const char* name() { return "char"; } };
|
||||
template<> struct get_typename<void> { static const char* name() { return "char"; } };
|
||||
template<> struct get_typename<string> { static const char* name() { return "string"; } };
|
||||
template<> struct get_typename<value> { static const char* name() { return "value"; } };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <fc/string.hpp>
|
||||
#include <fc/vector.hpp>
|
||||
#include <fc/aligned.hpp>
|
||||
#include <fc/typename.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
|
@ -23,15 +24,16 @@ namespace fc {
|
|||
*/
|
||||
class value {
|
||||
public:
|
||||
struct key_val;
|
||||
struct object {
|
||||
class key_val;
|
||||
class object {
|
||||
public:
|
||||
typedef fc::vector<key_val>::const_iterator const_iterator;
|
||||
//fc::string type;
|
||||
fc::vector<key_val> fields;
|
||||
};
|
||||
struct array {
|
||||
class array {
|
||||
public:
|
||||
array( size_t s = 0 ):fields(s){}
|
||||
//fc::string type;
|
||||
fc::vector<value> fields;
|
||||
};
|
||||
|
||||
|
|
@ -85,21 +87,31 @@ namespace fc {
|
|||
|
||||
value& operator=( value&& v );
|
||||
value& operator=( const value& v );
|
||||
value& operator=( value& v );
|
||||
|
||||
|
||||
/**
|
||||
* Include fc/value_cast.hpp for implementation
|
||||
*/
|
||||
template<typename T>
|
||||
explicit value( T&& v );
|
||||
explicit value( const T& v );
|
||||
|
||||
template<typename T>
|
||||
value& operator=( T&& v ) {
|
||||
value tmp(fc::forward<T>(v) );
|
||||
fc_swap(*this,tmp);
|
||||
return *this;
|
||||
value& operator=( const T& v );
|
||||
|
||||
template<typename T>
|
||||
T cast()const;
|
||||
/*
|
||||
{
|
||||
slog("operator= %p", this);
|
||||
value tmp(fc::forward<T>(v));
|
||||
slog( "swap...tmp %p this %p", &tmp, this );
|
||||
T tmp = fc::move(a);
|
||||
a = fc::move(b);
|
||||
b = fc::move(tmp);
|
||||
slog( "return" );
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
|
||||
/** used to iterate over object fields, use array index + size to iterate over array */
|
||||
object::const_iterator find( const char* key )const;
|
||||
|
|
@ -126,6 +138,7 @@ namespace fc {
|
|||
/** gets the stored type **/
|
||||
const char* type()const;
|
||||
bool is_null()const;
|
||||
bool is_string()const;
|
||||
|
||||
void visit( const_visitor&& v )const;
|
||||
|
||||
|
|
@ -145,30 +158,45 @@ namespace fc {
|
|||
template<typename T>
|
||||
friend T value_cast( const value& v );
|
||||
|
||||
aligned<24> holder;
|
||||
aligned<40> holder;
|
||||
};
|
||||
bool operator == ( const value& v, std::nullptr_t );
|
||||
bool operator != ( const value& v, std::nullptr_t );
|
||||
|
||||
struct value::key_val {
|
||||
class value::key_val {
|
||||
public:
|
||||
key_val(){};
|
||||
|
||||
key_val( fc::string k, value v = value())
|
||||
:key(fc::move(k)),val(fc::move(v)){}
|
||||
key_val( fc::string k )
|
||||
:key(fc::move(k)){}
|
||||
|
||||
// key_val( fc::string k, value v )
|
||||
// :key(fc::move(k)),val(fc::move(v)){
|
||||
// slog("key_val(key,val)");}
|
||||
|
||||
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(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 ) {
|
||||
key = fc::move(k.key);
|
||||
val = fc::move(k.val);
|
||||
slog( "swap key");
|
||||
fc_swap( key, k.key );
|
||||
slog( "swap val");
|
||||
fc_swap( val, k.val );
|
||||
return *this;
|
||||
}
|
||||
|
||||
key_val& operator=( const key_val& k ) {
|
||||
slog( "copy key");
|
||||
key = k.key;
|
||||
slog( "copy val");
|
||||
val = k.val;
|
||||
return *this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace fc {
|
|||
virtual void operator()( const float& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const double& v ){ m_out = fc::lexical_cast<fc::string>(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 fc::string& v ) { m_out = v; }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
|
|
@ -274,6 +274,7 @@ namespace fc {
|
|||
virtual value_holder* copy_helper( char* c )const;
|
||||
};
|
||||
|
||||
void new_value_holder_void( value* v );
|
||||
} // namespace detail
|
||||
|
||||
|
||||
|
|
@ -300,9 +301,19 @@ namespace fc {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
value::value( T&& v ) {
|
||||
new (holder) detail::value_holder();
|
||||
fc::pack( *this, fc::forward<T>(v) );
|
||||
value::value( const T& v ) {
|
||||
detail::new_value_holder_void(this);
|
||||
fc::pack( *this, v);
|
||||
}
|
||||
template<typename T>
|
||||
value& value::operator=( const T& v ) {
|
||||
this->~value();
|
||||
value tmp(v);
|
||||
*this = fc::move(tmp);
|
||||
return *this;
|
||||
}
|
||||
template<typename T>
|
||||
T value::cast()const {
|
||||
return value_cast<T>(*this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace fc {
|
|||
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 = 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); }
|
||||
|
|
@ -93,7 +93,8 @@ namespace fc {
|
|||
*/
|
||||
template<typename T>
|
||||
inline void pack_helper( const T& v, const char* name )const {
|
||||
fc::pack( obj[name], v );
|
||||
value* o = &obj[name];
|
||||
fc::pack( *o, v );
|
||||
}
|
||||
template<typename T>
|
||||
inline void pack_helper( const fc::optional<T>& v, const char* name )const {
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ namespace fc {
|
|||
namespace detail {
|
||||
template<typename T>
|
||||
struct data {
|
||||
uint64_t size;
|
||||
uint64_t capacity;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
T first;
|
||||
|
||||
static data* allocate( uint64_t cap ) {
|
||||
static data* allocate( size_t cap ) {
|
||||
data* d = nullptr;
|
||||
if( cap ){
|
||||
d = (data*)malloc(sizeof(data) + sizeof(T)*(static_cast<size_t>(cap)-1));
|
||||
|
|
@ -26,7 +26,7 @@ namespace fc {
|
|||
d->size = 0;
|
||||
return d;
|
||||
}
|
||||
static data* reallocate( data* d, uint64_t cap ) {
|
||||
static data* reallocate( data* d, size_t cap ) {
|
||||
if( cap ){
|
||||
d = (data*)realloc(d,sizeof(data) + sizeof(T)*(static_cast<size_t>(cap)-1));
|
||||
d->capacity = static_cast<size_t>(cap);
|
||||
|
|
@ -62,7 +62,7 @@ namespace fc {
|
|||
resize(e-b);
|
||||
if( size() ) memcpy( data(), b, static_cast<size_t>(size()) );
|
||||
}
|
||||
vector_impl(uint64_t s):_data(nullptr){
|
||||
vector_impl(size_t s):_data(nullptr){
|
||||
resize(s);
|
||||
}
|
||||
~vector_impl() {
|
||||
|
|
@ -70,8 +70,8 @@ namespace fc {
|
|||
}
|
||||
|
||||
|
||||
uint64_t size()const { return _data ? _data->size : 0; }
|
||||
uint64_t capacity()const { return _data ? _data->capacity : 0; }
|
||||
size_t size()const { return _data ? _data->size : 0; }
|
||||
size_t capacity()const { return _data ? _data->capacity : 0; }
|
||||
|
||||
T& back() { return (&_data->first)[-1+_data->size]; }
|
||||
const T& back()const { return (&_data->first)[-1+_data->size]; }
|
||||
|
|
@ -85,11 +85,11 @@ namespace fc {
|
|||
iterator end() { return _data ? (&back())+1: 0;}
|
||||
const_iterator end()const { return _data ? (&back())+1: 0;}
|
||||
|
||||
T& operator[]( uint64_t i ) { return (&_data->first)[i]; }
|
||||
const T& operator[]( uint64_t i )const { return (&_data->first)[i]; }
|
||||
T& operator[]( size_t i ) { return (&_data->first)[i]; }
|
||||
const T& operator[]( size_t i )const { return (&_data->first)[i]; }
|
||||
|
||||
T& at( uint64_t i ) { return (&_data->first)[i]; }
|
||||
const T& at( uint64_t i )const { return (&_data->first)[i]; }
|
||||
T& at( size_t i ) { return (&_data->first)[i]; }
|
||||
const T& at( size_t i )const { return (&_data->first)[i]; }
|
||||
|
||||
void pop_back() { erase( &back() ); }
|
||||
|
||||
|
|
@ -100,11 +100,11 @@ namespace fc {
|
|||
_data = nullptr;
|
||||
}
|
||||
|
||||
void reserve( uint64_t i ) {
|
||||
void reserve( size_t i ) {
|
||||
_data = detail::data<T>::reallocate( _data, i );
|
||||
}
|
||||
|
||||
void resize( uint64_t i ) {
|
||||
void resize( size_t i ) {
|
||||
if( capacity() < i ) {
|
||||
if( _data )
|
||||
_data = detail::data<T>::reallocate( _data, i );
|
||||
|
|
@ -122,7 +122,7 @@ namespace fc {
|
|||
|
||||
template<typename U>
|
||||
iterator insert( const_iterator loc, U&& t ) {
|
||||
uint64_t pos = loc - begin();
|
||||
size_t pos = loc - begin();
|
||||
resize( size()+1 );
|
||||
char* src = &at(pos);
|
||||
if( src != &back() )
|
||||
|
|
@ -134,11 +134,11 @@ namespace fc {
|
|||
iterator insert( iterator pos, const_iterator first, const_iterator last ) {
|
||||
if( first >= last ) return pos;
|
||||
|
||||
uint64_t loc = pos - begin();
|
||||
uint64_t right_size = size() - loc;
|
||||
size_t loc = pos - begin();
|
||||
size_t right_size = size() - loc;
|
||||
resize( size() + (last-first) );
|
||||
char* src = &at(loc);
|
||||
uint64_t s = last-first;
|
||||
size_t s = last-first;
|
||||
memmove( src + s, src, right_size );
|
||||
memcpy( src, first, s );
|
||||
_data->size += (last-first);
|
||||
|
|
@ -201,7 +201,7 @@ namespace fc {
|
|||
}
|
||||
}
|
||||
|
||||
vector_impl(uint64_t s):_data(nullptr){
|
||||
vector_impl(size_t s):_data(nullptr){
|
||||
resize(s);
|
||||
}
|
||||
~vector_impl() {
|
||||
|
|
@ -209,8 +209,8 @@ namespace fc {
|
|||
}
|
||||
|
||||
|
||||
uint64_t size()const { return _data ? _data->size : 0; }
|
||||
uint64_t capacity()const { return _data ? _data->capacity : 0; }
|
||||
size_t size()const { return _data ? _data->size : 0; }
|
||||
size_t capacity()const { return _data ? _data->capacity : 0; }
|
||||
|
||||
T& back() { return (&_data->first)[-1+_data->size]; }
|
||||
const T& back()const { return (&_data->first)[-1+_data->size]; }
|
||||
|
|
@ -223,11 +223,11 @@ namespace fc {
|
|||
const_iterator begin()const { return _data ? &front() : 0;}
|
||||
const_iterator end()const { return _data ? (&back())+1: 0;}
|
||||
|
||||
T& operator[]( uint64_t i ) { return (&_data->first)[i]; }
|
||||
const T& operator[]( uint64_t i )const { return (&_data->first)[i]; }
|
||||
T& operator[]( size_t i ) { return (&_data->first)[i]; }
|
||||
const T& operator[]( size_t i )const { return (&_data->first)[i]; }
|
||||
|
||||
T& at( uint64_t i ) { return (&_data->first)[i]; }
|
||||
const T& at( uint64_t i )const { return (&_data->first)[i]; }
|
||||
T& at( size_t i ) { return (&_data->first)[i]; }
|
||||
const T& at( size_t i )const { return (&_data->first)[i]; }
|
||||
|
||||
void pop_back() { erase( &back() ); }
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ namespace fc {
|
|||
this->_data = nullptr;
|
||||
}
|
||||
|
||||
void reserve( uint64_t i ) {
|
||||
void reserve( size_t i ) {
|
||||
if( nullptr != this->_data && i <= this->_data->capacity )
|
||||
return;
|
||||
|
||||
|
|
@ -264,7 +264,7 @@ namespace fc {
|
|||
if( _ndata ) free(_ndata);
|
||||
}
|
||||
|
||||
void resize( uint64_t i ) {
|
||||
void resize( size_t i ) {
|
||||
this->reserve(i);
|
||||
while( i < this->_data->size ) {
|
||||
this->back().~T();
|
||||
|
|
@ -285,7 +285,7 @@ namespace fc {
|
|||
|
||||
template<typename U>
|
||||
iterator insert( const_iterator loc, U&& t ) {
|
||||
uint64_t pos = loc - this->begin();
|
||||
size_t pos = loc - this->begin();
|
||||
this->reserve( this->size()+1 );
|
||||
loc = this->begin() + pos;
|
||||
if( this->size() != 0 ) {
|
||||
|
|
@ -351,7 +351,7 @@ namespace fc {
|
|||
class vector : public detail::vector_impl<T, typename fc::is_class<T>::type> {
|
||||
public:
|
||||
vector(){}
|
||||
vector( uint64_t s ):detail::vector_impl<T, typename fc::is_class<T>::type>(s){}
|
||||
vector( size_t s ):detail::vector_impl<T, typename fc::is_class<T>::type>(s){}
|
||||
vector( const vector& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(v){}
|
||||
vector( vector&& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(fc::move(v)){}
|
||||
|
||||
|
|
|
|||
|
|
@ -606,10 +606,17 @@ inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vch
|
|||
|
||||
namespace fc {
|
||||
|
||||
fc::string to_base58( const char* d, uint32_t s ) {
|
||||
fc::string to_base58( const char* d, size_t s ) {
|
||||
return EncodeBase58( (const unsigned char*)d, (const unsigned char*)d+s ).c_str();
|
||||
}
|
||||
|
||||
fc::vector<char> from_base58( const fc::string& base58_str ) {
|
||||
std::vector<unsigned char> 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) );
|
||||
}
|
||||
return fc::vector<char>((const char*)out.data(), ((const char*)out.data())+out.size() );
|
||||
}
|
||||
/**
|
||||
* @return the number of bytes decoded
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -83,12 +83,12 @@ fc::string error_frame::to_detail_string()const {
|
|||
}
|
||||
fc::string error_frame::to_string()const {
|
||||
fc::stringstream ss;
|
||||
int64_t prev = 0;
|
||||
size_t prev = 0;
|
||||
auto next = desc.find( '$' );
|
||||
while( prev != int64_t(fc::string::npos) && prev < int64_t(desc.size()) ) {
|
||||
while( prev != size_t(fc::string::npos) && prev < size_t(desc.size()) ) {
|
||||
// slog( "prev: %d next %d %s", prev, next, desc.substr(prev,next).c_str() );
|
||||
// print everything from the last pos until the first '$'
|
||||
ss << desc.substr( prev, next-prev );
|
||||
ss << desc.substr( prev, size_t(next-prev) );
|
||||
|
||||
// if we got to the end, return it.
|
||||
if( next == string::npos ) { return ss.str(); }
|
||||
|
|
@ -107,7 +107,11 @@ fc::string error_frame::to_string()const {
|
|||
if( meta ) {
|
||||
auto itr = meta->find( key.c_str() );
|
||||
if( itr != meta->end() ) {
|
||||
ss << fc::json::to_string( itr->val );
|
||||
if( itr->val.is_string() ) {
|
||||
ss<<itr->val.cast<fc::string>();
|
||||
} else {
|
||||
ss << fc::json::to_string( itr->val );
|
||||
}
|
||||
} else {
|
||||
ss << "???";
|
||||
}
|
||||
|
|
@ -128,14 +132,14 @@ fc::string error_frame::to_string()const {
|
|||
}
|
||||
fc::string error_report::to_string()const {
|
||||
fc::stringstream ss;
|
||||
for( int i = 0; i < stack.size(); ++i ) {
|
||||
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( int i = 0; i < stack.size(); ++i ) {
|
||||
for( uint32_t i = 0; i < stack.size(); ++i ) {
|
||||
ss << stack[i].to_detail_string() << "\n";
|
||||
}
|
||||
return ss.str();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
//#define BOOST_NO_SCOPED_ENUMS
|
||||
#include <fc/filesystem.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <fc/utility.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <fc/value_cast.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
|
||||
namespace fc {
|
||||
void pack( fc::value& v, const fc::path& s ) {
|
||||
v = s.generic_string();
|
||||
}
|
||||
void unpack( const fc::value& v, fc::path& s ) {
|
||||
s = path(fc::value_cast<fc::string>(v));
|
||||
}
|
||||
|
||||
path::path(){}
|
||||
path::~path(){};
|
||||
|
|
@ -59,6 +69,9 @@ namespace fc {
|
|||
fc::path path::filename()const {
|
||||
return _p->filename();
|
||||
}
|
||||
void path::replace_extension( const fc::path& e ) {
|
||||
_p->replace_extension(e);
|
||||
}
|
||||
fc::path path::extension()const {
|
||||
return _p->extension();
|
||||
}
|
||||
|
|
@ -68,6 +81,8 @@ namespace fc {
|
|||
fc::path path::parent_path()const {
|
||||
return _p->parent_path();
|
||||
}
|
||||
bool path::is_relative()const { return _p->is_relative(); }
|
||||
bool path::is_absolute()const { return _p->is_absolute(); }
|
||||
|
||||
directory_iterator::directory_iterator( const fc::path& p )
|
||||
:_p(p){}
|
||||
|
|
@ -86,12 +101,49 @@ namespace fc {
|
|||
return *r._p != *l._p;
|
||||
}
|
||||
|
||||
|
||||
recursive_directory_iterator::recursive_directory_iterator( const fc::path& p )
|
||||
:_p(p){}
|
||||
|
||||
recursive_directory_iterator::recursive_directory_iterator(){}
|
||||
recursive_directory_iterator::~recursive_directory_iterator(){}
|
||||
|
||||
fc::path recursive_directory_iterator::operator*()const { return boost::filesystem::path(*(*_p)); }
|
||||
recursive_directory_iterator& recursive_directory_iterator::operator++(int) { (*_p)++; return *this; }
|
||||
recursive_directory_iterator& recursive_directory_iterator::operator++() { (*_p)++; return *this; }
|
||||
|
||||
bool operator==( const recursive_directory_iterator& r, const recursive_directory_iterator& l) {
|
||||
return *r._p == *l._p;
|
||||
}
|
||||
bool operator!=( const recursive_directory_iterator& r, const recursive_directory_iterator& l) {
|
||||
return *r._p != *l._p;
|
||||
}
|
||||
|
||||
|
||||
bool exists( const path& p ) { return boost::filesystem::exists(p); }
|
||||
void create_directories( const path& p ) { boost::filesystem::create_directories(p); }
|
||||
void create_directories( const path& p ) {
|
||||
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() ) );
|
||||
}
|
||||
}
|
||||
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 copy( const path& f, const path& t ) { boost::filesystem::copy( f, t ); }
|
||||
void remove_all( const path& p ) { boost::filesystem::remove_all(p); }
|
||||
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() ) );
|
||||
} catch ( ... ) {
|
||||
FC_THROW_REPORT( "Copy from ${srcfile} to ${dstfile} failed",
|
||||
fc::value().set("srcfile",f).set("dstfile",t).set("inner", fc::except_str() ) );
|
||||
}
|
||||
}
|
||||
void create_hard_link( const path& f, const path& t ) { boost::filesystem::create_hard_link( f, t ); }
|
||||
bool remove( const path& f ) { return boost::filesystem::remove( f ); }
|
||||
fc::path canonical( const fc::path& p ) { return boost::filesystem::canonical(p); }
|
||||
fc::path absolute( const fc::path& p ) { return boost::filesystem::absolute(p); }
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace fc {
|
|||
my->ifs.open( file.string().c_str(), std::ios::binary );
|
||||
}
|
||||
size_t ifstream::readsome( char* buf, size_t len ) {
|
||||
return my->ifs.readsome( buf, len );
|
||||
return size_t(my->ifs.readsome( buf, len ));
|
||||
}
|
||||
ifstream& ifstream::read( char* buf, size_t len ) {
|
||||
my->ifs.read(buf,len);
|
||||
|
|
@ -61,6 +61,7 @@ namespace fc {
|
|||
case cur: my->ifs.seekg( p, std::ios_base::cur ); return *this;
|
||||
case end: my->ifs.seekg( p, std::ios_base::end ); return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void ifstream::close() { return my->ifs.close(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <fc/iostream.hpp>
|
||||
#include <fc/exception.hpp>
|
||||
#include <fc/ip.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
#include <fc/hex.hpp>
|
||||
|
||||
|
||||
FC_START_SHARED_IMPL(fc::http::connection)
|
||||
|
|
@ -154,4 +156,42 @@ http::request connection::read_request()const {
|
|||
return req;
|
||||
}
|
||||
|
||||
fc::string request::get_header( const fc::string& key )const {
|
||||
for( auto itr = headers.begin(); itr != headers.end(); ++itr ) {
|
||||
if( itr->key == key ) { return itr->val; }
|
||||
}
|
||||
return fc::string();
|
||||
}
|
||||
fc::vector<header> parse_urlencoded_params( const fc::string& f ) {
|
||||
int num_args = 0;
|
||||
for( size_t i = 0; i < f.size(); ++i ) {
|
||||
if( f[i] == '=' ) ++num_args;
|
||||
}
|
||||
fc::vector<header> h(num_args);
|
||||
int arg = 0;
|
||||
for( size_t i = 0; i < f.size(); ++i ) {
|
||||
while( f[i] != '=' && i < f.size() ) {
|
||||
if( f[i] == '%' ) {
|
||||
h[arg].key += char((fc::from_hex(f[i+1]) << 4) | fc::from_hex(f[i+2]));
|
||||
i += 3;
|
||||
} else {
|
||||
h[arg].key += f[i];
|
||||
++i;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
while( i < f.size() && f[i] != '&' ) {
|
||||
if( f[i] == '%' ) {
|
||||
h[arg].val += char((fc::from_hex(f[i+1]) << 4) | fc::from_hex(f[i+2]));
|
||||
i += 3;
|
||||
} else {
|
||||
h[arg].val += f[i] == '+' ? ' ' : f[i];
|
||||
++i;
|
||||
}
|
||||
}
|
||||
++arg;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
} } // fc::http
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <fc/log.hpp>
|
||||
#include <fc/mutex.hpp>
|
||||
#include <fc/scoped_lock.hpp>
|
||||
#include <string>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
namespace fc {
|
||||
ostream& operator<<( ostream& o, const char* v ) {
|
||||
|
|
@ -32,18 +35,27 @@ namespace fc {
|
|||
buf[write_pos&0xfffff] = c;
|
||||
++write_pos;
|
||||
|
||||
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
|
||||
fc::promise<void>::ptr tmp;
|
||||
{ // copy read_ready because it is accessed from multiple threads
|
||||
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
|
||||
tmp = read_ready;
|
||||
}
|
||||
if( tmp && !tmp->ready() ) {
|
||||
tmp->set_value();
|
||||
}
|
||||
std::cin.read(&c,1);
|
||||
}
|
||||
eof = true;
|
||||
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
|
||||
fc::promise<void>::ptr tmp;
|
||||
{ // copy read_ready because it is accessed from multiple threads
|
||||
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
|
||||
tmp = read_ready;
|
||||
}
|
||||
if( tmp && !tmp->ready() ) {
|
||||
tmp->set_value();
|
||||
}
|
||||
}
|
||||
boost::mutex read_ready_mutex;
|
||||
fc::promise<void>::ptr read_ready;
|
||||
fc::promise<void>::ptr write_ready;
|
||||
|
||||
|
|
@ -91,10 +103,10 @@ namespace fc {
|
|||
|
||||
size_t cin_t::readsome( char* buf, size_t len ) {
|
||||
cin_buffer& b = get_cin_buffer();
|
||||
size_t avail = b.write_pos - b.read_pos;
|
||||
avail = (fc::min)(len,avail);
|
||||
size_t u = 0;
|
||||
while( avail && len ) {
|
||||
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;
|
||||
|
|
@ -102,20 +114,36 @@ namespace fc {
|
|||
--len;
|
||||
++u;
|
||||
}
|
||||
return 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<void>::ptr rr( new fc::promise<void>() );
|
||||
b.read_ready = rr;
|
||||
// b.read_ready = rr;
|
||||
{ // copy read_ready because it is accessed from multiple threads
|
||||
fc::scoped_lock<boost::mutex> 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<boost::mutex> lock( b.read_ready_mutex );
|
||||
b.read_ready.reset();
|
||||
}
|
||||
}
|
||||
if( b.eof ) return *this;
|
||||
size_t r = readsome( buf, len );
|
||||
|
|
|
|||
11
src/ip.cpp
11
src/ip.cpp
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/ip.hpp>
|
||||
#include <fc/value_cast.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <string>
|
||||
|
|
@ -53,4 +54,12 @@ namespace fc { namespace ip {
|
|||
return string(_ip) + ':' + fc::string(boost::lexical_cast<std::string>(_port).c_str());
|
||||
}
|
||||
|
||||
} }
|
||||
}
|
||||
void pack( fc::value& v, const fc::ip::endpoint& s ) {
|
||||
v = fc::string(s);
|
||||
}
|
||||
void unpack( const fc::value& v, fc::ip::endpoint& s ) {
|
||||
s = fc::ip::endpoint::from_string(fc::value_cast<fc::string>(v));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
16
src/json.cpp
16
src/json.cpp
|
|
@ -6,6 +6,8 @@
|
|||
#include <fc/interprocess/file_mapping.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace fc { namespace json {
|
||||
|
|
@ -21,7 +23,7 @@ namespace fc { namespace json {
|
|||
string(){}
|
||||
|
||||
string& operator=( const fc::string& s ) {
|
||||
json_data = fc::vector<char>(s.begin(),s.end());
|
||||
json_data = std::vector<char>(s.begin(),s.end());
|
||||
return *this;
|
||||
}
|
||||
template<typename T>
|
||||
|
|
@ -38,7 +40,7 @@ namespace fc { namespace json {
|
|||
json_data = s.json_data;
|
||||
return *this;
|
||||
}
|
||||
fc::vector<char> json_data;
|
||||
std::vector<char> json_data;
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
@ -444,6 +446,7 @@ struct temp_set {
|
|||
* 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 == ',' ) {
|
||||
|
|
@ -571,7 +574,7 @@ char* read_key_val( std::map<fc::string,fc::json::string>& obj, bool sc, char* i
|
|||
temp_set ntemp(name_end,'\0');
|
||||
temp_set vtemp(val_end,'\0');
|
||||
//slog( "name: '%1%'", fc::string(name,name_end) );
|
||||
obj[name] = fc::vector<char>(val,val_end);
|
||||
obj[name] = std::vector<char>(val,val_end);
|
||||
// obj.fields.push_back( key_val( name, to_value( val, val_end, ec ) ) );
|
||||
return val_end;
|
||||
}
|
||||
|
|
@ -664,7 +667,6 @@ char* read_key_val( fc::value::object& obj, bool sc, char* in, char* end, error_
|
|||
}
|
||||
temp_set ntemp(name_end,'\0');
|
||||
temp_set vtemp(val_end,'\0');
|
||||
//slog( "name: '%1%'", fc::string(name,name_end) );
|
||||
obj.fields.push_back( fc::value::key_val( name, to_value( val, val_end, ec ) ) );
|
||||
return val_end;
|
||||
}
|
||||
|
|
@ -701,7 +703,7 @@ std::map<fc::string,fc::json::string> read_key_vals( char* in, char* end, error_
|
|||
*/
|
||||
fc::value to_value( fc::vector<char>&& v, error_collector& ec ) {
|
||||
if( v.size() == 0 ) return fc::value();
|
||||
return to_value( &v.front(), &v.front() + v.size(), ec );
|
||||
return to_value( v.data(), v.data() + v.size(), ec );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -945,7 +947,9 @@ fc::string pretty_print( fc::vector<char>&& v, uint8_t indent ) {
|
|||
}
|
||||
|
||||
value from_string( const fc::string& s ) {
|
||||
return from_string( s.c_str(), s.c_str() + s.size() );
|
||||
std::vector<char> 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<char>&& v ) {
|
||||
error_collector ec;
|
||||
|
|
|
|||
|
|
@ -80,8 +80,10 @@ namespace fc { namespace json {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <fc/sstream.hpp>
|
||||
#include <fc/thread.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace fc { namespace json {
|
||||
|
||||
class rpc_stream_connection::impl : public fc::retainable {
|
||||
|
|
@ -32,6 +34,8 @@ namespace fc { namespace json {
|
|||
fc::string line;
|
||||
fc::getline( in, line );
|
||||
while( !in.eof() ) {
|
||||
// std::cerr<<"\n**line size: "<<line.size()<<"\n\n";
|
||||
// slog( "line size: '%d'", line.size() );
|
||||
try {
|
||||
fc::value v= fc::json::from_string( line );
|
||||
self.handle_message(v);
|
||||
|
|
@ -52,10 +56,9 @@ namespace fc { namespace json {
|
|||
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(){ slog( "%p...",this); }
|
||||
rpc_stream_connection::rpc_stream_connection(const rpc_stream_connection& c):my(c.my){ slog( "%p",this); }
|
||||
rpc_stream_connection::~rpc_stream_connection(){
|
||||
// slog( "%p", my.get() );
|
||||
}
|
||||
|
||||
// the life of the streams must exceed the life of all copies
|
||||
|
|
|
|||
15
src/log.cpp
15
src/log.cpp
|
|
@ -15,7 +15,6 @@ 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;
|
||||
|
|
@ -27,7 +26,9 @@ namespace fc {
|
|||
}
|
||||
return file_name;
|
||||
}
|
||||
*/
|
||||
boost::mutex& log_mutex() {
|
||||
static boost::mutex* m = new boost::mutex(); return *m;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#define isatty _isatty
|
||||
|
|
@ -36,14 +37,13 @@ namespace fc {
|
|||
|
||||
void log( const char* color, const char* file_name, size_t line_num,
|
||||
const char* method_name, const char* format, ... ) {
|
||||
fc::unique_lock<boost::mutex> lock(log_mutex());
|
||||
#ifndef WIN32
|
||||
if(isatty(fileno(stderr)))
|
||||
std::cerr<<"\r"<<color;
|
||||
fprintf( stderr, "\r%s",color);
|
||||
#endif
|
||||
|
||||
fprintf( stderr, "%-15s %-15s %-5zd %-15s ", thread_name(), fc::path(file_name).filename().generic_string().c_str(), line_num, method_name );
|
||||
//std::cerr<<thread_ptr()<< thread_name()<< short_name(file_name)<< line_num<< method_name ;
|
||||
fc::unique_lock<boost::mutex> 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 );
|
||||
|
|
@ -54,6 +54,7 @@ namespace fc {
|
|||
#endif
|
||||
fprintf( stderr, "\n" );
|
||||
fflush( stderr );
|
||||
return;
|
||||
}
|
||||
|
||||
/** used to add extra fields to be printed (thread,fiber,time,etc) */
|
||||
|
|
|
|||
46
src/pke.cpp
46
src/pke.cpp
|
|
@ -1,6 +1,10 @@
|
|||
#include <fc/pke.hpp>
|
||||
#include <fc/error.hpp>
|
||||
#include <fc/exception.hpp>
|
||||
#include <fc/raw.hpp>
|
||||
#include <fc/value.hpp>
|
||||
#include <fc/value_cast.hpp>
|
||||
#include <fc/base58.hpp>
|
||||
#include <iostream>
|
||||
#include <fc/sha1.hpp>
|
||||
#include <openssl/rsa.h>
|
||||
|
|
@ -10,6 +14,44 @@
|
|||
#include <openssl/err.h>
|
||||
|
||||
namespace fc {
|
||||
void pack( fc::value& v, const fc::public_key_t& s ) {
|
||||
fc::vector<char> 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<fc::string>(v));
|
||||
s = fc::raw::unpack<public_key_t>(ve);
|
||||
} catch ( ... ) {
|
||||
wlog( "error unpacking signature" );
|
||||
}
|
||||
}
|
||||
|
||||
void pack( fc::value& v, const fc::private_key_t& s ) {
|
||||
fc::vector<char> 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<fc::string>(v));
|
||||
s = fc::raw::unpack<private_key_t>(ve);
|
||||
} catch ( ... ) {
|
||||
wlog( "error unpacking private_key" );
|
||||
}
|
||||
}
|
||||
void pack( fc::value& v, const fc::signature_t& s ) {
|
||||
fc::vector<char> 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<fc::string>(v));
|
||||
s = fc::raw::unpack<signature_t>(ve);
|
||||
} catch ( ... ) {
|
||||
wlog( "error unpacking signature" );
|
||||
}
|
||||
}
|
||||
|
||||
RSA* get_pub( const char* key, uint32_t key_size, uint32_t pe )
|
||||
{
|
||||
RSA* rsa = RSA_new();
|
||||
|
|
@ -29,9 +71,9 @@ namespace fc {
|
|||
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);
|
||||
bool v = RSA_verify( NID_sha1, (const uint8_t*)digest.data(), 20, (uint8_t*)sig, key_size, pub );
|
||||
auto v = RSA_verify( NID_sha1, (const uint8_t*)digest.data(), 20, (uint8_t*)sig, key_size, pub );
|
||||
RSA_free(pub);
|
||||
return v;
|
||||
return 0 != v;
|
||||
}
|
||||
bool sign_data( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const sha1& digest, char* sig )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,14 +4,29 @@
|
|||
#include <fc/asio.hpp>
|
||||
#include <fc/filesystem.hpp>
|
||||
#include <fc/vector.hpp>
|
||||
#include <boost/process.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
#include <fc/value.hpp>
|
||||
#include <boost/process/all.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
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 {};
|
||||
|
|
@ -43,12 +58,13 @@ namespace fc {
|
|||
try {
|
||||
return static_cast<std::streamsize>(fc::asio::read_some( *m_pi, boost::asio::buffer( s, static_cast<size_t>(n) ) ));
|
||||
} catch ( const boost::system::system_error& e ) {
|
||||
wlog( "%s", fc::except_str().c_str() );
|
||||
// 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() );
|
||||
//wlog( "%s", fc::except_str().c_str() );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -74,8 +90,7 @@ FC_START_SHARED_IMPL( fc::process )
|
|||
inp->close();
|
||||
}
|
||||
if( _exited.valid() && !_exited.ready()) {
|
||||
slog( "terminate...");
|
||||
child->terminate();
|
||||
//child->terminate();
|
||||
_exited.wait();
|
||||
}
|
||||
}catch(...) {
|
||||
|
|
@ -132,7 +147,7 @@ fc::future<int> process::exec( const fc::path& exe, fc::vector<fc::string>&& arg
|
|||
my->pctx.streams[boost::process::stdin_id] = bp::behavior::close();
|
||||
|
||||
std::vector<std::string> a;
|
||||
a.reserve(args.size());
|
||||
a.reserve(size_t(args.size()));
|
||||
for( uint32_t i = 0; i < args.size(); ++i ) {
|
||||
a.push_back( args[i] );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,12 @@
|
|||
|
||||
namespace fc {
|
||||
retainable::retainable()
|
||||
:_ref_count(1) { }
|
||||
:_ref_count(1) {
|
||||
static_assert( sizeof(_ref_count) == sizeof(boost::atomic<int32_t>), "failed to reserve enough space" );
|
||||
}
|
||||
|
||||
retainable::~retainable() {
|
||||
assert( _ref_count <= 0 );
|
||||
assert( _ref_count == 0 );
|
||||
}
|
||||
void retainable::retain() {
|
||||
|
|
@ -15,8 +18,8 @@ namespace fc {
|
|||
}
|
||||
|
||||
void retainable::release() {
|
||||
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
|
||||
boost::atomic_thread_fence(boost::memory_order_acquire);
|
||||
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -478,7 +478,7 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
}
|
||||
try {
|
||||
uint64_t wrote = 0;
|
||||
size_t wrote = 0;
|
||||
char* pos = reinterpret_cast<char*>(mr.get_address());
|
||||
while( progress( wrote, fsize ) && wrote < fsize ) {
|
||||
int r = libssh2_channel_write( chan, pos, fsize - wrote );
|
||||
|
|
@ -800,7 +800,7 @@ namespace fc { namespace ssh {
|
|||
}
|
||||
|
||||
bool detail::process_istream::eof()const {
|
||||
return libssh2_channel_eof( proc.chan );
|
||||
return 0 != libssh2_channel_eof( proc.chan );
|
||||
}
|
||||
|
||||
ostream& detail::process_ostream::write( const char* buf, size_t len ) {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace fc {
|
|||
return *this;
|
||||
}
|
||||
size_t stringstream::readsome( char* buf, size_t len ) {
|
||||
return my->ss.readsome(buf,len);
|
||||
return static_cast<size_t>(my->ss.readsome(buf,len));
|
||||
}
|
||||
istream& stringstream::read( char* buf, size_t len ) {
|
||||
my->ss.read(buf,len);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ namespace fc {
|
|||
|
||||
string::string(const char* s, int l) :my(s,l){ }
|
||||
string::string(){}
|
||||
string::string( const string& c ):my(c.my) { }
|
||||
string::string( string&& m ):my(fc::move(m.my)) {}
|
||||
string::string( const fc::string& c ):my(*c.my) { }
|
||||
string::string( string&& m ):my(fc::move(*m.my)) {}
|
||||
string::string( const char* c ):my(c){}
|
||||
string::string( const_iterator b, const_iterator e ):my(b,e){}
|
||||
string::string( const std::string& s ):my(s) {}
|
||||
|
|
@ -27,16 +27,18 @@ namespace fc {
|
|||
string::const_iterator string::begin()const { return my->c_str(); }
|
||||
string::const_iterator string::end()const { return my->c_str() + my->size(); }
|
||||
|
||||
char& string::operator[](uint64_t idx) { return (*my)[idx]; }
|
||||
const char& string::operator[](uint64_t idx)const { return (*my)[idx]; }
|
||||
char& string::operator[](size_t idx) { return (*my)[idx]; }
|
||||
const char& string::operator[](size_t idx)const { return (*my)[idx]; }
|
||||
|
||||
void string::reserve(uint64_t r) { my->reserve(r); }
|
||||
uint64_t string::size()const { return my->size(); }
|
||||
uint64_t string::find(char c, uint64_t p)const { return my->find(c,p); }
|
||||
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::rfind(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); }
|
||||
void string::clear() { my->clear(); }
|
||||
void string::resize( uint64_t s ) { my->resize(s); }
|
||||
void string::resize( size_t s ) { my->resize(s); }
|
||||
|
||||
fc::string string::substr( int32_t start, int32_t len )const { return my->substr(start,len); }
|
||||
fc::string string::substr( size_t start, size_t len )const { return my->substr(start,len); }
|
||||
const char* string::c_str()const { return my->c_str(); }
|
||||
|
||||
bool string::operator == ( const char* s )const { return *my == s; }
|
||||
|
|
|
|||
|
|
@ -9,9 +9,6 @@ namespace fc {
|
|||
void* thread_ptr() {
|
||||
return &thread::current();
|
||||
}
|
||||
boost::mutex& log_mutex() {
|
||||
static boost::mutex m; return m;
|
||||
}
|
||||
|
||||
thread*& current_thread() {
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include <fc/url.hpp>
|
||||
#include <fc/Value.hpp>
|
||||
#include <fc/value.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
#include <fc/lexical_cast.hpp>
|
||||
#include <fc/value_cast.hpp>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <fc/exception.hpp>
|
||||
#include <fc/typename.hpp>
|
||||
#include <string.h>
|
||||
#include <fc/error_report.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
|
|
@ -32,6 +33,9 @@ namespace fc {
|
|||
template<typename T>
|
||||
struct value_holder_impl : value_holder {
|
||||
static_assert( !fc::is_class<T>::value, "only fundamental types can be stored without specialization" );
|
||||
value_holder_impl(){
|
||||
static_assert( sizeof(value_holder_impl) <= 40, "Validate size" );
|
||||
}
|
||||
virtual const char* type()const { return fc::get_typename<T>::name(); }
|
||||
virtual void visit( value::const_visitor&& v )const{ v(val); }
|
||||
virtual void visit( value_visitor&& v ) { v(val); }
|
||||
|
|
@ -53,14 +57,12 @@ namespace fc {
|
|||
virtual void visit( value::const_visitor&& v )const{ v(); }
|
||||
virtual void visit( value_visitor&& v ) { v(); }
|
||||
// typedef void_t T;
|
||||
/*
|
||||
virtual const char* type()const { return "void"; }
|
||||
virtual void clear() { }
|
||||
virtual size_t size()const { return 0; }
|
||||
// virtual const char* type()const { return "void"; }
|
||||
// virtual void clear() { }
|
||||
// virtual size_t size()const { return 0; }
|
||||
|
||||
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();}
|
||||
*/
|
||||
virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl<void>(); }
|
||||
virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl<void>();}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -68,7 +70,9 @@ namespace fc {
|
|||
template<>
|
||||
struct value_holder_impl<fc::string> : value_holder {
|
||||
template<typename V>
|
||||
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){}
|
||||
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){
|
||||
static_assert( sizeof(value_holder_impl<fc::string>) <= 40, "Validate size" );
|
||||
}
|
||||
|
||||
virtual const char* type()const { return "string"; }
|
||||
virtual void visit( value::const_visitor&& v )const { v(val); }
|
||||
|
|
@ -124,12 +128,17 @@ namespace fc {
|
|||
|
||||
value::array val;
|
||||
};
|
||||
static_assert( sizeof( value_holder_impl<value::object> ) <= 40, "sanity check" );
|
||||
static_assert( sizeof( value_holder_impl<value::array> ) <= 40, "sanity check" );
|
||||
|
||||
value_holder::~value_holder(){}
|
||||
const char* value_holder::type()const { return "void"; }
|
||||
value_holder* value_holder::move_helper( char* c ) { return new(c) value_holder(); }
|
||||
value_holder* value_holder::copy_helper( char* c )const { return new(c) value_holder(); }
|
||||
value_holder* value_holder::move_helper( char* c ) { return new(c) value_holder_impl<void>(); }
|
||||
value_holder* value_holder::copy_helper( char* c )const { return new(c) value_holder_impl<void>(); }
|
||||
|
||||
void new_value_holder_void( value* v ) {
|
||||
new (v) value_holder_impl<void>();
|
||||
}
|
||||
|
||||
void value_holder::clear() {}
|
||||
size_t value_holder::size()const { return 0; }
|
||||
|
|
@ -150,7 +159,7 @@ namespace fc {
|
|||
value_holder* value_holder_impl<value::array>::copy_helper( char* c )const{ return new(c) value_holder_impl(val); }
|
||||
|
||||
void value_holder_impl<value::array>::clear() { val.fields.clear(); }
|
||||
size_t value_holder_impl<value::array>::size()const { return val.fields.size(); }
|
||||
size_t value_holder_impl<value::array>::size()const { return static_cast<size_t>(val.fields.size()); }
|
||||
void value_holder_impl<value::array>::visit( value::const_visitor&& v )const { v(val); }
|
||||
void value_holder_impl<value::array>::visit( value_visitor&& v ) { v(val); }
|
||||
void value_holder_impl<value::array>::push_back( value&& v ) { val.fields.push_back( fc::move(v) ); }
|
||||
|
|
@ -158,19 +167,19 @@ namespace fc {
|
|||
|
||||
void value_holder_impl<value::object>::visit( value::const_visitor&& v )const { v(val); }
|
||||
void value_holder_impl<value::object>::visit( value_visitor&& v ) { v(val); }
|
||||
value_holder* value_holder_impl<value::object>::move_helper( char* c ) { return new(c) value_holder_impl( fc::move(val) ); }
|
||||
value_holder* value_holder_impl<value::object>::copy_helper( char* c )const { return new(c) value_holder_impl(val); }
|
||||
value_holder* value_holder_impl<value::object>::move_helper( char* c ) { return new(c) value_holder_impl<value::object>( fc::move(val) ); }
|
||||
value_holder* value_holder_impl<value::object>::copy_helper( char* c )const { return new(c) value_holder_impl<value::object>(val); }
|
||||
void value_holder_impl<value::object>::reserve( size_t s ) { val.fields.reserve(s); }
|
||||
|
||||
void value_holder_impl<value::object>::clear() { val = value::object(); }
|
||||
size_t value_holder_impl<value::object>::size()const { return val.fields.size(); }
|
||||
} // namespace detail
|
||||
|
||||
static detail::value_holder* gh( aligned<24>& h ) {
|
||||
static detail::value_holder* gh( aligned<40>& h ) {
|
||||
return (detail::value_holder*)h._store._data;
|
||||
}
|
||||
static const detail::value_holder* gh( const aligned<24>& h ) {
|
||||
return (const 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() {
|
||||
|
|
@ -224,12 +233,15 @@ value::value( bool v){
|
|||
new (holder) detail::value_holder_impl<bool>(v);
|
||||
}
|
||||
value::value( fc::string&& v){
|
||||
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<fc::string> ), "size check" );
|
||||
new (holder) detail::value_holder_impl<fc::string>(fc::move(v));
|
||||
}
|
||||
value::value( fc::string& v){
|
||||
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<fc::string> ), "size check" );
|
||||
new (holder) detail::value_holder_impl<fc::string>(v);
|
||||
}
|
||||
value::value( const fc::string& v){
|
||||
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<fc::string> ), "size check" );
|
||||
new (holder) detail::value_holder_impl<fc::string>(v);
|
||||
}
|
||||
value::value( value::object&& o ){
|
||||
|
|
@ -276,15 +288,12 @@ value& value::operator=( const value& v ){
|
|||
gh(v.holder)->copy_helper(holder);
|
||||
return *this;
|
||||
}
|
||||
value& value::operator=( 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 strcmp(gh(holder)->type(), "void") == 0;
|
||||
}
|
||||
bool value::is_string()const {
|
||||
return strcmp(gh(holder)->type(), "string") == 0;
|
||||
}
|
||||
|
||||
|
||||
value::object::const_iterator value::find( const char* key )const {
|
||||
|
|
@ -297,40 +306,43 @@ value::object::const_iterator value::find( const char* key )const {
|
|||
}
|
||||
return o->val.fields.end();
|
||||
}
|
||||
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
|
||||
return nullptr;
|
||||
//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( strcmp(gh(holder)->type(), "object") == 0 ) {
|
||||
const detail::value_holder_impl<value::object>* o = static_cast<const detail::value_holder_impl<value::object>*>(gh(holder));
|
||||
return o->val.fields.begin();
|
||||
}
|
||||
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
|
||||
return nullptr;
|
||||
//// 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( strcmp(gh(holder)->type(), "object" ) == 0 ) {
|
||||
const detail::value_holder_impl<value::object>* o = static_cast<const detail::value_holder_impl<value::object>*>(gh(holder));
|
||||
return o->val.fields.end();
|
||||
}
|
||||
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
|
||||
return nullptr;
|
||||
////FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
|
||||
return value::object::const_iterator();
|
||||
//return nullptr;
|
||||
}
|
||||
value& value::operator[]( const char* key ) {
|
||||
if( strcmp(gh(holder)->type(), "object") == 0) {
|
||||
detail::value_holder_impl<value::object>* o = static_cast<detail::value_holder_impl<value::object>*>(gh(holder));
|
||||
detail::value_holder_impl<value::object>* o = dynamic_cast<detail::value_holder_impl<value::object>*>(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 (strcmp(gh(holder)->type(), "void" ) == 0 ) {
|
||||
new (holder) detail::value_holder_impl<value::object>(value::object());
|
||||
new (gh(holder)) detail::value_holder_impl<value::object>(value::object());
|
||||
return (*this)[key];
|
||||
}
|
||||
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
|
||||
FC_THROW_REPORT( "Bad cast of ${type} to object", fc::value().set("type",gh(holder)->type()) );
|
||||
return *((value*)0);
|
||||
}
|
||||
value& value::operator[]( const fc::string& key ) { return (*this)[key.c_str()]; }
|
||||
|
|
|
|||
|
|
@ -33,6 +33,21 @@ FC_STUB( test, (add)(namep_test)(sub)(sub1)(sub2)(sub3)(sub4)(sub5)(sub6)(sub7)(
|
|||
|
||||
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<test> t( new test() );
|
||||
fc::json::rpc_tcp_server serv;
|
||||
serv.add_interface( t );
|
||||
|
|
|
|||
3
vendor/CMakeLists.txt
vendored
Normal file
3
vendor/CMakeLists.txt
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
add_subdirectory( libssh2-1.4.2 )
|
||||
add_subdirectory( zlib-1.2.7)
|
||||
add_subdirectory( sigar )
|
||||
48
vendor/libssh2-1.4.2/AUTHORS
vendored
Normal file
48
vendor/libssh2-1.4.2/AUTHORS
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
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
|
||||
28
vendor/libssh2-1.4.2/CMakeLists.txt
vendored
Normal file
28
vendor/libssh2-1.4.2/CMakeLists.txt
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
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
|
||||
)
|
||||
|
||||
SETUP_LIBRARY( ssh2 SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC )
|
||||
42
vendor/libssh2-1.4.2/COPYING
vendored
Normal file
42
vendor/libssh2-1.4.2/COPYING
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2005,2006 Mikhail Gusarov <dottedmag@dottedmag.net>
|
||||
* Copyright (c) 2006-2007 The Written Word, Inc.
|
||||
* Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
1
vendor/libssh2-1.4.2/ChangeLog
vendored
Normal file
1
vendor/libssh2-1.4.2/ChangeLog
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
see NEWS
|
||||
13
vendor/libssh2-1.4.2/HACKING
vendored
Normal file
13
vendor/libssh2-1.4.2/HACKING
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
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
|
||||
102
vendor/libssh2-1.4.2/README
vendored
Normal file
102
vendor/libssh2-1.4.2/README
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
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).
|
||||
21
vendor/libssh2-1.4.2/RELEASE-NOTES
vendored
Normal file
21
vendor/libssh2-1.4.2/RELEASE-NOTES
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
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)
|
||||
|
||||
1188
vendor/libssh2-1.4.2/include/libssh2.h
vendored
Normal file
1188
vendor/libssh2-1.4.2/include/libssh2.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
118
vendor/libssh2-1.4.2/include/libssh2_publickey.h
vendored
Normal file
118
vendor/libssh2-1.4.2/include/libssh2_publickey.h
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* 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 */
|
||||
345
vendor/libssh2-1.4.2/include/libssh2_sftp.h
vendored
Normal file
345
vendor/libssh2-1.4.2/include/libssh2_sftp.h
vendored
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* 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 <unistd.h>
|
||||
#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 */
|
||||
BIN
vendor/libssh2-1.4.2/libssh2_debug.a
vendored
Normal file
BIN
vendor/libssh2-1.4.2/libssh2_debug.a
vendored
Normal file
Binary file not shown.
793
vendor/libssh2-1.4.2/src/agent.c
vendored
Normal file
793
vendor/libssh2-1.4.2/src/agent.c
vendored
Normal file
|
|
@ -0,0 +1,793 @@
|
|||
/*
|
||||
* 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 <errno.h>
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#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);
|
||||
}
|
||||
2570
vendor/libssh2-1.4.2/src/channel.c
vendored
Normal file
2570
vendor/libssh2-1.4.2/src/channel.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
141
vendor/libssh2-1.4.2/src/channel.h
vendored
Normal file
141
vendor/libssh2-1.4.2/src/channel.h
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#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 */
|
||||
|
||||
390
vendor/libssh2-1.4.2/src/comp.c
vendored
Normal file
390
vendor/libssh2-1.4.2/src/comp.c
vendored
Normal file
|
|
@ -0,0 +1,390 @@
|
|||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
|
||||
* 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 <zlib.h>
|
||||
#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;
|
||||
}
|
||||
45
vendor/libssh2-1.4.2/src/comp.h
vendored
Normal file
45
vendor/libssh2-1.4.2/src/comp.h
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#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 */
|
||||
334
vendor/libssh2-1.4.2/src/crypt.c
vendored
Normal file
334
vendor/libssh2-1.4.2/src/crypt.c
vendored
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/* Copyright (c) 2009, 2010 Simon Josefsson <simon@josefsson.org>
|
||||
* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
* with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
118
vendor/libssh2-1.4.2/src/crypto.h
vendored
Normal file
118
vendor/libssh2-1.4.2/src/crypto.h
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/* 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
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue