This commit is contained in:
Tank Tang 2019-02-20 16:46:32 +08:00 коммит произвёл Vincent Jiang (LEI)
Родитель 710c46315b
Коммит 983420cc8f
18 изменённых файлов: 762 добавлений и 257 удалений

4
.gitignore поставляемый
Просмотреть файл

@ -52,9 +52,13 @@ dkms.conf
# Cmake
build
build.release
# VS folder
.vs/
# Git
*.orig
# Test framework
test/catch2

Просмотреть файл

@ -8,6 +8,7 @@ option(BUILD_SAMPLES "Build sample codes" OFF)
set(AZURE_STORAGE_LITE_HEADER
include/storage_EXPORTS.h
include/logging.h
include/base64.h
include/common.h
include/constants.h
@ -71,6 +72,7 @@ set(AZURE_STORAGE_LITE_HEADER
)
set(AZURE_STORAGE_LITE_SOURCE
src/logging.cpp
src/base64.cpp
src/constants.cpp
src/hash.cpp
@ -106,26 +108,138 @@ set(AZURE_STORAGE_LITE_SOURCE
src/blob/blob_client_wrapper.cpp
)
find_package(CURL REQUIRED)
option(USE_OPENSSL "Use OpenSSL instead of GnuTLS" OFF)
find_package(Threads REQUIRED)
pkg_search_module(UUID REQUIRED uuid)
if (NOT ${USE_OPENSSL})
find_package(GnuTLS REQUIRED)
set(EXTRA_INCLUDE ${GNUTLS_INCLUDE_DIR})
set(EXTRA_LIBRARIES ${GNUTLS_LIBRARIES})
if (UNIX)
option(USE_OPENSSL "Use OpenSSL instead of GnuTLS" OFF)
find_package(Threads REQUIRED)
find_package(CURL REQUIRED)
pkg_search_module(UUID REQUIRED uuid)
if (NOT ${USE_OPENSSL})
find_package(GnuTLS REQUIRED)
set(EXTRA_INCLUDE ${GNUTLS_INCLUDE_DIR})
set(EXTRA_LIBRARIES ${GNUTLS_LIBRARIES})
include_directories(${PROJECT_SOURCE_DIR}/include ${CURL_INCLUDE_DIRS} ${UUID_INCLUDE_DIR} ${EXTRA_INCLUDE})
else()
add_definitions(-DUSE_OPENSSL)
find_package(OpenSSL REQUIRED)
include_directories(${PROJECT_SOURCE_DIR}/include ${CURL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${UUID_INCLUDE_DIR} ${EXTRA_INCLUDE})
endif()
else()
# Add the parameter/definition specifically for Windows.
option(USE_OPENSSL "Use OpenSSL instead of GnuTLS" ON)
option(CMAKE_BUILD_TYPE "The default build type" "Debug")
option(CMAKE_GENERATOR_PLATFORM "The Generator platform used for CMake" "x86")
#Construct the libcurl folder path
#This is because the cmake's FindCurl.cmake not being compatible with libcurl's buildscript on Windows.
#e.g. libcurl-vc15-x64-debug-static-ssl-static-ipv6-sspi
if((DEFINED CURL_ROOT_DIR) AND (NOT (CURL_ROOT_DIR STREQUAL "")))
if(CMAKE_CL_64)
set(INHERIT_ENV "x64")
else()
set(INHERIT_ENV "x86")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(LIBRARY_BUILD_TYPE "debug")
else()
set(LIBRARY_BUILD_TYPE "release")
endif()
if(CURL_LINK_TYPE STREQUAL "static")
add_definitions(-DCURL_STATICLIB)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CURL_LIBRARY_NAME "lib\\libcurl_a_debug.lib")
else()
set(CURL_LIBRARY_NAME "lib\\libcurl_a.lib")
endif()
else()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CURL_LIBRARY_NAME "bin\\libcurl_debug.dll")
else()
set(CURL_LIBRARY_NAME "bin\\libcurl.dll")
endif()
endif()
set(CURL_LIBRARIES "${CURL_ROOT_DIR}\\builds\\libcurl-vc15-${INHERIT_ENV}-${LIBRARY_BUILD_TYPE}-${CURL_LINK_TYPE}-ssl-${OPENSSL_LINK_TYPE}-ipv6-sspi\\${CURL_LIBRARY_NAME}")
set(CURL_INCLUDE_DIRS "${CURL_ROOT_DIR}\\builds\\libcurl-vc15-${INHERIT_ENV}-${LIBRARY_BUILD_TYPE}-${CURL_LINK_TYPE}-ssl-${OPENSSL_LINK_TYPE}-ipv6-sspi\\include\\")
message (STATUS "Constructed curl library path: ${CURL_LIBRARIES}")
message (STATUS "Constructed curl include path: ${CURL_INCLUDE_DIRS}")
unset(INHERIT_ENV)
unset(LIBRARY_BUILD_TYPE)
unset(CURL_LIBRARY_NAME)
else()
if(CURL_LINK_TYPE STREQUAL "static")
add_definitions(-DCURL_STATICLIB)
endif()
#if there isn't a customized openssl library and include, then use FindOpenSSL.cmake to find Openssl on Windows
if(NOT((DEFINED CURL_INCLUDE_DIRS) OR (DEFINED CURL_LIBRARIES)))
find_package(CURL REQUIRED)
endif()
endif()
#Constructing OPENSSL path on windows.
if((DEFINED OPENSSL_ROOT_DIR) AND (NOT (OPENSSL_ROOT_DIR STREQUAL "")))
if(CMAKE_CL_64)
set(INHERIT_ENV "x64")
else()
set(INHERIT_ENV "x86")
endif()
if(OPENSSL_LINK_TYPE STREQUAL "static")
add_definitions(-DOPENSSL_STATICLIB)
set(OPENSSL_LIBRARY_NAME "ssleay32.lib")
set(OPENSSL_CRYPTO_LIBRARY_NAME "libeay32.lib")
else()
set(OPENSSL_LIBRARY_NAME "ssleay32.dll")
set(OPENSSL_CRYPTO_LIBRARY_NAME "libeay32.dll")
endif()
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}\\lib\\${CMAKE_BUILD_TYPE}\\${OPENSSL_LIBRARY_NAME}")
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}\\lib\\${CMAKE_BUILD_TYPE}\\${OPENSSL_CRYPTO_LIBRARY_NAME}")
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}\\include\\openssl\\")
message (STATUS "Constructed openssl library path: ${OPENSSL_SSL_LIBRARY}")
message (STATUS "Constructed openssl include path: ${OPENSSL_INCLUDE_DIR}")
message (STATUS "Constructed openssl crypto library path: ${OPENSSL_CRYPTO_LIBRARY}")
unset(INHERIT_ENV)
unset(OPENSSL_LIBRARY_NAME)
unset(OPENSSL_CRYPTO_LIBRARY_NAME)
else()
if(OPENSSL_LINK_TYPE STREQUAL "static")
add_definitions(-DOPENSSL_STATICLIB)
endif()
#if there isn't a customized openssl library and include, then use FindOpenSSL.cmake to find Openssl on Windows
if(NOT((DEFINED OPENSSL_INCLUDE_DIR) AND (DEFINED OPENSSL_CRYPTO_LIBRARY) AND (DEFINED OPENSSL_SSL_LIBRARY)))
message(STATUS "OpenSSL folder is not specified, need to find it automatically.")
find_package(OpenSSL REQUIRED)
endif()
endif()
if(OPENSSL_LINK_TYPE STREQUAL "static")
add_definitions(-DOPENSSL_STATICLIB)
endif()
add_definitions(-DUSE_OPENSSL)
find_package(OpenSSL REQUIRED)
set(OPENSSL_MSVC_STATIC_RT "true")
if (BUILD_WITH_MT)
set(CMAKE_CXX_FLAGS_RELEASE "/MT")
set(CMAKE_CXX_FLAGS_DEBUG "/MT")
endif()
#adding extra dependency libraries for windows
set(EXTRA_LIBRARIES ${EXTRA_LIBRARIES} rpcrt4 ws2_32 wldap32 crypt32 normaliz)
include_directories(${PROJECT_SOURCE_DIR}/include ${CURL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${EXTRA_INCLUDE})
endif()
add_definitions(-std=c++11)
set(WARNING "-Wall -Wextra -Werror -pedantic -pedantic-errors")
set(CMAKE_CXX_FLAGS "${CMAKE_THREAD_LIBS_INIT} ${WARNING} ${CMAKE_CXX_FLAGS}")
include_directories(${PROJECT_SOURCE_DIR}/include ${CURL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${UUID_INCLUDE_DIR} ${EXTRA_INCLUDE})
if(CMAKE_COMPILER_IS_GNUCXX)
message(STATUS "GCC detected, adding compile flags")
add_definitions(-std=c++11)
set(WARNING "-Wall -Wextra -Werror -pedantic -pedantic-errors")
set(CMAKE_CXX_FLAGS "${CMAKE_THREAD_LIBS_INIT} ${WARNING} ${CMAKE_CXX_FLAGS}")
endif(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_MACOSX_RPATH ON)
@ -135,7 +249,11 @@ else ()
add_library(azure-storage-lite STATIC ${AZURE_STORAGE_LITE_HEADER} ${AZURE_STORAGE_LITE_SOURCE})
endif()
target_link_libraries(azure-storage-lite ${CURL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${UUID_LIBRARIES} ${EXTRA_LIBRARIES})
if (NOT ${USE_OPENSSL})
target_link_libraries(azure-storage-lite ${CURL_LIBRARIES} ${UUID_LIBRARIES} ${EXTRA_LIBRARIES})
else()
target_link_libraries(azure-storage-lite ${CURL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${UUID_LIBRARIES} ${EXTRA_LIBRARIES})
endif()
if(BUILD_TESTS)
add_subdirectory(test)

Просмотреть файл

@ -1,4 +1,16 @@
{
"environments": [
{
"curlRootDir": "",
"opensslRootDir": "",
"buildWithMT": "true", //true or false
"buildSharedLibrary": "false", //true or false
"buildTests": "true", //true or false
"buildSamples": "true", //true or false
"opensslLinkType": "static", //static or dll
"curlLinkType": "static" //static or dll
}
],
"configurations": [
{
"name": "Linux-Release",
@ -17,11 +29,11 @@
"variables": [
{
"name": "BUILD_TESTS",
"value": "true"
"value": "${env.buildTests}"
},
{
"name": "BUILD_SAMPLES",
"value": "true"
"value": "${env.buildSamples}"
}
]
},
@ -45,11 +57,203 @@
"variables": [
{
"name": "BUILD_TESTS",
"value": "true"
"value": "${env.buildTests}"
},
{
"name": "BUILD_SAMPLES",
"value": "true"
"value": "${env.buildSamples}"
}
]
},
{
"name": "Windows-x86-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"ctestCommandArgs": "",
"buildCommandArgs": "",
"inheritEnvironments": [ "msvc_x86" ],
"variables": [
{
"name": "CURL_ROOT_DIR",
"value": "${env.curlRootDir}"
},
{
"name": "OPENSSL_ROOT_DIR",
"value": "${env.opensslRootDir}"
},
{
"name": "BUILD_TESTS",
"value": "${env.buildTests}"
},
{
"name": "BUILD_SAMPLES",
"value": "${env.buildSamples}"
},
{
"name": "OPENSSL_MSVC_STATIC_RT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_WITH_MT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_SHARED_LIBS",
"value": "${env.buildSharedLibrary}"
},
{
"name": "OPENSSL_LINK_TYPE",
"value": "${env.opensslLinkType}"
},
{
"name": "CURL_LINK_TYPE",
"value": "${env.curlLinkType}"
}
]
},
{
"name": "Windows-x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"ctestCommandArgs": "",
"buildCommandArgs": "",
"inheritEnvironments": [ "msvc_x64" ],
"variables": [
{
"name": "CURL_ROOT_DIR",
"value": "${env.curlRootDir}"
},
{
"name": "OPENSSL_ROOT_DIR",
"value": "${env.opensslRootDir}"
},
{
"name": "BUILD_TESTS",
"value": "${env.buildTests}"
},
{
"name": "BUILD_SAMPLES",
"value": "${env.buildSamples}"
},
{
"name": "OPENSSL_MSVC_STATIC_RT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_WITH_MT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_SHARED_LIBS",
"value": "${env.dynamicLinking}"
},
{
"name": "OPENSSL_LINK_TYPE",
"value": "${env.opensslLinkType}"
},
{
"name": "CURL_LINK_TYPE",
"value": "${env.curlLinkType}"
}
]
},
{
"name": "Windows-x86-Release",
"generator": "Ninja",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"ctestCommandArgs": "",
"buildCommandArgs": "",
"inheritEnvironments": [ "msvc_x86" ],
"variables": [
{
"name": "CURL_ROOT_DIR",
"value": "${env.curlRootDir}"
},
{
"name": "OPENSSL_ROOT_DIR",
"value": "${env.opensslRootDir}"
},
{
"name": "BUILD_TESTS",
"value": "${env.buildTests}"
},
{
"name": "BUILD_SAMPLES",
"value": "${env.buildSamples}"
},
{
"name": "OPENSSL_MSVC_STATIC_RT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_WITH_MT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_SHARED_LIBS",
"value": "${env.buildSharedLibrary}"
},
{
"name": "OPENSSL_LINK_TYPE",
"value": "${env.opensslLinkType}"
},
{
"name": "CURL_LINK_TYPE",
"value": "${env.curlLinkType}"
}
]
},
{
"name": "Windows-x64-Release",
"generator": "Ninja",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"ctestCommandArgs": "",
"buildCommandArgs": "",
"inheritEnvironments": [ "msvc_x64" ],
"variables": [
{
"name": "CURL_ROOT_DIR",
"value": "${env.curlRootDir}"
},
{
"name": "OPENSSL_ROOT_DIR",
"value": "${env.opensslRootDir}"
},
{
"name": "BUILD_TESTS",
"value": "${env.buildTests}"
},
{
"name": "BUILD_SAMPLES",
"value": "${env.buildSamples}"
},
{
"name": "OPENSSL_MSVC_STATIC_RT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_WITH_MT",
"value": "${env.buildWithMT}"
},
{
"name": "BUILD_SHARED_LIBS",
"value": "${env.buildSharedLibrary}"
},
{
"name": "OPENSSL_LINK_TYPE",
"value": "${env.opensslLinkType}"
},
{
"name": "CURL_LINK_TYPE",
"value": "${env.curlLinkType}"
}
]
}

128
README.md
Просмотреть файл

@ -25,12 +25,18 @@ The full supported Azure Storage API can be found in the following list, please
- [Append Block](https://docs.microsoft.com/en-us/rest/api/storageservices/append-block).
## Installation
### Clone the latest code from this repository:
### Build this library on Linux
Project dependencies:
- GNUTLS(or Openssl v1.0.1)
- libcurl v7.35.0
- CMake v2.8.12.2
- g++ v4.8.2
- UUID 2.13.1-0.4
#### Clone the latest code from this repository:
```
git clone https://github.com/azure/azure-storage-cpplite.git
```
### Install the dependencies, e.g. on Ubuntu:
#### Install the dependencies, e.g. on Ubuntu:
```
sudo apt-get install libssl-dev libcurl4-openssl-dev cmake g++ uuid-dev
```
@ -40,7 +46,7 @@ sudo yum install openssl-devel.x86_64 libcurl-devel.x86_64 cmake.x86_64 gcc-c++.
```
Please be aware that RHEL6 comes with gcc version 4.4.7, which does not meet the requirement of this SDK. In order to use this SDK, [devtoolset](http://linux.web.cern.ch/linux/devtoolset/#install) needs to be installed properly.
Please be aware that on some Linux distributions, pkg-config is not properly installed that would result in CMake to not behave as expected. Installing pkg-config or updating it will eliminate the potential issue. The tested version of pkg-config is 0.29.1-0.
### Build and install azure-storage-cpplite:
#### Build and install azure-storage-cpplite:
```
cd azure-storage-cpplite
mkdir build.release
@ -48,9 +54,109 @@ cd build.release
CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Release -DUSE_OPENSSL=true
sudo make install
```
### Use GNUTLS instead of OpenSSL:
#### Use GNUTLS instead of OpenSSL:
Alternatively, you can use GNUTLS instead of OpenSSL. Simply install GNUTLS and remove the argument `-DUSE_OPENSSL` during build.
### Build this library on Windows
Project dependencies:
- Openssl v1.0.2o
- libcurl v7.60.0
- CMake v2.8.12.2
- Visual Studio 2017
- Perl (If OpenSSL needs to be built manually)
#### Clone the latest code from this repository:
```
git clone https://github.com/azure/azure-storage-cpplite.git
```
#### Prepare and build the dependencies.
There are two major dependencies on Windows: libcurl and OpenSSL. You can reference the how-tos in this readme or install your own choice of pre-built binaries.
##### How to build libcurl and openssl?
You can use the following guide to build libcurl and openssl on your own. Note that Perl must be installed to build OpenSSL.
Clone the source code of libcurl and OpenSSL:
```
git clone --branch curl-7_60_0 https://github.com/curl/curl.git
git clone --branch OpenSSL_1_0_2o https://github.com/openssl/openssl.git
```
Build OpenSSL first, e.g. if you want to build x86-debug version, note that the perlpath should change to your systems perl install path:
```
.\curl\projects\build-openssl.bat vc14.1 x64 debug .\openssl\ -perlpath C:\Strawberry
```
Then build libcurl:
Run the setup batch file
```
.\curl\buildconf.bat
```
Modify .\curl\winbuild\MakefileBuild.vc to support linking with different configuration type.
Change line:
```
DEVEL_LIB = $(WITH_DEVEL)/lib
```
To:
```
!IF "$(DEBUG)"=="yes"
DEVEL_LIB = $(WITH_DEVEL)/lib/Debug
!ELSE
DEVEL_LIB = $(WITH_DEVEL)/lib/Release
!ENDIF
```
Create `.\curl\deps` folder.
Add `include`, `lib\Debug` and `lib\Release` to `.\curl\deps` folder.
Copy OpenSSL's include and built libraries into created `.\curl\deps` folder:
1. Create `openssl` folder in `.curl\deps\include`
2. Copy `.\openssl\inc32\openssl` into `.\curl\deps\include\openssl`, and you will see `.\curl\deps\include\openssl\openssl`. Please note the duplicated `openssl` in path is somehow necessary for curl build-script.
3. Copy `.\openssl\build\Win32\VC14.1\LIB Release\*.lib` to `.\curl\deps\lib\Release` folder if static libraries are built, otherwise copy the `*.dll` instead.
Open Visual Studio CMD tool, navigate to `.\curl\winbuild` and start building, e.g. Run 'x64 Native Tools command Prompt for VS2017.exe' and run:
```
nmake /f Makefile.vc mode=static VC=15 MACHINE=x64 WITH_SSL=static DEBUG=yes WITH_DEVEL=..\deps RTLIBCFG=static
```
#### Build azure-storage-cpplite using CMake in command line
Note that the `<path to OpenSSL>` should be the absolute path constructed in curl directory as dependency when building curl, normally it should be `<CURL_ROOT_PATH>\deps`. Also, `<CURL_ROOT_PATH>` should be absolute path. Using relative path can cause build to fail.
```
cd azure-storage-cpplite
mkdir build.release
cd build.release
cmake .. -DCURL_ROOT_DIR="<path to curl>" -DOPENSSL_ROOT_DIR="<path to OpenSSL>"
MSBuild.exe azurestoragelite.sln /p:Configuration=Release
```
If you have libcurl and OpenSSL built or installed by yourself with another approach, you can specify the path to the library and headers of them instead:
```
cmake .. -DCURL_LIBRARIES="<path to curl libraries>" -DCURL_INCLUDE_DIRS="<path to curl include folder>" -DOPENSSL_SSL_LIBRARY="<path to OpenSSL's ssl library>" -DOPENSSL_CRYPTO_LIBRARY="<path to OpenSSL's crypto library>" -DOPENSSL_INCLUDE_DIR="<path to OpenSSL's include folder>"
MSBuild.exe azurestoragelite.sln /p:Configuration=Release
```
There are some advanced options to config the build when using cmake commands:
`-DBUILD_TESTS` : specify `true` or `false` to control if tests should be built.
`-DBUILD_SAMPLES` : specify `true` or `false` to control if samples should be built.
`-DOPENSSL_MSVC_STATIC_RT` : specify `true` or `false` to control if the library is building into static library. Note this should be used together with `-DBUILD_SHARED_LIBS=` either `ON` or `OFF`.
`-DBUILD_WITH_MT` : specify `true` or `false` to control if the library is using `/MT` or `/MTd`.
`-DOPENSSL_LINK_TYPE` : specify `static` or `dll` to control if OpenSSL should be linked statically.
`-DCURL_LINK_TYPE` : specify `static` or `dll` to control if libcurl should be linked statically.
`-DCMAKE_GENERATOR_PLATFORM` : specify `x86` or `x64` to config the generator platform type.
`-DCMAKE_BUILD_TYPE` : specify `Debug` or `Release` to config the build type.
#### Build azure-storage-cpplite using Visual Studio 2017
Use Visual Studio 2017 to open the folder that contains this repository. Modify the `environments` in `CMakeSettings.json`. E.g.:
```
"environments": [
{
"curlRootDir": "E:\\dev\\src\\cpp\\curl",
"opensslRootDir": "E:\\dev\\src\\cpp\\curl\\deps",
"buildWithMT": "true", //true or false
"buildSharedLibrary": "false", //true or false
"buildTests": "true", //true or false
"buildSamples": "true", //true or false
"opensslLinkType": "static", //static or dll
"curlLinkType": "static" //static or dll
}
]
```
#### Build dependencies with /MD (/MDd) options instead.
If need to build /MD(/MDd) version, there are two things to do when building OpenSSL:
1. Modify .\openssl\ms\nt.mak, change CFLAG's from `/MT` to `/MD`
2. Comment out this line in .\curl\projects\build-openssl.bat: `perl Configure debug-VC-WIN32 no-asm --prefix=%CD%`
When building libcurl, remove the trailing `RTLIBCFG=static` option will build with `/MD` or `/MDd`
### Build static library instead of dynamic libraries.
By default, dynamic libraries are built. Adding `-DBUILD_SHARED_LIBS=OFF` will build static library instead.
@ -101,16 +207,8 @@ When contributing to this client library, there are following ground rules:
4. Introducing new dependency should be done with much great caution. Any new dependency should introduce significant performance improvement or unblock critical user scenario.
### Build Test
- Dev dependency: catch2.
Download [Catch2 single header version](https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp) and put it in the folder `.\test\catch2\`.
Add `-DBUILD_TESTS=true` when building the repository.
Please modify the [connection string here](https://github.com/azure/azure-storage-cpplite/blob/master/test/test_base.h#L18) in `.\test\test_base.h` line 18 `static std::string sscs = "DefaultEndpointsProtocol=https;";` to successfully run the tests. All the tests use standard Azure Storage account.
#### *Please note that in order to run test, a minimum version of g++ 5.1 is required.*
### Dependencies
- Project dependencies:
- GNUTLS(or Openssl v1.0.1)
- libcurl v7.35.0
- CMake v2.8.12.2
- g++ v4.8.2
- UUID 2.13.1-0.4
- Dev dependency: catch2.
#### *Please note that in order to run test, a minimum version of g++ 5.1 is required on Linux, and Visual Studio 2017 is required on Windows.*

Просмотреть файл

@ -3,10 +3,6 @@
#include <string>
#include <vector>
#ifdef _WIN32
#include <Windows.h>
#include <bcrypt.h>
#else
#ifdef USE_OPENSSL
#include <openssl/hmac.h>
#else
@ -14,54 +10,9 @@
#include <gnutls/crypto.h>
#endif
#define SHA256_DIGEST_LENGTH 32
#endif
#include "storage_EXPORTS.h"
namespace azure { namespace storage_lite {
#ifdef _WIN32
class hash_algorithm_base {};
class hmac_sha256_hash_algorithm : public hash_algorithm_base
{
BCRYPT_ALG_HANDLE _algorithm_handle;
public:
BCRYPT_ALG_HANDLE handle() { return _algorithm_handle; }
hmac_sha256_hash_algorithm()
{
NTSTATUS status = BCryptOpenAlgorithmProvider(&_algorithm_handle, BCRYPT_SHA256_ALGORITHM /* BCRYPT_MD5_ALGORITHM */, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG /* 0 */);
if (status != 0) {
throw std::system_error(status, std::system_category());
}
}
~hmac_sha256_hash_algorithm()
{
BCryptCloseAlgorithmProvider(_algorithm_handle, 0);
}
};
template<typename Hash_Provider>
class hash_provider_base
{
static std::string hash_impl(const std::string &input, const std::vector<unsigned char> &key) = delete;
public:
static std::string hash(const std::string &input, const std::vector<unsigned char> &key
{
return Hash_Provider::hash_impl(input, key);
}
};
class hmac_sha256_hash_provider : public hash_provider_base<hmac_sha256_hash_provider>
{
static hmac_sha256_hash_algorithm _algorithm;
public:
AZURE_STORAGE_API static std::string hash_impl(const std::string &input, const std::vector<unsigned char> &key);
};
#else
std::string hash(const std::string &to_sign, const std::vector<unsigned char> &key);
#endif
AZURE_STORAGE_API std::string hash(const std::string &to_sign, const std::vector<unsigned char> &key);
}} // azure::storage_lite

Просмотреть файл

@ -19,6 +19,9 @@
#include "http_base.h"
#pragma push_macro("min")
#undef min
namespace azure { namespace storage_lite {
class CurlEasyClient;
@ -273,3 +276,5 @@ namespace azure { namespace storage_lite {
};
}} // azure::storage_lite
#pragma pop_macro("min")

98
include/logging.h Normal file
Просмотреть файл

@ -0,0 +1,98 @@
#pragma once
#include <string>
#include <functional>
#include <memory>
#ifdef _WIN32
#include <Rpc.h>
#pragma warning(disable : 4996)
#define _SNPRINTF _snprintf
#else
#include <unistd.h>
#define _SNPRINTF snprintf
#endif
#include "storage_EXPORTS.h"
constexpr auto MAX_LOG_LENGTH = 8192u;
namespace azure { namespace storage_lite {
enum log_level {
trace = 0x0,
debug,
info,
warn,
error,
critical,
none
};
class logger
{
public:
static void log(log_level level, const std::string& msg)
{
s_logger(level, msg);
}
template<typename ... Args>
static void log(log_level level, const char* format, Args ... args)
{
if (level > log_level::critical)
{
return; // does not support higher level logging.
}
size_t size = _SNPRINTF(nullptr, 0, format, args ...) + 1;
// limit the maximum size of this log string to 8kb, as the buffer needs
// to be allocated to a continuous memory and is likely to fail
// when the size is relatively big.
size = size > MAX_LOG_LENGTH ? MAX_LOG_LENGTH : size;
std::unique_ptr<char[]> buf(new char[size]);
_SNPRINTF(buf.get(), size, format, args ...);
auto msg = std::string(buf.get(), buf.get() + size - 1);
log(level, msg);
}
static void debug(const std::string& msg)
{
log(log_level::debug, msg);
}
static void info(const std::string& msg)
{
log(log_level::info, msg);
}
static void warn(const std::string& msg)
{
log(log_level::warn, msg);
}
static void error(const std::string& msg)
{
log(log_level::error, msg);
}
static void critical(const std::string& msg)
{
log(log_level::critical, msg);
}
static void trace(const std::string& msg)
{
log(log_level::trace, msg);
}
static void set_logger(const std::function<void(log_level, const std::string&)>& new_logger)
{
s_logger = new_logger;
}
protected:
static std::function<void(log_level, const std::string&)> s_logger;
static void simple_logger(log_level level, const std::string& msg);
};
}}

Просмотреть файл

@ -9,6 +9,9 @@
#include "http_base.h"
#include "utility.h"
#pragma push_macro("min")
#undef min
namespace azure { namespace storage_lite {
class retry_info
@ -98,3 +101,5 @@ namespace azure { namespace storage_lite {
};
}} // azure::storage_lite
#pragma pop_macro("min")

Просмотреть файл

@ -2,6 +2,6 @@
#ifdef _WIN32
#define AZURE_STORAGE_API __declspec(dllexport)
#else /* ifdef WIN32 */
#else /* ifdef _WIN32 */
#define AZURE_STORAGE_API
#endif

Просмотреть файл

@ -11,6 +11,9 @@
#include "storage_request_base.h"
#include "storage_url.h"
#pragma push_macro("max")
#undef max
namespace azure { namespace storage_lite {
enum class date_format
@ -124,6 +127,7 @@ namespace azure { namespace storage_lite {
AZURE_STORAGE_API std::string get_uuid();
AZURE_STORAGE_API bool create_or_resize_file(const std::string& path, unsigned long long length) noexcept;
inline bool unsuccessful(http_base::http_code status_code)
{
@ -182,3 +186,5 @@ namespace azure { namespace storage_lite {
}
}} // azure::storage_lite
#pragma pop_macro("max")

Просмотреть файл

@ -1,5 +1,11 @@
#include <algorithm>
#include <sstream>
#ifdef _WIN32
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#include "blob/blob_client.h"
#include "blob/download_blob_request.h"

Просмотреть файл

@ -1,20 +1,19 @@
/* C++ interface wrapper for blob client
* No exceptions will throw.
*/
#include <sys/stat.h>
#ifdef __linux__
#include <unistd.h>
#else
#include <Rpc.h>
#endif //__linux__
#include <sys/types.h>
#include <fcntl.h>
#include <iostream>
#include <fstream>
#include "blob/blob_client.h"
#include "logging.h"
#include "storage_errno.h"
#pragma push_macro("max")
#undef max
#pragma push_macro("min")
#undef min
namespace azure { namespace storage_lite {
const unsigned long long DOWNLOAD_CHUNK_SIZE = 16 * 1024 * 1024;
@ -152,7 +151,7 @@ namespace azure { namespace storage_lite {
}
catch(const std::exception &ex)
{
syslog(LOG_ERR, "Failed to create blob client. ex.what() = %s.", ex.what());
logger::log(log_level::error, "Failed to create blob client. ex.what() = %s.", ex.what());
errno = unknown_error;
return blob_client_wrapper(false);
}
@ -190,7 +189,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in create_container. ex.what() = %s, container = %s.", ex.what(), container.c_str());
logger::log(log_level::error, "Unknown failure in create_container. ex.what() = %s, container = %s.", ex.what(), container.c_str());
errno = unknown_error;
return;
}
@ -225,7 +224,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in delete_container. ex.what() = %s, container = %s.", ex.what(), container.c_str());
logger::log(log_level::error, "Unknown failure in delete_container. ex.what() = %s, container = %s.", ex.what(), container.c_str());
errno = unknown_error;
return;
}
@ -255,14 +254,14 @@ namespace azure { namespace storage_lite {
}
else
{
syslog(LOG_ERR, "Unknown failure in container_exists. No exception, but the container property object is invalid. errno = %d.", errno);
logger::log(log_level::error, "Unknown failure in container_exists. No exception, but the container property object is invalid. errno = %d.", errno);
errno = unknown_error;
return false;
}
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in container_exists. ex.what() = %s, container = %s.", ex.what(), container.c_str());
logger::log(log_level::error, "Unknown failure in container_exists. ex.what() = %s, container = %s.", ex.what(), container.c_str());
errno = unknown_error;
return false;
}
@ -295,7 +294,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in list_containers. ex.what() = %s, prefix = %s.", ex.what(), prefix.c_str());
logger::log(log_level::error, "Unknown failure in list_containers. ex.what() = %s, prefix = %s.", ex.what(), prefix.c_str());
errno = unknown_error;
return std::vector<list_containers_item>();
}
@ -332,7 +331,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in list_blobs_hierarchial. ex.what() = %s, container = %s, prefix = %s.", ex.what(), container.c_str(), prefix.c_str());
logger::log(log_level::error, "Unknown failure in list_blobs_hierarchial. ex.what() = %s, container = %s, prefix = %s.", ex.what(), container.c_str(), prefix.c_str());
errno = unknown_error;
return list_blobs_segmented_response();
}
@ -359,7 +358,7 @@ namespace azure { namespace storage_lite {
catch(std::exception& ex)
{
// TODO open failed
syslog(LOG_ERR, "Failure to open the input stream in put_blob. ex.what() = %s, sourcePath = %s.", ex.what(), sourcePath.c_str());
logger::log(log_level::error, "Failure to open the input stream in put_blob. ex.what() = %s, sourcePath = %s.", ex.what(), sourcePath.c_str());
errno = unknown_error;
return;
}
@ -379,7 +378,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Failure to upload the blob in put_blob. ex.what() = %s, container = %s, blob = %s, sourcePath = %s.", ex.what(), container.c_str(), blob.c_str(), sourcePath.c_str());
logger::log(log_level::error, "Failure to upload the blob in put_blob. ex.what() = %s, container = %s, blob = %s, sourcePath = %s.", ex.what(), container.c_str(), blob.c_str(), sourcePath.c_str());
errno = unknown_error;
}
@ -390,7 +389,7 @@ namespace azure { namespace storage_lite {
catch(std::exception& ex)
{
// TODO close failed
syslog(LOG_ERR, "Failure to close the input stream in put_blob. ex.what() = %s, container = %s, blob = %s, sourcePath = %s.", ex.what(), container.c_str(), blob.c_str(), sourcePath.c_str());
logger::log(log_level::error, "Failure to close the input stream in put_blob. ex.what() = %s, container = %s, blob = %s, sourcePath = %s.", ex.what(), container.c_str(), blob.c_str(), sourcePath.c_str());
errno = unknown_error;
}
}
@ -426,7 +425,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in upload_block_blob_from_stream. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
logger::log(log_level::error, "Unknown failure in upload_block_blob_from_stream. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
errno = unknown_error;
}
}
@ -481,7 +480,7 @@ namespace azure { namespace storage_lite {
std::ifstream ifs(sourcePath);
if(!ifs)
{
syslog(LOG_ERR, "Failed to open the input stream in upload_file_to_blob. errno = %d, sourcePath = %s.", errno, sourcePath.c_str());
logger::log(log_level::error, "Failed to open the input stream in upload_file_to_blob. errno = %d, sourcePath = %s.", errno, sourcePath.c_str());
errno = unknown_error;
return;
}
@ -506,20 +505,20 @@ namespace azure { namespace storage_lite {
if (0 != result) {
break;
}
int length = block_size;
long long length = block_size;
if(offset + length > fileSize)
{
length = fileSize - offset;
}
char* buffer = (char*)malloc(block_size);
char* buffer = (char*)malloc(static_cast<size_t>(block_size)); // This cast is save because block size should always be lower than 4GB
if (!buffer) {
result = 12;
break;
}
if(!ifs.read(buffer, length))
{
syslog(LOG_ERR, "Failed to read from input stream in upload_file_to_blob. sourcePath = %s, container = %s, blob = %s, offset = %lld, length = %d.", sourcePath.c_str(), container.c_str(), blob.c_str(), offset, length);
logger::log(log_level::error, "Failed to read from input stream in upload_file_to_blob. sourcePath = %s, container = %s, blob = %s, offset = %lld, length = %d.", sourcePath.c_str(), container.c_str(), blob.c_str(), offset, length);
result = unknown_error;
break;
}
@ -587,7 +586,7 @@ namespace azure { namespace storage_lite {
if(!r.success())
{
result = std::stoi(r.error().code);
syslog(LOG_ERR, "put_block_list failed in upload_file_to_blob. error code = %d, sourcePath = %s, container = %s, blob = %s.", result, sourcePath.c_str(), container.c_str(), blob.c_str());
logger::log(log_level::error, "put_block_list failed in upload_file_to_blob. error code = %d, sourcePath = %s, container = %s, blob = %s.", result, sourcePath.c_str(), container.c_str(), blob.c_str());
if (0 == result) {
result = unknown_error;
}
@ -633,7 +632,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in download_blob_to_stream. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
logger::log(log_level::error, "Unknown failure in download_blob_to_stream. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
errno = unknown_error;
return;
}
@ -657,7 +656,7 @@ namespace azure { namespace storage_lite {
firstChunk = m_blobClient->get_chunk_to_stream_sync(container, blob, 0, DOWNLOAD_CHUNK_SIZE, os);
os.close();
if (!os) {
syslog(LOG_ERR, "get_chunk_to_stream_async failed for firstchunk in download_blob_to_file. container = %s, blob = %s, destPath = %s.", container.c_str(), blob.c_str(), destPath.c_str());
logger::log(log_level::error, "get_chunk_to_stream_async failed for firstchunk in download_blob_to_file. container = %s, blob = %s, destPath = %s.", container.c_str(), blob.c_str(), destPath.c_str());
errno = unknown_error;
return;
}
@ -680,16 +679,8 @@ namespace azure { namespace storage_lite {
const auto originalEtag = firstChunk.response().etag;
const auto length = static_cast<unsigned long long>(firstChunk.response().totalSize);
// Resize the target file.
auto fd = open(destPath.c_str(), O_WRONLY, 0770);
if (-1 == fd) {
return;
}
if (-1 == ftruncate(fd, length)) {
close(fd);
return;
}
close(fd);
// Create or resize the target file if already exist.
create_or_resize_file(destPath, length);
// Download the rest.
const auto left = length - firstChunk.response().size;
@ -718,7 +709,7 @@ namespace azure { namespace storage_lite {
}
// Check for any writing errors.
if (!output) {
syslog(LOG_ERR, "get_chunk_to_stream_async failure in download_blob_to_file. container = %s, blob = %s, destPath = %s, offset = %llu, range = %llu.", container.c_str(), blob.c_str(), destPath.c_str(), offset, range);
logger::log(log_level::error, "get_chunk_to_stream_async failure in download_blob_to_file. container = %s, blob = %s, destPath = %s, offset = %llu, range = %llu.", container.c_str(), blob.c_str(), destPath.c_str(), offset, range);
return unknown_error;
}
return 0;
@ -740,7 +731,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in download_blob_to_file. ex.what() = %s, container = %s, blob = %s, destPath = %s.", ex.what(), container.c_str(), blob.c_str(), destPath.c_str());
logger::log(log_level::error, "Unknown failure in download_blob_to_file. ex.what() = %s, container = %s, blob = %s, destPath = %s.", ex.what(), container.c_str(), blob.c_str(), destPath.c_str());
errno = unknown_error;
return;
}
@ -773,7 +764,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in get_blob_property. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
logger::log(log_level::error, "Unknown failure in get_blob_property. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
errno = unknown_error;
return blob_property(false);
}
@ -799,7 +790,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in blob_exists. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
logger::log(log_level::error, "Unknown failure in blob_exists. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
errno = unknown_error;
return false;
}
@ -835,7 +826,7 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in delete_blob. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
logger::log(log_level::error, "Unknown failure in delete_blob. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
errno = unknown_error;
return;
}
@ -873,10 +864,13 @@ namespace azure { namespace storage_lite {
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in start_copy. ex.what() = %s, sourceContainer = %s, sourceBlob = %s, destContainer = %s, destBlob = %s.", ex.what(), sourceContainer.c_str(), sourceBlob.c_str(), destContainer.c_str(), destBlob.c_str());
logger::log(log_level::error, "Unknown failure in start_copy. ex.what() = %s, sourceContainer = %s, sourceBlob = %s, destContainer = %s, destBlob = %s.", ex.what(), sourceContainer.c_str(), sourceBlob.c_str(), destContainer.c_str(), destBlob.c_str());
errno = unknown_error;
return;
}
}
}} // azure::storage_lite
#pragma pop_macro("min")
#pragma pop_macro("max")

Просмотреть файл

@ -3,51 +3,6 @@
#include "base64.h"
namespace azure { namespace storage_lite {
#ifdef _WIN32
hmac_sha256_hash_algorithm hmac_sha256_hash_provider::_algorithm;
std::string hmac_sha256_hash_provider::hash_impl(const std::string &input, const std::vector<unsigned char> &key)
{
ULONG object_size = 0;
ULONG size_length = 0;
NTSTATUS status = BCryptGetProperty(_algorithm.handle(), BCRYPT_OBJECT_LENGTH, (PUCHAR)&object_size, sizeof(ULONG), &size_length, 0);
if (status != 0)
{
throw std::system_error(status, std::system_category());
}
std::vector<UCHAR> hash_object(object_size);
BCRYPT_HASH_HANDLE hash_handle;
status = BCryptCreateHash(_algorithm.handle(), &hash_handle, (PUCHAR)hash_object.data(), (ULONG)hash_object.size(), (PUCHAR)key.data(), (ULONG)key.size(), 0);
if (status != 0)
{
throw std::system_error(status, std::system_category());
}
status = BCryptHashData(hash_handle, (PUCHAR)input.data(), (ULONG)input.size(), 0);
if (status != 0)
{
throw std::system_error(status, std::system_category());
}
status = BCryptGetProperty(hash_handle, BCRYPT_HASH_LENGTH, (PUCHAR)&object_size, sizeof(ULONG), &size_length, 0);
if (status != 0)
{
throw std::system_error(status, std::system_category());
}
std::vector<UCHAR> hash(object_size);
status = BCryptFinishHash(hash_handle, hash.data(), (ULONG)hash.size(), 0);
if (status != 0 && status != 0xc0000008)
{
throw std::system_error(status, std::system_category());
}
status = BCryptDestroyHash(hash_handle);
return to_base64(hash);
}
#else
std::string hash(const std::string &to_sign, const std::vector<unsigned char> &key)
{
unsigned int l = SHA256_DIGEST_LENGTH;
@ -57,17 +12,17 @@ namespace azure { namespace storage_lite {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key.data(), key.size(), EVP_sha256(), NULL);
HMAC_Init_ex(&ctx, key.data(), static_cast<int>(key.size()), EVP_sha256(), NULL);
HMAC_Update(&ctx, (const unsigned char*)to_sign.c_str(), to_sign.size());
HMAC_Final(&ctx, digest, &l);
HMAC_CTX_cleanup(&ctx);
#else
HMAC_CTX *ctx = HMAC_CTX_new();
HMAC_CTX * ctx = HMAC_CTX_new();
HMAC_CTX_reset(ctx);
HMAC_Init_ex(ctx, key.data(), key.size(), EVP_sha256(), NULL);
HMAC_Update(ctx, (const unsigned char*)to_sign.c_str(), to_sign.size());
HMAC_Final(ctx, digest, &l);
HMAC_CTX_free(ctx);
HMAC_CTX_free(ctx);
#endif
#else
gnutls_hmac_fast(GNUTLS_MAC_SHA256, key.data(), key.size(), (const unsigned char *)to_sign.data(), to_sign.size(), digest);
@ -75,6 +30,4 @@ namespace azure { namespace storage_lite {
return to_base64(std::vector<unsigned char>(digest, digest + l));
}
#endif
}} // azure::storage_lite

26
src/logging.cpp Normal file
Просмотреть файл

@ -0,0 +1,26 @@
#include "logging.h"
namespace azure { namespace storage_lite {
std::function<void(log_level, const std::string&)> logger::s_logger = logger::simple_logger;
#ifdef _WIN32
void logger::simple_logger(log_level level, const std::string& msg)
{
//Do nothing for now.
//TODO: integrate with Windows trace log.
}
#else
int get_syslog_priority(log_level level)
{
static indexing = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERR, LOG_CRIT };
return indexing[level];
}
void logger::simple_logger(log_level level, const std::string& msg)
{
syslog(get_syslog_priority(level), msg.c_str());
}
#endif
}}

Просмотреть файл

@ -57,11 +57,7 @@ namespace azure { namespace storage_lite {
}
std::string authorization("SharedKey ");
#ifdef _WIN32
authorization.append(m_account_name).append(":").append(hmac_sha256_hash_provider::hash(string_to_sign, m_account_key));
#else
authorization.append(m_account_name).append(":").append(hash(string_to_sign, m_account_key));
#endif
h.add_header(constants::header_authorization, authorization);
}

Просмотреть файл

@ -4,24 +4,65 @@
#include "constants.h"
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#include <filesystem>
#else
#include <uuid/uuid.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#endif
namespace azure { namespace storage_lite {
std::string get_uuid()
{
std::string res;
#ifdef _WIN32
UUID uuid;
UuidCreate(&uuid);
char* uuid_cstr = nullptr;
UuidToString(&uuid, reinterpret_cast<RPC_CSTR*>(uuid_cstr));
res = std::string(uuid_cstr);
RpcStringFreeA(reinterpret_cast<RPC_CSTR*>(uuid_cstr));
#else
uuid_t uuid;
char uuid_cstr[37]; // 36 byte uuid plus null.
uuid_generate(uuid);
uuid_unparse(uuid, uuid_cstr);
res = std::string(uuid_cstr);
#endif
return std::string(uuid_cstr);
}
bool create_or_resize_file(const std::string& path, unsigned long long length) noexcept
{
#ifdef _WIN32
try
{
std::experimental::filesystem::resize_file(path, static_cast<uintmax_t>(length));
}
catch (...)
{
return false;
}
return true;
#else
auto fd = open(path.c_str(), O_WRONLY, 0770);
if (-1 == fd) {
return false;
}
if (-1 == ftruncate(fd, length)) {
close(fd);
return false;
}
close(fd);
return true;
#endif
}
std::string get_ms_date(date_format format)
{
char buf[30];

Просмотреть файл

@ -10,28 +10,28 @@
#include <vector>
namespace as_test {
std::string get_random_string(size_t size) {
std::string get_random_string(size_t size) {
static bool initialized = false;
if (!initialized) {
srand(time(NULL));
srand(static_cast<unsigned int>(time(NULL)));
initialized = true;
}
auto randchar = []() -> char
{
auto randchar = []() -> char
{
const char charset[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(size, 0);
std::generate_n(str.begin(), size, randchar);
return str;
}
"0123456789abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(size, 0);
std::generate_n(str.begin(), size, randchar);
return str;
}
std::istringstream get_istringstream_with_random_buffer(size_t size) {
static bool initialized = false;
if (!initialized) {
srand(time(NULL));
srand(static_cast<unsigned int>(time(NULL)));
initialized = true;
}
auto randchar = []() -> char
@ -96,70 +96,70 @@ namespace as_test {
return result;
}
azure::storage_lite::blob_client& base::test_blob_client(int size) {
static std::unordered_map<int, std::shared_ptr<azure::storage_lite::blob_client>> bcs;
if (bcs[size] == NULL)
{
azure::storage_lite::blob_client& base::test_blob_client(int size) {
static std::unordered_map<int, std::shared_ptr<azure::storage_lite::blob_client>> bcs;
if (bcs[size] == NULL)
{
bcs[size] = std::make_shared<azure::storage_lite::blob_client>(azure::storage_lite::blob_client(init_account(standard_storage_connection_string()), size));
}
return *bcs[size];
}
}
return *bcs[size];
}
const std::shared_ptr<azure::storage_lite::storage_account> base::init_account(const std::string& connection_string) {
auto settings = parse_string_into_settings(connection_string);
auto credential = std::make_shared<azure::storage_lite::shared_key_credential>(azure::storage_lite::shared_key_credential(settings["AccountName"], settings["AccountKey"]));
bool use_https = true;
if (settings["DefaultEndpointsProtocol"] == "http")
{
use_https = false;
}
std::string blob_endpoint;
if (!settings["BlobEndpoint"].empty())
{
blob_endpoint = settings["BlobEndpoint"];
}
auto settings = parse_string_into_settings(connection_string);
auto credential = std::make_shared<azure::storage_lite::shared_key_credential>(azure::storage_lite::shared_key_credential(settings["AccountName"], settings["AccountKey"]));
bool use_https = true;
if (settings["DefaultEndpointsProtocol"] == "http")
{
use_https = false;
}
std::string blob_endpoint;
if (!settings["BlobEndpoint"].empty())
{
blob_endpoint = settings["BlobEndpoint"];
}
return std::make_shared<azure::storage_lite::storage_account>(azure::storage_lite::storage_account(settings["AccountName"], credential, use_https, blob_endpoint));
}
return std::make_shared<azure::storage_lite::storage_account>(azure::storage_lite::storage_account(settings["AccountName"], credential, use_https, blob_endpoint));
}
std::map<std::string, std::string> base::parse_string_into_settings(const std::string& connection_string)
{
std::map<std::string, std::string> settings;
std::vector<std::string> splitted_string;
std::map<std::string, std::string> base::parse_string_into_settings(const std::string& connection_string)
{
std::map<std::string, std::string> settings;
std::vector<std::string> splitted_string;
// Split the connection string by ';'
{
std::istringstream iss(connection_string);
std::string s;
while (getline(iss, s, ';')) {
splitted_string.push_back(s);
}
}
// Split the connection string by ';'
{
std::istringstream iss(connection_string);
std::string s;
while (getline(iss, s, ';')) {
splitted_string.push_back(s);
}
}
for (auto iter = splitted_string.cbegin(); iter != splitted_string.cend(); ++iter)
{
if (!iter->empty())
{
auto equals = iter->find('=');
for (auto iter = splitted_string.cbegin(); iter != splitted_string.cend(); ++iter)
{
if (!iter->empty())
{
auto equals = iter->find('=');
std::string key = iter->substr(0, equals);
if (!key.empty())
{
std::string value;
if (equals != std::string::npos)
{
value = iter->substr(equals + 1);
}
std::string key = iter->substr(0, equals);
if (!key.empty())
{
std::string value;
if (equals != std::string::npos)
{
value = iter->substr(equals + 1);
}
settings.insert(std::make_pair(std::move(key), std::move(value)));
}
else
{
throw std::logic_error("The format of connection string cannot be recognized.");
}
}
}
settings.insert(std::make_pair(std::move(key), std::move(value)));
}
else
{
throw std::logic_error("The format of connection string cannot be recognized.");
}
}
}
return settings;
}
return settings;
}
}

Просмотреть файл

@ -10,17 +10,17 @@ namespace as_test {
std::istringstream get_istringstream_with_random_buffer(size_t size);
std::string to_base64(const char* base, size_t length);
class base {
class base {
public:
static azure::storage_lite::blob_client& test_blob_client(int size = 1);
static azure::storage_lite::blob_client& test_blob_client(int size = 1);
static const std::string& standard_storage_connection_string() {
static std::string sscs = "DefaultEndpointsProtocol=https;";
return sscs;
}
static const std::string& standard_storage_connection_string() {
static std::string sscs = "DefaultEndpointsProtocol=https;";
return sscs;
}
private:
static const std::shared_ptr<azure::storage_lite::storage_account> init_account(const std::string& connection_string);
static std::map<std::string, std::string> parse_string_into_settings(const std::string& connection_string);
};
};
}