From 0c9f75d688910e9b68daf513ac121394bac0b4d5 Mon Sep 17 00:00:00 2001 From: Julia Cox <41338503+astrocox@users.noreply.github.com> Date: Sat, 24 Feb 2024 21:11:54 -0500 Subject: [PATCH] Add MS Windows support (#108) --- .github/workflows/ci.yml | 35 ++++++++++++++++++++++++++++++++++- .gitignore | 5 +++++ CMakeLists.txt | 10 ++++++++-- include/http.h | 4 ++++ include/providers.h | 5 +++++ include/utils.h | 21 +++++++++++++-------- src/client.cc | 2 +- src/utils.cc | 23 +++++++++++++++++++++-- tests/tests.cc | 8 +++----- 9 files changed, 94 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf772a5f..1accba77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,6 +37,13 @@ jobs: cc: "clang", cxx: "clang++" } + - { + name: "Windows Latest MSVC", + os: windows-latest, + build_type: "Release", + cc: "cl", + cxx: "cl" + } steps: - uses: actions/checkout@v2 @@ -67,6 +74,15 @@ jobs: minio --version clang-format --version + - name: Install dependencies if Windows + shell: bash + if: startsWith(matrix.config.os, 'windows') + run: | + choco install -y --no-progress cmake wget + wget --quiet https://dl.min.io/server/minio/release/windows-amd64/minio.exe + chmod +x minio.exe + cmake --version + - name: Install vcpkg shell: bash run: | @@ -78,7 +94,8 @@ jobs: ./vcpkg-master/vcpkg integrate install ./vcpkg-master/vcpkg install - - name: C++ Style check + - name: C++ Style check if not Windows + if: ${{ !startsWith(matrix.config.os, 'windows') }} shell: bash run: | ./check-style.sh @@ -105,6 +122,16 @@ jobs: MINIO_CI_CD=true minio server test-xl/{1...4}/ & sleep 10 + - name: Start MinIO server if Windows + if: startsWith(matrix.config.os, 'windows') + shell: bash + run: | + mkdir -p ~/.minio/certs + cp ./tests/public.crt ./tests/private.key ~/.minio/certs/ + certutil -addstore -f "ROOT" ./tests/public.crt + MINIO_CI_CD=true ./minio.exe server test-xl/{1...4}/ & + sleep 10 + - name: Run tests if Ubuntu if: startsWith(matrix.config.name, 'Ubuntu_Latest_GCC') run: | @@ -115,6 +142,12 @@ jobs: run: | SERVER_ENDPOINT=localhost:9000 ACCESS_KEY=minioadmin SECRET_KEY=minioadmin ./build/tests/tests + - name: Run tests if Windows + shell: bash + if: startsWith(matrix.config.os, 'windows') + run: | + SERVER_ENDPOINT=localhost:9000 ACCESS_KEY=minioadmin SECRET_KEY=minioadmin ENABLE_HTTPS=1 ./build/tests/Release/tests.exe + - name: Run CMake test working-directory: ${{github.workspace}}/build # Execute tests defined by the CMake configuration. diff --git a/.gitignore b/.gitignore index 6405d865..a5559007 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,8 @@ docs/*svg docs/*map docs/*md5 include/config.h +.idea/ +cmake-build* +vcpkg-master.zip +vcpkg-master/ + diff --git a/CMakeLists.txt b/CMakeLists.txt index f2b81c3f..4a90ac70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,11 +12,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +cmake_minimum_required(VERSION 3.10) +cmake_policy(SET CMP0091 NEW) project(miniocpp) -cmake_minimum_required(VERSION 3.10) - include(GNUInstallDirs) macro(set_globals) @@ -80,6 +80,12 @@ ELSE(OPENSSL_FOUND) MESSAGE(FATAL_ERROR "Could not find the OpenSSL library and development files.") ENDIF(OPENSSL_FOUND) +if(WIN32) + list(APPEND requiredlibs wsock32) + list(APPEND requiredlibs ws2_32) + list(APPEND requiredlibs ZLIB::ZLIB) +endif() + message(STATUS "Found required libs: ${requiredlibs}") INCLUDE (CheckIncludeFiles) diff --git a/include/http.h b/include/http.h index c3645b95..284cb5e7 100644 --- a/include/http.h +++ b/include/http.h @@ -16,7 +16,11 @@ #ifndef _MINIO_HTTP_H #define _MINIO_HTTP_H +#ifdef _WIN32 +#include +#else #include +#endif #include #include diff --git a/include/providers.h b/include/providers.h index aae8a3e4..b61d83d9 100644 --- a/include/providers.h +++ b/include/providers.h @@ -17,9 +17,14 @@ #define _MINIO_CREDS_PROVIDERS_H #include +#ifdef _WIN32 +#include +#include +#else #include #include #include +#endif #include #include diff --git a/include/utils.h b/include/utils.h index 12e81e48..10cf378d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -16,17 +16,20 @@ #ifndef _MINIO_UTILS_H #define _MINIO_UTILS_H -#include +#ifndef _WIN32 +#include +#endif + #include #include -#include #include -#include #include #include +#include #include #include +#include #include #include #include @@ -41,9 +44,8 @@ namespace minio { namespace utils { inline constexpr unsigned int kMaxMultipartCount = 10000; // 10000 parts -inline constexpr unsigned long kMaxObjectSize = - 5L * 1024 * 1024 * 1024 * 1024; // 5TiB -inline constexpr unsigned long kMaxPartSize = 5L * 1024 * 1024 * 1024; // 5GiB +inline constexpr unsigned long long kMaxObjectSize = 5497558138880ULL; // 5TiB +inline constexpr unsigned long long kMaxPartSize = 5368709120UL; // 5GiB inline constexpr unsigned int kMinPartSize = 5 * 1024 * 1024; // 5MiB bool GetEnv(std::string& var, const char* name); @@ -122,7 +124,7 @@ class Time { public: Time() {} - Time(std::time_t tv_sec, suseconds_t tv_usec, bool utc) { + Time(std::time_t tv_sec, long tv_usec, bool utc) { this->tv_.tv_sec = tv_sec; this->tv_.tv_usec = tv_usec; this->utc_ = utc; @@ -146,7 +148,10 @@ class Time { static Time Now() { Time t; - gettimeofday(&t.tv_, NULL); + auto usec = std::chrono::system_clock::now().time_since_epoch() / + std::chrono::microseconds(1); + t.tv_.tv_sec = static_cast(usec / 1000000); + t.tv_.tv_usec = static_cast(usec % 1000000); return t; } diff --git a/src/client.cc b/src/client.cc index e476195b..7f5436ff 100644 --- a/src/client.cc +++ b/src/client.cc @@ -637,7 +637,7 @@ minio::s3::DownloadObjectResponse minio::s3::Client::DownloadObject( std::string temp_filename = args.filename + "." + curlpp::escape(etag) + ".part.minio"; - std::ofstream fout(temp_filename, fout.trunc | fout.out); + std::ofstream fout(temp_filename, std::ios::trunc | std::ios::out); if (!fout.is_open()) { return error::Error("unable to open file " + temp_filename); } diff --git a/src/utils.cc b/src/utils.cc index d7cac522..54e9a3a9 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -28,6 +28,19 @@ const std::regex IPV4_REGEX( "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}" "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"); +#ifdef _WIN32 +// strptime is defined here because it's not available on Windows. +static char* strptime(const char* s, const char* f, struct tm* tm) { + std::istringstream input(s); + input.imbue(std::locale(setlocale(LC_ALL, nullptr))); + input >> std::get_time(tm, f); + if (input.fail()) { + return nullptr; + } + return (char*)(s + input.tellg()); +} +#endif + bool minio::utils::GetEnv(std::string& var, const char* name) { if (const char* value = std::getenv(name)) { var = value; @@ -38,8 +51,13 @@ bool minio::utils::GetEnv(std::string& var, const char* name) { std::string minio::utils::GetHomeDir() { std::string home; +#ifdef _WIN32 + GetEnv(home, "USERPROFILE"); + return home; +#else if (GetEnv(home, "HOME")) return home; return getpwuid(getuid())->pw_dir; +#endif } std::string minio::utils::Printable(std::string s) { @@ -258,7 +276,8 @@ std::string minio::utils::FormatTime(const std::tm* time, const char* format) { std::tm* minio::utils::Time::ToUTC() { std::tm* t = new std::tm; - *t = utc_ ? *std::localtime(&tv_.tv_sec) : *std::gmtime(&tv_.tv_sec); + const time_t secs = tv_.tv_sec; + *t = utc_ ? *std::localtime(&secs) : *std::gmtime(&secs); return t; } @@ -336,7 +355,7 @@ minio::utils::Time minio::utils::Time::FromISO8601UTC(const char* value) { char* rv = strptime(value, "%Y-%m-%dT%H:%M:%S", &t); unsigned long ul = 0; sscanf(rv, ".%lu", &ul); - suseconds_t tv_usec = (suseconds_t)ul; + long tv_usec = (long)ul; std::time_t time = std::mktime(&t); return Time(time, tv_usec, true); } diff --git a/tests/tests.cc b/tests/tests.cc index 5e75a44a..7f9443a1 100644 --- a/tests/tests.cc +++ b/tests/tests.cc @@ -12,9 +12,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - -#include - +#include #include #include @@ -39,7 +37,7 @@ class RandomBuf : public std::streambuf { int_type underflow() override { if (size_ == 0) return EOF; - size_t size = std::min(size_, buf_.size()); + size_t size = std::min(size_, buf_.size()); setg(&buf_[0], &buf_[0], &buf_[size]); for (size_t i = 0; i < size; ++i) buf_[i] = charset[pick(rg)]; size_ -= size; @@ -623,7 +621,7 @@ class Tests { } }}; - usleep(10 * 1000); // sleep for 10ms. + std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::string object_name = RandObjectName(); try {