diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:18 +0000 |
commit | 5da14042f70711ea5cf66e034699730335462f66 (patch) | |
tree | 0f6354ccac934ed87a2d555f45be4c831cf92f4a /src/fluent-bit/lib/chunkio | |
parent | Releasing debian version 1.44.3-2. (diff) | |
download | netdata-5da14042f70711ea5cf66e034699730335462f66.tar.xz netdata-5da14042f70711ea5cf66e034699730335462f66.zip |
Merging upstream version 1.45.3+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/fluent-bit/lib/chunkio')
85 files changed, 11922 insertions, 0 deletions
diff --git a/src/fluent-bit/lib/chunkio/.github/workflows/ci.yaml b/src/fluent-bit/lib/chunkio/.github/workflows/ci.yaml new file mode 100644 index 000000000..c937a2c90 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/.github/workflows/ci.yaml @@ -0,0 +1,45 @@ +name: Build PR(s) and master branch. +on: + push: + branches: + - master + pull_request: + branches: + - master + types: [opened, edited, synchronize] +jobs: + build-windows: + name: Build sources on amd64 for ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + max-parallel: 48 + fail-fast: false + matrix: + os: [windows-latest, windows-2019] + steps: + - uses: actions/checkout@v2 + - name: Build on ${{ matrix.os }} with vs-2019 + run: | + .\scripts\win_build.bat + - name: Run unit tests. + run: | + ctest --rerun-failed --output-on-failure -C Debug --test-dir . + build-unix: + name: Build sources on amd64 for ${{ matrix.os }} - ${{ matrix.compiler }} + runs-on: ${{ matrix.os }} + strategy: + max-parallel: 48 + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + compiler: [ gcc, clang ] + steps: + - uses: actions/checkout@v2 + - name: Build on ${{ matrix.os }} with ${{ matrix.compiler }} + run: | + echo "CC = $CC, CXX = $CXX" + cmake -DCIO_TESTS=On . + make all + ctest --rerun-failed --output-on-failure -C Debug --test-dir . + env: + CC: ${{ matrix.compiler }} diff --git a/src/fluent-bit/lib/chunkio/.gitignore b/src/fluent-bit/lib/chunkio/.gitignore new file mode 100644 index 000000000..fcfb6d2c5 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/.gitignore @@ -0,0 +1,5 @@ +*~ +build/ +tests/cio_tests_internal.h +include/chunkio/cio_info.h +include/chunkio/cio_version.h diff --git a/src/fluent-bit/lib/chunkio/AUTHORS.md b/src/fluent-bit/lib/chunkio/AUTHORS.md new file mode 100644 index 000000000..03bb852e4 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/AUTHORS.md @@ -0,0 +1 @@ +Eduardo Silva <eduardo@monkey.io> diff --git a/src/fluent-bit/lib/chunkio/CMakeLists.txt b/src/fluent-bit/lib/chunkio/CMakeLists.txt new file mode 100644 index 000000000..f49d01d90 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/CMakeLists.txt @@ -0,0 +1,127 @@ +cmake_minimum_required(VERSION 3.0) +project(chunk-io C) + +set(CIO_VERSION_MAJOR 1) +set(CIO_VERSION_MINOR 5) +set(CIO_VERSION_PATCH 1) +set(CIO_VERSION_STR "${CIO_VERSION_MAJOR}.${CIO_VERSION_MINOR}.${CIO_VERSION_PATCH}") + +# CFLAGS +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +if(MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 ") +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall ") +endif() + +# Set __FILENAME__ +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__FILENAME__=__FILE__") + +include(cmake/macros.cmake) + +# ChunkIO options +option(CIO_DEV "Enable dev/test mode" Off) +option(CIO_LIB_STATIC "Enable static library build" On) +option(CIO_LIB_SHARED "Enable shared library build" Off) +option(CIO_SANITIZE_ADDRESS "Enable address sanitizer" Off) +option(CIO_TESTS "Enable tests" Off) +option(CIO_BACKEND_FILESYSTEM "Enable filesystem backend" On) + +# Force Option value +macro(CIO_OPTION option value) + set(${option} ${value} CACHE INTERNAL "" FORCE) +endmacro() + +# Development/Test mode +if(CIO_DEV) + CIO_OPTION(CMAKE_BUILD_TYPE "Debug") + CIO_OPTION(CIO_TESTS On) + CIO_OPTION(CIO_LIB_STATIC On) +endif() + + +# Check if Address Sanitizer is enabled +if(CIO_SANITIZE_ADDRESS OR SANITIZE_ADDRESS) + set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH}) + if(NOT SANITIZE_ADDRESS) + add_definitions(-DSANITIZE_ADDRESS=On) + endif() + find_package(Sanitizers) + + # Note that this package don't define Sanitizers_FOUND: + # https://github.com/arsenm/sanitizers-cmake/issues/16 + if (NOT DEFINED SANITIZE_LINK_STATIC) + message(FATAL_ERROR "CMake Sanitizer not found") + else() + message(STATUS "Enabling address sanitizer") + endif() +endif() + +if(CIO_BACKEND_FILESYSTEM) + CIO_DEFINITION(CIO_HAVE_BACKEND_FILESYSTEM) +endif() + +include(CheckCSourceCompiles) + +# getpagesize(2) support +check_c_source_compiles(" + #include <unistd.h> + int main() { + getpagesize(); + return 0; + }" CIO_HAVE_GETPAGESIZE) + +if(CIO_HAVE_GETPAGESIZE) + CIO_DEFINITION(CIO_HAVE_GETPAGESIZE) +endif() + +# fallocate(2) support +check_c_source_compiles(" + #include <fcntl.h> + int main() { + fallocate(0,0,0); + return 0; + }" CIO_HAVE_FALLOCATE) + +if(CIO_HAVE_FALLOCATE) + CIO_DEFINITION(CIO_HAVE_FALLOCATE) +endif() + +# posix_fallocate(2) support +check_c_source_compiles(" + #include <fcntl.h> + int main() { + posix_fallocate(0,0,0); + return 0; + }" CIO_HAVE_POSIX_FALLOCATE) + +if(CIO_HAVE_POSIX_FALLOCATE) + CIO_DEFINITION(CIO_HAVE_POSIX_FALLOCATE) +endif() + +configure_file( + "${PROJECT_SOURCE_DIR}/include/chunkio/cio_info.h.in" + "${PROJECT_BINARY_DIR}/include/chunkio/cio_info.h" + ) + +configure_file( + "${PROJECT_SOURCE_DIR}/include/chunkio/cio_version.h.in" + "${PROJECT_BINARY_DIR}/include/chunkio/cio_version.h" + ) + +include_directories( + include + deps/ + deps/monkey/include + ${PROJECT_BINARY_DIR}/include/ + ) + +add_subdirectory(deps/crc32) +add_subdirectory(src) +add_subdirectory(tools) + +# Tests +if(CIO_TESTS) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/src/fluent-bit/lib/chunkio/LICENSE b/src/fluent-bit/lib/chunkio/LICENSE new file mode 100644 index 000000000..f433b1a53 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/src/fluent-bit/lib/chunkio/README.md b/src/fluent-bit/lib/chunkio/README.md new file mode 100644 index 000000000..4512b38e8 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/README.md @@ -0,0 +1,157 @@ +# Chunk I/O + +Chunk I/O is a library to manage chunks of data in the file system and load in memory upon demand. It's designed to support: + +- Fixed path in the file system to organize data (root_path) +- Streams: categorize data into streams +- Multiple data files per stream +- Data file or chunks are composed by: + - Optional CRC32 content checksum. CRC32 is stored in network-byte-order (big-endian) + - Metadata (optional, up to 65535 bytes) + - User data + +## File System Structure + +The library uses a _root path_ to store the content, where different streams can be defined to store data files called chunks, e.g: + +``` +root_path/ +root_path/stream_1/ +root_path/stream_1/chunk1 +root_path/stream_1/chunk2 +root_path/stream_1/chunkN +root_path/stream_N +``` + +It's up to the caller program how to define the names, basically it needs to set streams and associate chunks to it: + +| concept | description | +| --------- | ------------------------------------------------------------ | +| root_path | storage area, file system directory that exists or can be created | +| stream | directory or parent group of chunks of files. The stream name is customizable, it can be anything allowed by the file system. | +| chunk | regular file that contains the data. | + +Creating a file system structure like the proposed one requires several checks and usage of I/O interfaces, Chunk I/O aims to abstract the internals of I/O interfaces providing helpers that behind the scenes relies on mmap(2), msync(2), munmap(2) and ftruncate(2). + +### File Layout + +Each chunk file created by the library have the following layout: + +``` ++--------------+----------------+ +| 0xC1 | 0x00 +--> Header 2 bytes ++--------------+----------------+ +| 4 BYTES CRC32 + 16 BYTES +--> CRC32(Content) + Padding ++-------------------------------+ +| Content | +| +-------------------------+ | +| | 2 BYTES +-----> Metadata Length +| +-------------------------+ | +| +-------------------------+ | +| | | | +| | Metadata +-----> Optional Metadata (up to 65535 bytes) +| | | | +| +-------------------------+ | +| +-------------------------+ | +| | | | +| | Content Data +-----> User Data +| | | | +| +-------------------------+ | ++-------------------------------+ +``` + +## cio - client tool + +This repository provides a client tool called _cio_ for testing and managing purposes. a quick start for testing could be to stream a file over STDIN and flush it under a specific stream and chunk name, e.g: + +```bash +$ cat somefile | tools/cio -i -s stdin -f somefile -vvv +``` + +the command above specify to gather data from the standard input (_-i_), use a stream called _stdin_ (_-s stdin_) and store the data into the chunk called _data_ (_-f data_) and enabling some verbose messages (_-vvv_) + +```bash +[chunkio] created root path /home/edsiper/.cio => src/chunkio.c:48 +[chunkio] [cio scan] opening path /home/edsiper/.cio => src/cio_scan.c:100 +[ cli ] root_path => /home/edsiper/.cio => tools/cio.c:340 +[chunkio] created stream path /home/edsiper/.cio/stdin => src/cio_stream.c:62 +[chunkio] [cio stream] new stream registered: stdin => src/cio_stream.c:117 +[chunkio] stdin:somefile mapped OK => src/cio_file.c:357 +[chunkio] [cio file] synced at: stdin/somefile => src/cio_file.c:508 +[ cli ] stdin total bytes => 153 (153b) => tools/cio.c:248 +``` + +now that the chunk file has been generated you can list the content with the _-l_ option: + +```bash +$ tools/cio -l + stream:stdin 1 chunks + stdin/somefile alloc_size=4096, data_size=4072, crc=6dd73d2e +``` + +### Performance Test + +The _cli_ tool offers a simple performance test which can be used to measure how fast data can be processed and stored under different setups. The following options are available: + +| option | value | description | default | +| ------ | ------------------------------------------------------ | ------------------------------------------------------------ | ------- | +| -p | path to a file that will be used to perform I/O tests. | Enable performance mode setting up a file that will be used for the test. | | +| -e | integer value | Set number of files to create. | 1000 | +| -w | integer value | For each file being created, this option set the number of times the content will be written to each file. | 5 | + +The following example will take the data sample file provided in chunkio source code of 400KB, run the performance test creating 1000 files of 2MB each (5 writes of 400KB per file): + +``` +$ tools/cio -p ../tests/data/400kb.txt +=== perf write === +- crc32 checksum : disabled +- fs sync mode : normal +- file size : 400.0K (409600 bytes) +- total files : 1000 +- file writes : 5 +- bytes written : 1.9G (2048000000 bytes) +- elapsed time : 1.46 seconds +- rate : 1.3G per second (1398600425.33 bytes) +``` + +Enabling the checksum mode with the option __-k__ will calculate the CRC32 checksum of the content. This option will make it run slower but it provides an integrity check option inside each created file: + +``` +$ tools/cio -k -p ../tests/data/400kb.txt +=== perf write === +- crc32 checksum : enabled +- fs sync mode : normal +- file size : 400.0K (409600 bytes) +- total files : 1000 +- file writes : 5 +- bytes written : 1.9G (2048000000 bytes) +- elapsed time : 3.75 seconds +- rate : 520.2M per second (545507660.63 bytes) +``` + +By default the synchronization mode to flush the changes to the file system is __normal__ (based on MAP_ASYNC). In technical terms we let the Kernel decide when to flush the memory pages to disk based on it I/O strategy. If the program is killed or it crash while some pages have not been flushed, that file will be incomplete or corrupted. Depending of the use case, a user would prefer data safety over performance, for such scenario a synchronization mode called __full__ (based on MAP_SYNC) is available through the __-F__ option: + +``` +$ tools/cio -F -k -p ../tests/data/400kb.txt +=== perf write === +- crc32 checksum : enabled +- fs sync mode : full +- file size : 400.0K (409600 bytes) +- total files : 1000 +- file writes : 5 +- bytes written : 1.9G (2048000000 bytes) +- elapsed time : 24.40 seconds +- rate : 80.1M per second (83950015.02 bytes) +``` + +For most of scenarios running synchronization in __normal__ mode is good enough, but we let the user to decide it own strategy. + +## TODO + +- [ ] Document C API: dev is still in progress, so constant changes are expected +- [ ] Restricted memory mapping: load in memory up to a limit, not all the content of a root_path +- [ ] Export metrics + +## License + +Chunk I/O is under the terms of [Apache License v2.0](LICENSE) diff --git a/src/fluent-bit/lib/chunkio/cmake/macros.cmake b/src/fluent-bit/lib/chunkio/cmake/macros.cmake new file mode 100644 index 000000000..cbc5d6ae4 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/macros.cmake @@ -0,0 +1,6 @@ +# Macro to set definitions +macro(CIO_DEFINITION var) + add_definitions(-D${var}) + set(CIO_BUILD_FLAGS "${CIO_BUILD_FLAGS}#ifndef ${var}\n#define ${var}\n#endif\n") + set(CIO_INFO_FLAGS "${CIO_INFO_FLAGS} ${var}") +endmacro() diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/.gitignore b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/.gitignore new file mode 100644 index 000000000..c4a70a619 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/.gitignore @@ -0,0 +1,3 @@ +# out-of-source build top-level folders. +build/ +_build/ diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/CMakeLists.txt b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/CMakeLists.txt new file mode 100644 index 000000000..a19285255 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/CMakeLists.txt @@ -0,0 +1,51 @@ +# This file is part of CMake-sanitizers. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# +# Copyright (c) +# 2013-2015 Matt Arsenault +# 2015 RWTH Aachen University, Federal Republic of Germany +# + + +# +# project information +# + +# minimum required cmake version +cmake_minimum_required(VERSION 2.8.12) + +# project name +project("CMake-sanitizers") + + + +# +# cmake configuration +# +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) + + + +# +# add tests +# +enable_testing() +add_subdirectory(tests) diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/LICENSE b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/LICENSE new file mode 100644 index 000000000..2520efdc0 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) + 2013 Matthew Arsenault + 2015-2016 RWTH Aachen University, Federal Republic of Germany + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/README.md b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/README.md new file mode 100644 index 000000000..b4ca621c3 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/README.md @@ -0,0 +1,73 @@ +# sanitizers-cmake + + [![](https://img.shields.io/github/issues-raw/arsenm/sanitizers-cmake.svg?style=flat-square)](https://github.com/arsenm/sanitizers-cmake/issues) +[![MIT](http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) + +CMake module to enable sanitizers for binary targets. + + +## Include into your project + +To use [FindSanitizers.cmake](cmake/FindSanitizers.cmake), simply add this repository as git submodule into your own repository +```Shell +mkdir externals +git submodule add git@github.com:arsenm/sanitizers-cmake.git externals/sanitizers-cmake +``` +and adding ```externals/sanitizers-cmake/cmake``` to your ```CMAKE_MODULE_PATH``` +```CMake +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH}) +``` + +If you don't use git or dislike submodules you can copy the files in [cmake directory](cmake) into your repository. *Be careful and keep updates in mind!* + +Now you can simply run ```find_package``` in your CMake files: +```CMake +find_package(Sanitizers) +``` + + +## Usage + +You can enable the sanitizers with ``SANITIZE_ADDRESS``, ``SANITIZE_MEMORY``, ``SANITIZE_THREAD`` or ``SANITIZE_UNDEFINED`` options in your CMake configuration. You can do this by passing e.g. ``-DSANITIZE_ADDRESS=On`` on your command line or with your graphical interface. + +If sanitizers are supported by your compiler, the specified targets will be build with sanitizer support. If your compiler has no sanitizing capabilities (I asume intel compiler doesn't) you'll get a warning but CMake will continue processing and sanitizing will simply just be ignored. + +#### Compiler issues + +Different compilers may be using different implementations for sanitizers. If you'll try to sanitize targets with C and Fortran code but don't use gcc & gfortran but clang & gfortran, this will cause linking problems. To avoid this, such problems will be detected and sanitizing will be disabled for these targets. + +Even C only targets may cause problems in certain situations. Some problems have been seen with AddressSanitizer for preloading or dynamic linking. In such cases you may try the ``SANITIZE_LINK_STATIC`` to link sanitizers for gcc static. + + + +## Build targets with sanitizer support + +To enable sanitizer support you simply have to add ``add_sanitizers(<TARGET>)`` after defining your target. To provide a sanitizer blacklist file you can use the ``sanitizer_add_blacklist_file(<FILE>)`` function: +```CMake +find_package(Sanitizers) + +sanitizer_add_blacklist_file("blacklist.txt") + +add_executable(some_exe foo.c bar.c) +add_sanitizers(some_exe) + +add_library(some_lib foo.c bar.c) +add_sanitizers(some_lib) +``` + +## Run your application + +The sanitizers check your program, while it's running. In some situations (e.g. LD_PRELOAD your target) it might be required to preload the used AddressSanitizer library first. In this case you may use the ``asan-wrapper`` script defined in ``ASan_WRAPPER`` variable to execute your application with ``${ASan_WRAPPER} myexe arg1 ...``. + + +## Contribute + +Anyone is welcome to contribute. Simply fork this repository, make your changes **in an own branch** and create a pull-request for your change. Please do only one change per pull-request. + +You found a bug? Please fill out an [issue](https://github.com/arsenm/sanitizers-cmake/issues) and include any data to reproduce the bug. + + +#### Contributors + +* [Matt Arsenault](https://github.com/arsenm) +* [Alexander Haase](https://github.com/alehaa) diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindASan.cmake b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindASan.cmake new file mode 100644 index 000000000..4548e46a8 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindASan.cmake @@ -0,0 +1,62 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES + # MSVC uses + "/fsanitize=address" + + # Clang 3.2+ use this version. The no-omit-frame-pointer option is optional. + "-g -fsanitize=address -fno-omit-frame-pointer" + "-g -fsanitize=address" + + # Older deprecated flag for ASan + "-g -faddress-sanitizer" +) + + +if (SANITIZE_ADDRESS AND (SANITIZE_THREAD OR SANITIZE_MEMORY)) + message(FATAL_ERROR "AddressSanitizer is not compatible with " + "ThreadSanitizer or MemorySanitizer.") +endif () + + +include(sanitize-helpers) + +if (SANITIZE_ADDRESS) + sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "AddressSanitizer" + "ASan") + + find_program(ASan_WRAPPER "asan-wrapper" PATHS ${CMAKE_MODULE_PATH}) + mark_as_advanced(ASan_WRAPPER) +endif () + +function (add_sanitize_address TARGET) + if (NOT SANITIZE_ADDRESS) + return() + endif () + + sanitizer_add_flags(${TARGET} "AddressSanitizer" "ASan") +endfunction () diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindMSan.cmake b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindMSan.cmake new file mode 100644 index 000000000..d744c34be --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindMSan.cmake @@ -0,0 +1,60 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES + # MSVC uses + "/fsanitize=memory" + # GNU/Clang + "-g -fsanitize=memory" +) + + +include(sanitize-helpers) + +if (SANITIZE_MEMORY) + if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + message(WARNING "MemorySanitizer disabled for target ${TARGET} because " + "MemorySanitizer is supported for Linux systems only.") + set(SANITIZE_MEMORY Off CACHE BOOL + "Enable MemorySanitizer for sanitized targets." FORCE) + elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8) + message(WARNING "MemorySanitizer disabled for target ${TARGET} because " + "MemorySanitizer is supported for 64bit systems only.") + set(SANITIZE_MEMORY Off CACHE BOOL + "Enable MemorySanitizer for sanitized targets." FORCE) + else () + sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer" + "MSan") + endif () +endif () + +function (add_sanitize_memory TARGET) + if (NOT SANITIZE_MEMORY) + return() + endif () + + sanitizer_add_flags(${TARGET} "MemorySanitizer" "MSan") +endfunction () diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindSanitizers.cmake b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindSanitizers.cmake new file mode 100755 index 000000000..d9b438c0f --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindSanitizers.cmake @@ -0,0 +1,91 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# If any of the used compiler is a GNU compiler, add a second option to static +# link against the sanitizers. +option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off) + +# Highlight this module has been loaded. +set(Sanitizers_FOUND TRUE) + +set(FIND_QUIETLY_FLAG "") +if (DEFINED Sanitizers_FIND_QUIETLY) + set(FIND_QUIETLY_FLAG "QUIET") +endif () + +find_package(ASan ${FIND_QUIETLY_FLAG}) +find_package(TSan ${FIND_QUIETLY_FLAG}) +find_package(MSan ${FIND_QUIETLY_FLAG}) +find_package(UBSan ${FIND_QUIETLY_FLAG}) + +function(sanitizer_add_blacklist_file FILE) + if(NOT IS_ABSOLUTE ${FILE}) + set(FILE "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}") + endif() + get_filename_component(FILE "${FILE}" REALPATH) + + sanitizer_check_compiler_flags("-fsanitize-blacklist=${FILE}" + "SanitizerBlacklist" "SanBlist") +endfunction() + +function(add_sanitizers) + # If no sanitizer is enabled, return immediately. + if (NOT (SANITIZE_ADDRESS OR SANITIZE_MEMORY OR SANITIZE_THREAD OR + SANITIZE_UNDEFINED)) + return() + endif () + + foreach (TARGET ${ARGV}) + # Check if this target will be compiled by exactly one compiler. Other- + # wise sanitizers can't be used and a warning should be printed once. + get_target_property(TARGET_TYPE ${TARGET} TYPE) + if (TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") + message(WARNING "Can't use any sanitizers for target ${TARGET}, " + "because it is an interface library and cannot be " + "compiled directly.") + return() + endif () + sanitizer_target_compilers(${TARGET} TARGET_COMPILER) + list(LENGTH TARGET_COMPILER NUM_COMPILERS) + if (NUM_COMPILERS GREATER 1) + message(WARNING "Can't use any sanitizers for target ${TARGET}, " + "because it will be compiled by incompatible compilers. " + "Target will be compiled without sanitizers.") + return() + + elseif (NUM_COMPILERS EQUAL 0) + # If the target is compiled by no known compiler, give a warning. + message(WARNING "Sanitizers for target ${TARGET} may not be" + " usable, because it uses no or an unknown compiler. " + "This is a false warning for targets using only " + "object lib(s) as input.") + endif () + + # Add sanitizers for target. + add_sanitize_address(${TARGET}) + add_sanitize_thread(${TARGET}) + add_sanitize_memory(${TARGET}) + add_sanitize_undefined(${TARGET}) + endforeach () +endfunction(add_sanitizers) diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindTSan.cmake b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindTSan.cmake new file mode 100644 index 000000000..efb2e9525 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindTSan.cmake @@ -0,0 +1,68 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES + # MSVC uses + "/fsanitize=thread" + # GNU/Clang + "-g -fsanitize=thread" +) + + +# ThreadSanitizer is not compatible with MemorySanitizer. +if (SANITIZE_THREAD AND SANITIZE_MEMORY) + message(FATAL_ERROR "ThreadSanitizer is not compatible with " + "MemorySanitizer.") +endif () + + +include(sanitize-helpers) + +if (SANITIZE_THREAD) + if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND + NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + message(WARNING "ThreadSanitizer disabled for target ${TARGET} because " + "ThreadSanitizer is supported for Linux systems and macOS only.") + set(SANITIZE_THREAD Off CACHE BOOL + "Enable ThreadSanitizer for sanitized targets." FORCE) + elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8) + message(WARNING "ThreadSanitizer disabled for target ${TARGET} because " + "ThreadSanitizer is supported for 64bit systems only.") + set(SANITIZE_THREAD Off CACHE BOOL + "Enable ThreadSanitizer for sanitized targets." FORCE) + else () + sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer" + "TSan") + endif () +endif () + +function (add_sanitize_thread TARGET) + if (NOT SANITIZE_THREAD) + return() + endif () + + sanitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan") +endfunction () diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindUBSan.cmake b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindUBSan.cmake new file mode 100644 index 000000000..4354c2e4d --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/FindUBSan.cmake @@ -0,0 +1,49 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_UNDEFINED + "Enable UndefinedBehaviorSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES + # MSVC uses + "/fsanitize=undefined" + # GNU/Clang + "-g -fsanitize=undefined" +) + + +include(sanitize-helpers) + +if (SANITIZE_UNDEFINED) + sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" + "UndefinedBehaviorSanitizer" "UBSan") +endif () + +function (add_sanitize_undefined TARGET) + if (NOT SANITIZE_UNDEFINED) + return() + endif () + + sanitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan") +endfunction () diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/asan-wrapper b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/asan-wrapper new file mode 100755 index 000000000..5d5410337 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/asan-wrapper @@ -0,0 +1,55 @@ +#!/bin/sh + +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# This script is a wrapper for AddressSanitizer. In some special cases you need +# to preload AddressSanitizer to avoid error messages - e.g. if you're +# preloading another library to your application. At the moment this script will +# only do something, if we're running on a Linux platform. OSX might not be +# affected. + + +# Exit immediately, if platform is not Linux. +if [ "$(uname)" != "Linux" ] +then + exec $@ +fi + + +# Get the used libasan of the application ($1). If a libasan was found, it will +# be prepended to LD_PRELOAD. +libasan=$(ldd $1 | grep libasan | sed "s/^[[:space:]]//" | cut -d' ' -f1) +if [ -n "$libasan" ] +then + if [ -n "$LD_PRELOAD" ] + then + export LD_PRELOAD="$libasan:$LD_PRELOAD" + else + export LD_PRELOAD="$libasan" + fi +fi + +# Execute the application. +exec $@ diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/sanitize-helpers.cmake b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/sanitize-helpers.cmake new file mode 100755 index 000000000..efc325ce3 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/cmake/sanitize-helpers.cmake @@ -0,0 +1,178 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Helper function to get the language of a source file. +function (sanitizer_lang_of_source FILE RETURN_VAR) + get_filename_component(LONGEST_EXT "${FILE}" EXT) + # If extension is empty return. This can happen for extensionless headers + if("${LONGEST_EXT}" STREQUAL "") + set(${RETURN_VAR} "" PARENT_SCOPE) + return() + endif() + # Get shortest extension as some files can have dot in their names + string(REGEX REPLACE "^.*(\\.[^.]+)$" "\\1" FILE_EXT ${LONGEST_EXT}) + string(TOLOWER "${FILE_EXT}" FILE_EXT) + string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT) + + get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + foreach (LANG ${ENABLED_LANGUAGES}) + list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP) + if (NOT ${TEMP} EQUAL -1) + set(${RETURN_VAR} "${LANG}" PARENT_SCOPE) + return() + endif () + endforeach() + + set(${RETURN_VAR} "" PARENT_SCOPE) +endfunction () + + +# Helper function to get compilers used by a target. +function (sanitizer_target_compilers TARGET RETURN_VAR) + # Check if all sources for target use the same compiler. If a target uses + # e.g. C and Fortran mixed and uses different compilers (e.g. clang and + # gfortran) this can trigger huge problems, because different compilers may + # use different implementations for sanitizers. + set(BUFFER "") + get_target_property(TSOURCES ${TARGET} SOURCES) + foreach (FILE ${TSOURCES}) + # If expression was found, FILE is a generator-expression for an object + # library. Object libraries will be ignored. + string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE}) + if ("${_file}" STREQUAL "") + sanitizer_lang_of_source(${FILE} LANG) + if (LANG) + list(APPEND BUFFER ${CMAKE_${LANG}_COMPILER_ID}) + endif () + endif () + endforeach () + + list(REMOVE_DUPLICATES BUFFER) + set(${RETURN_VAR} "${BUFFER}" PARENT_SCOPE) +endfunction () + + +# Helper function to check compiler flags for language compiler. +function (sanitizer_check_compiler_flag FLAG LANG VARIABLE) + + if (${LANG} STREQUAL "C") + include(CheckCCompilerFlag) + check_c_compiler_flag("${FLAG}" ${VARIABLE}) + + elseif (${LANG} STREQUAL "CXX") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("${FLAG}" ${VARIABLE}) + + elseif (${LANG} STREQUAL "Fortran") + # CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible + # with older Cmake versions, we will check if this module is present + # before we use it. Otherwise we will define Fortran coverage support as + # not available. + include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED) + if (INCLUDED) + check_fortran_compiler_flag("${FLAG}" ${VARIABLE}) + elseif (NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VARIABLE}") + message(STATUS "Performing Test ${VARIABLE}" + " - Failed (Check not supported)") + endif () + endif() + +endfunction () + + +# Helper function to test compiler flags. +function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX) + set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY}) + + get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + foreach (LANG ${ENABLED_LANGUAGES}) + # Sanitizer flags are not dependend on language, but the used compiler. + # So instead of searching flags foreach language, search flags foreach + # compiler used. + set(COMPILER ${CMAKE_${LANG}_COMPILER_ID}) + if (COMPILER AND NOT DEFINED ${PREFIX}_${COMPILER}_FLAGS) + foreach (FLAG ${FLAG_CANDIDATES}) + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Try ${COMPILER} ${NAME} flag = [${FLAG}]") + endif() + + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + unset(${PREFIX}_FLAG_DETECTED CACHE) + sanitizer_check_compiler_flag("${FLAG}" ${LANG} + ${PREFIX}_FLAG_DETECTED) + + if (${PREFIX}_FLAG_DETECTED) + # If compiler is a GNU compiler, search for static flag, if + # SANITIZE_LINK_STATIC is enabled. + if (SANITIZE_LINK_STATIC AND (${COMPILER} STREQUAL "GNU")) + string(TOLOWER ${PREFIX} PREFIX_lower) + sanitizer_check_compiler_flag( + "-static-lib${PREFIX_lower}" ${LANG} + ${PREFIX}_STATIC_FLAG_DETECTED) + + if (${PREFIX}_STATIC_FLAG_DETECTED) + set(FLAG "-static-lib${PREFIX_lower} ${FLAG}") + endif () + endif () + + set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}" CACHE STRING + "${NAME} flags for ${COMPILER} compiler.") + mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS) + break() + endif () + endforeach () + + if (NOT ${PREFIX}_FLAG_DETECTED) + set(${PREFIX}_${COMPILER}_FLAGS "" CACHE STRING + "${NAME} flags for ${COMPILER} compiler.") + mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS) + + message(WARNING "${NAME} is not available for ${COMPILER} " + "compiler. Targets using this compiler will be " + "compiled without ${NAME}.") + endif () + endif () + endforeach () +endfunction () + + +# Helper to assign sanitizer flags for TARGET. +function (sanitizer_add_flags TARGET NAME PREFIX) + # Get list of compilers used by target and check, if sanitizer is available + # for this target. Other compiler checks like check for conflicting + # compilers will be done in add_sanitizers function. + sanitizer_target_compilers(${TARGET} TARGET_COMPILER) + list(LENGTH TARGET_COMPILER NUM_COMPILERS) + if ("${${PREFIX}_${TARGET_COMPILER}_FLAGS}" STREQUAL "") + return() + endif() + + separate_arguments(flags_list UNIX_COMMAND "${${PREFIX}_${TARGET_COMPILER}_FLAGS} ${SanBlist_${TARGET_COMPILER}_FLAGS}") + target_compile_options(${TARGET} PUBLIC ${flags_list}) + + separate_arguments(flags_list UNIX_COMMAND "${${PREFIX}_${TARGET_COMPILER}_FLAGS}") + target_link_options(${TARGET} PUBLIC ${flags_list}) + +endfunction () diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/CMakeLists.txt b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/CMakeLists.txt new file mode 100644 index 000000000..8553e6326 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/CMakeLists.txt @@ -0,0 +1,67 @@ +# This file is part of CMake-sanitizers. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# +# Copyright (c) +# 2013-2015 Matt Arsenault +# 2015 RWTH Aachen University, Federal Republic of Germany +# + +# Function to add testcases. +function(add_testcase TESTNAME SOURCEFILES) + # remove ${TESTNAME} from ${ARGV} to use ${ARGV} as ${SOURCEFILES} + list(REMOVE_AT ARGV 0) + + # add a new executable + add_executable(${TESTNAME} ${ARGV}) + + # add a testcase for executable + add_test(${TESTNAME} ${TESTNAME}) +endfunction(add_testcase) + +# Function to add testcases with asan enabled. +function(add_sanitized_testcase TESTNAME SOURCEFILES) + add_testcase(${TESTNAME} ${SOURCEFILES}) + add_sanitizers(${TESTNAME}) +endfunction(add_sanitized_testcase) + + + +set(SANITIZE_ADDRESS TRUE) + +# +# search for sanitizers +# +find_package(Sanitizers) + + +# +# add testcases +# +add_sanitized_testcase("asan_test_cpp" asan_test.cpp) +add_sanitized_testcase("shortest_ext_test_cpp" shortest.ext.test.cpp) + +set_tests_properties( + "asan_test_cpp" + "shortest_ext_test_cpp" +PROPERTIES + WILL_FAIL TRUE +) + diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/asan_test.cpp b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/asan_test.cpp new file mode 100644 index 000000000..6c0a370c3 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/asan_test.cpp @@ -0,0 +1,40 @@ +/* This file is part of CMake-sanitizers. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Copyright (c) + * 2013-2015 Matt Arsenault + * 2015 RWTH Aachen University, Federal Republic of Germany + */ + + +int +main(int argc, char **argv) +{ + // Allocate a new array and delete it. + int *array = new int[argc + 1]; + array[argc] = 0; + delete[] array; + + /* Access element of the deleted array. This will cause an memory error with + * address sanitizer. + */ + return array[argc]; +} diff --git a/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/shortest.ext.test.cpp b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/shortest.ext.test.cpp new file mode 100644 index 000000000..6c0a370c3 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/cmake/sanitizers-cmake/tests/shortest.ext.test.cpp @@ -0,0 +1,40 @@ +/* This file is part of CMake-sanitizers. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Copyright (c) + * 2013-2015 Matt Arsenault + * 2015 RWTH Aachen University, Federal Republic of Germany + */ + + +int +main(int argc, char **argv) +{ + // Allocate a new array and delete it. + int *array = new int[argc + 1]; + array[argc] = 0; + delete[] array; + + /* Access element of the deleted array. This will cause an memory error with + * address sanitizer. + */ + return array[argc]; +} diff --git a/src/fluent-bit/lib/chunkio/deps/crc32/CMakeLists.txt b/src/fluent-bit/lib/chunkio/deps/crc32/CMakeLists.txt new file mode 100644 index 000000000..8ae182348 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/deps/crc32/CMakeLists.txt @@ -0,0 +1,5 @@ +set(src + crc32.c + ) + +add_library(cio-crc32 STATIC ${src}) diff --git a/src/fluent-bit/lib/chunkio/deps/crc32/crc32.c b/src/fluent-bit/lib/chunkio/deps/crc32/crc32.c new file mode 100644 index 000000000..58b39125c --- /dev/null +++ b/src/fluent-bit/lib/chunkio/deps/crc32/crc32.c @@ -0,0 +1,390 @@ +/** + * \file + * Functions and types for CRC checks. + * + * Generated on Wed Mar 18 12:41:20 2020 + * by pycrc v0.9.2, https://pycrc.org + * using the configuration: + * - Width = 32 + * - Poly = 0x04c11db7 + * - XorIn = 0xffffffff + * - ReflectIn = True + * - XorOut = 0xffffffff + * - ReflectOut = True + * - Algorithm = table-driven + * - SliceBy = 8 + */ +#include "crc32.h" /* include the header file generated with pycrc */ +#include <stdlib.h> +#include <stdint.h> + +/* Patch by Fluent Bit Authors */ +#ifdef __APPLE__ +# include <machine/endian.h> +# include <libkern/OSByteOrder.h> +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) +#elif defined(_WIN32) +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) +# define __BIG_ENDIAN 1 +# define __LITTLE_ENDIAN 2 +# define __BYTE_ORDER __LITTLE_ENDIAN +#elif defined(__FreeBSD__) +# include <sys/endian.h> +#elif defined(__sun) || defined(sun) +# include <sys/byteorder.h> +# if !defined(LITTLE_ENDIAN) +# define LITTLE_ENDIAN 4321 +# endif +# if !defined(BIG_ENDIAN) +# define BIG_ENDIAN 1234 +# endif +# if !defined(BYTE_ORDER) +# if defined(_BIG_ENDIAN) +# define BYTE_ORDER BIG_ENDIAN +# else +# define BYTE_ORDER LITTLE_ENDIAN +# endif +# endif +#else +# include <endian.h> +#endif + +/** + * Static table used for the table_driven implementation. + */ +static const crc_t crc_table[8][256] = { + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + }, + { + 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, + 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, + 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, + 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, + 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, + 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, + 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, + 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, + 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, + 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, + 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, + 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, + 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, + 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, + 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, + 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, + 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, + 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, + 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, + 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, + 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, + 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, + 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, + 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, + 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, + 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72 + }, + { + 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, + 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, + 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, + 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, + 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, + 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, + 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, + 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, + 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, + 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, + 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, + 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, + 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, + 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, + 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, + 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, + 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, + 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, + 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, + 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, + 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, + 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, + 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, + 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, + 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, + 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed + }, + { + 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, + 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, + 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, + 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, + 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, + 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, + 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, + 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, + 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, + 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, + 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, + 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, + 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, + 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, + 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, + 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, + 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, + 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, + 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, + 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, + 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, + 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, + 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, + 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, + 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, + 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1 + }, + { + 0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, + 0x30704bc1, 0x0d106271, 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, 0x825097d1, + 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, + 0x5090dc43, 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, 0xdfd029e3, 0xe2b00053, + 0xc1c12f04, 0xfca106b4, 0xbb017c64, 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, 0x3951ebb5, 0x7ef19165, 0x4391b8d5, + 0xa121b886, 0x9c419136, 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, 0x13016496, + 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, + 0x58f35849, 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, 0xd7b3ade9, 0xead38459, + 0x68831388, 0x55e33a38, 0x124340e8, 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, 0xf0f340bb, 0xb7533a6b, 0x8a3313db, + 0x0863840a, 0x3503adba, 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, 0xba43581a, + 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, + 0xa9423c8c, 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, 0x2602c92c, 0x1b62e09c, + 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, 0x0142247e, 0x46e25eae, 0x7b82771e, + 0xb1e6b092, 0x8c869922, 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, 0x03c66c82, + 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, + 0xd1062710, 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, 0x5e46d2b0, 0x6326fb00, + 0xe1766cd1, 0xdc164561, 0x9bb63fb1, 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, 0xb8c710e6, 0xff676a36, 0xc2074386, + 0x4057d457, 0x7d37fde7, 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, 0xf2770847, + 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, + 0x20b743d5, 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, 0xaff7b675, 0x92979fc5, + 0xe915e8db, 0xd475c16b, 0x93d5bbbb, 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, 0x11852c6a, 0x562556ba, 0x6b457f0a, + 0x89f57f59, 0xb49556e9, 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, 0x3bd5a349, + 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, + 0x28d4c7df, 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, 0xa794327f, 0x9af41bcf, + 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, + 0x78441b9c, 0x4524322c, 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, 0xca64c78c + }, + { + 0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, 0x50cd91b3, 0xd659e31d, 0x1d0530b8, + 0xec53826d, 0x270f51c8, 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, 0xf156b2d5, + 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, + 0xef8580f6, 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, 0x39dc63eb, 0xf280b04e, + 0x07ac0536, 0xccf0d693, 0x4a64a43d, 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, 0xbb3216e8, 0x3da66446, 0xf6fab7e3, + 0x047a07ad, 0xcf26d408, 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, 0x197f3715, + 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, + 0x0f580a6c, 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, 0xd901e971, 0x125d3ad4, + 0xe30b8801, 0x28575ba4, 0xaec3290a, 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, 0x5c439944, 0xdad7ebea, 0x118b384f, + 0xe0dd8a9a, 0x2b81593f, 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, 0xfdd8ba22, + 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, + 0xe4a78d37, 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, 0x32fe6e2a, 0xf9a2bd8f, + 0x0b220dc1, 0xc07ede64, 0x46eaacca, 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, + 0x1eb014d8, 0xd5ecc77d, 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, 0x03b52460, + 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, + 0x1d661643, 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, 0xcb3ff55e, 0x006326fb, + 0xf135942e, 0x3a69478b, 0xbcfd3525, 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, 0x49d1805d, 0xcf45f2f3, 0x04192156, + 0xf54f9383, 0x3e134026, 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, 0xe84aa33b, + 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, + 0xf6999118, 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, 0x20c07205, 0xeb9ca1a0, + 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, 0xad760d6a, 0x2be27fc4, 0xe0beac61, + 0x123e1c2f, 0xd962cf8a, 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, 0x0f3b2c97, + 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, + 0x16441b82, 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, 0xc01df89f, 0x0b412b3a, + 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, 0x455f88aa, 0xc3cbfa04, 0x089729a1, + 0xf9c19b74, 0x329d48d1, 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, 0xe4c4abcc + }, + { + 0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, 0x52382fa7, 0x63d0353a, 0xc5a73e8e, + 0x33ef4e67, 0x959845d3, 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, 0xf64870e9, + 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, + 0x5431d2a9, 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, 0x37e1e793, 0x9196ec27, + 0xcfbd399c, 0x69ca3228, 0x582228b5, 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, 0xae6a585c, 0x9f8242c1, 0x39f54975, + 0xa863a552, 0x0e14aee6, 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, 0x6dc49bdc, + 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, + 0x440b7579, 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, 0x27db4043, 0x81ac4bf7, + 0x77e43b1e, 0xd19330aa, 0xe07b2a37, 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, 0x71edc610, 0x4005dc8d, 0xe672d739, + 0x103aa7d0, 0xb64dac64, 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, 0xd59d995e, + 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, + 0xb8590282, 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, 0xdb8937b8, 0x7dfe3c0c, + 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, + 0x8816eaf2, 0x2e61e146, 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, 0x4db1d47c, + 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, + 0xefc8763c, 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, 0x8c184306, 0x2a6f48b2, + 0xdc27385b, 0x7a5033ef, 0x4bb82972, 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, 0x1593fcc9, 0x247be654, 0x820cede0, + 0x74449d09, 0xd23396bd, 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, 0xb1e3a387, + 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, + 0x139a01c7, 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, 0x704a34fd, 0xd63d3f49, + 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, + 0xabc30345, 0x0db408f1, 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, 0x6e643dcb, + 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, + 0x03a0a617, 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, 0x6070932d, 0xc6079899, + 0x304fe870, 0x9638e3c4, 0xa7d0f959, 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, 0x3646157e, 0x07ae0fe3, 0xa1d90457, + 0x579174be, 0xf1e67f0a, 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, 0x92364a30 + }, + { + 0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, 0x48e00e64, 0xc66f0987, 0x0ac50919, + 0xd3e51bb5, 0x1f4f1b2b, 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, 0xd92012ac, + 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, + 0xaf5e2a9e, 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, 0x69312319, 0xa59b2387, + 0xf9766256, 0x35dc62c8, 0xbb53652b, 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, 0x62737787, 0xecfc7064, 0x205670fa, + 0x85cd537d, 0x496753e3, 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, 0x8f085a64, + 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, + 0x299dc2ed, 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, 0xeff2cb6a, 0x2358cbf4, + 0xfa78d958, 0x36d2d9c6, 0xb85dde25, 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, + 0x86c3e873, 0x4a69e8ed, 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, 0x8c06e16a, + 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, + 0x030ebb0e, 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, 0xc561b289, 0x09cbb217, + 0xac509190, 0x60fa910e, 0xee7596ed, 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, 0x37558441, 0xb9da83a2, 0x7570833c, + 0x533b85da, 0x9f918544, 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, 0x59fe8cc3, + 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, + 0x2f80b4f1, 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, 0xe9efbd76, 0x2545bde8, + 0xfc65af44, 0x30cfafda, 0xbe40a839, 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, + 0x79a8fc39, 0xb502fca7, 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, 0x736df520, + 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, + 0x0513cd12, 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, 0xc37cc495, 0x0fd6c40b, + 0x7aa64737, 0xb60c47a9, 0x3883404a, 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, 0xe1a352e6, 0x6f2c5505, 0xa386559b, + 0x061d761c, 0xcab77682, 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, 0x0cd87f05, + 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, + 0x83d02561, 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, 0x45bf2ce6, 0x89152c78, + 0x50353ed4, 0x9c9f3e4a, 0x121039a9, 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, + 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, 0x264b06e6 + } +}; + + +crc_t crc_update(crc_t crc, const void *data, size_t data_len) +{ + const unsigned char *d = (const unsigned char *)data; + unsigned int tbl_idx; + + /* Align to a multiple of 8 bytes */ + while (data_len && (((uintptr_t)(const void *)d) % 8 != 0)) { + tbl_idx = (crc ^ *d) & 0xff; + crc = (crc_table[0][tbl_idx] ^ (crc >> 8)) & 0xffffffff; + d++; + data_len--; + } + + const uint32_t *d32 = (const uint32_t *)d; + while (data_len >= 8) + { +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN + crc_t d1 = *d32++ ^ le16toh(crc); + crc_t d2 = *d32++; + crc = + crc_table[0][d2 & 0xffu] ^ + crc_table[1][(d2 >> 8) & 0xffu] ^ + crc_table[2][(d2 >> 16) & 0xffu] ^ + crc_table[3][(d2 >> 24) & 0xffu] ^ + crc_table[4][d1 & 0xffu] ^ + crc_table[5][(d1 >> 8) & 0xffu] ^ + crc_table[6][(d1 >> 16) & 0xffu] ^ + crc_table[7][(d1 >> 24) & 0xffu]; +#else + crc_t d1 = *d32++ ^ crc; + crc_t d2 = *d32++; + crc = + crc_table[0][(d2 >> 24) & 0xffu] ^ + crc_table[1][(d2 >> 16) & 0xffu] ^ + crc_table[2][(d2 >> 8) & 0xffu] ^ + crc_table[3][d2 & 0xffu] ^ + crc_table[4][(d1 >> 24) & 0xffu] ^ + crc_table[5][(d1 >> 16) & 0xffu] ^ + crc_table[6][(d1 >> 8) & 0xffu] ^ + crc_table[7][d1 & 0xffu]; +#endif + + data_len -= 8; + } + + /* Remaining bytes with the standard algorithm */ + d = (const unsigned char *)d32; + while (data_len--) { + tbl_idx = (crc ^ *d) & 0xff; + crc = (crc_table[0][tbl_idx] ^ (crc >> 8)) & 0xffffffff; + d++; + } + return crc & 0xffffffff; +} diff --git a/src/fluent-bit/lib/chunkio/deps/crc32/crc32.h b/src/fluent-bit/lib/chunkio/deps/crc32/crc32.h new file mode 100644 index 000000000..c3ec3fa30 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/deps/crc32/crc32.h @@ -0,0 +1,107 @@ +/** + * \file + * Functions and types for CRC checks. + * + * Generated on Wed Mar 18 12:41:20 2020 + * by pycrc v0.9.2, https://pycrc.org + * using the configuration: + * - Width = 32 + * - Poly = 0x04c11db7 + * - XorIn = 0xffffffff + * - ReflectIn = True + * - XorOut = 0xffffffff + * - ReflectOut = True + * - Algorithm = table-driven + * - SliceBy = 8 + * + * This file defines the functions crc_init(), crc_update() and crc_finalize(). + * + * The crc_init() function returns the inital \c crc value and must be called + * before the first call to crc_update(). + * Similarly, the crc_finalize() function must be called after the last call + * to crc_update(), before the \c crc is being used. + * is being used. + * + * The crc_update() function can be called any number of times (including zero + * times) in between the crc_init() and crc_finalize() calls. + * + * This pseudo-code shows an example usage of the API: + * \code{.c} + * crc_t crc; + * unsigned char data[MAX_DATA_LEN]; + * size_t data_len; + * + * crc = crc_init(); + * while ((data_len = read_data(data, MAX_DATA_LEN)) > 0) { + * crc = crc_update(crc, data, data_len); + * } + * crc = crc_finalize(crc); + * \endcode + */ +#ifndef CRC32_H +#define CRC32_H + +#include <stdlib.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * The definition of the used algorithm. + * + * This is not used anywhere in the generated code, but it may be used by the + * application code to call algorithm-specific code, if desired. + */ +#define CRC_ALGO_TABLE_DRIVEN 1 + + +/** + * The type of the CRC values. + * + * This type must be big enough to contain at least 32 bits. + */ +typedef uint_fast32_t crc_t; + + +/** + * Calculate the initial crc value. + * + * \return The initial crc value. + */ +static inline crc_t crc_init(void) +{ + return 0xffffffff; +} + + +/** + * Update the crc value with new data. + * + * \param[in] crc The current crc value. + * \param[in] data Pointer to a buffer of \a data_len bytes. + * \param[in] data_len Number of bytes in the \a data buffer. + * \return The updated crc value. + */ +crc_t crc_update(crc_t crc, const void *data, size_t data_len); + + +/** + * Calculate the final crc value. + * + * \param[in] crc The current crc value. + * \return The final crc value. + */ +static inline crc_t crc_finalize(crc_t crc) +{ + return crc ^ 0xffffffff; +} + + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif + +#endif /* CRC32_H */ diff --git a/src/fluent-bit/lib/chunkio/deps/crc32/gen.sh b/src/fluent-bit/lib/chunkio/deps/crc32/gen.sh new file mode 100755 index 000000000..8fc39597a --- /dev/null +++ b/src/fluent-bit/lib/chunkio/deps/crc32/gen.sh @@ -0,0 +1,2 @@ +pycrc-0.9.2/pycrc.py --generate c --algorithm table-driven --model crc-32 --slice-by 8 -o crc32.c +pycrc-0.9.2/pycrc.py --generate h --algorithm table-driven --model crc-32 --slice-by 8 -o crc32.h diff --git a/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/external/wingetopt.h b/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/external/wingetopt.h new file mode 100644 index 000000000..29ea1002c --- /dev/null +++ b/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/external/wingetopt.h @@ -0,0 +1,282 @@ +/* This is a drop-in replacement of getopt library, based on the work of + * musl libc. This file is distributed under MIT License. + * + * ---- + * Copyright © 2005-2014 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _WINGETOPT_H +#define _WINGETOPT_H + +#define _GNU_SOURCE +#include <wchar.h> +#include <string.h> +#include <limits.h> +#include <stdlib.h> +#include <stdio.h> + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +static char *optarg; +static int optind=1, opterr=1, optopt, __optpos, __optreset=0; + +#define optpos __optpos +#define optreset __optreset +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +/* + * Implementation of getopt() + */ +static inline void __getopt_msg(const char *a, const char *b, const char *c, size_t l) +{ + FILE *f = stderr; + fputs(a, f); + fwrite(b, strlen(b), 1, f); + fwrite(c, 1, l, f); + putc('\n', f); +} + +static int getopt(int argc, char * const argv[], const char *optstring) +{ + int i; + wchar_t c, d; + int k, l; + char *optchar; + + if (!optind || __optreset) { + __optreset = 0; + __optpos = 0; + optind = 1; + } + + if (optind >= argc || !argv[optind]) + return -1; + + if (argv[optind][0] != '-') { + if (optstring[0] == '-') { + optarg = argv[optind++]; + return 1; + } + return -1; + } + + if (!argv[optind][1]) + return -1; + + if (argv[optind][1] == '-' && !argv[optind][2]) + return optind++, -1; + + if (!optpos) optpos++; + if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) { + k = 1; + c = 0xfffd; /* replacement char */ + } + optchar = argv[optind]+optpos; + optpos += k; + + if (!argv[optind][optpos]) { + optind++; + optpos = 0; + } + + if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + + i = 0; + d = 0; + do { + l = mbtowc(&d, optstring+i, MB_LEN_MAX); + if (l>0) i+=l; else i++; + } while (l && d != c); + + if (d != c || c == ':') { + optopt = c; + if (optstring[0] != ':' && opterr) + __getopt_msg(argv[0], ": unrecognized option: ", optchar, k); + return '?'; + } + if (optstring[i] == ':') { + optarg = 0; + if (optstring[i+1] != ':' || optpos) { + optarg = argv[optind++] + optpos; + optpos = 0; + } + if (optind > argc) { + optopt = c; + if (optstring[0] == ':') return ':'; + if (opterr) __getopt_msg(argv[0], + ": option requires an argument: ", + optchar, k); + return '?'; + } + } + return c; +} + +/* + * Implementation of getopt_long() and getopt_long_only() + */ +static inline void __getopt_permute(char *const *argv, int dest, int src) +{ + char **av = (char **)argv; + char *tmp = av[src]; + int i; + for (i=src; i>dest; i--) + av[i] = av[i-1]; + av[dest] = tmp; +} + +static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly); + +static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) +{ + int ret, skipped, resumed; + if (!optind || __optreset) { + __optreset = 0; + __optpos = 0; + optind = 1; + } + if (optind >= argc || !argv[optind]) return -1; + skipped = optind; + if (optstring[0] != '+' && optstring[0] != '-') { + int i; + for (i=optind; ; i++) { + if (i >= argc || !argv[i]) return -1; + if (argv[i][0] == '-' && argv[i][1]) break; + } + optind = i; + } + resumed = optind; + ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly); + if (resumed > skipped) { + int i, cnt = optind-resumed; + for (i=0; i<cnt; i++) + __getopt_permute(argv, skipped, optind-1); + optind = skipped + cnt; + } + return ret; +} + +static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) +{ + optarg = 0; + if (longopts && argv[optind][0] == '-' && + ((longonly && argv[optind][1] && argv[optind][1] != '-') || + (argv[optind][1] == '-' && argv[optind][2]))) + { + int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; + int i, cnt, match; + char *arg, *opt, *start = argv[optind]+1; + for (cnt=i=0; longopts[i].name; i++) { + const char *name = longopts[i].name; + opt = start; + if (*opt == '-') opt++; + while (*opt && *opt != '=' && *opt == *name) + name++, opt++; + if (*opt && *opt != '=') continue; + arg = opt; + match = i; + if (!*name) { + cnt = 1; + break; + } + cnt++; + } + if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) { + int l = arg-start; + for (i=0; optstring[i]; i++) { + int j; + for (j=0; j<l && start[j]==optstring[i+j]; j++); + if (j==l) { + cnt++; + break; + } + } + } + if (cnt==1) { + i = match; + opt = arg; + optind++; + if (*opt == '=') { + if (!longopts[i].has_arg) { + optopt = longopts[i].val; + if (colon || !opterr) + return '?'; + __getopt_msg(argv[0], + ": option does not take an argument: ", + longopts[i].name, + strlen(longopts[i].name)); + return '?'; + } + optarg = opt+1; + } else if (longopts[i].has_arg == required_argument) { + if (!(optarg = argv[optind])) { + optopt = longopts[i].val; + if (colon) return ':'; + if (!opterr) return '?'; + __getopt_msg(argv[0], + ": option requires an argument: ", + longopts[i].name, + strlen(longopts[i].name)); + return '?'; + } + optind++; + } + if (idx) *idx = i; + if (longopts[i].flag) { + *longopts[i].flag = longopts[i].val; + return 0; + } + return longopts[i].val; + } + if (argv[optind][1] == '-') { + optopt = 0; + if (!colon && opterr) + __getopt_msg(argv[0], cnt ? + ": option is ambiguous: " : + ": unrecognized option: ", + argv[optind]+2, + strlen(argv[optind]+2)); + optind++; + return '?'; + } + } + return getopt(argc, argv, optstring); +} + +static int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 0); +} + +static int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 1); +} +#endif diff --git a/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/mk_getopt.h b/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/mk_getopt.h new file mode 100644 index 000000000..70059ed22 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/mk_getopt.h @@ -0,0 +1,29 @@ +/*-*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MK_GETOPT_H +#define MK_GETOPT_H + +#ifdef __GNUC__ /* Heaven */ +#include <getopt.h> +#else /* Not Heaven */ +#include "external/wingetopt.h" +#endif + +#endif diff --git a/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/mk_list.h b/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/mk_list.h new file mode 100644 index 000000000..a83be12e7 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/deps/monkey/include/monkey/mk_core/mk_list.h @@ -0,0 +1,180 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * Copyright (C) 2010, Jonathan Gonzalez V. <zeus@gnu.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MK_LIST_H_ +#define MK_LIST_H_ + +#include <stddef.h> + +#ifdef _WIN32 +/* Windows */ +#define container_of(address, type, field) ((type *)( \ + (PCHAR)(address) - \ + (ULONG_PTR)(&((type *)0)->field))) +#else +/* Rest of the world */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +struct mk_list +{ + struct mk_list *prev, *next; +}; + +static inline void mk_list_init(struct mk_list *list) +{ + list->next = list; + list->prev = list; +} + +static inline void __mk_list_add(struct mk_list *_new, struct mk_list *prev, + struct mk_list *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +static inline void mk_list_add(struct mk_list *_new, struct mk_list *head) +{ + __mk_list_add(_new, head->prev, head); +} + +static inline void mk_list_add_after(struct mk_list *_new, + struct mk_list *prev, + struct mk_list *head) +{ + struct mk_list *next; + + if (head->prev == head->next || head->prev == prev) { + mk_list_add(_new, head); + return; + } + + next = prev->next; + next->prev = prev; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +static inline void __mk_list_del(struct mk_list *prev, struct mk_list *next) +{ + prev->next = next; + next->prev = prev; +} + +static inline void mk_list_del(struct mk_list *entry) +{ + __mk_list_del(entry->prev, entry->next); + entry->prev = NULL; + entry->next = NULL; +} + +static inline int mk_list_is_empty(struct mk_list *head) +{ + if (head->next == head) return 0; + else return -1; +} + +static inline int mk_list_is_set(struct mk_list *head) +{ + if (head->next && head->prev) { + return 0; + } + + return -1; +} + +static inline int mk_list_size(struct mk_list *head) +{ + int ret = 0; + struct mk_list *it; + for (it = head->next; it != head; it = it->next, ret++); + return ret; +} + +static inline int mk_list_entry_orphan(struct mk_list *head) +{ + if (head->next && head->prev) { + return 0; + } + + return -1; +} + +static inline void mk_list_cat(struct mk_list *list, struct mk_list *head) +{ + struct mk_list *last; + + last = head->prev; + last->next = list->next; + list->next->prev = last; + list->prev->next = head; + head->prev = list->prev; +} + +#define mk_list_foreach(curr, head) for( curr = (head)->next; curr != (head); curr = curr->next ) +#define mk_list_foreach_safe(curr, n, head) \ + for (curr = (head)->next, n = curr->next; curr != (head); curr = n, n = curr->next) + + +#define mk_list_foreach_r(curr, head) for( curr = (head)->prev; curr != (head); curr = curr->prev ) +#define mk_list_foreach_safe_r(curr, n, head) \ + for (curr = (head)->prev, n = curr->prev; curr != (head); curr = n, n = curr->prev) + +#define mk_list_entry( ptr, type, member ) container_of( ptr, type, member ) + +/* + * First node of the list + * ---------------------- + * Be careful with this Macro, its intended to be used when some node is already linked + * to the list (ptr). If the list is empty it will return the list address as it points + * to it self: list == list->prev == list->next. + * + * If exists some possiblity that your code handle an empty list, use mk_list_is_empty() + * previously to check if its empty or not. + */ +#define mk_list_entry_first(ptr, type, member) container_of((ptr)->next, type, member) + +/* First node of the list + * --------------------- + * Be careful with this Macro, its intended to be used when some node is already linked + * to the list (ptr). If the list is empty it will return the list address as it points + * to it self: list == list->prev == list->next. + * + * If exists some possiblity that your code handle an empty list, use mk_list_is_empty() + * previously to check if its empty or not. + */ +#define mk_list_entry_last(ptr, type, member) container_of((ptr)->prev, type, member) + +/* Next node */ +#define mk_list_entry_next(ptr, type, member, head) \ + (ptr)->next == (head) ? container_of((head)->next, type, member) : \ + container_of((ptr)->next, type, member); + +#endif /* !MK_LIST_H_ */ diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/chunkio.h b/src/fluent-bit/lib/chunkio/include/chunkio/chunkio.h new file mode 100644 index 000000000..c60ddacce --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/chunkio.h @@ -0,0 +1,143 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CHUNKIO_H +#define CHUNKIO_H + +#include <chunkio/cio_info.h> +#include <monkey/mk_core/mk_list.h> + +#define CIO_FALSE 0 +#define CIO_TRUE !0 + +/* debug levels */ +#define CIO_LOG_ERROR 1 +#define CIO_LOG_WARN 2 +#define CIO_LOG_INFO 3 +#define CIO_LOG_DEBUG 4 +#define CIO_LOG_TRACE 5 + +/* Storage backend */ +#define CIO_STORE_FS 0 +#define CIO_STORE_MEM 1 + +/* flags */ +#define CIO_OPEN 1 /* open/create file reference */ +#define CIO_OPEN_RW CIO_OPEN /* new name for read/write mode */ +#define CIO_OPEN_RD 2 /* open and read/mmap content if exists */ +#define CIO_CHECKSUM 4 /* enable checksum verification (crc32) */ +#define CIO_FULL_SYNC 8 /* force sync to fs through MAP_SYNC */ +#define CIO_DELETE_IRRECOVERABLE 16 /* delete irrecoverable chunks from disk */ +#define CIO_TRIM_FILES 32 /* trim files to their required size */ + +/* Return status */ +#define CIO_CORRUPTED -3 /* Indicate that a chunk is corrupted */ +#define CIO_RETRY -2 /* The operations needs to be retried */ +#define CIO_ERROR -1 /* Generic error */ +#define CIO_OK 0 /* OK */ + +/* Configuration limits */ +/* The file minimum growth factor is 8 memory pages and + * the file maximum growth factor is 8 megabytes + */ +#define CIO_REALLOC_HINT_MIN (cio_getpagesize() * 8) +#define CIO_REALLOC_HINT_MAX (8 * 1000 * 1000) + +/* defaults */ +#define CIO_MAX_CHUNKS_UP 64 /* default limit for cio_ctx->max_chunks_up */ +#define CIO_DISABLE_REALLOC_HINT -1 /* default value of size of realloc hint */ +#define CIO_DEFAULT_REALLOC_HINT CIO_REALLOC_HINT_MIN +#define CIO_INITIALIZED 1337 + +struct cio_ctx; + +struct cio_options { + /* this bool flag sets if the options has been initialized, that's a mandatory step */ + int initialized; + + int flags; + char *root_path; + + /* logging */ + int log_level; + int (*log_cb)(struct cio_ctx *, int, const char *, int, char *); + + char *user; + char *group; + char *chmod; + + /* chunk handlings */ + int realloc_size_hint; +}; + +struct cio_ctx { + int page_size; + int realloc_size_hint; + struct cio_options options; + + void *processed_user; + void *processed_group; + + /* + * Internal counters + */ + size_t total_chunks; /* Total number of registered chunks */ + size_t total_chunks_up; /* Total number of chunks 'up' in memory */ + + /* + * maximum open 'file' chunks: this limit helps where there are many + * chunks in the filesystem and you don't need all of them up in + * memory. For short, it restrict the open number of files and + * the amount of memory mapped. + */ + size_t max_chunks_up; + + /* streams */ + struct mk_list streams; + + /* errors */ + int last_chunk_error; /* this field is necessary to discard irrecoverable + * chunks in cio_scan_stream_files, it's not the + * best approach but the only at the moment. + */ +}; + +#include <chunkio/cio_stream.h> +#include <chunkio/cio_chunk.h> + +void cio_options_init(struct cio_options *options); +struct cio_ctx *cio_create(struct cio_options *options); +void cio_destroy(struct cio_ctx *ctx); +int cio_load(struct cio_ctx *ctx, char *chunk_extension); +int cio_qsort(struct cio_ctx *ctx, int (*compar)(const void *, const void *)); + +void cio_set_log_callback(struct cio_ctx *ctx, void (*log_cb)); +int cio_set_log_level(struct cio_ctx *ctx, int level); +int cio_set_max_chunks_up(struct cio_ctx *ctx, int n); +int cio_set_realloc_size_hint(struct cio_ctx *ctx, size_t realloc_size_hint); + +void cio_enable_file_trimming(struct cio_ctx *ctx); +void cio_disable_file_trimming(struct cio_ctx *ctx); + +int cio_meta_write(struct cio_chunk *ch, char *buf, size_t size); +int cio_meta_cmp(struct cio_chunk *ch, char *meta_buf, int meta_len); +int cio_meta_read(struct cio_chunk *ch, char **meta_buf, int *meta_len); +int cio_meta_size(struct cio_chunk *ch); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/chunkio_compat.h b/src/fluent-bit/lib/chunkio/include/chunkio/chunkio_compat.h new file mode 100644 index 000000000..3e4951b98 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/chunkio_compat.h @@ -0,0 +1,93 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CHUNKIO_COMPAT_H +#define CHUNKIO_COMPAT_H + +#include <chunkio/cio_info.h> + +#ifdef _WIN32 +#include <sys/types.h> +#include <sys/stat.h> +#include <winsock2.h> +#include <windows.h> +#include <aclapi.h> +#include <io.h> +#include <direct.h> +#pragma comment(lib, "ws2_32.lib") + +/** mode flags for access() */ +#define R_OK 04 +#define W_OK 02 +#define X_OK 01 +#define F_OK 00 + +#define PATH_MAX MAX_PATH +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define strerror_r(errno,buf,len) strerror_s(buf,len,errno) + +typedef SSIZE_T ssize_t; +typedef unsigned mode_t; + +static inline char* dirname(const char *path) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + static char buf[_MAX_PATH]; + + _splitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, + fname, _MAX_FNAME, ext, _MAX_EXT); + + _makepath_s(buf, _MAX_PATH, drive, dir, "", ""); + + /* + * If path does not contain a separator, dirname() must + * return the string ".". + */ + if (strlen(buf) == 0) { + strcpy_s(buf, _MAX_PATH, "."); + } + + return buf; +} + +#ifndef CIO_HAVE_GETPAGESIZE +static inline int cio_getpagesize(void) +{ + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + return system_info.dwPageSize; +} +#else +static inline int cio_getpagesize(void) +{ + return getpagesize(); +} +#endif + +#else +#include <unistd.h> +#include <libgen.h> +#include <dirent.h> +#include <arpa/inet.h> +#endif + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_chunk.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_chunk.h new file mode 100644 index 000000000..369401bf8 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_chunk.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_CHUNK_H +#define CIO_CHUNK_H + +#include <sys/types.h> +#include <inttypes.h> + +#include <chunkio/chunkio_compat.h> + +struct cio_chunk { + int lock; /* locked for write operations ? */ + char *name; /* chunk name */ + void *backend; /* backend context (cio_file, cio_memfs) */ + + /* Transaction helpers */ + int tx_active; /* active transaction ? */ + uint32_t tx_crc; /* CRC32 upon transaction begin */ + off_t tx_content_length; /* content length */ + + struct cio_ctx *ctx; /* library context */ + struct cio_stream *st; /* stream context */ + + /* error handling */ + int error_n; + + /* + * The state head links to the stream->chunks_up or stream->chunks_down + * linked list. + */ + struct mk_list _state_head; + + struct mk_list _head; /* head link to stream->files */ +}; + +struct cio_chunk *cio_chunk_open(struct cio_ctx *ctx, struct cio_stream *st, + const char *name, int flags, size_t size, + int *err); +void cio_chunk_close(struct cio_chunk *ch, int delete); +int cio_chunk_delete(struct cio_ctx *ctx, struct cio_stream *st, const char *name); +int cio_chunk_write(struct cio_chunk *ch, const void *buf, size_t count); +int cio_chunk_write_at(struct cio_chunk *ch, off_t offset, + const void *buf, size_t count); +int cio_chunk_sync(struct cio_chunk *ch); +int cio_chunk_get_content(struct cio_chunk *ch, char **buf, size_t *size); +int cio_chunk_get_content_copy(struct cio_chunk *ch, + void **out_buf, size_t *out_size); + +ssize_t cio_chunk_get_content_size(struct cio_chunk *ch); +ssize_t cio_chunk_get_real_size(struct cio_chunk *ch); +size_t cio_chunk_get_content_end_pos(struct cio_chunk *ch); +void cio_chunk_close_stream(struct cio_stream *st); +char *cio_chunk_hash(struct cio_chunk *ch); +int cio_chunk_lock(struct cio_chunk *ch); +int cio_chunk_unlock(struct cio_chunk *ch); +int cio_chunk_is_locked(struct cio_chunk *ch); + +/* transaction handling */ +int cio_chunk_tx_begin(struct cio_chunk *ch); +int cio_chunk_tx_commit(struct cio_chunk *ch); +int cio_chunk_tx_rollback(struct cio_chunk *ch); + +/* Chunk content up/down */ +int cio_chunk_is_up(struct cio_chunk *ch); +int cio_chunk_is_file(struct cio_chunk *ch); +int cio_chunk_up(struct cio_chunk *ch); +int cio_chunk_up_force(struct cio_chunk *ch); +int cio_chunk_down(struct cio_chunk *ch); +char *cio_version(); + +/* Counters */ +size_t cio_chunk_counter_total_add(struct cio_ctx *ctx); +size_t cio_chunk_counter_total_sub(struct cio_ctx *ctx); +size_t cio_chunk_counter_total_up_add(struct cio_ctx *ctx); +size_t cio_chunk_counter_total_up_sub(struct cio_ctx *ctx); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_crc32.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_crc32.h new file mode 100644 index 000000000..dd15cd270 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_crc32.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_CRC32_H +#define CIO_CRC32_H + +#include <crc32/crc32.h> + +#define cio_crc32_init() crc_init() +#define cio_crc32_update(a, b, c) crc_update(a, b, c) +#define cio_crc32_finalize(a) crc_finalize(a) + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_error.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_error.h new file mode 100644 index 000000000..faec54073 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_error.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2021 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_ERROR_H +#define CIO_ERROR_H + +#include <chunkio/chunkio.h> +#include <chunkio/cio_chunk.h> + +/* + * Error status (do not confuse with return statuses!) + */ +#define CIO_ERR_BAD_CHECKSUM -10 /* Chunk has a bad checksum */ +#define CIO_ERR_BAD_LAYOUT -11 /* Bad magic bytes or general layout */ +#define CIO_ERR_PERMISSION -12 /* Permission error */ +#define CIO_ERR_BAD_FILE_SIZE -13 /* Chunk has a bad file size */ + +char *cio_error_get_str(struct cio_chunk *ch); +int cio_error_get(struct cio_chunk *ch); +void cio_error_set(struct cio_chunk *ch, int status); +void cio_error_reset(struct cio_chunk *ch); + +#endif
\ No newline at end of file diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_file.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_file.h new file mode 100644 index 000000000..7d4474929 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_file.h @@ -0,0 +1,86 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_FILE_H +#define CIO_FILE_H + +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_file_st.h> +#include <chunkio/cio_crc32.h> + +/* Linux fallocate() strategy */ +#define CIO_FILE_LINUX_FALLOCATE 0 +#define CIO_FILE_LINUX_POSIX_FALLOCATE 1 + +struct cio_file { + int fd; /* file descriptor */ + int flags; /* open flags */ + int synced; /* sync after latest write ? */ + int allocate_strategy; /* linux-only: fallocate strategy */ + size_t fs_size; /* original size in the file system */ + size_t data_size; /* number of bytes used */ + size_t page_size; /* curent page size */ + size_t alloc_size; /* allocated size */ + size_t realloc_size; /* chunk size to increase alloc */ + char *path; /* root path + stream */ + char *map; /* map of data */ +#ifdef _WIN32 + HANDLE backing_file; + HANDLE backing_mapping; +#endif + /* cached addr */ + char *st_content; + crc_t crc_cur; /* crc: current value calculated */ + int crc_reset; /* crc: must recalculate from the beginning ? */ +}; + +size_t cio_file_real_size(struct cio_file *cf); +struct cio_file *cio_file_open(struct cio_ctx *ctx, + struct cio_stream *st, + struct cio_chunk *ch, + int flags, + size_t size, + int *err); +void cio_file_close(struct cio_chunk *ch, int delete); +int cio_file_delete(struct cio_ctx *ctx, struct cio_stream *st, const char *name); +int cio_file_write(struct cio_chunk *ch, const void *buf, size_t count); +int cio_file_write_metadata(struct cio_chunk *ch, char *buf, size_t size); +int cio_file_sync(struct cio_chunk *ch); +int cio_file_resize(struct cio_file *cf, size_t new_size); +char *cio_file_hash(struct cio_file *cf); +void cio_file_hash_print(struct cio_file *cf); +void cio_file_calculate_checksum(struct cio_file *cf, crc_t *out); +void cio_file_scan_dump(struct cio_ctx *ctx, struct cio_stream *st); +int cio_file_read_prepare(struct cio_ctx *ctx, struct cio_chunk *ch); +int cio_file_content_copy(struct cio_chunk *ch, + void **out_buf, size_t *out_size); + + +int cio_file_is_up(struct cio_chunk *ch, struct cio_file *cf); +int cio_file_down(struct cio_chunk *ch); +int cio_file_up(struct cio_chunk *ch); +int cio_file_up_force(struct cio_chunk *ch); +int cio_file_lookup_user(char *user, void **result); +int cio_file_lookup_group(char *group, void **result); +int cio_file_update_size(struct cio_file *cf); + +#define cio_file_report_runtime_error() { cio_file_native_report_runtime_error(); } +#define cio_file_report_os_error() { cio_file_native_report_os_error(); } + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_file_native.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_file_native.h new file mode 100644 index 000000000..1658495fd --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_file_native.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_FILE_NATIVE_H +#define CIO_FILE_NATIVE_H + +#include <chunkio/cio_file.h> + + + +#ifdef _WIN32 +#define cio_file_native_is_open(cf) (cf->backing_file != INVALID_HANDLE_VALUE) +#define cio_file_native_is_mapped(cf) (cf->backing_mapping != INVALID_HANDLE_VALUE) +#define cio_file_native_report_runtime_error() { cio_errno(); } +#define cio_file_native_report_os_error() { cio_winapi_error(); } +#else +#define cio_file_native_is_open(cf) (cf->fd != -1) +#define cio_file_native_is_mapped(cf) (cf->map != NULL) +#define cio_file_native_report_runtime_error() { cio_errno(); } +#define cio_file_native_report_os_error() { cio_errno(); } +#endif + +int cio_file_native_apply_acl_and_settings(struct cio_ctx *ctx, struct cio_file *cf); +char *cio_file_native_compose_path(char *root_path, char *stream_name, + char *chunk_name); +int cio_file_native_unmap(struct cio_file *cf); +int cio_file_native_map(struct cio_file *cf, size_t map_size); +int cio_file_native_remap(struct cio_file *cf, size_t new_size); +int cio_file_native_lookup_user(char *user, void **result); +int cio_file_native_lookup_group(char *group, void **result); +int cio_file_native_get_size(struct cio_file *cf, size_t *file_size); +int cio_file_native_filename_check(char *name); +int cio_file_native_open(struct cio_file *cf); +int cio_file_native_close(struct cio_file *cf); +int cio_file_native_delete(struct cio_file *cf); +int cio_file_native_delete_by_path(const char *path); +int cio_file_native_sync(struct cio_file *cf, int sync_mode); +int cio_file_native_resize(struct cio_file *cf, size_t new_size); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_file_st.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_file_st.h new file mode 100644 index 000000000..4b1552b61 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_file_st.h @@ -0,0 +1,170 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_FILE_ST_H +#define CIO_FILE_ST_H + +#include <stdlib.h> +#include <inttypes.h> + +/* + * ChunkIO data file layout as of 2018/10/26 + * + * - 2 first bytes as identification: 0xC1 0x00 + * - 4 bytes for checksum of content section (CRC32) + * - Content section is composed by: + * - 2 bytes to specify the length of metadata + * - optional metadata + * - user data + * + * +--------------+----------------+ + * | 0xC1 | 0x00 +--> Header 2 bytes + * +--------------+----------------+ + * | 4 BYTES +--> CRC32(Content) + * | 4 BYTES +--> CRC32(Padding) + * | 4 BYTES +--> Content length + * | 8 BYTES +--> Padding + * +-------------------------------+ + * | Content | + * | +-------------------------+ | + * | | 2 BYTES +-----> Metadata Length + * | +-------------------------+ | + * | +-------------------------+ | + * | | | | + * | | Metadata +-----> Optional Metadata (up to 65535 bytes) + * | | | | + * | +-------------------------+ | + * | +-------------------------+ | + * | | | | + * | | Content Data +-----> User Data + * | | | | + * | +-------------------------+ | + * +-------------------------------+ + */ + +#define CIO_FILE_ID_00 0xc1 /* header: first byte */ +#define CIO_FILE_ID_01 0x00 /* header: second byte */ +#define CIO_FILE_HEADER_MIN 24 /* 24 bytes for the header */ +#define CIO_FILE_CONTENT_OFFSET 22 +#define CIO_FILE_CONTENT_LENGTH_OFFSET 10 /* We store the content length + * right after the checksum in + * what used to be padding + */ +/* Return pointer to hash position */ +static inline char *cio_file_st_get_hash(char *map) +{ + return map + 2; +} + +/* Return metadata length */ +static inline uint16_t cio_file_st_get_meta_len(char *map) +{ + return (uint16_t) ((uint8_t) map[22] << 8) | (uint8_t) map[23]; +} + +/* Set metadata length */ +static inline void cio_file_st_set_meta_len(char *map, uint16_t len) +{ + map[22] = (uint8_t) (len >> 8); + map[23] = (uint8_t) (len & 0xFF); +} + +/* Return pointer to start point of metadata */ +static inline char *cio_file_st_get_meta(char *map) +{ + return map + CIO_FILE_HEADER_MIN; +} + +/* Return pointer to start point of content */ +static inline char *cio_file_st_get_content(char *map) +{ + uint16_t len; + + len = cio_file_st_get_meta_len(map); + return map + CIO_FILE_HEADER_MIN + len; +} + +/* Infer content length when not available */ +static inline ssize_t cio_file_st_infer_content_len(char *map, size_t size) +{ + size_t content_length; + + content_length = size; + content_length -= CIO_FILE_HEADER_MIN; + content_length -= cio_file_st_get_meta_len(map); + + return content_length; +} + +/* Get content length */ +static inline ssize_t cio_file_st_get_content_len(char *map, size_t size, + size_t page_size) +{ + uint8_t *content_length_buffer; + ssize_t content_length; + + if (size < CIO_FILE_HEADER_MIN) { + return -1; + } + + content_length_buffer = (uint8_t *) &map[CIO_FILE_CONTENT_LENGTH_OFFSET]; + + content_length = (ssize_t) (((uint32_t) content_length_buffer[0]) << 24) | + (((uint32_t) content_length_buffer[1]) << 16) | + (((uint32_t) content_length_buffer[2]) << 8) | + (((uint32_t) content_length_buffer[3]) << 0); + + /* This is required in order to be able to load chunk files generated by + * previous versions of chunkio that didn't include the content length + * as part of the headers. + * + * The reason why we need to ensure that the file size is larger than 4096 + * is that this is the minimal expected page size which is the unit used + * to initialize chunk files when they are created. + * + * In doing so, we effectively avoid returning bogus results when loading + * newly created, non trimmed files while at the same time retaining the + * capability of loading legacy files (that don't have a content size) + * that are larger than 4096 bytes. + * + * The only caveat is that trimmed files + */ + if (content_length == 0 && + size > 0 && + size != page_size) { + content_length = cio_file_st_infer_content_len(map, size); + } + + return content_length; +} + +/* Set content length */ +static inline void cio_file_st_set_content_len(char *map, uint32_t len) +{ + uint8_t *content_length_buffer; + + content_length_buffer = (uint8_t *) &map[CIO_FILE_CONTENT_LENGTH_OFFSET]; + + content_length_buffer[0] = (uint8_t) ((len & 0xFF000000) >> 24); + content_length_buffer[1] = (uint8_t) ((len & 0x00FF0000) >> 16); + content_length_buffer[2] = (uint8_t) ((len & 0x0000FF00) >> 8); + content_length_buffer[3] = (uint8_t) ((len & 0x000000FF) >> 0); +} + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_info.h.in b/src/fluent-bit/lib/chunkio/include/chunkio/cio_info.h.in new file mode 100644 index 000000000..87924fbf5 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_info.h.in @@ -0,0 +1,26 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2020 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_INFO_H +#define CIO_INFO_H + +/* General flags set by CMakeLists.txt */ +@CIO_BUILD_FLAGS@ + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_log.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_log.h new file mode 100644 index 000000000..83dc46169 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_log.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_LOG_H +#define CIO_LOG_H + +#include <errno.h> + +#define CIO_LOG_BUF_SIZE 256 + +void cio_log_print(void *ctx, int level, const char *file, int line, + const char *fmt, ...); +int cio_errno_print(int errnum, const char *file, int line); + +#define cio_log_error(ctx, fmt, ...) \ + cio_log_print(ctx, CIO_LOG_ERROR, __FILENAME__, \ + __LINE__, fmt, ##__VA_ARGS__) + +#define cio_log_warn(ctx, fmt, ...) \ + cio_log_print(ctx, CIO_LOG_WARN, __FILENAME__, \ + __LINE__, fmt, ##__VA_ARGS__) + +#define cio_log_info(ctx, fmt, ...) \ + cio_log_print(ctx, CIO_LOG_INFO, __FILENAME__, \ + __LINE__, fmt, ##__VA_ARGS__) + +#define cio_log_debug(ctx, fmt, ...) \ + cio_log_print(ctx, CIO_LOG_DEBUG, __FILENAME__, \ + __LINE__, fmt, ##__VA_ARGS__) + +#define cio_log_trace(ctx, fmt, ...) \ + cio_log_print(ctx, CIO_LOG_TRACE, __FILENAME__, \ + __LINE__, fmt, ##__VA_ARGS__) + +#ifdef __FILENAME__ +#define cio_errno() cio_errno_print(errno, __FILENAME__, __LINE__) +#else +#define cio_errno() cio_errno_print(errno, __FILE__, __LINE__) +#endif + +#ifdef _WIN32 +void cio_winapi_error_print(const char *func, int line); +#define cio_winapi_error() cio_winapi_error_print(__func__, __LINE__) +#endif + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_memfs.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_memfs.h new file mode 100644 index 000000000..ffcaeae4c --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_memfs.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_MEMFS_H +#define CIO_MEMFS_H + +#include <chunkio/chunkio.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_crc32.h> + +struct cio_memfs { + char *name; /* file name */ + crc_t crc_cur; /* un-finalized checksum */ + + /* metadata */ + char *meta_data; + int meta_len; + + /* content-data */ + char *buf_data; /* buffer with content data */ + size_t buf_len; /* buffer content length */ + size_t buf_size; /* buffer allocated size */ + size_t realloc_size; /* chunk size to increase buf_data */ +}; + + +struct cio_memfs *cio_memfs_open(struct cio_ctx *ctx, struct cio_stream *st, + struct cio_chunk *ch, int flags, + size_t size); +void cio_memfs_close(struct cio_chunk *ch); +int cio_memfs_write(struct cio_chunk *ch, const void *buf, size_t count); +int cio_memfs_close_stream(struct cio_stream *st); +void cio_memfs_scan_dump(struct cio_ctx *ctx, struct cio_stream *st); +int cio_memfs_content_copy(struct cio_chunk *ch, + void **out_buf, size_t *out_size); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_meta.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_meta.h new file mode 100644 index 000000000..885e8c636 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_meta.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_META_H +#define CIO_META_H + +#include <chunkio/cio_file.h> +#include <chunkio/cio_chunk.h> + +int cio_meta_write(struct cio_chunk *ch, char *buf, size_t size); +int cio_meta_read(struct cio_chunk *ch, char **meta_buf, int *meta_len); +int cio_meta_cmp(struct cio_chunk *ch, char *meta_buf, int meta_len); +int cio_meta_size(struct cio_chunk *ch); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_os.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_os.h new file mode 100644 index 000000000..388de89db --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_os.h @@ -0,0 +1,27 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_OS_H +#define CIO_OS_H +#include <sys/types.h> + +int cio_os_isdir(const char *dir); +int cio_os_mkpath(const char *dir, mode_t mode); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_scan.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_scan.h new file mode 100644 index 000000000..ce74229bb --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_scan.h @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_SCAN_H +#define CIO_SCAN_H + +#include <chunkio/chunkio.h> + +int cio_scan_streams(struct cio_ctx *ctx, char *chunk_extension); +void cio_scan_dump(struct cio_ctx *ctx); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_sha1.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_sha1.h new file mode 100644 index 000000000..3899d2b8b --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_sha1.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_SHA1_H +#define CIO_SHA1_H + +#include <sha1/sha1.h> + +struct cio_sha1 { + SHA_CTX sha; +}; + +void cio_sha1_init(struct cio_sha1 *ctx); +void cio_sha1_update(struct cio_sha1 *ctx, const void *data, unsigned long len); +void cio_sha1_final(unsigned char hash[20], struct cio_sha1 *ctx); +void cio_sha1_hash(const void *data_in, unsigned long length, + unsigned char *data_out, void *state); +void cio_sha1_to_hex(unsigned char *in, char *out); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_stats.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_stats.h new file mode 100644 index 000000000..b3c41789b --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_stats.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_STATS_H +#define CIO_STATS_H + +#include <chunkio/chunkio.h> + +struct cio_stats { + /* Streams */ + int streams_total; /* total number of registered streams */ + + /* Chunks */ + int chunks_total; /* total number of registered chunks */ + int chunks_mem; /* number of chunks of memory type */ + int chunks_fs; /* number of chunks in file type */ + int chunks_fs_up; /* number of chunks in file type 'Up' in memory */ + int chunks_fs_down; /* number of chunks in file type 'down' */ +}; + +void cio_stats_get(struct cio_ctx *ctx, struct cio_stats *stats); +void cio_stats_print_summary(struct cio_ctx *ctx); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_stream.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_stream.h new file mode 100644 index 000000000..22e34c2ca --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_stream.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_STREAM_H +#define CIO_STREAM_H + +#include <monkey/mk_core/mk_list.h> + +struct cio_stream { + int type; /* type: CIO_STORE_FS or CIO_STORE_MEM */ + char *name; /* stream name */ + struct mk_list _head; /* head link to ctx->streams list */ + struct mk_list chunks; /* list of all chunks in the stream */ + struct mk_list chunks_up; /* list of chunks who are 'up' */ + struct mk_list chunks_down; /* list of chunks who are 'down' */ + void *parent; /* ref to parent ctx */ +}; + +struct cio_stream *cio_stream_create(struct cio_ctx *ctx, const char *name, + int type); +struct cio_stream *cio_stream_get(struct cio_ctx *ctx, const char *name); +int cio_stream_delete(struct cio_stream *st); +void cio_stream_destroy(struct cio_stream *st); +void cio_stream_destroy_all(struct cio_ctx *ctx); +size_t cio_stream_size_chunks_up(struct cio_stream *st); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_utils.h b/src/fluent-bit/lib/chunkio/include/chunkio/cio_utils.h new file mode 100644 index 000000000..b8a9deac6 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_utils.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_UTILS_H +#define CIO_UTILS_H + +#include <chunkio/cio_info.h> + +#ifdef CIO_HAVE_GETPAGESIZE +int cio_getpagesize(); +#endif + +int cio_utils_recursive_delete(const char *dir); +int cio_utils_read_file(const char *path, char **buf, size_t *size); + +#endif diff --git a/src/fluent-bit/lib/chunkio/include/chunkio/cio_version.h.in b/src/fluent-bit/lib/chunkio/include/chunkio/cio_version.h.in new file mode 100644 index 000000000..852151f4e --- /dev/null +++ b/src/fluent-bit/lib/chunkio/include/chunkio/cio_version.h.in @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2020 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_VERSION_H +#define CIO_VERSION_H + +/* Helpers to convert/format version string */ +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) + +/* Chunk I/O Version */ +#define CIO_VERSION_MAJOR @CIO_VERSION_MAJOR@ +#define CIO_VERSION_MINOR @CIO_VERSION_MINOR@ +#define CIO_VERSION_PATCH @CIO_VERSION_PATCH@ +#define CIO_VERSION (CIO_VERSION_MAJOR * 10000 \ + CIO_VERSION_MINOR * 100 \ + CIO_VERSION_PATCH) +#define CIO_VERSION_STR "@CIO_VERSION_STR@" + +#endif diff --git a/src/fluent-bit/lib/chunkio/scripts/win_build.bat b/src/fluent-bit/lib/chunkio/scripts/win_build.bat new file mode 100755 index 000000000..9a30c7b69 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/scripts/win_build.bat @@ -0,0 +1,6 @@ +setlocal +call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" +path "C:\Program Files (x86)\MSBuild\16.0\Bin;C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin";%path% +cmake -G "NMake Makefiles" -DCIO_TESTS=On . +cmake --build . +endlocal diff --git a/src/fluent-bit/lib/chunkio/src/CMakeLists.txt b/src/fluent-bit/lib/chunkio/src/CMakeLists.txt new file mode 100644 index 000000000..9e666381d --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/CMakeLists.txt @@ -0,0 +1,53 @@ +set(src + cio_os.c + cio_log.c + cio_file.c + cio_memfs.c + cio_chunk.c + cio_meta.c + cio_scan.c + cio_utils.c + cio_stream.c + cio_stats.c + cio_error.c + chunkio.c + ) + +set(libs cio-crc32) + +if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(src + ${src} + cio_file_win32.c + win32/dirent.c + ) + set(libs + ${libs} + Shell32.lib + Shlwapi.lib) +else() + set(src + ${src} + cio_file_unix.c + ) +endif() + +if(CIO_LIB_STATIC) + add_library(chunkio-static STATIC ${src}) + target_link_libraries(chunkio-static ${libs}) + if(CIO_SANITIZE_ADDRESS) + add_sanitizers(chunkio-static) + endif() +endif() + +if (CIO_LIB_SHARED) + add_library(chunkio-shared SHARED ${src}) + target_link_libraries(chunkio-static ${libs}) + if(CIO_SANITIZE_ADDRESS) + add_sanitizers(chunkio-shared) + endif() +endif() + +if (NOT CIO_LIB_STATIC AND NOT CIO_LIB_SHARED) + message(FATAL_ERROR "What are you doing?, you should build something") +endif() diff --git a/src/fluent-bit/lib/chunkio/src/chunkio.c b/src/fluent-bit/lib/chunkio/src/chunkio.c new file mode 100644 index 000000000..a69325cfe --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/chunkio.c @@ -0,0 +1,369 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <chunkio/chunkio.h> +#include <chunkio/chunkio_compat.h> +#include <chunkio/cio_os.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_scan.h> +#include <chunkio/cio_utils.h> + +#include <monkey/mk_core/mk_list.h> + +/* + * Validate if root_path exists, if don't, create it, otherwise + * check if we have write access to it. + */ +static int check_root_path(struct cio_ctx *ctx, const char *root_path) +{ + int ret; + int len; + + if (!root_path) { + return -1; + } + + len = strlen(root_path); + if (len <= 0) { + return -1; + } + + ret = cio_os_isdir(root_path); + if (ret == -1) { + /* Try to create the path */ + ret = cio_os_mkpath(root_path, 0755); + if (ret == -1) { + return -1; + } + cio_log_info(ctx, "created root path %s", root_path); + return 0; + } + + /* Directory already exists, check write access */ + return access(root_path, W_OK); +} + +void cio_options_init(struct cio_options *options) +{ + memset(options, 0, sizeof(struct cio_options)); + + options->initialized = CIO_INITIALIZED; + + options->root_path = NULL; + options->user = NULL; + options->group = NULL; + options->chmod = NULL; + options->log_cb = NULL; + options->log_level = CIO_LOG_INFO; + options->flags = CIO_OPEN_RW; + options->realloc_size_hint = CIO_DISABLE_REALLOC_HINT; +} + +struct cio_ctx *cio_create(struct cio_options *options) +{ + int ret; + struct cio_ctx *ctx; + struct cio_options default_options; + + if (options == NULL) { + cio_options_init(&default_options); + options = &default_options; + } + else { + if (options->initialized != CIO_INITIALIZED) { + /* the caller 'must' call cio_options_init() or pass NULL before creating a context */ + fprintf(stderr, "[cio] 'options' has not been initialized properly\n"); + return NULL; + } + } + + /* sanitize chunk open flags */ + if (!(options->flags & CIO_OPEN_RW) && !(options->flags & CIO_OPEN_RD)) { + options->flags |= CIO_OPEN_RW; + } + + if (options->log_level < CIO_LOG_ERROR || + options->log_level > CIO_LOG_TRACE) { + fprintf(stderr, "[cio] invalid log level, aborting\n"); + return NULL; + } +#ifndef CIO_HAVE_BACKEND_FILESYSTEM + if (root_path) { + fprintf(stderr, "[cio] file system backend not supported\n"); + return NULL; + } +#endif + + /* Create context */ + ctx = calloc(1, sizeof(struct cio_ctx)); + if (!ctx) { + perror("calloc"); + return NULL; + } + mk_list_init(&ctx->streams); + ctx->page_size = cio_getpagesize(); + ctx->max_chunks_up = CIO_MAX_CHUNKS_UP; + ctx->options.flags = options->flags; + ctx->realloc_size_hint = CIO_DISABLE_REALLOC_HINT; + + if (options->user != NULL) { + ctx->options.user = strdup(options->user); + } + + if (options->group != NULL) { + ctx->options.group = strdup(options->group); + } + + if (options->chmod != NULL) { + ctx->options.chmod = strdup(options->chmod); + } + + /* Counters */ + ctx->total_chunks = 0; + ctx->total_chunks_up = 0; + + /* Logging */ + cio_set_log_callback(ctx, options->log_cb); + cio_set_log_level(ctx, options->log_level); + + /* Check or initialize file system root path */ + if (options->root_path) { + ret = check_root_path(ctx, options->root_path); + if (ret == -1) { + cio_log_error(ctx, + "[chunkio] cannot initialize root path %s\n", + options->root_path); + free(ctx); + return NULL; + } + + ctx->options.root_path = strdup(options->root_path); + } + else { + ctx->options.root_path = NULL; + } + + if (ctx->options.user != NULL) { + ret = cio_file_lookup_user(ctx->options.user, &ctx->processed_user); + + if (ret != CIO_OK) { + cio_destroy(ctx); + + return NULL; + } + } + else { + ctx->processed_user = NULL; + } + + if (ctx->options.group != NULL) { + ret = cio_file_lookup_group(ctx->options.group, &ctx->processed_group); + + if (ret != CIO_OK) { + cio_destroy(ctx); + + return NULL; + } + } + else { + ctx->processed_group = NULL; + } + + if (options->realloc_size_hint > 0) { + ret = cio_set_realloc_size_hint(ctx, options->realloc_size_hint); + if (ret == -1) { + cio_log_error(ctx, + "[chunkio] cannot initialize with realloc size hint %d\n", + options->realloc_size_hint); + cio_destroy(ctx); + + return NULL; + } + } + + return ctx; +} + +int cio_load(struct cio_ctx *ctx, char *chunk_extension) +{ + int ret; + + if (ctx->options.root_path) { + ret = cio_scan_streams(ctx, chunk_extension); + return ret; + } + + return 0; +} + +static int qsort_stream(struct cio_stream *stream, + int (*compar)(const void *, const void *)) +{ + int i = 0; + int items; + struct mk_list *tmp; + struct mk_list *head; + struct cio_chunk **arr; + struct cio_chunk *chunk; + + items = mk_list_size(&stream->chunks); + if (items == 0) { + return 0; + } + + arr = malloc(sizeof(struct cio_chunk *) * items); + if (!arr) { + perror("malloc"); + return -1; + } + + /* map chunks to the array and and unlink them */ + mk_list_foreach_safe(head, tmp, &stream->chunks) { + chunk = mk_list_entry(head, struct cio_chunk, _head); + arr[i++] = chunk; + mk_list_del(&chunk->_head); + } + + /* sort the chunks, just trust in 'compar' external function */ + qsort(arr, items, sizeof(struct cio_chunk *), compar); + + /* link the chunks in the proper order back to the list head */ + for (i = 0; i < items; i++) { + chunk = arr[i]; + mk_list_add(&chunk->_head, &stream->chunks); + } + + free(arr); + return 0; +} + +/* + * Sort chunks using the 'compar' callback function. This is pretty much a + * wrapper over qsort(3). The sort is done inside every stream content. + * + * Use this function after cio_load() only. + */ +int cio_qsort(struct cio_ctx *ctx, int (*compar)(const void *, const void *)) +{ + struct mk_list *head; + struct cio_stream *stream; + + mk_list_foreach(head, &ctx->streams) { + stream = mk_list_entry(head, struct cio_stream, _head); + qsort_stream(stream, compar); + } + + return 0; +} + +void cio_destroy(struct cio_ctx *ctx) +{ + if (!ctx) { + return; + } + + cio_stream_destroy_all(ctx); + + if (ctx->options.user != NULL) { + free(ctx->options.user); + } + + if (ctx->options.group != NULL) { + free(ctx->options.group); + } + + if (ctx->options.chmod != NULL) { + free(ctx->options.chmod); + } + + if (ctx->processed_user != NULL) { + free(ctx->processed_user); + } + + if (ctx->processed_group != NULL) { + free(ctx->processed_group); + } + + if (ctx->options.root_path != NULL) { + free(ctx->options.root_path); + } + + free(ctx); +} + +void cio_set_log_callback(struct cio_ctx *ctx, void (*log_cb)) +{ + ctx->options.log_cb = log_cb; +} + +int cio_set_log_level(struct cio_ctx *ctx, int level) +{ + if (level < CIO_LOG_ERROR || level > CIO_LOG_TRACE) { + return -1; + } + + ctx->options.log_level = level; + return 0; +} + +int cio_set_max_chunks_up(struct cio_ctx *ctx, int n) +{ + if (n < 1) { + return -1; + } + + ctx->max_chunks_up = n; + return 0; +} + +int cio_set_realloc_size_hint(struct cio_ctx *ctx, size_t realloc_size_hint) +{ + if (realloc_size_hint < CIO_REALLOC_HINT_MIN) { + cio_log_error(ctx, + "[chunkio] cannot specify less than %zu bytes\n", + CIO_REALLOC_HINT_MIN); + return -1; + } + else if (realloc_size_hint > CIO_REALLOC_HINT_MAX) { + cio_log_error(ctx, + "[chunkio] cannot specify more than %zu bytes\n", + CIO_REALLOC_HINT_MAX); + return -1; + } + + ctx->realloc_size_hint = realloc_size_hint; + + return 0; +} + +void cio_enable_file_trimming(struct cio_ctx *ctx) +{ + ctx->options.flags |= CIO_TRIM_FILES; +} + +void cio_disable_file_trimming(struct cio_ctx *ctx) +{ + ctx->options.flags &= ~CIO_TRIM_FILES; +}
\ No newline at end of file diff --git a/src/fluent-bit/lib/chunkio/src/cio_chunk.c b/src/fluent-bit/lib/chunkio/src/cio_chunk.c new file mode 100644 index 000000000..7917cd2a8 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_chunk.c @@ -0,0 +1,642 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_version.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_memfs.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_error.h> + +#include <string.h> + +struct cio_chunk *cio_chunk_open(struct cio_ctx *ctx, struct cio_stream *st, + const char *name, int flags, size_t size, + int *err) +{ + int len; + void *backend = NULL; + struct cio_chunk *ch; + + if (!st) { + cio_log_error(ctx, "[cio chunk] invalid stream"); + return NULL; + } + + if (!name) { + cio_log_error(ctx, "[cio chunk] invalid file name"); + return NULL; + } + + len = strlen(name); + if (len == 0) { + cio_log_error(ctx, "[cio chunk] invalid file name"); + return NULL; + } +#ifndef CIO_HAVE_BACKEND_FILESYSTEM + if (st->type == CIO_STORE_FS) { + cio_log_error(ctx, "[cio chunk] file system backend not supported"); + return NULL; + } +#endif + + /* allocate chunk context */ + ch = malloc(sizeof(struct cio_chunk)); + if (!ch) { + cio_errno(); + return NULL; + } + ch->name = strdup(name); + ch->ctx = ctx; + ch->st = st; + ch->lock = CIO_FALSE; + ch->tx_active = CIO_FALSE; + ch->tx_crc = 0; + ch->tx_content_length = 0; + ch->backend = NULL; + + mk_list_add(&ch->_head, &st->chunks); + + cio_error_reset(ch); + + /* create backend context */ + if (st->type == CIO_STORE_FS) { + backend = cio_file_open(ctx, st, ch, flags, size, err); + } + else if (st->type == CIO_STORE_MEM) { + *err = CIO_OK; + backend = cio_memfs_open(ctx, st, ch, flags, size); + } + + if (!backend) { + mk_list_del(&ch->_head); + free(ch->name); + free(ch); + return NULL; + } + + ch->backend = backend; + + /* Adjust counter */ + cio_chunk_counter_total_add(ctx); + + /* Link the chunk state to the proper stream list */ + if (cio_chunk_is_up(ch) == CIO_TRUE) { + mk_list_add(&ch->_state_head, &st->chunks_up); + } + else { + mk_list_add(&ch->_state_head, &st->chunks_down); + } + + return ch; +} + +void cio_chunk_close(struct cio_chunk *ch, int delete) +{ + int type; + struct cio_ctx *ctx; + + if (!ch) { + return; + } + + cio_error_reset(ch); + + ctx = ch->ctx; + type = ch->st->type; + if (type == CIO_STORE_MEM) { + cio_memfs_close(ch); + } + else if (type == CIO_STORE_FS) { + cio_file_close(ch, delete); + } + + mk_list_del(&ch->_head); + mk_list_del(&ch->_state_head); + free(ch->name); + free(ch); + + /* Adjust counter */ + cio_chunk_counter_total_sub(ctx); +} + +int cio_chunk_delete(struct cio_ctx *ctx, struct cio_stream *st, const char *name) +{ + int result; + + if (st == NULL) { + cio_log_error(ctx, "[cio chunk] invalid stream"); + + return CIO_ERROR; + } + + if (name == NULL) { + cio_log_error(ctx, "[cio chunk] invalid file name"); + + return CIO_ERROR; + } + + if (strlen(name) == 0) { + cio_log_error(ctx, "[cio chunk] invalid file name"); + + return CIO_ERROR; + } + +#ifndef CIO_HAVE_BACKEND_FILESYSTEM + if (st->type == CIO_STORE_FS) { + cio_log_error(ctx, "[cio chunk] file system backend not supported"); + + return CIO_ERROR; + } +#endif + + if (st->type == CIO_STORE_FS) { + result = cio_file_delete(ctx, st, name); + } + else { + result = CIO_ERROR; + } + + return result; +} + +/* + * Write at a specific offset of the content area. Offset must be >= 0 and + * less than current data length. + */ +int cio_chunk_write_at(struct cio_chunk *ch, off_t offset, + const void *buf, size_t count) +{ + int type; + struct cio_memfs *mf; + struct cio_file *cf; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + mf = ch->backend; + mf->buf_len = offset; + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + cf->data_size = offset; + cf->crc_reset = CIO_TRUE; + } + + /* + * By default backends (fs, mem) appends data after the it last position, + * so we just adjust the content size to the given offset. + */ + return cio_chunk_write(ch, buf, count); +} + +int cio_chunk_write(struct cio_chunk *ch, const void *buf, size_t count) +{ + int ret = 0; + int type; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + ret = cio_memfs_write(ch, buf, count); + } + else if (type == CIO_STORE_FS) { + ret = cio_file_write(ch, buf, count); + } + + return ret; +} + +int cio_chunk_sync(struct cio_chunk *ch) +{ + int ret = 0; + int type; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_FS) { + ret = cio_file_sync(ch); + } + + return ret; +} + +int cio_chunk_get_content(struct cio_chunk *ch, char **buf, size_t *size) +{ + int ret = 0; + int type; + struct cio_memfs *mf; + struct cio_file *cf; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + mf = ch->backend; + *size = mf->buf_len; + *buf = mf->buf_data; + return ret; + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + ret = cio_file_read_prepare(ch->ctx, ch); + if (ret != CIO_OK) { + return ret; + } + *size = cf->data_size; + *buf = cio_file_st_get_content(cf->map); + return ret; + } + + return CIO_ERROR; +} + +/* Using the content of the chunk, generate a copy using the heap */ +int cio_chunk_get_content_copy(struct cio_chunk *ch, + void **out_buf, size_t *out_size) +{ + int type; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + return cio_memfs_content_copy(ch, out_buf, out_size); + } + else if (type == CIO_STORE_FS) { + return cio_file_content_copy(ch, out_buf, out_size); + } + + return CIO_ERROR; +} + +size_t cio_chunk_get_content_end_pos(struct cio_chunk *ch) +{ + int type; + off_t pos = 0; + struct cio_memfs *mf; + struct cio_file *cf; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + mf = ch->backend; + pos = (off_t) (mf->buf_data + mf->buf_len); + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + pos = (off_t) (cio_file_st_get_content(cf->map) + cf->data_size); + } + + return pos; +} + +ssize_t cio_chunk_get_content_size(struct cio_chunk *ch) +{ + int type; + struct cio_memfs *mf; + struct cio_file *cf; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + mf = ch->backend; + return mf->buf_len; + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + return cf->data_size; + } + + return -1; +} + +ssize_t cio_chunk_get_real_size(struct cio_chunk *ch) +{ + int type; + struct cio_memfs *mf; + struct cio_file *cf; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + mf = ch->backend; + return mf->buf_len; + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + + /* If the file is not open we need to explicitly get its size */ + if (cf->fs_size == 0) { + return cio_file_real_size(cf); + } + + return cf->fs_size; + } + + return -1; +} + +void cio_chunk_close_stream(struct cio_stream *st) +{ + struct mk_list *tmp; + struct mk_list *head; + struct cio_chunk *ch; + + mk_list_foreach_safe(head, tmp, &st->chunks) { + ch = mk_list_entry(head, struct cio_chunk, _head); + cio_chunk_close(ch, CIO_FALSE); + } +} + +char *cio_chunk_hash(struct cio_chunk *ch) +{ + if (ch->st->type == CIO_STORE_FS) { + return cio_file_hash(ch->backend); + } + + return NULL; +} + +int cio_chunk_lock(struct cio_chunk *ch) +{ + cio_error_reset(ch); + + if (ch->lock == CIO_TRUE) { + return CIO_ERROR; + } + + ch->lock = CIO_TRUE; + + if (cio_chunk_is_up(ch) == CIO_TRUE) { + return cio_chunk_sync(ch); + } + + return CIO_OK; +} + +int cio_chunk_unlock(struct cio_chunk *ch) +{ + cio_error_reset(ch); + + if (ch->lock == CIO_FALSE) { + return CIO_ERROR; + } + + ch->lock = CIO_FALSE; + return CIO_OK; +} + +int cio_chunk_is_locked(struct cio_chunk *ch) +{ + return ch->lock; +} + +/* + * Start a transaction context: it keep a state of the current calculated + * CRC32 (if enabled) and the current number of bytes in the content + * area. + */ +int cio_chunk_tx_begin(struct cio_chunk *ch) +{ + int type; + struct cio_memfs *mf; + struct cio_file *cf; + + cio_error_reset(ch); + + if (cio_chunk_is_locked(ch)) { + return CIO_RETRY; + } + + if (ch->tx_active == CIO_TRUE) { + return CIO_OK; + } + + ch->tx_active = CIO_TRUE; + type = ch->st->type; + if (type == CIO_STORE_MEM) { + mf = ch->backend; + ch->tx_crc = mf->crc_cur; + ch->tx_content_length = mf->buf_len; + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + ch->tx_crc = cf->crc_cur; + ch->tx_content_length = cf->data_size; + } + + return CIO_OK; +} + +/* + * Commit transaction changes, reset transaction context and leave new + * changes in place. + */ +int cio_chunk_tx_commit(struct cio_chunk *ch) +{ + int ret; + + cio_error_reset(ch); + + ret = cio_chunk_sync(ch); + if (ret == -1) { + return CIO_ERROR; + } + + ch->tx_active = CIO_FALSE; + return CIO_OK; +} + +/* + * Drop changes done since a transaction was initiated */ +int cio_chunk_tx_rollback(struct cio_chunk *ch) +{ + int type; + struct cio_memfs *mf; + struct cio_file *cf; + + cio_error_reset(ch); + + if (ch->tx_active == CIO_FALSE) { + return -1; + } + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + mf = ch->backend; + mf->crc_cur = ch->tx_crc; + mf->buf_len = ch->tx_content_length; + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + cf->crc_cur = ch->tx_crc; + cf->data_size = ch->tx_content_length; + } + + ch->tx_active = CIO_FALSE; + return CIO_OK; +} + +/* + * Determinate if a Chunk content is available in memory for I/O operations. For + * Memory backend this is always true, for Filesystem backend it checks if the + * memory map exists and file descriptor is open. + */ +int cio_chunk_is_up(struct cio_chunk *ch) +{ + int type; + struct cio_file *cf; + + type = ch->st->type; + if (type == CIO_STORE_MEM) { + return CIO_TRUE; + } + else if (type == CIO_STORE_FS) { + cf = ch->backend; + return cio_file_is_up(ch, cf); + } + + return CIO_FALSE; +} + +int cio_chunk_is_file(struct cio_chunk *ch) +{ + int type; + + type = ch->st->type; + if (type == CIO_STORE_FS) { + return CIO_TRUE; + } + + return CIO_FALSE; +} + +static inline void chunk_state_sync(struct cio_chunk *ch) +{ + struct cio_stream *st; + + if (!ch) { + return; + } + + mk_list_del(&ch->_state_head); + st = ch->st; + if (cio_chunk_is_up(ch) == CIO_TRUE) { + mk_list_add(&ch->_state_head, &st->chunks_up); + } + else { + mk_list_add(&ch->_state_head, &st->chunks_down); + } +} + +int cio_chunk_down(struct cio_chunk *ch) +{ + int ret; + int type; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_FS) { + ret = cio_file_down(ch); + chunk_state_sync(ch); + return ret; + } + + return CIO_OK; +} + +int cio_chunk_up(struct cio_chunk *ch) +{ + int ret; + int type; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_FS) { + ret = cio_file_up(ch); + chunk_state_sync(ch); + return ret; + } + + return CIO_OK; +} + +int cio_chunk_up_force(struct cio_chunk *ch) +{ + int ret; + int type; + + cio_error_reset(ch); + + type = ch->st->type; + if (type == CIO_STORE_FS) { + ret = cio_file_up_force(ch); + chunk_state_sync(ch); + return ret; + } + + return CIO_OK; +} + +char *cio_version() +{ + return CIO_VERSION_STR; +} + +/* + * Counters API + */ + +/* Increase the number of total chunks registered (+1) */ +size_t cio_chunk_counter_total_add(struct cio_ctx *ctx) +{ + ctx->total_chunks++; + return ctx->total_chunks; +} + +/* Decrease the total number of chunks (-1) */ +size_t cio_chunk_counter_total_sub(struct cio_ctx *ctx) +{ + ctx->total_chunks--; + return ctx->total_chunks; +} + +/* Increase the number of total chunks up in memory (+1) */ +size_t cio_chunk_counter_total_up_add(struct cio_ctx *ctx) +{ + ctx->total_chunks_up++; + return ctx->total_chunks_up; +} + +/* Decrease the total number of chunks up in memory (-1) */ +size_t cio_chunk_counter_total_up_sub(struct cio_ctx *ctx) +{ + ctx->total_chunks_up--; + return ctx->total_chunks_up; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_error.c b/src/fluent-bit/lib/chunkio/src/cio_error.c new file mode 100644 index 000000000..9049b0a3f --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_error.c @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2021 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <chunkio/chunkio.h> +#include <chunkio/cio_error.h> + +char *cio_error_get_str(struct cio_chunk *ch) +{ + int err = cio_error_get(ch); + + switch (err) { + case CIO_ERR_BAD_CHECKSUM: + return "bad checksum"; + case CIO_ERR_BAD_LAYOUT: + return "bad layout or invalid header"; + case CIO_ERR_PERMISSION: + return "permission error"; + default: + return "no error has been specified"; + } +} + +/* Return the current error number from a chunk */ +int cio_error_get(struct cio_chunk *ch) +{ + return ch->error_n; +} + +/* Set an error number in the chunk */ +void cio_error_set(struct cio_chunk *ch, int status) +{ + ch->error_n = status; + + if (ch->ctx != NULL) { + ch->ctx->last_chunk_error = status; + } +} + +/* Reset the error number in a chunk */ +void cio_error_reset(struct cio_chunk *ch) +{ + ch->error_n = 0; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_file.c b/src/fluent-bit/lib/chunkio/src/cio_file.c new file mode 100644 index 000000000..019baa890 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_file.c @@ -0,0 +1,1344 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> + +#include <chunkio/chunkio.h> +#include <chunkio/chunkio_compat.h> +#include <chunkio/cio_crc32.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_file_native.h> +#include <chunkio/cio_file_st.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_error.h> +#include <chunkio/cio_utils.h> + +size_t scio_file_page_size = 0; + +char cio_file_init_bytes[] = { + /* file type (2 bytes) */ + CIO_FILE_ID_00, CIO_FILE_ID_01, + + /* crc32 (4 bytes) in network byte order */ + 0xff, 0x12, 0xd9, 0x41, + + /* padding bytes (we have 16 extra bytes) */ + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, + + /* metadata length (2 bytes) */ + 0x00, 0x00 +}; + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + + +/* Calculate content checksum in a variable */ +void cio_file_calculate_checksum(struct cio_file *cf, crc_t *out) +{ + crc_t val; + size_t len; + ssize_t content_length; + unsigned char *in_data; + + if (cf->fs_size == 0) { + cio_file_update_size(cf); + } + + /* Metadata length header + metadata length + content length */ + len = 2; + len += cio_file_st_get_meta_len(cf->map); + + content_length = cio_file_st_get_content_len(cf->map, + cf->fs_size, + cf->page_size); + + if (content_length > 0) { + len += content_length; + } + + in_data = (unsigned char *) cf->map + CIO_FILE_CONTENT_OFFSET; + val = cio_crc32_update(cf->crc_cur, in_data, len); + *out = val; +} + +/* Update crc32 checksum into the memory map */ +static void update_checksum(struct cio_file *cf, + unsigned char *data, size_t len) +{ + crc_t crc; + crc_t tmp; + + if (cf->crc_reset) { + cf->crc_cur = cio_crc32_init(); + cio_file_calculate_checksum(cf, &tmp); + cf->crc_cur = tmp; + cf->crc_reset = CIO_FALSE; + } + + crc = cio_crc32_update(cf->crc_cur, data, len); + memcpy(cf->map + 2, &crc, sizeof(crc)); + cf->crc_cur = crc; +} + +/* Finalize CRC32 context and update the memory map */ +static void finalize_checksum(struct cio_file *cf) +{ + crc_t crc; + + crc = cio_crc32_finalize(cf->crc_cur); + crc = htonl(crc); + + memcpy(cf->map + 2, &crc, sizeof(crc)); +} + +/* + * adjust_layout: if metadata has changed, we need to adjust the content + * data and reference pointers. + */ +static int adjust_layout(struct cio_chunk *ch, + struct cio_file *cf, size_t meta_size) +{ + cio_file_st_set_meta_len(cf->map, (uint16_t) meta_size); + + /* Update checksum */ + if (ch->ctx->options.flags & CIO_CHECKSUM) { + /* reset current crc since we are calculating from zero */ + cf->crc_cur = cio_crc32_init(); + cio_file_calculate_checksum(cf, &cf->crc_cur); + } + + /* Sync changes to disk */ + cf->synced = CIO_FALSE; + + return 0; +} + +/* Initialize Chunk header & structure */ +static void write_init_header(struct cio_chunk *ch, struct cio_file *cf) +{ + memcpy(cf->map, cio_file_init_bytes, sizeof(cio_file_init_bytes)); + + /* If no checksum is enabled, reset the initial crc32 bytes */ + if (!(ch->ctx->options.flags & CIO_CHECKSUM)) { + cf->map[2] = 0; + cf->map[3] = 0; + cf->map[4] = 0; + cf->map[5] = 0; + } + + cio_file_st_set_content_len(cf->map, 0); +} + +/* Return the available size in the file map to write data */ +static size_t get_available_size(struct cio_file *cf, int *meta_len) +{ + size_t av; + int metadata_len; + + /* Get metadata length */ + metadata_len = cio_file_st_get_meta_len(cf->map); + + av = cf->alloc_size; + av -= CIO_FILE_HEADER_MIN; + av -= metadata_len; + av -= cf->data_size; + + *meta_len = metadata_len; + + return av; +} + +/* + * For the recently opened or created file, check the structure format + * and validate relevant fields. + */ +static int cio_file_format_check(struct cio_chunk *ch, + struct cio_file *cf, int flags) +{ + size_t metadata_length; + ssize_t content_length; + ssize_t logical_length; + unsigned char *p; + crc_t crc_check; + crc_t crc; + + (void) flags; + + p = (unsigned char *) cf->map; + + /* If the file is empty, put the structure on it */ + if (cf->fs_size == 0) { + /* check we have write permissions */ + if ((cf->flags & CIO_OPEN) == 0) { + cio_log_warn(ch->ctx, + "[cio file] cannot initialize chunk (read-only)"); + cio_error_set(ch, CIO_ERR_PERMISSION); + + return -1; + } + + /* at least we need 24 bytes as allocated space */ + if (cf->alloc_size < CIO_FILE_HEADER_MIN) { + cio_log_warn(ch->ctx, "[cio file] cannot initialize chunk"); + cio_error_set(ch, CIO_ERR_BAD_LAYOUT); + + return -1; + } + + /* Initialize init bytes */ + write_init_header(ch, cf); + + /* Write checksum in context (note: crc32 not finalized) */ + if (ch->ctx->options.flags & CIO_CHECKSUM) { + cio_file_calculate_checksum(cf, &cf->crc_cur); + } + } + else { + /* Check first two bytes */ + if (p[0] != CIO_FILE_ID_00 || p[1] != CIO_FILE_ID_01) { + cio_log_debug(ch->ctx, "[cio file] invalid header at %s", + ch->name); + cio_error_set(ch, CIO_ERR_BAD_LAYOUT); + + return -1; + } + + /* Expected / logical file size verification */ + content_length = cio_file_st_get_content_len(cf->map, + cf->fs_size, + cf->page_size); + + if (content_length == -1) { + cio_log_debug(ch->ctx, "[cio file] truncated header (%zu / %zu) %s", + cf->fs_size, CIO_FILE_HEADER_MIN, ch->name); + cio_error_set(ch, CIO_ERR_BAD_FILE_SIZE); + + return -1; + } + + metadata_length = cio_file_st_get_meta_len(cf->map); + + logical_length = CIO_FILE_HEADER_MIN + + metadata_length + + content_length; + + if (logical_length > cf->fs_size) { + cio_log_debug(ch->ctx, "[cio file] truncated file (%zd / %zd) %s", + cf->fs_size, logical_length, ch->name); + cio_error_set(ch, CIO_ERR_BAD_FILE_SIZE); + + return -1; + } + + /* Checksum */ + if (ch->ctx->options.flags & CIO_CHECKSUM) { + /* Initialize CRC variable */ + cf->crc_cur = cio_crc32_init(); + + /* Get checksum stored in the mmap */ + p = (unsigned char *) cio_file_st_get_hash(cf->map); + + /* Calculate content checksum */ + cio_file_calculate_checksum(cf, &crc); + + /* Compare */ + crc_check = cio_crc32_finalize(crc); + crc_check = htonl(crc_check); + + if (memcmp(p, &crc_check, sizeof(crc_check)) != 0) { + cio_log_info(ch->ctx, "[cio file] invalid crc32 at %s/%s", + ch->name, cf->path); + cio_error_set(ch, CIO_ERR_BAD_CHECKSUM); + + return -1; + } + + cf->crc_cur = crc; + } + } + + return 0; +} + +/* + * Unmap the memory for the opened file in question. It make sure + * to sync changes to disk first. + */ +static int munmap_file(struct cio_ctx *ctx, struct cio_chunk *ch) +{ + int ret; + struct cio_file *cf; + + cf = (struct cio_file *) ch->backend; + + if (!cf) { + return -1; + } + + /* File not mapped */ + if (cf->map == NULL) { + return -1; + } + + /* Sync pending changes to disk */ + if (cf->synced == CIO_FALSE) { + ret = cio_file_sync(ch); + if (ret == -1) { + cio_log_error(ch->ctx, + "[cio file] error syncing file at " + "%s:%s", ch->st->name, ch->name); + } + } + + /* Unmap file */ + cio_file_native_unmap(cf); + + cf->data_size = 0; + cf->alloc_size = 0; + + /* Adjust counters */ + cio_chunk_counter_total_up_sub(ctx); + + return 0; +} + +/* + * This function creates the memory map for the open file descriptor plus + * setup the chunk structure reference. + */ +static int mmap_file(struct cio_ctx *ctx, struct cio_chunk *ch, size_t size) +{ + ssize_t content_size; + size_t fs_size; + int ret; + struct cio_file *cf; + + cf = (struct cio_file *) ch->backend; + + if (cf->map != NULL) { + return CIO_OK; + } + + /* + * 'size' value represents the value of a previous fstat(2) set by a previous + * caller. If the value is greater than zero, just use it, otherwise do a new + * fstat(2) of the file descriptor. + */ + + fs_size = 0; + + if (size > 0) { + fs_size = size; + } + else { + /* Get file size from the file system */ + ret = cio_file_native_get_size(cf, &fs_size); + + if (ret != CIO_OK) { + cio_file_report_os_error(); + + return CIO_ERROR; + } + } + + /* If the file is not empty, use file size for the memory map */ + if (fs_size > 0) { + size = fs_size; + cf->synced = CIO_TRUE; + } + else if (fs_size == 0) { + /* We can only prepare a file if it has been opened in RW mode */ + if ((cf->flags & CIO_OPEN_RW) == 0) { + cio_error_set(ch, CIO_ERR_PERMISSION); + + return CIO_CORRUPTED; + } + + cf->synced = CIO_FALSE; + + /* Adjust size to make room for headers */ + if (size < CIO_FILE_HEADER_MIN) { + size += CIO_FILE_HEADER_MIN; + } + + /* For empty files, make room in the file system */ + size = ROUND_UP(size, ctx->page_size); + ret = cio_file_resize(cf, size); + + if (ret != CIO_OK) { + cio_log_error(ctx, "cannot adjust chunk size '%s' to %lu bytes", + cf->path, size); + + return CIO_ERROR; + } + + cio_log_debug(ctx, "%s:%s adjusting size OK", ch->st->name, ch->name); + } + + cf->alloc_size = size; + + /* Map the file */ + ret = cio_file_native_map(cf, cf->alloc_size); + + if (ret != CIO_OK) { + cio_log_error(ctx, "cannot mmap/read chunk '%s'", cf->path); + + return CIO_ERROR; + } + + /* check content data size */ + if (fs_size > 0) { + content_size = cio_file_st_get_content_len(cf->map, + fs_size, + cf->page_size); + + if (content_size == -1) { + cio_error_set(ch, CIO_ERR_BAD_FILE_SIZE); + + cio_log_error(ctx, "invalid content size %s", cf->path); + + cio_file_native_unmap(cf); + + cf->data_size = 0; + cf->alloc_size = 0; + + return CIO_CORRUPTED; + } + + + cf->data_size = content_size; + cf->fs_size = fs_size; + } + else { + cf->data_size = 0; + cf->fs_size = 0; + } + + ret = cio_file_format_check(ch, cf, cf->flags); + + if (ret != 0) { + cio_log_error(ctx, "format check failed: %s/%s", + ch->st->name, ch->name); + + cio_file_native_unmap(cf); + + cf->data_size = 0; + + return CIO_CORRUPTED; + } + + cf->st_content = cio_file_st_get_content(cf->map); + cio_log_debug(ctx, "%s:%s mapped OK", ch->st->name, ch->name); + + /* The mmap succeeded, adjust the counters */ + cio_chunk_counter_total_up_add(ctx); + + return CIO_OK; +} + +int cio_file_lookup_user(char *user, void **result) +{ + return cio_file_native_lookup_user(user, result); +} + +int cio_file_lookup_group(char *group, void **result) +{ + return cio_file_native_lookup_group(group, result); +} + +int cio_file_read_prepare(struct cio_ctx *ctx, struct cio_chunk *ch) +{ + return mmap_file(ctx, ch, 0); +} + +int cio_file_content_copy(struct cio_chunk *ch, + void **out_buf, size_t *out_size) +{ + int ret; + int set_down = CIO_FALSE; + char *buf; + char *data = NULL; + size_t size; + struct cio_file *cf = ch->backend; + + /* If the file content is already up, just do a copy of the memory map */ + if (cio_chunk_is_up(ch) == CIO_FALSE) { + ret = cio_chunk_up_force(ch); + if (ret != CIO_OK ){ + return CIO_ERROR; + } + set_down = CIO_TRUE; + } + + size = cf->data_size; + data = cio_file_st_get_content(cf->map); + + if (!data) { + if (set_down == CIO_TRUE) { + cio_chunk_down(ch); + } + return CIO_ERROR; + } + + buf = malloc(size + 1); + if (!buf) { + cio_errno(); + if (set_down == CIO_TRUE) { + cio_chunk_down(ch); + } + return CIO_ERROR; + } + memcpy(buf, data, size); + buf[size] = '\0'; + + *out_buf = buf; + *out_size = size; + + if (set_down == CIO_TRUE) { + cio_chunk_down(ch); + } + + return CIO_OK; +} + +/* + * If the maximum number of 'up' chunks is reached, put this chunk + * down (only at open time). + */ +static inline int open_and_up(struct cio_ctx *ctx) +{ + if (ctx->total_chunks_up >= ctx->max_chunks_up) { + return CIO_FALSE; + } + + return CIO_TRUE; +} + +/* + * Fetch the file size regardless of if we opened this file or not. + */ +size_t cio_file_real_size(struct cio_file *cf) +{ + size_t file_size; + int ret; + + ret = cio_file_native_get_size(cf, &file_size); + + if (ret != CIO_OK) { + return 0; + } + + return file_size; +} + +static int format_acl_error_message(struct cio_ctx *ctx, + struct cio_file *cf, + char *output_buffer, + size_t output_buffer_size) +{ + char *connector; + int result; + char *group; + char *user; + + user = ctx->options.user; + group = ctx->options.group; + connector = "with group"; + + if (user == NULL) { + user = ""; + connector = ""; + } + + if (group == NULL) { + group = ""; + connector = ""; + } + + result = snprintf(output_buffer, output_buffer_size - 1, + "cannot change ownership of %s to %s %s %s", + cf->path, user, connector, group); + + if (result < 0) { + return CIO_ERROR; + } + + return CIO_OK; +} + +/* + * Open or create a data file: the following behavior is expected depending + * of the passed flags: + * + * CIO_OPEN | CIO_OPEN_RW: + * - Open for read/write, if the file don't exist, it's created and the + * memory map size is assigned to the given value on 'size'. + * + * CIO_OPEN_RD: + * - If file exists, open it in read-only mode. + */ +struct cio_file *cio_file_open(struct cio_ctx *ctx, + struct cio_stream *st, + struct cio_chunk *ch, + int flags, + size_t size, + int *err) +{ + char error_message[256]; + char *path; + int ret; + struct cio_file *cf; + + (void) size; + + ret = cio_file_native_filename_check(ch->name); + if (ret != CIO_OK) { + cio_log_error(ctx, "[cio file] invalid file name"); + + return NULL; + } + + path = cio_file_native_compose_path(ctx->options.root_path, st->name, ch->name); + if (path == NULL) { + return NULL; + } + + /* Create file context */ + cf = calloc(1, sizeof(struct cio_file)); + if (!cf) { + cio_errno(); + free(path); + + return NULL; + } + + cf->fd = -1; + cf->flags = flags; + cf->page_size = cio_getpagesize(); + + if (ctx->realloc_size_hint > 0) { + cf->realloc_size = ctx->realloc_size_hint; + } + else { + cf->realloc_size = CIO_REALLOC_HINT_MIN; + } + + cf->st_content = NULL; + cf->crc_cur = cio_crc32_init(); + cf->path = path; + cf->map = NULL; + ch->backend = cf; + +#ifdef _WIN32 + cf->backing_file = INVALID_HANDLE_VALUE; + cf->backing_mapping = INVALID_HANDLE_VALUE; +#endif + +#if defined (CIO_HAVE_FALLOCATE) + cf->allocate_strategy = CIO_FILE_LINUX_FALLOCATE; +#endif + + /* Should we open and put this file up ? */ + ret = open_and_up(ctx); + + if (ret == CIO_FALSE) { + /* we reached our limit, leave the file 'down' */ + cio_file_update_size(cf); + + /* + * Due to he current resource limiting logic we could + * get to this point without a file existing so we just + * ignore the error. + */ + + return cf; + } + + /* Open the file */ + ret = cio_file_native_open(cf); + + if (ret != CIO_OK) { + free(path); + free(cf); + + *err = ret; + + return NULL; + } + + /* Update the file size field */ + ret = cio_file_update_size(cf); + + if (ret != CIO_OK) { + cio_file_native_close(cf); + + free(path); + free(cf); + + *err = ret; + + return NULL; + } + + /* Set the file ownership and permissions */ + ret = cio_file_native_apply_acl_and_settings(ctx, cf); + + if (ret != CIO_OK) { + *err = ret; + + ret = format_acl_error_message(ctx, cf, error_message, sizeof(error_message)); + + if (ret != CIO_OK) { + cio_log_error(ctx, "error generating error message for acl failure"); + } + else { + cio_log_error(ctx, error_message); + } + + cio_file_native_close(cf); + + free(path); + free(cf); + + return NULL; + } + + /* Map the file */ + ret = mmap_file(ctx, ch, cf->fs_size); + if (ret == CIO_ERROR || ret == CIO_CORRUPTED || ret == CIO_RETRY) { + cio_file_native_close(cf); + + free(path); + free(cf); + + *err = ret; + + return NULL; + } + + *err = CIO_OK; + + return cf; +} + +/* This function is used to delete a chunk by name, its only purpose is to delete + * chunks that cannnot be loaded (otherwise we would set them down with the delete + * flag set to TRUE). + */ +int cio_file_delete(struct cio_ctx *ctx, struct cio_stream *st, const char *name) +{ + char *path; + int ret; + + ret = cio_file_native_filename_check((char *) name); + if (ret != CIO_OK) { + cio_log_error(ctx, "[cio file] invalid file name"); + + return CIO_ERROR; + } + + path = cio_file_native_compose_path(ctx->options.root_path, st->name, (char *) name); + if (path == NULL) { + return CIO_ERROR; + } + + ret = cio_file_native_delete_by_path(path); + + free(path); + + return ret; +} + +/* + * Put a file content back into memory, only IF it has been set 'down' + * before. + */ +static int _cio_file_up(struct cio_chunk *ch, int enforced) +{ + int ret; + struct cio_file *cf = (struct cio_file *) ch->backend; + + if (cf->map) { + cio_log_error(ch->ctx, "[cio file] file is already mapped: %s/%s", + ch->st->name, ch->name); + return CIO_ERROR; + } + + if (cf->fd > 0) { + cio_log_error(ch->ctx, "[cio file] file descriptor already exists: " + "[fd=%i] %s:%s", cf->fd, ch->st->name, ch->name); + return CIO_ERROR; + } + + /* + * Enforced mechanism provides safety based on Chunk I/O storage + * pre-set limits. + */ + if (enforced == CIO_TRUE) { + ret = open_and_up(ch->ctx); + if (ret == CIO_FALSE) { + return CIO_ERROR; + } + } + + /* Open file */ + ret = cio_file_native_open(cf); + + if (ret != CIO_OK) { + cio_log_error(ch->ctx, "[cio file] cannot open chunk: %s/%s", + ch->st->name, ch->name); + return CIO_ERROR; + } + + ret = cio_file_update_size(cf); + if (ret != CIO_OK) { + return CIO_ERROR; + } + + /* + * Map content: + * + * return values = CIO_OK, CIO_ERROR, CIO_CORRUPTED or CIO_RETRY + */ + ret = mmap_file(ch->ctx, ch, cf->fs_size); + if (ret == CIO_ERROR) { + cio_log_error(ch->ctx, "[cio file] cannot map chunk: %s/%s", + ch->st->name, ch->name); + } + + /* + * 'ret' can still be CIO_CORRUPTED or CIO_RETRY on those cases we + * close the file descriptor + */ + if (ret == CIO_CORRUPTED || ret == CIO_RETRY) { + /* + * we just remove resources: close the recently opened file + * descriptor, we never delete the Chunk at this stage since + * the caller must take that action. + */ + cio_file_native_close(cf); + } + + return ret; +} + +/* + * Load a file using 'enforced' mode: do not load the file in memory + * if we already passed memory or max_chunks_up restrictions. + */ +int cio_file_up(struct cio_chunk *ch) +{ + return _cio_file_up(ch, CIO_TRUE); +} + +/* Load a file in non-enforced mode. This means it will load the file + * in memory skipping restrictions set by configuration. + * + * The use case of this call is when the caller needs to write data + * to a file which is down due to restrictions. But then the caller + * must put the chunk 'down' again if that was it original status. + */ +int cio_file_up_force(struct cio_chunk *ch) +{ + return _cio_file_up(ch, CIO_FALSE); +} + +int cio_file_update_size(struct cio_file *cf) +{ + int result; + + result = cio_file_native_get_size(cf, &cf->fs_size); + + if (result != CIO_OK) { + cf->fs_size = 0; + } + + return result; +} + +/* Release memory and file descriptor resources but keep context */ +int cio_file_down(struct cio_chunk *ch) +{ + int ret; + struct cio_file *cf; + + cf = (struct cio_file *) ch->backend; + + if (cf->map == NULL) { + cio_log_error(ch->ctx, "[cio file] file is not mapped: %s/%s", + ch->st->name, ch->name); + return -1; + } + + /* unmap memory */ + munmap_file(ch->ctx, ch); + + /* Allocated map size is zero */ + cf->alloc_size = 0; + + /* Update the file size */ + ret = cio_file_update_size(cf); + + if (ret != CIO_OK) { + cio_errno(); + } + + /* Close file descriptor */ + cio_file_native_close(cf); + + return 0; +} + +void cio_file_close(struct cio_chunk *ch, int delete) +{ + int ret; + struct cio_file *cf; + + cf = (struct cio_file *) ch->backend; + + if (cf == NULL) { + return; + } + + /* Safe unmap of the file content */ + munmap_file(ch->ctx, ch); + + /* Close file descriptor */ + cio_file_native_close(cf); + + /* Should we delete the content from the file system ? */ + if (delete == CIO_TRUE) { + ret = cio_file_native_delete(cf); + + if (ret != CIO_OK) { + cio_log_error(ch->ctx, + "[cio file] error deleting file at close %s:%s", + ch->st->name, ch->name); + } + } + + free(cf->path); + free(cf); +} + + +int cio_file_write(struct cio_chunk *ch, const void *buf, size_t count) +{ + int ret; + int meta_len; + int pre_content; + size_t av_size; + size_t old_size; + size_t new_size; + struct cio_file *cf; + + if (count == 0) { + /* do nothing */ + return 0; + } + + if (!ch) { + return -1; + } + + cf = (struct cio_file *) ch->backend; + + if (cio_chunk_is_up(ch) == CIO_FALSE) { + cio_log_error(ch->ctx, "[cio file] file is not mmap()ed: %s:%s", + ch->st->name, ch->name); + return -1; + } + + /* get available size */ + av_size = get_available_size(cf, &meta_len); + + /* validate there is enough space, otherwise resize */ + if (av_size < count) { + /* Set the pre-content size (chunk header + metadata) */ + pre_content = (CIO_FILE_HEADER_MIN + meta_len); + + new_size = cf->alloc_size + cf->realloc_size; + while (new_size < (pre_content + cf->data_size + count)) { + new_size += cf->realloc_size; + } + + old_size = cf->alloc_size; + new_size = ROUND_UP(new_size, ch->ctx->page_size); + + ret = cio_file_resize(cf, new_size); + + if (ret != CIO_OK) { + cio_log_error(ch->ctx, + "[cio_file] error setting new file size on write"); + return -1; + } + + cio_log_debug(ch->ctx, + "[cio file] alloc_size from %lu to %lu", + old_size, new_size); + } + + /* If crc_reset was toggled we know that data_size was + * modified by cio_chunk_write_at which means we need + * to update the header before we recalculate the checksum + */ + if (cf->crc_reset) { + cio_file_st_set_content_len(cf->map, cf->data_size); + } + + if (ch->ctx->options.flags & CIO_CHECKSUM) { + update_checksum(cf, (unsigned char *) buf, count); + } + + cf->st_content = cio_file_st_get_content(cf->map); + memcpy(cf->st_content + cf->data_size, buf, count); + + cf->data_size += count; + cf->synced = CIO_FALSE; + + cio_file_st_set_content_len(cf->map, cf->data_size); + + return 0; +} + +int cio_file_write_metadata(struct cio_chunk *ch, char *buf, size_t size) +{ + int ret; + char *meta; + char *cur_content_data; + char *new_content_data; + size_t new_size; + size_t content_av; + size_t meta_av; + struct cio_file *cf; + + cf = ch->backend; + + if (cio_file_is_up(ch, cf) == CIO_FALSE) { + return -1; + } + + /* Get metadata pointer */ + meta = cio_file_st_get_meta(cf->map); + + /* Check if meta already have some space available to overwrite */ + meta_av = cio_file_st_get_meta_len(cf->map); + + /* If there is some space available, just overwrite */ + if (meta_av >= size) { + /* copy new metadata */ + memcpy(meta, buf, size); + + /* there are some remaining bytes, adjust.. */ + cur_content_data = cio_file_st_get_content(cf->map); + new_content_data = meta + size; + memmove(new_content_data, cur_content_data, cf->data_size); + adjust_layout(ch, cf, size); + + return 0; + } + + /* + * The optimal case is if there is no content data, the non-optimal case + * where we need to increase the memory map size, move the content area + * bytes to a different position and write the metadata. + * + * Calculate the available space in the content area. + */ + content_av = cf->alloc_size - cf->data_size; + + /* If there is no enough space, increase the file size and it memory map */ + if (content_av < size) { + new_size = (size - meta_av) + cf->data_size + CIO_FILE_HEADER_MIN; + + ret = cio_file_resize(cf, new_size); + + if (ret != CIO_OK) { + cio_log_error(ch->ctx, + "[cio meta] error resizing mapped file"); + + return -1; + } + } + + /* get meta reference again in case the map address has changed */ + meta = cio_file_st_get_meta(cf->map); + + /* set new position for the content data */ + cur_content_data = cio_file_st_get_content(cf->map); + new_content_data = meta + size; + memmove(new_content_data, cur_content_data, size); + + /* copy new metadata */ + memcpy(meta, buf, size); + adjust_layout(ch, cf, size); + + return 0; +} + +int cio_file_sync(struct cio_chunk *ch) +{ + int ret; + int meta_len; + size_t desired_size; + size_t file_size; + size_t av_size; + struct cio_file *cf; + + if (ch == NULL) { + return -1; + } + + cf = (struct cio_file *) ch->backend; + + if (cf == NULL) { + return -1; + } + + if (cf->flags & CIO_OPEN_RD) { + return 0; + } + + if (cf->synced == CIO_TRUE) { + return 0; + } + + ret = cio_file_native_get_size(cf, &file_size); + + if (ret != CIO_OK) { + cio_file_report_os_error(); + + return -1; + } + + /* File trimming has been made opt-in because it causes + * performance degradation and excessive fragmentation + * in XFS. + */ + if ((ch->ctx->options.flags & CIO_TRIM_FILES) != 0) { + /* If there are extra space, truncate the file size */ + av_size = get_available_size(cf, &meta_len); + + if (av_size > 0) { + desired_size = cf->alloc_size - av_size; + } + else if (cf->alloc_size > file_size) { + desired_size = cf->alloc_size; + } + else { + desired_size = file_size; + } + + if (desired_size != file_size) { + /* When file trimming is enabled we still round the file size up + * to the memory page size because even though not explicitly + * stated there seems to be a performance degradation issue that + * correlates with sub-page mapping. + */ + desired_size = ROUND_UP(desired_size, ch->ctx->page_size); + + ret = cio_file_resize(cf, desired_size); + + if (ret != CIO_OK) { + cio_log_error(ch->ctx, + "[cio file sync] error adjusting size at: " + " %s/%s", ch->st->name, ch->name); + + return ret; + } + } + } + + /* Finalize CRC32 checksum */ + if (ch->ctx->options.flags & CIO_CHECKSUM) { + finalize_checksum(cf); + } + + /* Commit changes to disk */ + ret = cio_file_native_sync(cf, ch->ctx->options.flags); + + if (ret != CIO_OK) { + return -1; + } + + cf->synced = CIO_TRUE; + + ret = cio_file_update_size(cf); + + if (ret != CIO_OK) { + return -1; + } + + cio_log_debug(ch->ctx, "[cio file] synced at: %s/%s", + ch->st->name, ch->name); + + return 0; +} + +int cio_file_resize(struct cio_file *cf, size_t new_size) +{ + int inner_result; + size_t mapped_size; + int mapped_flag; + int result; + + mapped_flag = cio_file_native_is_mapped(cf); + mapped_size = cf->alloc_size; + +#ifdef _WIN32 + if (mapped_flag) { + result = cio_file_native_unmap(cf); + + if (result != CIO_OK) { + return result; + } + } +#endif + + result = cio_file_native_resize(cf, new_size); + + if (result != CIO_OK) { + cio_file_native_report_os_error(); + +#ifdef _WIN32 + if (mapped_flag) { + inner_result = cio_file_native_map(cf, mapped_size); + } +#endif + + return result; + } + + if (mapped_flag) { +#ifdef _WIN32 + result = cio_file_native_map(cf, new_size); +#else + result = cio_file_native_remap(cf, new_size); +#endif + + if (result != CIO_OK) { + return result; + } + } + + (void) mapped_size; + (void) inner_result; + + return CIO_OK; +} + +char *cio_file_hash(struct cio_file *cf) +{ + return (cf->map + 2); +} + +void cio_file_hash_print(struct cio_file *cf) +{ + printf("crc cur=%lu\n", (long unsigned int)cf->crc_cur); + printf("%08lx\n", (long unsigned int ) cf->crc_cur); +} + +/* Dump files from given stream */ +void cio_file_scan_dump(struct cio_ctx *ctx, struct cio_stream *st) +{ + int ret; + int meta_len; + int set_down = CIO_FALSE; + char *p; + crc_t crc; + crc_t crc_fs; + char tmp[PATH_MAX]; + struct mk_list *head; + struct cio_chunk *ch; + struct cio_file *cf; + + mk_list_foreach(head, &st->chunks) { + ch = mk_list_entry(head, struct cio_chunk, _head); + cf = ch->backend; + + if (cio_file_is_up(ch, cf) == CIO_FALSE) { + ret = cio_file_up(ch); + if (ret == -1) { + continue; + } + set_down = CIO_TRUE; + } + + snprintf(tmp, sizeof(tmp) -1, "%s/%s", st->name, ch->name); + meta_len = cio_file_st_get_meta_len(cf->map); + + p = cio_file_st_get_hash(cf->map); + + memcpy(&crc_fs, p, sizeof(crc_fs)); + crc_fs = ntohl(crc_fs); + + printf(" %-60s", tmp); + + /* + * the crc32 specified in the file is stored in 'val' now, if + * checksum mode is enabled we have to verify it. + */ + if (ctx->options.flags & CIO_CHECKSUM) { + cio_file_calculate_checksum(cf, &crc); + + /* + * finalize the checksum and compare it value using the + * host byte order. + */ + crc = cio_crc32_finalize(crc); + if (crc != crc_fs) { + printf("checksum error=%08x expected=%08x, ", + (uint32_t) crc_fs, (uint32_t) crc); + } + } + printf("meta_len=%d, data_size=%zu, crc=%08x\n", + meta_len, cf->data_size, (uint32_t) crc_fs); + + if (set_down == CIO_TRUE) { + cio_file_down(ch); + } + } +} + +/* Check if a file content is up in memory and a file descriptor is set */ +int cio_file_is_up(struct cio_chunk *ch, struct cio_file *cf) +{ + (void) ch; + + if (cio_file_native_is_open(cf) && + cio_file_native_is_mapped(cf)) { + return CIO_TRUE; + } + + return CIO_FALSE; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_file_unix.c b/src/fluent-bit/lib/chunkio/src/cio_file_unix.c new file mode 100644 index 000000000..72d49312d --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_file_unix.c @@ -0,0 +1,570 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <limits.h> +#include <pwd.h> +#include <grp.h> + +#include <chunkio/chunkio.h> +#include <chunkio/chunkio_compat.h> +#include <chunkio/cio_crc32.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_file_native.h> +#include <chunkio/cio_file_st.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_error.h> +#include <chunkio/cio_utils.h> + + +int cio_file_native_unmap(struct cio_file *cf) +{ + int ret; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (!cio_file_native_is_mapped(cf)) { + return CIO_OK; + } + + ret = munmap(cf->map, cf->alloc_size); + + if (ret != 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->alloc_size = 0; + cf->map = NULL; + + return CIO_OK; +} + +int cio_file_native_map(struct cio_file *cf, size_t map_size) +{ + int flags; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (!cio_file_native_is_open(cf)) { + return CIO_ERROR; + } + + if (cio_file_native_is_mapped(cf)) { + return CIO_OK; + } + + if (cf->flags & CIO_OPEN_RW) { + flags = PROT_READ | PROT_WRITE; + } + else if (cf->flags & CIO_OPEN_RD) { + flags = PROT_READ; + } + else { + return CIO_ERROR; + } + + cf->map = mmap(0, map_size, flags, MAP_SHARED, cf->fd, 0); + + if (cf->map == MAP_FAILED) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->alloc_size = map_size; + + return CIO_OK; +} + +int cio_file_native_remap(struct cio_file *cf, size_t new_size) +{ + int result; + void *tmp; + + result = 0; + +/* OSX mman does not implement mremap or MREMAP_MAYMOVE. */ +#ifndef MREMAP_MAYMOVE + result = cio_file_native_unmap(cf); + + if (result == -1) { + return result; + } + + tmp = mmap(0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, cf->fd, 0); +#else + (void) result; + + tmp = mremap(cf->map, cf->alloc_size, new_size, MREMAP_MAYMOVE); +#endif + + if (tmp == MAP_FAILED) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->map = tmp; + cf->alloc_size = new_size; + + return CIO_OK; +} + +int cio_file_native_lookup_user(char *user, void **result) +{ + long query_buffer_size; + struct passwd *query_result; + char *query_buffer; + struct passwd passwd_entry; + int api_result; + + if (user == NULL) { + *result = calloc(1, sizeof(uid_t)); + + if (*result == NULL) { + cio_file_native_report_runtime_error(); + + return CIO_ERROR; + } + + **(uid_t **) result = (uid_t) -1; + } + + query_buffer_size = sysconf(_SC_GETPW_R_SIZE_MAX); + + if (query_buffer_size == -1) { + query_buffer_size = 4096 * 10; + } + + query_buffer = calloc(1, query_buffer_size); + + if (query_buffer == NULL) { + return CIO_ERROR; + } + + query_result = NULL; + + api_result = getpwnam_r(user, &passwd_entry, query_buffer, + query_buffer_size, &query_result); + + if (api_result != 0 || query_result == NULL) { + cio_file_native_report_os_error(); + + free(query_buffer); + + return CIO_ERROR; + } + + *result = calloc(1, sizeof(uid_t)); + + if (*result == NULL) { + cio_file_native_report_runtime_error(); + + free(query_buffer); + + return CIO_ERROR; + } + + **(uid_t **) result = query_result->pw_uid; + + free(query_buffer); + + return CIO_OK; +} + +int cio_file_native_lookup_group(char *group, void **result) +{ + long query_buffer_size; + struct group *query_result; + char *query_buffer; + struct group group_entry; + int api_result; + + if (group == NULL) { + *result = calloc(1, sizeof(gid_t)); + + if (*result == NULL) { + cio_file_native_report_runtime_error(); + + return CIO_ERROR; + } + + **(gid_t **) result = (gid_t) -1; + } + + query_buffer_size = sysconf(_SC_GETGR_R_SIZE_MAX); + + if (query_buffer_size == -1) { + query_buffer_size = 4096 * 10; + } + + query_buffer = calloc(1, query_buffer_size); + + if (query_buffer == NULL) { + return CIO_ERROR; + } + + query_result = NULL; + + api_result = getgrnam_r(group, &group_entry, query_buffer, + query_buffer_size, &query_result); + + if (api_result != 0 || query_result == NULL) { + cio_file_native_report_os_error(); + + free(query_buffer); + + return CIO_ERROR; + } + + *result = calloc(1, sizeof(gid_t)); + + if (*result == NULL) { + cio_file_native_report_runtime_error(); + + free(query_buffer); + + return CIO_ERROR; + } + + **(gid_t **) result = query_result->gr_gid; + + free(query_buffer); + + return CIO_OK; +} + +int cio_file_native_apply_acl_and_settings(struct cio_ctx *ctx, struct cio_file *cf) +{ + mode_t filesystem_acl; + gid_t numeric_group; + uid_t numeric_user; + int result; + + numeric_group = -1; + numeric_user = -1; + + if (ctx->processed_user != NULL) { + numeric_user = *(uid_t *) ctx->processed_user; + } + + if (ctx->processed_group != NULL) { + numeric_group = *(gid_t *) ctx->processed_group; + } + + if (numeric_user != -1 || numeric_group != -1) { + result = chown(cf->path, numeric_user, numeric_group); + + if (result == -1) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + } + + if (ctx->options.chmod != NULL) { + filesystem_acl = strtoul(ctx->options.chmod, NULL, 8); + + result = chmod(cf->path, filesystem_acl); + + if (result == -1) { + cio_file_native_report_os_error(); + + cio_log_error(ctx, "cannot change acl of %s to %s", + cf->path, ctx->options.user); + + return CIO_ERROR; + } + } + + return CIO_OK; +} + +int cio_file_native_get_size(struct cio_file *cf, size_t *file_size) +{ + int ret; + struct stat st; + + ret = -1; + + if (cio_file_native_is_open(cf)) { + ret = fstat(cf->fd, &st); + } + + if (ret == -1) { + ret = stat(cf->path, &st); + } + + if (ret == -1) { + return CIO_ERROR; + } + + if (file_size != NULL) { + *file_size = st.st_size; + } + + return CIO_OK; +} + +char *cio_file_native_compose_path(char *root_path, char *stream_name, + char *chunk_name) +{ + size_t psize; + char *path; + int ret; + + /* Compose path for the file */ + psize = strlen(root_path) + + strlen(stream_name) + + strlen(chunk_name) + + 8; + + path = malloc(psize); + + if (path == NULL) { + cio_file_native_report_runtime_error(); + + return NULL; + } + + ret = snprintf(path, psize, "%s/%s/%s", + root_path, stream_name, chunk_name); + + if (ret == -1) { + cio_file_native_report_runtime_error(); + + free(path); + + return NULL; + } + + return path; +} + +int cio_file_native_filename_check(char *name) +{ + size_t len; + + len = strlen(name); + + if (len == 0) { + return CIO_ERROR; + } + if (len == 1) { + if ((name[0] == '.' || name[0] == '/')) { + return CIO_ERROR; + } + } + + return CIO_OK; +} + +int cio_file_native_open(struct cio_file *cf) +{ + if (cio_file_native_is_open(cf)) { + return CIO_OK; + } + + /* Open file descriptor */ + if (cf->flags & CIO_OPEN_RW) { + cf->fd = open(cf->path, O_RDWR | O_CREAT, (mode_t) 0600); + } + else if (cf->flags & CIO_OPEN_RD) { + cf->fd = open(cf->path, O_RDONLY); + } + + if (cf->fd == -1) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_close(struct cio_file *cf) +{ + int result; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (cio_file_native_is_open(cf)) { + result = close(cf->fd); + + if (result == -1) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->fd = -1; + } + + return CIO_OK; +} + +int cio_file_native_delete_by_path(const char *path) +{ + int result; + + result = unlink(path); + + if (result == -1) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_delete(struct cio_file *cf) +{ + int result; + + if (cio_file_native_is_open(cf) || + cio_file_native_is_mapped(cf)) { + return CIO_ERROR; + } + + result = unlink(cf->path); + + if (result == -1) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_sync(struct cio_file *cf, int sync_mode) +{ + int result; + + if (sync_mode & CIO_FULL_SYNC) { + sync_mode = MS_SYNC; + } + else { + sync_mode = MS_ASYNC; + } + + result = msync(cf->map, cf->alloc_size, sync_mode); + + if (result == -1) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_resize(struct cio_file *cf, size_t new_size) +{ + int fallocate_available; + int result; + + result = -1; + +#if defined(CIO_HAVE_FALLOCATE) || defined(CIO_HAVE_POSIX_FALLOCATE) + fallocate_available = CIO_TRUE; +#else + fallocate_available = CIO_FALSE; +#endif + + /* + * fallocate() is not portable an Linux only. Since macOS does not have + * fallocate() we use ftruncate(). + */ + if (fallocate_available && new_size > cf->fs_size) { + retry: + + if (cf->allocate_strategy == CIO_FILE_LINUX_FALLOCATE) { + /* + * To increase the file size we use fallocate() since this option + * will send a proper ENOSPC error if the file system ran out of + * space. ftruncate() will not fail and upon memcpy() over the + * mmap area it will trigger a 'Bus Error' crashing the program. + * + * fallocate() is not portable, Linux only. + */ +#if defined(CIO_HAVE_FALLOCATE) + result = fallocate(cf->fd, 0, 0, new_size); + +#elif defined(CIO_HAVE_POSIX_FALLOCATE) + result = -1; + errno = EOPNOTSUPP; +#endif + + if (result == -1 && errno == EOPNOTSUPP) { + /* + * If fallocate fails with an EOPNOTSUPP try operation using + * posix_fallocate. Required since some filesystems do not support + * the fallocate operation e.g. ext3 and reiserfs. + */ + cf->allocate_strategy = CIO_FILE_LINUX_POSIX_FALLOCATE; + goto retry; + } + } + else if (cf->allocate_strategy == CIO_FILE_LINUX_POSIX_FALLOCATE) { +#if defined(CIO_HAVE_POSIX_FALLOCATE) + result = posix_fallocate(cf->fd, 0, new_size); +#else + goto fallback; +#endif + } + } + else + { +#if !defined(CIO_HAVE_POSIX_FALLOCATE) + fallback: +#endif + + result = ftruncate(cf->fd, new_size); + } + + if (result) { + cio_file_native_report_os_error(); + } + else { + cf->fs_size = new_size; + } + + return result; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_file_win32.c b/src/fluent-bit/lib/chunkio/src/cio_file_win32.c new file mode 100644 index 000000000..18044c404 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_file_win32.c @@ -0,0 +1,549 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <inttypes.h> +#include <stdio.h> + +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_crc32.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_file_native.h> +#include <chunkio/cio_file_st.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_stream.h> + +int cio_file_native_unmap(struct cio_file *cf) +{ + int result; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (!cio_file_native_is_open(cf)) { + return CIO_OK; + } + + if (!cio_file_native_is_mapped(cf)) { + return CIO_OK; + } + + result = UnmapViewOfFile(cf->map); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + CloseHandle(cf->backing_mapping); + + cf->backing_mapping = INVALID_HANDLE_VALUE; + cf->alloc_size = 0; + cf->map = NULL; + + return CIO_OK; +} + +int cio_file_native_map(struct cio_file *cf, size_t map_size) +{ + DWORD desired_protection; + DWORD desired_access; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (!cio_file_native_is_open(cf)) { + return CIO_ERROR; + } + + if (cio_file_native_is_mapped(cf)) { + return CIO_OK; + } + + if (cf->flags & CIO_OPEN_RW) { + desired_protection = PAGE_READWRITE; + desired_access = FILE_MAP_ALL_ACCESS; + } + else if (cf->flags & CIO_OPEN_RD) { + desired_protection = PAGE_READONLY; + desired_access = FILE_MAP_READ; + } + else { + return CIO_ERROR; + } + + cf->backing_mapping = CreateFileMappingA(cf->backing_file, NULL, + desired_protection, + 0, 0, NULL); + + if (cf->backing_mapping == NULL) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->map = MapViewOfFile(cf->backing_mapping, desired_access, 0, 0, map_size); + + if (cf->map == NULL) { + cio_file_native_report_os_error(); + + CloseHandle(cf->backing_mapping); + + cf->backing_mapping = INVALID_HANDLE_VALUE; + + return CIO_ERROR; + } + + cf->alloc_size = map_size; + + return CIO_OK; +} + +int cio_file_native_remap(struct cio_file *cf, size_t new_size) +{ + /* + * There's no reason for this function to exist because in windows + * we need to unmap, resize and then map again so there's no benefit + * from remapping and I'm not implementing a dummy version because I + * don't want anyone to read it and think there are any reasonable use + * cases for it. + */ + + (void) cf; + (void) new_size; + + return CIO_ERROR; +} + +static SID *perform_sid_lookup(char *account_name, SID_NAME_USE *result_sid_type) +{ + DWORD referenced_domain_name_length; + char referenced_domain_name[256]; + SID *reallocated_sid_buffer; + DWORD sid_buffer_size; + size_t retry_index; + SID *sid_buffer; + SID_NAME_USE sid_type; + int result; + + referenced_domain_name_length = 256; + sid_buffer_size = 256; + + sid_buffer = calloc(1, sid_buffer_size); + + if (sid_buffer == NULL) { + cio_file_native_report_runtime_error(); + + return NULL; + } + + result = 0; + sid_type = SidTypeUnknown; + + for (retry_index = 0 ; retry_index < 5 && !result ; retry_index++) { + result = LookupAccountNameA(NULL, + account_name, + sid_buffer, + &sid_buffer_size, + referenced_domain_name, + &referenced_domain_name_length, + &sid_type); + + if (!result) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + sid_buffer_size *= 2; + + reallocated_sid_buffer = realloc(sid_buffer, sid_buffer_size); + + if (reallocated_sid_buffer == NULL) { + cio_file_native_report_runtime_error(); + + free(sid_buffer); + + return NULL; + } + } + else { + cio_file_native_report_os_error(); + + free(sid_buffer); + + return NULL; + } + } + } + + if (result_sid_type != NULL) { + *result_sid_type = sid_type; + } + + return sid_buffer; +} + +static int perform_entity_lookup(char *name, + void **result, + SID_NAME_USE desired_sid_type) +{ + SID_NAME_USE result_sid_type; + + *result = (void **) perform_sid_lookup(name, &result_sid_type); + + if (*result == NULL) { + return CIO_ERROR; + } + + if (desired_sid_type != result_sid_type) { + free(*result); + + *result = NULL; + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_lookup_user(char *user, void **result) +{ + return perform_entity_lookup(user, result, SidTypeUser); +} + +int cio_file_native_lookup_group(char *group, void **result) +{ + return perform_entity_lookup(group, result, SidTypeGroup); +} + +static DWORD cio_file_win_chown(char *path, SID *user, SID *group) +{ + int result; + + /* Ownership here does not work in the same way it works in unixes + * so specifying both a user and group will end up with the group + * overriding the user if possible which can cause some misunderstandings. + */ + + result = ERROR_SUCCESS; + + if (user != NULL) { + result = SetNamedSecurityInfoA(path, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION, + user, NULL, NULL, NULL); + } + + if (group != NULL && result == ERROR_SUCCESS) { + result = SetNamedSecurityInfoA(path, SE_FILE_OBJECT, + GROUP_SECURITY_INFORMATION, + group, NULL, NULL, NULL); + } + + return result; +} + +int cio_file_native_apply_acl_and_settings(struct cio_ctx *ctx, struct cio_file *cf) +{ + int result; + + if (ctx->processed_user != NULL) { + result = cio_file_win_chown(cf->path, ctx->processed_user, ctx->processed_group); + + if (result != ERROR_SUCCESS) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + } + + return CIO_OK; +} + +static int get_file_size_by_handle(struct cio_file *cf, size_t *file_size) +{ + LARGE_INTEGER native_file_size; + int ret; + + memset(&native_file_size, 0, sizeof(native_file_size)); + + ret = GetFileSizeEx(cf->backing_file, &native_file_size); + + if (ret == 0) { + return CIO_ERROR; + } + + if (file_size != NULL) { + *file_size = (size_t) native_file_size.QuadPart; + } + + return CIO_OK; +} + +static int get_file_size_by_path(struct cio_file *cf, size_t *file_size) +{ + int ret; +#ifdef _WIN64 + struct _stat64 st; +#else + struct _stat32 st; +#endif + +#ifdef _WIN64 + ret = _stat64(cf->path, &st); +#else + ret = _stat32(cf->path, &st); +#endif + + if (ret == -1) { + return CIO_ERROR; + } + + if (file_size != NULL) { + *file_size = st.st_size; + } + + return CIO_OK; +} + +int cio_file_native_get_size(struct cio_file *cf, size_t *file_size) +{ + int ret; + + ret = CIO_ERROR; + + if (cf->backing_file != INVALID_HANDLE_VALUE) { + ret = get_file_size_by_handle(cf, file_size); + } + + if (ret != CIO_OK) { + ret = get_file_size_by_path(cf, file_size); + } + + return ret; +} + +char *cio_file_native_compose_path(char *root_path, char *stream_name, + char *chunk_name) +{ + size_t psize; + char *path; + int ret; + + /* Compose path for the file */ + psize = strlen(root_path) + + strlen(stream_name) + + strlen(chunk_name) + + 3; + + path = malloc(psize); + + if (path == NULL) { + cio_file_native_report_runtime_error(); + + return NULL; + } + + ret = snprintf(path, psize, "%s\\%s\\%s", + root_path, stream_name, chunk_name); + + if (ret == -1) { + cio_file_native_report_runtime_error(); + + free(path); + + return NULL; + } + + return path; +} + +int cio_file_native_filename_check(char *name) +{ + size_t len; + + len = strlen(name); + + if (len == 0) { + return CIO_ERROR; + } + else if (len == 1) { + if (name[0] == '\\' || name[0] == '.' || name[0] == '/') { + return CIO_ERROR; + } + } + + return CIO_OK; +} + +int cio_file_native_open(struct cio_file *cf) +{ + DWORD creation_disposition; + DWORD desired_access; + + if (cio_file_native_is_open(cf)) { + return CIO_OK; + } + + if (cf->flags & CIO_OPEN) { + desired_access = GENERIC_READ | GENERIC_WRITE; + creation_disposition = OPEN_ALWAYS; + } + else if (cf->flags & CIO_OPEN_RD) { + desired_access = GENERIC_READ; + creation_disposition = OPEN_EXISTING; + } + else { + return CIO_ERROR; + } + + cf->backing_file = CreateFileA(cf->path, + desired_access, + FILE_SHARE_DELETE | + FILE_SHARE_READ | + FILE_SHARE_WRITE, + NULL, + creation_disposition, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (cf->backing_file == INVALID_HANDLE_VALUE) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_close(struct cio_file *cf) +{ + int result; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (cio_file_native_is_open(cf)) { + result = CloseHandle(cf->backing_file); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->backing_file = INVALID_HANDLE_VALUE; + } + + return CIO_OK; +} + +int cio_file_native_delete_by_path(const char *path) +{ + int result; + + result = DeleteFileA(path); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_delete(struct cio_file *cf) +{ + int result; + + result = DeleteFileA(cf->path); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_sync(struct cio_file *cf, int sync_mode) +{ + int result; + + result = FlushViewOfFile(cf->map, cf->alloc_size); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + if (sync_mode & CIO_FULL_SYNC) { + result = FlushFileBuffers(cf->backing_file); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + } + + return CIO_OK; +} + +int cio_file_native_resize(struct cio_file *cf, size_t new_size) +{ + LARGE_INTEGER movement_distance; + int result; + + if (!cio_file_native_is_open(cf)) { + return CIO_ERROR; + } + + if (cio_file_native_is_mapped(cf)) { + return CIO_ERROR; + } + + movement_distance.QuadPart = new_size; + + result = SetFilePointerEx(cf->backing_file, + movement_distance, + NULL, FILE_BEGIN); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + result = SetEndOfFile(cf->backing_file); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->fs_size = new_size; + + return CIO_OK; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_log.c b/src/fluent-bit/lib/chunkio/src/cio_log.c new file mode 100644 index 000000000..8c6e8123c --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_log.c @@ -0,0 +1,87 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_log.h> + +void cio_log_print(void *ctx, int level, const char *file, int line, + const char *fmt, ...) +{ + int ret; + char buf[CIO_LOG_BUF_SIZE]; + va_list args; + struct cio_ctx *cio = ctx; + + if (!cio->options.log_cb) { + return; + } + + if (level > cio->options.log_level) { + return; + } + + va_start(args, fmt); + ret = vsnprintf(buf, CIO_LOG_BUF_SIZE - 1, fmt, args); + + if (ret >= 0) { + buf[ret] = '\0'; + } + va_end(args); + + cio->options.log_cb(ctx, level, file, line, buf); +} + +int cio_errno_print(int errnum, const char *file, int line) +{ + char buf[256]; + + strerror_r(errnum, buf, sizeof(buf) - 1); + fprintf(stderr, "[%s:%i errno=%i] %s\n", + file, line, errnum, buf); + return 0; +} + +#ifdef _WIN32 +void cio_winapi_error_print(const char *func, int line) +{ + int error = GetLastError(); + char buf[256]; + int success; + + success = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error, + LANG_SYSTEM_DEFAULT, + buf, + sizeof(buf), + NULL); + if (success) { + fprintf(stderr, "[%s() line=%i error=%i] %s\n", func, line, error, buf); + } + else { + fprintf(stderr, "[%s() line=%i error=%i] Win32 API failed\n", func, line, error); + } +} +#endif diff --git a/src/fluent-bit/lib/chunkio/src/cio_memfs.c b/src/fluent-bit/lib/chunkio/src/cio_memfs.c new file mode 100644 index 000000000..8cd0f6c10 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_memfs.c @@ -0,0 +1,156 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <chunkio/chunkio.h> +#include <chunkio/cio_utils.h> +#include <chunkio/chunkio_compat.h> +#include <chunkio/cio_memfs.h> +#include <chunkio/cio_log.h> + +#include <stdio.h> +#include <string.h> +#include <limits.h> + +struct cio_memfs *cio_memfs_open(struct cio_ctx *ctx, struct cio_stream *st, + struct cio_chunk *ch, int flags, + size_t size) +{ + struct cio_memfs *mf; + + (void) flags; + (void) ctx; + (void) ch; + (void) st; + + mf = calloc(1, sizeof(struct cio_memfs)); + if (!mf) { + cio_errno(); + return NULL; + } + mf->crc_cur = cio_crc32_init(); + + mf->buf_data = malloc(size); + if (!mf->buf_data) { + cio_errno(); + free(mf->name); + free(mf); + return NULL; + } + mf->buf_size = size; + mf->buf_len = 0; + if (ctx->realloc_size_hint > 0) { + mf->realloc_size = ctx->realloc_size_hint; + } else { + mf->realloc_size = cio_getpagesize() * 8; + } + + return mf; +} + +void cio_memfs_close(struct cio_chunk *ch) +{ + struct cio_memfs *mf = ch->backend; + + if (!mf) { + return; + } + + free(mf->name); + free(mf->buf_data); + free(mf->meta_data); + free(mf); +} + +int cio_memfs_write(struct cio_chunk *ch, const void *buf, size_t count) +{ + size_t av_size; + size_t new_size; + char *tmp; + struct cio_memfs *mf = ch->backend; + + if (count == 0) { + return 0; + } + + /* Calculate available size */ + av_size = (mf->buf_size - mf->buf_len); + if (av_size < count) { + + /* Suggest initial new size */ + new_size = mf->buf_size + mf->realloc_size; + while (new_size < (mf->buf_len + count)) { + new_size += mf->realloc_size; + } + + tmp = realloc(mf->buf_data, new_size); + if (!tmp) { + cio_errno(); + return -1; + } + + mf->buf_data = tmp; + mf->buf_size = new_size; + } + + memcpy(mf->buf_data + mf->buf_len, buf, count); + mf->buf_len += count; + + return 0; +} + +int cio_memfs_content_copy(struct cio_chunk *ch, + void **out_buf, size_t *out_size) +{ + char *buf; + struct cio_memfs *mf = ch->backend; + + buf = malloc(mf->buf_len + 1); + if (!buf) { + cio_errno(); + return -1; + } + + /* Copy the data and append an extra NULL byte */ + memcpy(buf, mf->buf_data, mf->buf_len); + buf[mf->buf_len] = '\0'; + + *out_buf = buf; + *out_size = mf->buf_len; + + return 0; +} + +void cio_memfs_scan_dump(struct cio_ctx *ctx, struct cio_stream *st) +{ + char tmp[PATH_MAX]; + struct mk_list *head; + struct cio_memfs *mf; + struct cio_chunk *ch; + + (void) ctx; + + mk_list_foreach(head, &st->chunks) { + ch = mk_list_entry(head, struct cio_chunk, _head); + mf = ch->backend; + + snprintf(tmp, sizeof(tmp) -1, "%s/%s", ch->st->name, ch->name); + printf(" %-60s", tmp); + printf("meta_len=%i, data_size=%zu\n", mf->meta_len, mf->buf_len); + } +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_meta.c b/src/fluent-bit/lib/chunkio/src/cio_meta.c new file mode 100644 index 000000000..03e852e0b --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_meta.c @@ -0,0 +1,180 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include <string.h> + +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_file_st.h> +#include <chunkio/cio_memfs.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_log.h> + +/* + * Metadata is an optional information stored before the content of each file + * and can be used for different purposes. Manipulating metadata can have + * some performance impacts depending on 'when' it's added and how often + * is modified. + * + * For performance reasons, we suggest the metadata be stored before to write + * any data to the content area, otherwise if metadata grows in terms of bytes + * we need to move all the content data to a different position which is not + * ideal. + * + * The caller might want to fix the performance penalties setting up some + * empty metadata with specific sizes. + */ + +int cio_meta_write(struct cio_chunk *ch, char *buf, size_t size) +{ + struct cio_memfs *mf; + + if (size > 65535) { + return -1; + } + + if (ch->st->type == CIO_STORE_MEM) { + mf = (struct cio_memfs *) ch->backend; + if (mf->meta_data) { + free(mf->meta_data); + } + + mf->meta_data = malloc(size); + if (!mf->meta_data) { + cio_errno(); + return -1; + } + memcpy(mf->meta_data, buf, size); + mf->meta_len = size; + return 0; + } + else if (ch->st->type == CIO_STORE_FS) { + return cio_file_write_metadata(ch, buf, size); + } + return -1; +} + +int cio_meta_size(struct cio_chunk *ch) { + if (ch->st->type == CIO_STORE_MEM) { + struct cio_memfs *mf = (struct cio_memfs *) ch->backend; + return mf->meta_len; + } + else if (ch->st->type == CIO_STORE_FS) { + if (cio_file_read_prepare(ch->ctx, ch)) { + return -1; + } + struct cio_file *cf = ch->backend; + return cio_file_st_get_meta_len(cf->map); + } + + return -1; +} + +int cio_meta_read(struct cio_chunk *ch, char **meta_buf, int *meta_len) +{ + int len; + char *meta; + struct cio_file *cf; + struct cio_memfs *mf; + + /* In-memory type */ + if (ch->st->type == CIO_STORE_MEM) { + mf = (struct cio_memfs *) ch->backend; + + /* no metadata */ + if (!mf->meta_data) { + return -1; + } + + *meta_buf = mf->meta_data; + *meta_len = mf->meta_len; + + return 0; + } + else if (ch->st->type == CIO_STORE_FS) { + if (cio_file_read_prepare(ch->ctx, ch)) { + return -1; + } + + cf = ch->backend; + len = cio_file_st_get_meta_len(cf->map); + if (len <= 0) { + return -1; + } + + meta = cio_file_st_get_meta(cf->map); + *meta_buf = meta; + *meta_len = len; + + return 0; + } + + return -1; + +} + +int cio_meta_cmp(struct cio_chunk *ch, char *meta_buf, int meta_len) +{ + int len; + char *meta; + struct cio_file *cf = ch->backend; + struct cio_memfs *mf; + + /* In-memory type */ + if (ch->st->type == CIO_STORE_MEM) { + mf = (struct cio_memfs *) ch->backend; + + /* no metadata */ + if (!mf->meta_data) { + return -1; + } + + /* different lengths */ + if (mf->meta_len != meta_len) { + return -1; + } + + /* perfect match */ + if (memcmp(mf->meta_data, meta_buf, meta_len) == 0) { + return 0; + } + + return -1; + } + + if (cio_file_read_prepare(ch->ctx, ch)) { + return -1; + } + + /* File system type */ + len = cio_file_st_get_meta_len(cf->map); + if (len != meta_len) { + return -1; + } + + /* compare metadata */ + meta = cio_file_st_get_meta(cf->map); + if (memcmp(meta, meta_buf, meta_len) == 0) { + return 0; + } + + return -1; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_os.c b/src/fluent-bit/lib/chunkio/src/cio_os.c new file mode 100644 index 000000000..0adbc617c --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_os.c @@ -0,0 +1,134 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <chunkio/chunkio_compat.h> + +#ifdef _WIN32 +#include <Shlobj.h> +#endif + +/* Check if a path is a directory */ +int cio_os_isdir(const char *dir) +{ + int ret; + struct stat st; + + ret = stat(dir, &st); + if (ret == -1) { + return -1; + } + + if (st.st_mode & S_IFDIR) { + return 0; + } + + return -1; +} + +/* Create directory */ +int cio_os_mkpath(const char *dir, mode_t mode) +{ + struct stat st; + +#ifdef _WIN32 + char path[MAX_PATH]; +#else +# ifdef __APPLE__ + char *parent_dir = NULL; + char *path = NULL; +# endif + char *dup_dir; +#endif + + if (!dir) { + errno = EINVAL; + return 1; + } + + if (strlen(dir) == 0) { + errno = EINVAL; + return 1; + } + + if (!stat(dir, &st)) { + return 0; + } + +#ifdef _WIN32 + (void) mode; + + if (_fullpath(path, dir, MAX_PATH) == NULL) { + return 1; + } + + if (SHCreateDirectoryExA(NULL, path, NULL) != ERROR_SUCCESS) { + return 1; + } + return 0; +#elif __APPLE__ + dup_dir = strdup(dir); + if (!dup_dir) { + return -1; + } + + /* macOS's dirname(3) should return current directory when slash + * charachter is not included in passed string. + * And note that macOS's dirname(3) does not modify passed string. + */ + parent_dir = dirname(dup_dir); + if (stat(parent_dir, &st) == 0 && strncmp(parent_dir, ".", 1)) { + if (S_ISDIR (st.st_mode)) { + mkdir(dup_dir, mode); + free(dup_dir); + return 0; + } + } + + /* Create directories straightforward except for the last one hierarchy. */ + for (path = strchr(dup_dir + 1, '/'); path; path = strchr(path + 1, '/')) { + *path = '\0'; + if (mkdir(dup_dir, mode) == -1) { + if (errno != EEXIST) { + *path = '/'; + return -1; + } + } + *path = '/'; + } + + free(dup_dir); + return mkdir(dir, mode); +#else + dup_dir = strdup(dir); + if (!dup_dir) { + return 1; + } + cio_os_mkpath(dirname(dup_dir), mode); + free(dup_dir); + return mkdir(dir, mode); +#endif +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_scan.c b/src/fluent-bit/lib/chunkio/src/cio_scan.c new file mode 100644 index 000000000..5c90641df --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_scan.c @@ -0,0 +1,190 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_memfs.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_error.h> +#include <chunkio/cio_log.h> + +#ifdef _WIN32 +#include "win32/dirent.h" +#endif + +#ifdef CIO_HAVE_BACKEND_FILESYSTEM +static int cio_scan_stream_files(struct cio_ctx *ctx, struct cio_stream *st, + char *chunk_extension) +{ + int len; + int ret; + int err; + int ext_off; + int ext_len = 0; + char *path; + DIR *dir; + struct dirent *ent; + + len = strlen(ctx->options.root_path) + strlen(st->name) + 2; + path = malloc(len); + if (!path) { + cio_errno(); + return -1; + } + + ret = snprintf(path, len, "%s/%s", ctx->options.root_path, st->name); + if (ret == -1) { + cio_errno(); + free(path); + return -1; + } + + dir = opendir(path); + if (!dir) { + cio_errno(); + free(path); + return -1; + } + + if (chunk_extension) { + ext_len = strlen(chunk_extension); + } + + cio_log_debug(ctx, "[cio scan] opening stream %s", st->name); + + /* Iterate the root_path */ + while ((ent = readdir(dir)) != NULL) { + if ((ent->d_name[0] == '.') || (strcmp(ent->d_name, "..") == 0)) { + continue; + } + + /* Look just for directories */ + if (ent->d_type != DT_REG) { + continue; + } + + /* Check the file matches the desired extension (if set) */ + if (chunk_extension) { + len = strlen(ent->d_name); + if (len <= ext_len) { + continue; + } + + ext_off = len - ext_len; + if (strncmp(ent->d_name + ext_off, chunk_extension, ext_len) != 0) { + continue; + } + } + + ctx->last_chunk_error = 0; + + /* register every directory as a stream */ + cio_chunk_open(ctx, st, ent->d_name, ctx->options.flags, 0, &err); + + if (ctx->options.flags & CIO_DELETE_IRRECOVERABLE) { + if (err == CIO_CORRUPTED) { + if (ctx->last_chunk_error == CIO_ERR_BAD_FILE_SIZE || + ctx->last_chunk_error == CIO_ERR_BAD_LAYOUT) + { + cio_log_error(ctx, "[cio scan] discarding irrecoverable chunk"); + + cio_chunk_delete(ctx, st, ent->d_name); + } + } + } + } + + closedir(dir); + free(path); + + return 0; +} + +/* Given a cio context, scan it root_path and populate stream/files */ +int cio_scan_streams(struct cio_ctx *ctx, char *chunk_extension) +{ + DIR *dir; + struct dirent *ent; + struct cio_stream *st; + + dir = opendir(ctx->options.root_path); + if (!dir) { + cio_errno(); + return -1; + } + + cio_log_debug(ctx, "[cio scan] opening path %s", ctx->options.root_path); + + /* Iterate the root_path */ + while ((ent = readdir(dir)) != NULL) { + if ((ent->d_name[0] == '.') || (strcmp(ent->d_name, "..") == 0)) { + continue; + } + + /* Look just for directories */ + if (ent->d_type != DT_DIR) { + continue; + } + + /* register every directory as a stream */ + st = cio_stream_create(ctx, ent->d_name, CIO_STORE_FS); + if (st) { + cio_scan_stream_files(ctx, st, chunk_extension); + } + } + + closedir(dir); + return 0; +} +#else +int cio_scan_streams(struct cio_ctx *ctx) +{ + cio_log_error(ctx, "[cio scan] file system backend not supported"); + return -1; +} +#endif + +void cio_scan_dump(struct cio_ctx *ctx) +{ + struct mk_list *head; + struct cio_stream *st; + + cio_log_info(ctx, "scan dump of %s", ctx->options.root_path); + + /* Iterate streams */ + mk_list_foreach(head, &ctx->streams) { + st = mk_list_entry(head, struct cio_stream, _head); + printf(" stream:%-60s%i chunks\n", + st->name, mk_list_size(&st->chunks)); + + if (st->type == CIO_STORE_MEM) { + cio_memfs_scan_dump(ctx, st); + } + else if (st->type == CIO_STORE_FS) { + cio_file_scan_dump(ctx, st); + } + } +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_sha1.c b/src/fluent-bit/lib/chunkio/src/cio_sha1.c new file mode 100644 index 000000000..1748b683c --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_sha1.c @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Just a simple wrapper over sha1 routines */ + +#include <stdio.h> +#include <string.h> +#include <chunkio/cio_sha1.h> + +void cio_sha1_init(struct cio_sha1 *ctx) +{ + SHA1_Init(&ctx->sha); +} + +void cio_sha1_update(struct cio_sha1 *ctx, const void *data, unsigned long len) +{ + SHA1_Update(&ctx->sha, data, len); +} + +void cio_sha1_final(unsigned char hash[20], struct cio_sha1 *ctx) +{ + SHA1_Final(hash, &ctx->sha); +} + +void cio_sha1_hash(const void *data_in, unsigned long length, + unsigned char *data_out, void *state) +{ + SHA_CTX sha; + SHA1_Init(&sha); + SHA1_Update(&sha, data_in, length); + + /* + * If state is not NULL, make a copy of the SHA context for future + * iterations and updates. + */ + if (state != NULL) { + memcpy(state, &sha, sizeof(SHA_CTX)); + } + + SHA1_Final(data_out, &sha); +} + +void cio_sha1_to_hex(unsigned char *in, char *out) +{ + int i; + + for (i = 0; i < 20; ++i) { + sprintf(&out[i*2], "%02x", in[i]); + } + + out[40] = '\0'; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_stats.c b/src/fluent-bit/lib/chunkio/src/cio_stats.c new file mode 100644 index 000000000..2135f66f0 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_stats.c @@ -0,0 +1,79 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <string.h> + +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_stats.h> + +void cio_stats_get(struct cio_ctx *ctx, struct cio_stats *stats) +{ + struct mk_list *head; + struct mk_list *f_head; + struct cio_chunk *ch; + struct cio_stream *stream; + + memset(stats, 0, sizeof(struct cio_stats)); + + /* Iterate each stream */ + mk_list_foreach(head, &ctx->streams) { + stream = mk_list_entry(head, struct cio_stream, _head); + stats->streams_total++; + + /* Iterate chunks */ + mk_list_foreach(f_head, &stream->chunks) { + stats->chunks_total++; + + if (stream->type == CIO_STORE_MEM) { + stats->chunks_mem++; + continue; + } + + /* Only applicable for 'file' type chunks */ + ch = mk_list_entry(f_head, struct cio_chunk, _head); + stats->chunks_fs++; + + if (cio_chunk_is_up(ch) == CIO_TRUE) { + stats->chunks_fs_up++; + } + else { + stats->chunks_fs_down++; + } + } + } +} + +void cio_stats_print_summary(struct cio_ctx *ctx) +{ + struct cio_stats st; + + /* retrieve stats */ + cio_stats_get(ctx, &st); + + printf("======== Chunk I/O Stats ========\n"); + printf("- streams total : %i\n", st.streams_total); + printf("- chunks total : %i\n", st.chunks_total); + printf("- chunks memfs total: %i\n", st.chunks_mem); + printf("- chunks file total : %i\n", st.chunks_fs); + printf(" - files up : %i\n", st.chunks_fs_up); + printf(" - files down : %i\n", st.chunks_fs_down); +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_stream.c b/src/fluent-bit/lib/chunkio/src/cio_stream.c new file mode 100644 index 000000000..547d7eebf --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_stream.c @@ -0,0 +1,276 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <chunkio/chunkio_compat.h> + +#include <chunkio/chunkio.h> +#include <chunkio/cio_os.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_utils.h> + +#include <monkey/mk_core/mk_list.h> + +static char *get_stream_path(struct cio_ctx *ctx, struct cio_stream *st) +{ + int ret; + int len; + char *p; + + /* Compose final path */ + len = strlen(ctx->options.root_path) + strlen(st->name) + 2; + p = malloc(len + 1); + if (!p) { + cio_errno(); + return NULL; + } + + ret = snprintf(p, len, "%s/%s", ctx->options.root_path, st->name); + if (ret == -1) { + cio_errno(); + free(p); + return NULL; + } + + return p; +} + +static int check_stream_path(struct cio_ctx *ctx, const char *path) +{ + int ret; + int len; + char *p; + + /* Compose final path */ + len = strlen(ctx->options.root_path) + strlen(path) + 2; + p = malloc(len + 1); + if (!p) { + cio_errno(); + return -1; + } + ret = snprintf(p, len, "%s/%s", ctx->options.root_path, path); + if (ret == -1) { + cio_errno(); + free(p); + return -1; + } + + ret = cio_os_isdir(p); + if (ret == -1) { + /* Try to create the path */ + ret = cio_os_mkpath(p, 0755); + if (ret == -1) { + cio_log_error(ctx, "cannot create stream path %s", p); + free(p); + return -1; + } + cio_log_debug(ctx, "created stream path %s", p); + free(p); + return 0; + } + + /* Check write access and release*/ + ret = access(p, W_OK); + free(p); + return ret; +} + +struct cio_stream *cio_stream_get(struct cio_ctx *ctx, const char *name) +{ + struct mk_list *head; + struct cio_stream *st; + + mk_list_foreach(head, &ctx->streams) { + st = mk_list_entry(head, struct cio_stream, _head); + if (strcmp(st->name, name) == 0) { + return st; + } + } + + return NULL; +} + +struct cio_stream *cio_stream_create(struct cio_ctx *ctx, const char *name, + int type) +{ + int ret; + int len; + struct cio_stream *st; + + if (!name) { + cio_log_error(ctx, "[stream create] stream name not set"); + return NULL; + } + + len = strlen(name); + if (len == 0) { + cio_log_error(ctx, "[stream create] invalid stream name"); + return NULL; + } + + if (len == 1 && (name[0] == '.' || name[0] == '/')) { + cio_log_error(ctx, "[stream create] invalid stream name"); + return NULL; + } +#ifndef CIO_HAVE_BACKEND_FILESYSTEM + if (type == CIO_STORE_FS) { + cio_log_error(ctx, "[stream create] file system backend not supported"); + return NULL; + } +#endif + + /* Find duplicated */ + st = cio_stream_get(ctx, name); + if (st) { + cio_log_error(ctx, "[cio stream] stream already registered: %s", name); + return NULL; + } + + /* If backend is the file system, validate the stream path */ + if (type == CIO_STORE_FS) { + ret = check_stream_path(ctx, name); + if (ret == -1) { + return NULL; + } + } + + st = malloc(sizeof(struct cio_stream)); + if (!st) { + cio_errno(); + return NULL; + } + st->type = type; + st->name = strdup(name); + if (!st->name) { + cio_errno(); + free(st); + return NULL; + } + + st->parent = ctx; + mk_list_init(&st->chunks); + mk_list_init(&st->chunks_up); + mk_list_init(&st->chunks_down); + mk_list_add(&st->_head, &ctx->streams); + + cio_log_debug(ctx, "[cio stream] new stream registered: %s", name); + return st; +} + +void cio_stream_destroy(struct cio_stream *st) +{ + if (!st) { + return; + } + /* close all files */ + cio_chunk_close_stream(st); + + /* destroy stream */ + mk_list_del(&st->_head); + free(st->name); + free(st); +} + +/* Deletes a complete stream, this include all chunks available */ +int cio_stream_delete(struct cio_stream *st) +{ + int ret; + char *path; + struct mk_list *tmp; + struct mk_list *head; + struct cio_chunk *ch; + struct cio_ctx *ctx; + + ctx = st->parent; + + /* delete all chunks */ + mk_list_foreach_safe(head, tmp, &st->chunks) { + ch = mk_list_entry(head, struct cio_chunk, _head); + cio_chunk_close(ch, CIO_TRUE); + } + +#ifdef CIO_HAVE_BACKEND_FILESYSTEM + /* If the stream is filesystem based, destroy the real directory */ + if (st->type == CIO_STORE_FS) { + path = get_stream_path(ctx, st); + if (!path) { + cio_log_error(ctx, + "content from stream '%s' has been deleted, but the " + "directory might still exists.", path); + return -1; + } + + cio_log_debug(ctx, "[cio stream] delete stream path: %s", path); + + /* Recursive deletion */ + ret = cio_utils_recursive_delete(path); + if (ret == -1) { + cio_log_error(ctx, "error in recursive deletion of path %s", path); + free(path); + return -1; + } + free(path); + + return ret; + } +#endif + + return 0; +} + +void cio_stream_destroy_all(struct cio_ctx *ctx) +{ + struct mk_list *tmp; + struct mk_list *head; + struct cio_stream *st; + + if (!ctx) { + return; + } + + mk_list_foreach_safe(head, tmp, &ctx->streams) { + st = mk_list_entry(head, struct cio_stream, _head); + cio_stream_destroy(st); + } +} + +/* Return the total number of bytes being used by Chunks up in memory */ +size_t cio_stream_size_chunks_up(struct cio_stream *st) +{ + ssize_t bytes; + size_t total = 0; + struct cio_chunk *ch; + struct mk_list *head; + + mk_list_foreach(head, &st->chunks_up) { + ch = mk_list_entry(head, struct cio_chunk, _state_head); + + bytes = cio_chunk_get_content_size(ch); + if (bytes <= 0) { + continue; + } + total += bytes; + } + + return total; +} diff --git a/src/fluent-bit/lib/chunkio/src/cio_utils.c b/src/fluent-bit/lib/chunkio/src/cio_utils.c new file mode 100644 index 000000000..45cb0ae88 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/cio_utils.c @@ -0,0 +1,258 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#ifndef _MSC_VER +#include <fts.h> +#endif + +#include <chunkio/cio_info.h> +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_log.h> + +#ifndef _MSC_VER +/* + * Taken from StackOverflow: + * + * https://stackoverflow.com/questions/2256945/removing-a-non-empty-directory-programmatically-in-c-or-c + */ +int cio_utils_recursive_delete(const char *dir) +{ + int ret = 0; + FTS *ftsp = NULL; + FTSENT *curr; + char *files[] = { (char *) dir, NULL }; + struct stat st; + + ret = stat(dir, &st); + if (ret == -1) { + return -1; + } + + ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL); + if (!ftsp) { + fprintf(stderr, "%s: fts_open failed: %s\n", dir, strerror(errno)); + ret = -1; + goto finish; + } + + while ((curr = fts_read(ftsp))) { + switch (curr->fts_info) { + case FTS_NS: + case FTS_DNR: + case FTS_ERR: + fprintf(stderr, "%s: fts_read error: %s\n", + curr->fts_accpath, strerror(curr->fts_errno)); + break; + case FTS_DC: + case FTS_DOT: + case FTS_NSOK: + break; + case FTS_D: + break; + case FTS_DP: + case FTS_F: + case FTS_SL: + case FTS_SLNONE: + case FTS_DEFAULT: + if (remove(curr->fts_accpath) < 0) { + fprintf(stderr, "%s: Failed to remove: %s\n", + curr->fts_path, strerror(errno)); + ret = -1; + } + break; + } + } + + finish: + if (ftsp) { + fts_close(ftsp); + } + + return ret; +} +#else +static int cio_utils_recursive_delete_handler(const char *path, + size_t current_depth, + size_t depth_limit) +{ + char search_path[MAX_PATH]; + char entry_path[MAX_PATH]; + DWORD target_file_flags; + HANDLE find_file_handle; + WIN32_FIND_DATAA find_file_data; + int error_detected; + DWORD result; + + result = snprintf(search_path, sizeof(search_path) - 1, "%s\\*", path); + + if (result <= 0) { + return CIO_ERROR; + } + + find_file_handle = FindFirstFileA(search_path, &find_file_data); + + if (find_file_handle == INVALID_HANDLE_VALUE) { + return CIO_ERROR; + } + + target_file_flags = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE; + error_detected = CIO_FALSE; + result = 0; + + do { + if (strcmp(find_file_data.cFileName, ".") != 0 && + strcmp(find_file_data.cFileName, "..") != 0) { + + result = snprintf(entry_path, sizeof(entry_path) - 1, "%s\\%s", path, + find_file_data.cFileName); + + if (result > 0) { + if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (current_depth < depth_limit) { + result = (DWORD) cio_utils_recursive_delete_handler(entry_path, + current_depth + 1, + depth_limit); + + if (result != CIO_OK) { + error_detected = CIO_TRUE; + } + } + else { + error_detected = CIO_TRUE; + } + } + else if (find_file_data.dwFileAttributes & target_file_flags) { + result = DeleteFileA(entry_path); + + if (result == 0) { + error_detected = CIO_TRUE; + } + } + + } + else { + error_detected = CIO_TRUE; + } + } + + if (error_detected == CIO_FALSE) { + result = FindNextFile(find_file_handle, &find_file_data); + + if (result == 0) { + result = GetLastError(); + + if (result != ERROR_NO_MORE_FILES) { + error_detected = CIO_TRUE; + } + + break; + } + } + } + while (error_detected == CIO_FALSE); + + FindClose(find_file_handle); + + if (error_detected) { + return CIO_ERROR; + } + + result = RemoveDirectoryA(path); + + if (result == 0) { + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_utils_recursive_delete(const char *dir) +{ + DWORD result; + + result = cio_utils_recursive_delete_handler(dir, 0, 100); + + if (result != CIO_OK) { + return -1; + } + + return 0; +} +#endif + +int cio_utils_read_file(const char *path, char **buf, size_t *size) +{ + int ret; + char *data; + FILE *fp; + struct stat st; + + fp = fopen(path, "rb"); + if (fp == NULL) { + perror("fopen"); + return -1; + } + + ret = fstat(fileno(fp), &st); + if (ret == -1) { + fclose(fp); + perror("fstat"); + return -1; + } + if (!S_ISREG(st.st_mode)) { + fclose(fp); + return -1; + } + + data = calloc(st.st_size, 1); + if (!data) { + perror("calloc"); + fclose(fp); + return -1; + } + + ret = fread(data, st.st_size, 1, fp); + if (ret != 1) { + free(data); + fclose(fp); + return -1; + } + fclose(fp); + + *buf = data; + *size = st.st_size; + + return 0; +} + +#ifdef CIO_HAVE_GETPAGESIZE +int cio_getpagesize() +{ + return getpagesize(); +} +#endif diff --git a/src/fluent-bit/lib/chunkio/src/win32/dirent.c b/src/fluent-bit/lib/chunkio/src/win32/dirent.c new file mode 100644 index 000000000..6ea57f962 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/win32/dirent.c @@ -0,0 +1,135 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This module implements <dirent.h> emulation layer based on + * Win32's FIndFirstFile/FindNextFile API. + */ + +#include <Windows.h> +#include <shlwapi.h> + +#include "dirent.h" + +struct CIO_WIN32_DIR { + HANDLE h; + char *pattern; + int count; + WIN32_FIND_DATA find_data; + struct cio_win32_dirent dir; +}; + +/* + * Guess POSIX flle type from Win32 file attributes. + */ +static unsigned char get_filetype(int dwFileAttributes) +{ + if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + return DT_DIR; + } + else if (dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + return DT_LNK; + } + + return DT_REG; +} + +/* + * Construct a match pattern (e.g. 'c:\var\data\*') + */ +static char *create_pattern(const char *path) +{ + char *buf; + size_t len = strlen(path); + size_t buflen = len + 3; + + buf = malloc(buflen); + if (buf == NULL) { + return NULL; + } + + strcpy_s(buf, buflen, path); + + if (path[len - 1] == '\\') { + strcat_s(buf, buflen, "*"); + } + else { + strcat_s(buf, buflen, "\\*"); + } + return buf; +} + +struct CIO_WIN32_DIR *cio_win32_opendir(const char *path) +{ + struct CIO_WIN32_DIR *d; + + if (!PathIsDirectoryA(path)) { + return NULL; + } + + d = calloc(1, sizeof(struct CIO_WIN32_DIR)); + if (d == NULL) { + return NULL; + } + + d->pattern = create_pattern(path); + if (d->pattern == NULL) { + free(d); + return NULL; + } + + d->h = FindFirstFileA(d->pattern, &d->find_data); + if (d->h == INVALID_HANDLE_VALUE) { + return d; + } + return d; +} + +struct cio_win32_dirent *cio_win32_readdir(struct CIO_WIN32_DIR *d) +{ + if (d->h == INVALID_HANDLE_VALUE) { + return NULL; + } + + /* + * The initial entry should be retrieved by FindFirstFile(), + * so we can skip FindNextFile() on the first call. + */ + if (d->count > 0) { + if (FindNextFile(d->h, &d->find_data) == 0) { + return NULL; + } + } + + d->count++; + d->dir.d_name = d->find_data.cFileName; + d->dir.d_type = get_filetype(d->find_data.dwFileAttributes); + + return &d->dir; +} + +int cio_win32_closedir(struct CIO_WIN32_DIR *d) +{ + if (d->h != INVALID_HANDLE_VALUE) { + FindClose(d->h); + } + free(d->pattern); + free(d); + return 0; +} diff --git a/src/fluent-bit/lib/chunkio/src/win32/dirent.h b/src/fluent-bit/lib/chunkio/src/win32/dirent.h new file mode 100644 index 000000000..b21148a6c --- /dev/null +++ b/src/fluent-bit/lib/chunkio/src/win32/dirent.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018-2019 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * POSIX <dirent.h> emulation for Windows. + * + * This header file provies a drop-in replacement of opendir(), + * readdir() and closedir() for Windows platform. + */ + +#ifndef CIO_WIN32_DIRENT +#define CIO_WIN32_DIRENT + +struct CIO_WIN32_DIR; + +struct cio_win32_dirent { + int d_ino; + int d_off; + unsigned short d_reclen; + unsigned char d_type; + char *d_name; +}; + +struct CIO_WIN32_DIR *cio_win32_opendir(const char *path); +struct cio_win32_dirent *cio_win32_readdir(struct CIO_WIN32_DIR *d); +int cio_win32_closedir(struct CIO_WIN32_DIR *d); + +#define DIR struct CIO_WIN32_DIR +#define dirent cio_win32_dirent +#define closedir cio_win32_closedir +#define opendir cio_win32_opendir +#define readdir cio_win32_readdir + +#define DT_UNKNOWN -1 +#define DT_BLK 1 +#define DT_CHR 2 +#define DT_DIR 3 +#define DT_FIFO 4 +#define DT_LNK 5 +#define DT_REG 6 +#define DT_SOCK 7 + +#endif diff --git a/src/fluent-bit/lib/chunkio/tests/CMakeLists.txt b/src/fluent-bit/lib/chunkio/tests/CMakeLists.txt new file mode 100644 index 000000000..7cee7e6c9 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/CMakeLists.txt @@ -0,0 +1,57 @@ +include_directories(lib/acutest) + +set(UNIT_TESTS_FILES + context.c + memfs.c + stream.c + ) +if(CIO_BACKEND_FILESYSTEM) + set(UNIT_TESTS_FILES + ${UNIT_TESTS_FILES} + fs.c + ) +endif() + +set(CIO_TESTS_DATA_PATH ${CMAKE_CURRENT_SOURCE_DIR}/) +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cio_tests_internal.h.in" + "${CMAKE_CURRENT_SOURCE_DIR}/cio_tests_internal.h" + ) + +# Prepare list of unit tests +foreach(source_file ${UNIT_TESTS_FILES}) + get_filename_component(source_file_we ${source_file} NAME_WE) + set(source_file_we cio-test-${source_file_we}) + add_executable( + ${source_file_we} + ${source_file} + ) + target_link_libraries(${source_file_we} chunkio-static) + + if (CIO_SANITIZE_ADDRESS) + add_sanitizers(${source_file_we}) + endif() + + add_test(${source_file_we} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_file_we}) +endforeach() + +# Perf tests for dev purposes: note these tests are not registered, they need to +# be executed manually +set(UNIT_PERF_TESTS + fs_perf.c + fs_fragmentation.c + ) +foreach(source_file ${UNIT_PERF_TESTS}) + get_filename_component(source_file_we ${source_file} NAME_WE) + set(source_file_we cio-${source_file_we}) + add_executable( + ${source_file_we} + ${source_file} + ) + target_link_libraries(${source_file_we} chunkio-static) + + if (CIO_SANITIZE_ADDRESS) + add_sanitizers(${source_file_we}) + endif() + #add_test(${source_file_we} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source_file_we}) +endforeach() diff --git a/src/fluent-bit/lib/chunkio/tests/cio_tests_internal.h.in b/src/fluent-bit/lib/chunkio/tests/cio_tests_internal.h.in new file mode 100644 index 000000000..bf7b0d25b --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/cio_tests_internal.h.in @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_TEST_INTERNAL_H +#define CIO_TEST_INTERNAL_H + +#include "lib/acutest/include/acutest.h" +#include "test_utils.h" + +#define CIO_TESTS_DATA_PATH "@CIO_TESTS_DATA_PATH@" + +#endif diff --git a/src/fluent-bit/lib/chunkio/tests/context.c b/src/fluent-bit/lib/chunkio/tests/context.c new file mode 100644 index 000000000..7b7d9ea48 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/context.c @@ -0,0 +1,182 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <chunkio/chunkio.h> +#include <chunkio/cio_log.h> + +#include "cio_tests_internal.h" + +int log_check; + +/* Logging callback, once called it just turn on the log_check flag */ +static int log_cb(struct cio_ctx *ctx, int level, const char *file, int line, + char *str) +{ + (void) ctx; + (void) file; + (void) line; + (void) str; + + log_check = 1; + return 0; +} + +/* Basic tests on context creation */ +static void test_context() +{ + int flags; + struct cio_ctx *ctx; + struct cio_options cio_opts; + + flags = CIO_CHECKSUM; + + cio_options_init(&cio_opts); + cio_opts.flags = flags; + + /* Invalid path */ + cio_opts.root_path = ""; + cio_opts.log_level = CIO_LOG_INFO; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx == NULL); + + /* Invalid debug level -1 */ + cio_opts.root_path = "/tmp/"; + cio_opts.log_level = -1; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx == NULL); + + /* Invalid debug level 6 */ + cio_opts.log_level = 6; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx == NULL); + + /* Valid context without callback */ + log_check = 0; + cio_opts.log_level = CIO_LOG_INFO; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + cio_log_info(ctx, "test"); + TEST_CHECK(log_check == 0); + cio_destroy(ctx); + + /* Valid with context callback */ + log_check = 0; + cio_opts.log_cb = log_cb; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + cio_log_info(ctx, "test"); + TEST_CHECK(log_check == 1); + cio_destroy(ctx); +} + +static void test_log_level() +{ + struct cio_ctx *ctx; + struct cio_options cio_opts; + + cio_options_init(&cio_opts); + + /* Logging with unset callback at creation, but set later */ + log_check = 0; + cio_opts.root_path = "/tmp/"; + cio_opts.log_level = CIO_LOG_INFO; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + cio_log_info(ctx, "test"); + TEST_CHECK(log_check == 0); + + /* Loggin callback enable */ + cio_set_log_callback(ctx, log_cb); + cio_log_info(ctx, "test"); + TEST_CHECK(log_check == 1); + + /* Test: CIO_ERROR */ + cio_set_log_level(ctx, CIO_LOG_ERROR); + log_check = 0; + cio_log_warn(ctx, "test"); + TEST_CHECK(log_check == 0); + cio_log_error(ctx, "test"); + TEST_CHECK(log_check == 1); + + /* Test: CIO_WARN */ + cio_set_log_level(ctx, CIO_LOG_WARN); + log_check = 0; + cio_log_info(ctx, "test"); + TEST_CHECK(log_check == 0); + cio_log_warn(ctx, "test"); + TEST_CHECK(log_check == 1); + + /* Test: CIO_INFO */ + cio_set_log_level(ctx, CIO_LOG_INFO); + log_check = 0; + cio_log_debug(ctx, "test"); + TEST_CHECK(log_check == 0); + cio_log_info(ctx, "test"); + TEST_CHECK(log_check == 1); + + /* Test: CIO_DEBUG */ + cio_set_log_level(ctx, CIO_LOG_DEBUG); + log_check = 0; + cio_log_trace(ctx, "test"); + TEST_CHECK(log_check == 0); + cio_log_debug(ctx, "test"); + TEST_CHECK(log_check == 1); + + /* Test: CIO_TRACE */ + cio_set_log_level(ctx, CIO_LOG_TRACE); + log_check = 0; + cio_log_trace(ctx, "test"); + TEST_CHECK(log_check == 1); + + /* destroy context */ + cio_destroy(ctx); +} + +static void test_open_flags() +{ + struct cio_ctx *ctx; + struct cio_options cio_opts; + + cio_options_init(&cio_opts); + TEST_CHECK(cio_opts.flags & CIO_OPEN_RW); + + /* reset flags */ + cio_opts.flags = 0; + + /* check that after context creation a default has been set */ + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + TEST_CHECK(cio_opts.flags & CIO_OPEN_RW); + + /* destroy context */ + cio_destroy(ctx); +} + +TEST_LIST = { + {"context", test_context}, + {"log_level", test_log_level}, + {"open_flags", test_open_flags}, + { 0 } +}; diff --git a/src/fluent-bit/lib/chunkio/tests/data/400kb.txt b/src/fluent-bit/lib/chunkio/tests/data/400kb.txt new file mode 100644 index 000000000..8b0322c43 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/data/400kb.txt @@ -0,0 +1 @@ +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
\ No newline at end of file diff --git a/src/fluent-bit/lib/chunkio/tests/data/gen.sh b/src/fluent-bit/lib/chunkio/tests/data/gen.sh new file mode 100755 index 000000000..2a0ef6506 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/data/gen.sh @@ -0,0 +1 @@ +tr -dc A-Za-z0-9 </dev/urandom | head -c 409600 > 400kb.txt diff --git a/src/fluent-bit/lib/chunkio/tests/fs.c b/src/fluent-bit/lib/chunkio/tests/fs.c new file mode 100644 index 000000000..a976f46d1 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/fs.c @@ -0,0 +1,980 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WIN32 +#include <sys/mman.h> +#include <arpa/inet.h> +#endif +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <chunkio/chunkio.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_scan.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_meta.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_utils.h> +#include <chunkio/cio_error.h> +#include <chunkio/cio_file_native.h> + +#include "cio_tests_internal.h" + +#define CIO_ENV "/tmp/cio-fs-test/" +#define CIO_FILE_400KB CIO_TESTS_DATA_PATH "/data/400kb.txt" + + +/* Logging callback, once called it just turn on the log_check flag */ +static int log_cb(struct cio_ctx *ctx, int level, const char *file, int line, + char *str) +{ + (void) ctx; + + printf("[cio-test-fs] %-60s => %s:%i\n", str, file, line); + return 0; +} + +/* Test API generating files to the file system and then scanning them back */ +static void test_fs_write() +{ + int i; + int ret; + int len; + int err; + int n_files = 100; + int flags; + char *in_data; + size_t in_size; + char tmp[255]; + struct cio_ctx *ctx; + struct cio_stream *stream; + struct cio_chunk *chunk; + struct cio_chunk **carr; + struct cio_options cio_opts; + + /* Dummy break line for clarity on acutest output */ + printf("\n"); + + flags = CIO_CHECKSUM; + + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.flags = flags; + + /* cleanup environment */ + cio_utils_recursive_delete(CIO_ENV); + + /* Create main context */ + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + + /* Try to create a file with an invalid stream */ + chunk = cio_chunk_open(ctx, NULL, "invalid", 0, 0, &err); + TEST_CHECK(chunk == NULL); + + /* Check invalid stream */ + stream = cio_stream_create(ctx, "", CIO_STORE_FS); + TEST_CHECK(stream == NULL); + + /* Another invalid name */ + stream = cio_stream_create(ctx, "/", CIO_STORE_FS); + TEST_CHECK(stream == NULL); + + /* Create valid stream */ + stream = cio_stream_create(ctx, "test-write", CIO_STORE_FS); + TEST_CHECK(stream != NULL); + + /* + * Load sample data file and with the same content through multiple write + * operations generating other files. + */ + ret = cio_utils_read_file(CIO_FILE_400KB, &in_data, &in_size); + TEST_CHECK(ret == 0); + if (ret == -1) { + cio_destroy(ctx); + exit(EXIT_FAILURE); + } + + /* Number of test files to create */ + n_files = 100; + + /* Allocate files array */ + carr = calloc(1, sizeof(struct cio_file) * n_files); + if (!carr) { + perror("calloc"); + exit(EXIT_FAILURE); + } + + + for (i = 0; i < n_files; i++) { + len = snprintf(tmp, sizeof(tmp), "api-test-%04i.txt", i); + carr[i] = cio_chunk_open(ctx, stream, tmp, CIO_OPEN, 1000000, &err); + + if (carr[i] == NULL) { + continue; + } + + /* Check that next buffers are 'down' */ + if (i >= CIO_MAX_CHUNKS_UP) { + ret = cio_chunk_is_up(carr[i]); + TEST_CHECK(ret == CIO_FALSE); + cio_chunk_up_force(carr[i]); + } + + cio_chunk_write(carr[i], in_data, in_size); + cio_chunk_write(carr[i], in_data, in_size); + + /* update metadata */ + cio_meta_write(carr[i], tmp, len); + + /* continue appending data to content area */ + cio_chunk_write(carr[i], in_data, in_size); + cio_chunk_write(carr[i], in_data, in_size); + cio_chunk_write(carr[i], in_data, in_size); + + /* sync to disk */ + cio_chunk_sync(carr[i]); + } + + /* Release file data and destroy context */ + free(carr); + free(in_data); + cio_destroy(ctx); + + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_INFO; + cio_opts.flags = flags; + + /* Create new context using the data generated above */ + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + cio_scan_dump(ctx); + cio_destroy(ctx); +} + +/* + * Create one file chunk and check it updated sha1 after a couple of writes + * and sync. + */ +static void test_fs_checksum() +{ + int ret; + int err; + int flags; + char *in_data; + char *f_hash; + size_t in_size; + uint32_t val; + struct cio_ctx *ctx; + struct cio_stream *stream; + struct cio_chunk *chunk; + struct cio_options cio_opts; + + /* + * crc32 checksums + * =============== + */ + + /* Empty file */ + char crc32_test1[] = { + 0xff, 0x12, 0xd9, 0x41, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + /* CRC32 of 2 zero bytes + content of data/400kb.txt file */ + char crc32_test2[] = { + 0x67, 0xfa, 0x3c, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + flags = CIO_CHECKSUM; + + /* Dummy break line for clarity on acutest output */ + printf("\n"); + + /* cleanup environment */ + cio_utils_recursive_delete(CIO_ENV); + + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.flags = flags; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + + stream = cio_stream_create(ctx, "test-crc32", CIO_STORE_FS); + TEST_CHECK(stream != NULL); + + /* Load sample data file in memory */ + ret = cio_utils_read_file(CIO_FILE_400KB, &in_data, &in_size); + TEST_CHECK(ret == 0); + if (ret == -1) { + cio_destroy(ctx); + exit(EXIT_FAILURE); + } + + /* + * Test 1: + * - create one empty file + * - sync + * - validate crc32_test1 + */ + chunk = cio_chunk_open(ctx, stream, "test1.out", CIO_OPEN, 10, &err); + TEST_CHECK(chunk != NULL); + + /* Check default crc32() for an empty file after sync */ + f_hash = cio_chunk_hash(chunk); + TEST_CHECK(f_hash != NULL); + cio_chunk_sync(chunk); + + memcpy(&val, f_hash, sizeof(val)); + val = ntohl(val); + + ret = memcmp(&val, crc32_test1, 4); + TEST_CHECK(ret == 0); + + /* + * Test 2: + * - append content of 400kb.txt file to file context + * - validate file crc32 in mem is the same as crc_test1 + * - sync + * - validate file crc32 in mem is equal to sha_test2 + * + * note that the second sha1 calculation is done using the initial + * sha1 context so it skip old data to perform the verification. + */ + cio_chunk_write(chunk, in_data, in_size); + cio_chunk_sync(chunk); + + f_hash = cio_chunk_hash(chunk); + memcpy(&val, f_hash, sizeof(val)); + val = ntohl(val); + + ret = memcmp(&val, crc32_test2, 4); + TEST_CHECK(ret == 0); + + /* Release */ + cio_destroy(ctx); + free(in_data); +} + +/* + * Create one file chunk, do writes and invoke up()/down() calls, then validate + * it checksum. + */ +static void test_fs_up_down() +{ + int ret; + int err; + int flags; + char *in_data; + char *f_hash; + size_t in_size; + uint32_t val; + char path[1024]; + struct stat st; + struct cio_ctx *ctx; + struct cio_stream *stream; + struct cio_chunk *chunk; + struct cio_options cio_opts; + + /* + * crc32 checksums + * =============== + */ + + /* Empty file */ + char crc32_test1[] = { + 0xff, 0x12, 0xd9, 0x41, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + /* CRC32 of 2 zero bytes + content of data/400kb.txt file */ + char crc32_test2[] = { + 0x67, 0xfa, 0x3c, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + flags = CIO_CHECKSUM; + + /* Dummy break line for clarity on acutest output */ + printf("\n"); + + /* cleanup environment */ + cio_utils_recursive_delete(CIO_ENV); + + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_INFO; + cio_opts.flags = flags; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + + stream = cio_stream_create(ctx, "test-crc32", CIO_STORE_FS); + TEST_CHECK(stream != NULL); + + /* Load sample data file in memory */ + ret = cio_utils_read_file(CIO_FILE_400KB, &in_data, &in_size); + TEST_CHECK(ret == 0); + if (ret == -1) { + cio_destroy(ctx); + exit(EXIT_FAILURE); + } + + /* + * Test 1: + * - create one empty file + * - sync + * - validate crc32_test1 + */ + chunk = cio_chunk_open(ctx, stream, "test1.out", CIO_OPEN, 10, &err); + TEST_CHECK(chunk != NULL); + + /* file down/up */ + TEST_CHECK(cio_chunk_is_up(chunk) == CIO_TRUE); + ret = cio_chunk_down(chunk); + + TEST_CHECK(ret == 0); + TEST_CHECK(cio_chunk_is_up(chunk) == CIO_FALSE); + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == 0); + TEST_CHECK(cio_chunk_is_up(chunk) == CIO_TRUE); + + /* Check default crc32() for an empty file after sync */ + f_hash = cio_chunk_hash(chunk); + TEST_CHECK(f_hash != NULL); + cio_chunk_sync(chunk); + + memcpy(&val, f_hash, sizeof(val)); + val = ntohl(val); + + ret = memcmp(&val, crc32_test1, 4); + TEST_CHECK(ret == 0); + + /* + * Test 2: + * - append content of 400kb.txt file to file context + * - validate file crc32 in mem is the same as crc_test1 + * - sync + * - validate file crc32 in mem is equal to sha_test2 + * + * note that the second sha1 calculation is done using the initial + * sha1 context so it skip old data to perform the verification. + */ + cio_chunk_write(chunk, in_data, in_size); + + cio_chunk_sync(chunk); + + /* + * Bug https://github.com/fluent/fluent-bit/pull/3054#issuecomment-778831815 + * + * the fs_size cache value is not being updated after a sync, let's validate. + */ + snprintf(path, sizeof(path) - 1, "%s%s", CIO_ENV, "test-crc32/test1.out"); + ret = stat(path, &st); + TEST_CHECK(ret == 0); + TEST_CHECK(st.st_size == cio_chunk_get_real_size(chunk)); + + /* file down/up */ + TEST_CHECK(cio_chunk_is_up(chunk) == CIO_TRUE); + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == 0); + TEST_CHECK(cio_chunk_is_up(chunk) == CIO_FALSE); + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == 0); + TEST_CHECK(cio_chunk_is_up(chunk) == CIO_TRUE); + + f_hash = cio_chunk_hash(chunk); + memcpy(&val, f_hash, sizeof(val)); + val = ntohl(val); + + ret = memcmp(&val, crc32_test2, 4); + TEST_CHECK(ret == 0); + + /* Release */ + cio_destroy(ctx); + free(in_data); +} + +/* ref: https://github.com/edsiper/chunkio/pull/51 */ +static void test_issue_51() +{ + int fd; + int err; + struct cio_ctx *ctx; + struct cio_stream *stream; + struct cio_options cio_opts; + + /* Create a temporal storage */ + cio_options_init(&cio_opts); + + cio_opts.root_path = "tmp"; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_DEBUG; + cio_opts.flags = 0; + + ctx = cio_create(&cio_opts); + stream = cio_stream_create(ctx, "test", CIO_STORE_FS); + cio_chunk_open(ctx, stream, "c", CIO_OPEN, 1000, &err); + cio_destroy(ctx); + + /* Corrupt the file */ + fd = open("tmp/test/c", O_WRONLY); + TEST_CHECK(fd != -1); + if (fd == -1) { + perror("open"); + exit(1); + } + +#ifdef _WIN32 + _chsize(fd, 1); +#else + ftruncate(fd, 1); +#endif + + close(fd); + + /* Re-read the content */ + ctx = cio_create(&cio_opts); + + /* Upon scanning an existing stream, if not fixed, the program crashes */ + stream = cio_stream_create(ctx, "test", CIO_STORE_FS); + cio_chunk_open(ctx, stream, "c", CIO_OPEN, 1000, &err); + cio_destroy(ctx); +} + +/* ref: https://github.com/fluent/fluent-bit/2025 */ +static void test_issue_flb_2025() +{ + int i; + int ret; + int err; + int len; + char line[] = "this is a test line\n"; + struct cio_ctx *ctx; + struct cio_chunk *chunk; + struct cio_stream *stream; + struct cio_options cio_opts; + + cio_utils_recursive_delete("tmp"); + + /* Create a temporal storage */ + cio_options_init(&cio_opts); + + cio_opts.root_path = "tmp"; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_DEBUG; + cio_opts.flags = CIO_CHECKSUM; + + ctx = cio_create(&cio_opts); + stream = cio_stream_create(ctx, "test", CIO_STORE_FS); + chunk = cio_chunk_open(ctx, stream, "c", CIO_OPEN, 1000, &err); + TEST_CHECK(chunk != NULL); + if (!chunk) { + printf("cannot open chunk\n"); + exit(1); + } + + len = strlen(line); + for (i = 0; i < 1000; i++) { + ret = cio_chunk_write(chunk, line, len); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == CIO_OK); + } + + cio_destroy(ctx); +} + +void test_fs_size_chunks_up() +{ + int i; + int ret; + int len; + int err; + int flags; + char line[] = "this is a test line\n"; + char name[32]; + size_t expected; + struct cio_ctx *ctx; + struct cio_chunk *chunk; + struct cio_chunk *chunk_tmp; + struct cio_stream *stream; + struct cio_options cio_opts; + + /* cleanup environment */ + cio_utils_recursive_delete(CIO_ENV); + + flags = CIO_CHECKSUM; + + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_INFO; + cio_opts.flags = flags; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + + /* Set default number of chunks up */ + cio_set_max_chunks_up(ctx, 50); + + stream = cio_stream_create(ctx, "test_size_chunks_up", CIO_STORE_FS); + TEST_CHECK(stream != NULL); + + len = strlen(line); + for (i = 0; i < 100; i++) { + /* Create the chunk */ + snprintf(name, sizeof(name) - 1, "test-%i", i); + + chunk = cio_chunk_open(ctx, stream, name, CIO_OPEN, 1000, &err); + TEST_CHECK(chunk != NULL); + if (!chunk) { + exit(1); + } + + if (i < 50) { + /* First 50 chunks (0-49) will be in an 'up' state */ + ret = cio_chunk_is_up(chunk); + TEST_CHECK(ret == CIO_TRUE); + if (ret == CIO_FALSE) { + exit(1); + } + ret = cio_chunk_write(chunk, line, len); + TEST_CHECK(ret == CIO_OK); + + /* Check this chunk is in the 'chunks_up' list */ + chunk_tmp = mk_list_entry_last(&stream->chunks_up, + struct cio_chunk, + _state_head); + TEST_CHECK(chunk_tmp == chunk); + + /* Put the chunk down and now recheck 'chunks_down' list */ + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + /* Down list */ + chunk_tmp = mk_list_entry_last(&stream->chunks_down, + struct cio_chunk, + _state_head); + TEST_CHECK(chunk_tmp == chunk); + + /* Put the chunk UP again */ + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == CIO_OK); + + /* Check this chunk is in the 'chunks_up' list */ + chunk_tmp = mk_list_entry_last(&stream->chunks_up, + struct cio_chunk, + _state_head); + TEST_CHECK(chunk_tmp == chunk); + } + else { + /* + * Remaining created chunks are in a down state, after creation + * this chunks must be linked in the struct cio_stream->chunks_down + * list. + */ + chunk_tmp = mk_list_entry_last(&stream->chunks_down, + struct cio_chunk, + _state_head); + TEST_CHECK(chunk_tmp == chunk); + } + } + + /* 50 chunks are up, each chunk contains 'len' bytes */ + expected = 50 * len; + TEST_CHECK(cio_stream_size_chunks_up(stream) == expected); + + /* Cleanup */ + cio_destroy(ctx); +} + +void test_issue_write_at() +{ + int ret; + int len; + int err; + char line[] = "this is a test line\n"; + struct cio_ctx *ctx; + struct cio_chunk *chunk; + struct cio_stream *stream; + struct cio_options cio_opts; + + /* cleanup environment */ + cio_utils_recursive_delete(CIO_ENV); + + /* create Chunk I/O context */ + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_INFO; + cio_opts.flags = CIO_CHECKSUM; + + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + + /* Set default number of chunks up */ + cio_set_max_chunks_up(ctx, 50); + + /* create stream */ + stream = cio_stream_create(ctx, "test_write_at", CIO_STORE_FS); + TEST_CHECK(stream != NULL); + + /* create chunk */ + chunk = cio_chunk_open(ctx, stream, "test", CIO_OPEN, 1000, &err); + TEST_CHECK(chunk != NULL); + if (!chunk) { + exit(1); + } + + len = strlen(line); + + /* Write 3 lines */ + ret = cio_chunk_write(chunk, line, len); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_write(chunk, line, len); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_write(chunk, line, len); + TEST_CHECK(ret == CIO_OK); + + /* + * Write some content after the second line: this is the issue, when writing + * to a position lowest than the last offset the checksum is not updated, for + * hence after putting it down and up again, the checksym validation fails + * and we get in the wrong state. + */ + ret = cio_chunk_write_at(chunk, len * 2, "test\n", 5); + TEST_CHECK(ret == CIO_OK); + + /* Put the chunk down and up */ + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + /* Trigger the 'format check failed' error */ + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == CIO_OK); + + /* + * Corrupt the CRC manually, alter the current CRC and write a byte + * to the chunk to get the checksum corruption. Here we expect two + * things: + * + * - when trying to put the chunk get CIO_CORRUPTED + * - check the error number, it must be CIO_ERR_BAD_CHECKSUM + * - memory map must be null and file descriptor must be in a closed state + */ + struct cio_file *cf = (struct cio_file *) chunk->backend; + cf->crc_cur = 10; + cio_chunk_write(chunk, "\0", 1); + + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == CIO_CORRUPTED); + TEST_CHECK(cio_error_get(chunk) == CIO_ERR_BAD_CHECKSUM); + + cf = (struct cio_file *) chunk->backend; + TEST_CHECK(cf->map == NULL); + TEST_CHECK(cf->fd <= 0); +} + + +void test_fs_up_down_up_append() +{ + int ret; + int err; + struct cio_ctx *ctx; + struct cio_chunk *chunk; + struct cio_stream *stream; + struct cio_options cio_opts; + + void *out_buf; + size_t out_size; + + cio_utils_recursive_delete(CIO_ENV); + + /* create Chunk I/O context */ + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_DEBUG; + cio_opts.flags = CIO_CHECKSUM; + + /* Create a temporal storage */ + ctx = cio_create(&cio_opts); + stream = cio_stream_create(ctx, "cio", CIO_STORE_FS); + chunk = cio_chunk_open(ctx, stream, "c", CIO_OPEN, 1000, &err); + TEST_CHECK(chunk != NULL); + if (!chunk) { + printf("cannot open chunk\n"); + exit(1); + } + + ret = cio_chunk_get_content_copy(chunk, &out_buf, &out_size); + TEST_CHECK(ret == CIO_OK); + TEST_CHECK(memcmp(out_buf, "", 1) == 0); + TEST_CHECK(out_size == 0); + free(out_buf); + + ret = cio_chunk_write(chunk, "line 1\n", 7); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_get_content_copy(chunk, &out_buf, &out_size); + TEST_CHECK(ret == CIO_OK); + TEST_CHECK(memcmp(out_buf, "line 1\n", 7+1) == 0); + TEST_CHECK(out_size == 7); + free(out_buf); + + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_get_content_copy(chunk, &out_buf, &out_size); + TEST_CHECK(ret == CIO_OK); + TEST_CHECK(memcmp(out_buf, "line 1\n", 7+1) == 0); + TEST_CHECK(out_size == 7); + free(out_buf); + + /* append */ + ret = cio_chunk_write(chunk, "line 2\n", 7); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_get_content_copy(chunk, &out_buf, &out_size); + TEST_CHECK(ret == CIO_OK); + TEST_CHECK(memcmp(out_buf, "line 1\nline 2\n", 7*2+1) == 0); + TEST_CHECK(out_size == 7*2); + free(out_buf); + + cio_destroy(ctx); +} + +static void test_deep_hierarchy() +{ + int i; + int ret; + int err; + int len; + char line[] = "this is a test line\n"; + struct cio_ctx *ctx; + struct cio_chunk *chunk; + struct cio_stream *stream; + struct cio_options cio_opts; + + cio_utils_recursive_delete("tmp"); + + /* Create a temporal storage */ + cio_options_init(&cio_opts); + + cio_opts.root_path = "tmp/deep/log/dir"; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_DEBUG; + cio_opts.flags = 0; + + ctx = cio_create(&cio_opts); + stream = cio_stream_create(ctx, "test", CIO_STORE_FS); + chunk = cio_chunk_open(ctx, stream, "c", CIO_OPEN, 1000, &err); + TEST_CHECK(chunk != NULL); + if (!chunk) { + printf("cannot open chunk\n"); + exit(1); + } + + len = strlen(line); + for (i = 0; i < 1000; i++) { + ret = cio_chunk_write(chunk, line, len); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + ret = cio_chunk_up(chunk); + TEST_CHECK(ret == CIO_OK); + } + + cio_destroy(ctx); +} + +static void truncate_file(struct cio_file *chunk_file, + size_t new_file_size, + int remove_content_length) +{ + int result; + + result = cio_file_native_open(chunk_file); + TEST_CHECK(result == CIO_OK); + + result = cio_file_native_map(chunk_file, + chunk_file->page_size); + TEST_CHECK(result == CIO_OK); + + if (remove_content_length) { + chunk_file->map[CIO_FILE_CONTENT_LENGTH_OFFSET + 0] = 0; + chunk_file->map[CIO_FILE_CONTENT_LENGTH_OFFSET + 1] = 0; + chunk_file->map[CIO_FILE_CONTENT_LENGTH_OFFSET + 2] = 0; + chunk_file->map[CIO_FILE_CONTENT_LENGTH_OFFSET + 3] = 0; + } + + result = cio_file_native_unmap(chunk_file); + TEST_CHECK(result == CIO_OK); + + result = cio_file_native_resize(chunk_file, new_file_size); + TEST_CHECK(result == 0); + + result = cio_file_native_close(chunk_file); + TEST_CHECK(result == CIO_OK); +} + +static void test_legacy_core(int trigger_checksum_error) +{ + struct cio_options cio_opts; + char *in_data; + size_t in_size; + struct cio_stream *stream; + struct cio_chunk *chunk; + size_t delta; + struct cio_ctx *ctx; + int ret; + + /* delete any previous temporary content directory */ + cio_utils_recursive_delete(CIO_ENV); + /* + * Load sample data file and with the same content through multiple write + * operations generating other files. + */ + ret = cio_utils_read_file(CIO_FILE_400KB, &in_data, &in_size); + TEST_CHECK(ret == 0); + if (ret == -1) { + exit(EXIT_FAILURE); + } + + /* create Chunk I/O context */ + cio_options_init(&cio_opts); + + cio_opts.root_path = CIO_ENV; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_DEBUG; + cio_opts.flags = CIO_CHECKSUM; + + /* Create a temporal storage */ + ctx = cio_create(&cio_opts); + + stream = cio_stream_create(ctx, "test-legacy", CIO_STORE_FS); + + /* do not force a maximum of chunks up, we want to test writing overhead */ + cio_set_max_chunks_up(ctx, 1); + + chunk = cio_chunk_open(ctx, + stream, + "test_chunk", + CIO_OPEN, + 1000, + &ret); + + ret = cio_chunk_write(chunk, in_data, 128); + TEST_CHECK(ret == 0); + + ret = cio_chunk_down(chunk); + TEST_CHECK(ret == CIO_OK); + + delta = CIO_FILE_HEADER_MIN; + + if (trigger_checksum_error) { + delta++; + } + + truncate_file((struct cio_file *) chunk->backend, + 128 + delta, + CIO_TRUE); + + ret = cio_chunk_up(chunk); + + if (trigger_checksum_error) { + TEST_CHECK(ret != CIO_OK); + } + else { + TEST_CHECK(ret == CIO_OK); + } + + cio_destroy(ctx); + + free(in_data); +} + +void test_legacy_success() +{ + test_legacy_core(CIO_FALSE); +} + +void test_legacy_failure() +{ + test_legacy_core(CIO_TRUE); +} + +TEST_LIST = { + {"fs_write", test_fs_write}, + {"fs_checksum", test_fs_checksum}, + {"fs_up_down", test_fs_up_down}, + {"fs_size_chunks_up", test_fs_size_chunks_up}, + {"issue_51", test_issue_51}, + {"issue_flb_2025", test_issue_flb_2025}, + {"issue_write_at", test_issue_write_at}, + {"fs_up_down_up_append", test_fs_up_down_up_append}, + {"fs_deep_hierachy", test_deep_hierarchy}, + {"legacy_success", test_legacy_success}, + {"legacy_failure", test_legacy_failure}, + { 0 } +}; diff --git a/src/fluent-bit/lib/chunkio/tests/lib/acutest/.travis.yml b/src/fluent-bit/lib/chunkio/tests/lib/acutest/.travis.yml new file mode 100644 index 000000000..920821985 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/lib/acutest/.travis.yml @@ -0,0 +1,34 @@ +# YAML definition for travis-ci.com continuous integration. +# See https://docs.travis-ci.com/user/languages/c + +# Container-based infrastructure (Linux) +# * https://docs.travis-ci.com/user/migrating-from-legacy/#How-can-I-use-container-based-infrastructure%3F +sudo: +- false + +language: c++ + +compiler: + - gcc + - clang + +env: + - CFLAGS="-std=c99 -pedantic" CONFIG=Debug # C99 + - CFLAGS="-std=c99 -pedantic" CONFIG=Release + - CFLAGS="-std=c11 -pedantic" CONFIG=Debug # C11 + - CFLAGS="-std=c11 -pedantic" CONFIG=Release + - CXXFLAGS="-std=c++11 -pedantic" CONFIG=Debug # C++11 + - CXXFLAGS="-std=c++11 -pedantic" CONFIG=Release + # Too old compilers on travis-ci.org for these: + #- CXXFLAGS="-std=c++14 -pedantic" CONFIG=Debug # C++14 + #- CXXFLAGS="-std=c++14 -pedantic" CONFIG=Release + #- CXXFLAGS="-std=c++17 -pedantic" CONFIG=Debug # C++17 + #- CXXFLAGS="-std=c++17 -pedantic" CONFIG=Release + +before_script: + - mkdir build + - cd build + - cmake -DCMAKE_BUILD_TYPE=$CONFIG -G 'Unix Makefiles' .. + +script: + - make VERBOSE=1 diff --git a/src/fluent-bit/lib/chunkio/tests/lib/acutest/CMakeLists.txt b/src/fluent-bit/lib/chunkio/tests/lib/acutest/CMakeLists.txt new file mode 100644 index 000000000..4a741a424 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/lib/acutest/CMakeLists.txt @@ -0,0 +1,44 @@ + +cmake_minimum_required(VERSION 2.8) +project(Acutest C CXX) + + +set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo MinSizeRel) +if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE $ENV{CMAKE_BUILD_TYPE}) + + if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE "Release") + endif() +endif() + + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + + +if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") +elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") +elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") + # Specify proper C runtime library: + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} /MT") + set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_RELEASE} /MT") +endif() + +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # Specify proper C runtime library: + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_RELEASE} /MT") +endif() + + +add_subdirectory(examples) diff --git a/src/fluent-bit/lib/chunkio/tests/lib/acutest/GIT b/src/fluent-bit/lib/chunkio/tests/lib/acutest/GIT new file mode 100644 index 000000000..379ff1483 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/lib/acutest/GIT @@ -0,0 +1 @@ +03885e23ea27535251b91abf681257d3d4241eae (git master)
\ No newline at end of file diff --git a/src/fluent-bit/lib/chunkio/tests/lib/acutest/LICENSE.md b/src/fluent-bit/lib/chunkio/tests/lib/acutest/LICENSE.md new file mode 100644 index 000000000..973092017 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/lib/acutest/LICENSE.md @@ -0,0 +1,22 @@ + +# The MIT License (MIT) + +Copyright © 2013-2017 Martin Mitáš + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the “Software”), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/src/fluent-bit/lib/chunkio/tests/lib/acutest/README.md b/src/fluent-bit/lib/chunkio/tests/lib/acutest/README.md new file mode 100644 index 000000000..e7f75b652 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/lib/acutest/README.md @@ -0,0 +1,4 @@ +Taken from https://github.com/mity/acutest + +MIT License + diff --git a/src/fluent-bit/lib/chunkio/tests/lib/acutest/appveyor.yml b/src/fluent-bit/lib/chunkio/tests/lib/acutest/appveyor.yml new file mode 100644 index 000000000..6e85c7a00 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/lib/acutest/appveyor.yml @@ -0,0 +1,26 @@ +# YAML definition for Appveyor.com continuous integration. +# See http://www.appveyor.com/docs/appveyor-yml + +version: '{branch}-{build}' + +before_build: + - 'cmake --version' + - 'if "%PLATFORM%"=="x64" cmake -G "Visual Studio 12 Win64"' + - 'if not "%PLATFORM%"=="x64" cmake -G "Visual Studio 12"' + +build: + project: Acutest.sln + verbosity: minimal + +skip_tags: true + +os: + - Windows Server 2012 R2 + +configuration: + - Debug + - Release + +platform: + - x64 # 64-bit build + - win32 # 32-bit build diff --git a/src/fluent-bit/lib/chunkio/tests/lib/acutest/include/acutest.h b/src/fluent-bit/lib/chunkio/tests/lib/acutest/include/acutest.h new file mode 100644 index 000000000..cd5ffb2c7 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/lib/acutest/include/acutest.h @@ -0,0 +1,864 @@ +/* + * Acutest -- Another C/C++ Unit Test facility + * <http://github.com/mity/acutest> + * + * Copyright (c) 2013-2017 Martin Mitas + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef ACUTEST_H__ +#define ACUTEST_H__ + + +/************************ + *** Public interface *** + ************************/ + +/* By default, "acutest.h" provides the main program entry point (function + * main()). However, if the test suite is composed of multiple source files + * which include "acutest.h", then this causes a problem of multiple main() + * definitions. To avoid this problem, #define macro TEST_NO_MAIN in all + * compilation units but one. + */ + +/* Macro to specify list of unit tests in the suite. + * The unit test implementation MUST provide list of unit tests it implements + * with this macro: + * + * TEST_LIST = { + * { "test1_name", test1_func_ptr }, + * { "test2_name", test2_func_ptr }, + * ... + * { 0 } + * }; + * + * The list specifies names of each test (must be unique) and pointer to + * a function implementing it. The function does not take any arguments + * and has no return values, i.e. every test function has to be compatible + * with this prototype: + * + * void test_func(void); + */ +#define TEST_LIST const struct test__ test_list__[] + + +/* Macros for testing whether an unit test succeeds or fails. These macros + * can be used arbitrarily in functions implementing the unit tests. + * + * If any condition fails throughout execution of a test, the test fails. + * + * TEST_CHECK takes only one argument (the condition), TEST_CHECK_ allows + * also to specify an error message to print out if the condition fails. + * (It expects printf-like format string and its parameters). The macros + * return non-zero (condition passes) or 0 (condition fails). + * + * That can be useful when more conditions should be checked only if some + * preceding condition passes, as illustrated in this code snippet: + * + * SomeStruct* ptr = allocate_some_struct(); + * if(TEST_CHECK(ptr != NULL)) { + * TEST_CHECK(ptr->member1 < 100); + * TEST_CHECK(ptr->member2 > 200); + * } + */ +#define TEST_CHECK_(cond,...) test_check__((cond), __FILE__, __LINE__, __VA_ARGS__) +#define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, "%s", #cond) + + +/* printf-like macro for outputting an extra information about a failure. + * + * Note it does not output anything if there was not (yet) failed condition + * in the current test. Intended use is to output some computed output + * versus the expected value, e.g. like this: + * + * if(!TEST_CHECK(produced == expected)) { + * TEST_MSG("Expected: %d", expected); + * TEST_MSG("Produced: %d", produced); + * } + * + * The macro can deal with multi-line output fairly well. It also automatically + * adds a final new-line if there is none present. + */ +#define TEST_MSG(...) test_message__(__VA_ARGS__) + +/* Maximal output per TEST_MSG call. Longer messages are cut. + * You may define another limit prior including "acutest.h" + */ +#ifndef TEST_MSG_MAXSIZE + #define TEST_MSG_MAXSIZE 1024 +#endif + + +/********************** + *** Implementation *** + **********************/ + +/* The unit test files should not rely on anything below. */ + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) + #define ACUTEST_UNIX__ 1 + #include <errno.h> + #include <unistd.h> + #include <sys/types.h> + #include <sys/wait.h> + #include <signal.h> +#endif + +#if defined(__gnu_linux__) + #define ACUTEST_LINUX__ 1 + #include <fcntl.h> + #include <sys/stat.h> +#endif + +#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + #define ACUTEST_WIN__ 1 + #include <windows.h> + #include <io.h> +#endif + +#ifdef __cplusplus + #include <exception> +#endif + + +/* Note our global private identifiers end with '__' to mitigate risk of clash + * with the unit tests implementation. */ + + +#ifdef __cplusplus + extern "C" { +#endif + + +struct test__ { + const char* name; + void (*func)(void); +}; + +extern const struct test__ test_list__[]; + +int test_check__(int cond, const char* file, int line, const char* fmt, ...); +void test_message__(const char* fmt, ...); + + +#ifndef TEST_NO_MAIN + +static char* test_argv0__ = NULL; +static size_t test_list_size__ = 0; +static const struct test__** tests__ = NULL; +static char* test_flags__ = NULL; +static size_t test_count__ = 0; +static int test_no_exec__ = -1; +static int test_no_summary__ = 0; +static int test_skip_mode__ = 0; + +static int test_stat_failed_units__ = 0; +static int test_stat_run_units__ = 0; + +static const struct test__* test_current_unit__ = NULL; +static int test_current_already_logged__ = 0; +static int test_verbose_level__ = 2; +static int test_current_failures__ = 0; +static int test_colorize__ = 0; + +#define TEST_COLOR_DEFAULT__ 0 +#define TEST_COLOR_GREEN__ 1 +#define TEST_COLOR_RED__ 2 +#define TEST_COLOR_DEFAULT_INTENSIVE__ 3 +#define TEST_COLOR_GREEN_INTENSIVE__ 4 +#define TEST_COLOR_RED_INTENSIVE__ 5 + +static int +test_print_in_color__(int color, const char* fmt, ...) +{ + va_list args; + char buffer[256]; + int n; + + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + buffer[sizeof(buffer)-1] = '\0'; + + if(!test_colorize__) { + return printf("%s", buffer); + } + +#if defined ACUTEST_UNIX__ + { + const char* col_str; + switch(color) { + case TEST_COLOR_GREEN__: col_str = "\033[0;32m"; break; + case TEST_COLOR_RED__: col_str = "\033[0;31m"; break; + case TEST_COLOR_GREEN_INTENSIVE__: col_str = "\033[1;32m"; break; + case TEST_COLOR_RED_INTENSIVE__: col_str = "\033[1;31m"; break; + case TEST_COLOR_DEFAULT_INTENSIVE__: col_str = "\033[1m"; break; + default: col_str = "\033[0m"; break; + } + printf("%s", col_str); + n = printf("%s", buffer); + printf("\033[0m"); + return n; + } +#elif defined ACUTEST_WIN__ + { + HANDLE h; + CONSOLE_SCREEN_BUFFER_INFO info; + WORD attr; + + h = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(h, &info); + + switch(color) { + case TEST_COLOR_GREEN__: attr = FOREGROUND_GREEN; break; + case TEST_COLOR_RED__: attr = FOREGROUND_RED; break; + case TEST_COLOR_GREEN_INTENSIVE__: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; + case TEST_COLOR_RED_INTENSIVE__: attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break; + case TEST_COLOR_DEFAULT_INTENSIVE__: attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break; + default: attr = 0; break; + } + if(attr != 0) + SetConsoleTextAttribute(h, attr); + n = printf("%s", buffer); + SetConsoleTextAttribute(h, info.wAttributes); + return n; + } +#else + n = printf("%s", buffer); + return n; +#endif +} + +int +test_check__(int cond, const char* file, int line, const char* fmt, ...) +{ + const char *result_str; + int result_color; + int verbose_level; + + if(cond) { + result_str = "ok"; + result_color = TEST_COLOR_GREEN__; + verbose_level = 3; + } else { + if(!test_current_already_logged__ && test_current_unit__ != NULL) { + printf("[ "); + test_print_in_color__(TEST_COLOR_RED_INTENSIVE__, "FAILED"); + printf(" ]\n"); + } + result_str = "failed"; + result_color = TEST_COLOR_RED__; + verbose_level = 2; + test_current_failures__++; + test_current_already_logged__++; + } + + if(test_verbose_level__ >= verbose_level) { + va_list args; + + printf(" "); + + if(file != NULL) { + if(test_verbose_level__ < 3) { +#ifdef ACUTEST_WIN__ + const char* lastsep1 = strrchr(file, '\\'); + const char* lastsep2 = strrchr(file, '/'); + if(lastsep1 == NULL) + lastsep1 = file-1; + if(lastsep2 == NULL) + lastsep2 = file-1; + file = (lastsep1 > lastsep2 ? lastsep1 : lastsep2) + 1; +#else + const char* lastsep = strrchr(file, '/'); + if(lastsep != NULL) + file = lastsep+1; +#endif + } + printf("%s:%d: Check ", file, line); + } + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + printf("... "); + test_print_in_color__(result_color, result_str); + printf("\n"); + test_current_already_logged__++; + } + + return (cond != 0); +} + +void +test_message__(const char* fmt, ...) +{ + char buffer[TEST_MSG_MAXSIZE]; + char* line_beg; + char* line_end; + va_list args; + + if(test_verbose_level__ < 2) + return; + + /* We allow extra message only when something is already wrong in the + * current test. */ + if(!test_current_already_logged__ || test_current_unit__ == NULL) + return; + + va_start(args, fmt); + vsnprintf(buffer, TEST_MSG_MAXSIZE, fmt, args); + va_end(args); + buffer[TEST_MSG_MAXSIZE-1] = '\0'; + + line_beg = buffer; + while(1) { + line_end = strchr(line_beg, '\n'); + if(line_end == NULL) + break; + printf(" %.*s\n", (int)(line_end - line_beg), line_beg); + line_beg = line_end + 1; + } + if(line_beg[0] != '\0') + printf(" %s\n", line_beg); +} + +static void +test_list_names__(void) +{ + const struct test__* test; + + printf("Unit tests:\n"); + for(test = &test_list__[0]; test->func != NULL; test++) + printf(" %s\n", test->name); +} + +static void +test_remember__(int i) +{ + if(test_flags__[i]) + return; + else + test_flags__[i] = 1; + + tests__[test_count__] = &test_list__[i]; + test_count__++; +} + +static int +test_name_contains_word__(const char* name, const char* pattern) +{ + static const char word_delim[] = " \t-_."; + const char* substr; + size_t pattern_len; + int starts_on_word_boundary; + int ends_on_word_boundary; + + pattern_len = strlen(pattern); + + substr = strstr(name, pattern); + while(substr != NULL) { + starts_on_word_boundary = (substr == name || strchr(word_delim, substr[-1]) != NULL); + ends_on_word_boundary = (substr[pattern_len] == '\0' || strchr(word_delim, substr[pattern_len]) != NULL); + + if(starts_on_word_boundary && ends_on_word_boundary) + return 1; + + substr = strstr(substr+1, pattern); + } + + return 0; +} + +static int +test_lookup__(const char* pattern) +{ + int i; + int n = 0; + + /* Try exact match. */ + for(i = 0; i < (int) test_list_size__; i++) { + if(strcmp(test_list__[i].name, pattern) == 0) { + test_remember__(i); + n++; + break; + } + } + if(n > 0) + return n; + + /* Try word match. */ + for(i = 0; i < (int) test_list_size__; i++) { + if(test_name_contains_word__(test_list__[i].name, pattern)) { + test_remember__(i); + n++; + } + } + if(n > 0) + return n; + + /* Try relaxed match. */ + for(i = 0; i < (int) test_list_size__; i++) { + if(strstr(test_list__[i].name, pattern) != NULL) { + test_remember__(i); + n++; + } + } + + return n; +} + +/* Call directly the given test unit function. */ +static int +test_do_run__(const struct test__* test) +{ + test_current_unit__ = test; + test_current_failures__ = 0; + test_current_already_logged__ = 0; + + if(test_verbose_level__ >= 3) { + test_print_in_color__(TEST_COLOR_DEFAULT_INTENSIVE__, "Test %s:\n", test->name); + test_current_already_logged__++; + } else if(test_verbose_level__ >= 1) { + int n; + char spaces[48]; + + n = test_print_in_color__(TEST_COLOR_DEFAULT_INTENSIVE__, "Test %s... ", test->name); + memset(spaces, ' ', sizeof(spaces)); + if(n < (int) sizeof(spaces)) + printf("%.*s", (int) sizeof(spaces) - n, spaces); + } else { + test_current_already_logged__ = 1; + } + +#ifdef __cplusplus + try { +#endif + + /* This is good to do for case the test unit e.g. crashes. */ + fflush(stdout); + fflush(stderr); + + test->func(); + +#ifdef __cplusplus + } catch(std::exception& e) { + const char* what = e.what(); + if(what != NULL) + test_check__(0, NULL, 0, "Threw std::exception: %s", what); + else + test_check__(0, NULL, 0, "Threw std::exception"); + } catch(...) { + test_check__(0, NULL, 0, "Threw an exception"); + } +#endif + + if(test_verbose_level__ >= 3) { + switch(test_current_failures__) { + case 0: test_print_in_color__(TEST_COLOR_GREEN_INTENSIVE__, " All conditions have passed.\n\n"); break; + case 1: test_print_in_color__(TEST_COLOR_RED_INTENSIVE__, " One condition has FAILED.\n\n"); break; + default: test_print_in_color__(TEST_COLOR_RED_INTENSIVE__, " %d conditions have FAILED.\n\n", test_current_failures__); break; + } + } else if(test_verbose_level__ >= 1 && test_current_failures__ == 0) { + printf("[ "); + test_print_in_color__(TEST_COLOR_GREEN_INTENSIVE__, "OK"); + printf(" ]\n"); + } + + test_current_unit__ = NULL; + return (test_current_failures__ == 0) ? 0 : -1; +} + +#if defined(ACUTEST_UNIX__) || defined(ACUTEST_WIN__) +/* Called if anything goes bad in Acutest, or if the unit test ends in other + * way then by normal returning from its function (e.g. exception or some + * abnormal child process termination). */ +static void +test_error__(const char* fmt, ...) +{ + va_list args; + + if(test_verbose_level__ == 0) + return; + + if(test_verbose_level__ <= 2 && !test_current_already_logged__ && test_current_unit__ != NULL) { + printf("[ "); + test_print_in_color__(TEST_COLOR_RED_INTENSIVE__, "FAILED"); + printf(" ]\n"); + } + + if(test_verbose_level__ >= 2) { + test_print_in_color__(TEST_COLOR_RED_INTENSIVE__, " Error: "); + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + printf("\n"); + } +} +#endif + +/* Trigger the unit test. If possible (and not suppressed) it starts a child + * process who calls test_do_run__(), otherwise it calls test_do_run__() + * directly. */ +static void +test_run__(const struct test__* test) +{ + int failed = 1; + + test_current_unit__ = test; + test_current_already_logged__ = 0; + + if(!test_no_exec__) { + +#if defined(ACUTEST_UNIX__) + + pid_t pid; + int exit_code; + + pid = fork(); + if(pid == (pid_t)-1) { + test_error__("Cannot fork. %s [%d]", strerror(errno), errno); + failed = 1; + } else if(pid == 0) { + /* Child: Do the test. */ + failed = (test_do_run__(test) != 0); + exit(failed ? 1 : 0); + } else { + /* Parent: Wait until child terminates and analyze its exit code. */ + waitpid(pid, &exit_code, 0); + if(WIFEXITED(exit_code)) { + switch(WEXITSTATUS(exit_code)) { + case 0: failed = 0; break; /* test has passed. */ + case 1: /* noop */ break; /* "normal" failure. */ + default: test_error__("Unexpected exit code [%d]", WEXITSTATUS(exit_code)); + } + } else if(WIFSIGNALED(exit_code)) { + char tmp[32]; + const char* signame; + switch(WTERMSIG(exit_code)) { + case SIGINT: signame = "SIGINT"; break; + case SIGHUP: signame = "SIGHUP"; break; + case SIGQUIT: signame = "SIGQUIT"; break; + case SIGABRT: signame = "SIGABRT"; break; + case SIGKILL: signame = "SIGKILL"; break; + case SIGSEGV: signame = "SIGSEGV"; break; + case SIGILL: signame = "SIGILL"; break; + case SIGTERM: signame = "SIGTERM"; break; + default: sprintf(tmp, "signal %d", WTERMSIG(exit_code)); signame = tmp; break; + } + test_error__("Test interrupted by %s", signame); + } else { + test_error__("Test ended in an unexpected way [%d]", exit_code); + } + } + +#elif defined(ACUTEST_WIN__) + + char buffer[512] = {0}; + STARTUPINFOA startupInfo; + PROCESS_INFORMATION processInfo; + DWORD exitCode; + + /* Windows has no fork(). So we propagate all info into the child + * through a command line arguments. */ + _snprintf(buffer, sizeof(buffer)-1, + "%s --no-exec --no-summary --verbose=%d --color=%s -- \"%s\"", + test_argv0__, test_verbose_level__, + test_colorize__ ? "always" : "never", test->name); + memset(&startupInfo, 0, sizeof(startupInfo)); + startupInfo.cb = sizeof(STARTUPINFO); + if(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) { + WaitForSingleObject(processInfo.hProcess, INFINITE); + GetExitCodeProcess(processInfo.hProcess, &exitCode); + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + failed = (exitCode != 0); + } else { + test_error__("Cannot create unit test subprocess [%ld].", GetLastError()); + failed = 1; + } + +#else + + /* A platform where we don't know how to run child process. */ + failed = (test_do_run__(test) != 0); + +#endif + + } else { + /* Child processes suppressed through --no-exec. */ + failed = (test_do_run__(test) != 0); + } + + test_current_unit__ = NULL; + + test_stat_run_units__++; + if(failed) + test_stat_failed_units__++; +} + +#if defined(ACUTEST_WIN__) +/* Callback for SEH events. */ +static LONG CALLBACK +test_exception_filter__(EXCEPTION_POINTERS *ptrs) +{ + test_error__("Unhandled SEH exception %08lx at %p.", + ptrs->ExceptionRecord->ExceptionCode, + ptrs->ExceptionRecord->ExceptionAddress); + fflush(stdout); + fflush(stderr); + return EXCEPTION_EXECUTE_HANDLER; +} +#endif + + +static void +test_help__(void) +{ + printf("Usage: %s [options] [test...]\n", test_argv0__); + printf("Run the specified unit tests; or if the option '--skip' is used, run all\n"); + printf("tests in the suite but those listed. By default, if no tests are specified\n"); + printf("on the command line, all unit tests in the suite are run.\n"); + printf("\n"); + printf("Options:\n"); + printf(" -s, --skip Execute all unit tests but the listed ones\n"); + printf(" --exec=WHEN If supported, execute unit tests as child processes\n"); + printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" -E, --no-exec Same as --exec=never\n"); + printf(" --no-summary Suppress printing of test results summary\n"); + printf(" -l, --list List unit tests in the suite and exit\n"); + printf(" -v, --verbose Enable more verbose output\n"); + printf(" --verbose=LEVEL Set verbose level to LEVEL:\n"); + printf(" 0 ... Be silent\n"); + printf(" 1 ... Output one line per test (and summary)\n"); + printf(" 2 ... As 1 and failed conditions (this is default)\n"); + printf(" 3 ... As 1 and all conditions (and extended summary)\n"); + printf(" --color=WHEN Enable colorized output\n"); + printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" -h, --help Display this help and exit\n"); + + if(test_list_size__ < 16) { + printf("\n"); + test_list_names__(); + } +} + +#ifdef ACUTEST_LINUX__ +static int +test_is_tracer_present__(void) +{ + char buf[256+32+1]; + int tracer_present = 0; + int fd; + ssize_t n_read; + + fd = open("/proc/self/status", O_RDONLY); + if(fd == -1) + return 0; + + n_read = read(fd, buf, sizeof(buf)-1); + while(n_read > 0) { + static const char pattern[] = "TracerPid:"; + const char* field; + + buf[n_read] = '\0'; + field = strstr(buf, pattern); + if(field != NULL && field < buf + sizeof(buf) - 32) { + pid_t tracer_pid = (pid_t) atoi(field + sizeof(pattern) - 1); + tracer_present = (tracer_pid != 0); + break; + } + + if(n_read == sizeof(buf)-1) { + memmove(buf, buf + sizeof(buf)-1 - 32, 32); + n_read = read(fd, buf+32, sizeof(buf)-1-32); + if(n_read > 0) + n_read += 32; + } + } + + close(fd); + return tracer_present; +} +#endif + +int +main(int argc, char** argv) +{ + int i; + int seen_double_dash = 0; + + test_argv0__ = argv[0]; + +#if defined ACUTEST_UNIX__ + test_colorize__ = isatty(STDOUT_FILENO); +#elif defined ACUTEST_WIN__ + #if defined __BORLANDC__ + test_colorize__ = isatty(_fileno(stdout)); + #else + test_colorize__ = _isatty(_fileno(stdout)); + #endif +#else + test_colorize__ = 0; +#endif + + /* Count all test units */ + test_list_size__ = 0; + for(i = 0; test_list__[i].func != NULL; i++) + test_list_size__++; + + tests__ = (const struct test__**) malloc(sizeof(const struct test__*) * test_list_size__); + test_flags__ = (char*) malloc(sizeof(char) * test_list_size__); + if(tests__ == NULL || test_flags__ == NULL) { + fprintf(stderr, "Out of memory.\n"); + exit(2); + } + memset((void*) test_flags__, 0, sizeof(char) * test_list_size__); + + /* Parse options */ + for(i = 1; i < argc; i++) { + if(seen_double_dash || argv[i][0] != '-') { + if(test_lookup__(argv[i]) == 0) { + fprintf(stderr, "%s: Unrecognized unit test '%s'\n", argv[0], argv[i]); + fprintf(stderr, "Try '%s --list' for list of unit tests.\n", argv[0]); + exit(2); + } + } else if(strcmp(argv[i], "--") == 0) { + seen_double_dash = 1; + } else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + test_help__(); + exit(0); + } else if(strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) { + test_verbose_level__++; + } else if(strncmp(argv[i], "--verbose=", 10) == 0) { + test_verbose_level__ = atoi(argv[i] + 10); + } else if(strcmp(argv[i], "--color=auto") == 0) { + /* noop (set from above) */ + } else if(strcmp(argv[i], "--color=always") == 0 || strcmp(argv[i], "--color") == 0) { + test_colorize__ = 1; + } else if(strcmp(argv[i], "--color=never") == 0 || strcmp(argv[i], "--no-color") == 0) { + test_colorize__ = 0; + } else if(strcmp(argv[i], "--skip") == 0 || strcmp(argv[i], "-s") == 0) { + test_skip_mode__ = 1; + } else if(strcmp(argv[i], "--exec=auto") == 0) { + /* noop (set from above) */ + } else if(strcmp(argv[i], "--exec=always") == 0 || strcmp(argv[i], "--exec") == 0) { + test_no_exec__ = 0; + } else if(strcmp(argv[i], "--exec=never") == 0 || strcmp(argv[i], "--no-exec") == 0 || strcmp(argv[i], "-E") == 0) { + test_no_exec__ = 1; + } else if(strcmp(argv[i], "--no-summary") == 0) { + test_no_summary__ = 1; + } else if(strcmp(argv[i], "--list") == 0 || strcmp(argv[i], "-l") == 0) { + test_list_names__(); + exit(0); + } else { + fprintf(stderr, "%s: Unrecognized option '%s'\n", argv[0], argv[i]); + fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); + exit(2); + } + } + +#if defined(ACUTEST_WIN__) + SetUnhandledExceptionFilter(test_exception_filter__); +#endif + + /* By default, we want to run all tests. */ + if(test_count__ == 0) { + for(i = 0; test_list__[i].func != NULL; i++) + tests__[i] = &test_list__[i]; + test_count__ = test_list_size__; + } + + /* Guess whether we want to run unit tests as child processes. */ + if(test_no_exec__ < 0) { + test_no_exec__ = 0; + + if(test_count__ <= 1) { + test_no_exec__ = 1; + } else { +#ifdef ACUTEST_WIN__ + if(IsDebuggerPresent()) + test_no_exec__ = 1; +#endif +#ifdef ACUTEST_LINUX__ + if(test_is_tracer_present__()) + test_no_exec__ = 1; +#endif + } + } + + /* Run the tests */ + if(!test_skip_mode__) { + /* Run the listed tests. */ + for(i = 0; i < (int) test_count__; i++) + test_run__(tests__[i]); + } else { + /* Run all tests except those listed. */ + for(i = 0; test_list__[i].func != NULL; i++) { + if(!test_flags__[i]) + test_run__(&test_list__[i]); + } + } + + /* Write a summary */ + if(!test_no_summary__ && test_verbose_level__ >= 1) { + if(test_verbose_level__ >= 3) { + test_print_in_color__(TEST_COLOR_DEFAULT_INTENSIVE__, "Summary:\n"); + + printf(" Count of all unit tests: %4d\n", (int) test_list_size__); + printf(" Count of run unit tests: %4d\n", test_stat_run_units__); + printf(" Count of failed unit tests: %4d\n", test_stat_failed_units__); + printf(" Count of skipped unit tests: %4d\n", (int) test_list_size__ - test_stat_run_units__); + printf(" "); + } + + if(test_stat_failed_units__ == 0) { + test_print_in_color__(TEST_COLOR_GREEN_INTENSIVE__, "SUCCESS:"); + printf(" All unit tests have passed.\n"); + } else { + test_print_in_color__(TEST_COLOR_RED_INTENSIVE__, "FAILED:"); + printf(" %d of %d unit tests have failed.\n", + test_stat_failed_units__, test_stat_run_units__); + } + + if(test_verbose_level__ >= 3) + printf("\n"); + } + + free((void*) tests__); + free((void*) test_flags__); + + return (test_stat_failed_units__ == 0) ? 0 : 1; +} + + +#endif /* #ifndef TEST_NO_MAIN */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* #ifndef ACUTEST_H__ */ diff --git a/src/fluent-bit/lib/chunkio/tests/memfs.c b/src/fluent-bit/lib/chunkio/tests/memfs.c new file mode 100644 index 000000000..0c79f0097 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/memfs.c @@ -0,0 +1,181 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/stat.h> +#include <fcntl.h> + +#include <chunkio/chunkio.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_scan.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_memfs.h> +#include <chunkio/cio_meta.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_utils.h> + +#include "cio_tests_internal.h" + +#define CIO_FILE_400KB CIO_TESTS_DATA_PATH "/data/400kb.txt" +#define CIO_FILE_400KB_SIZE 409600 + +/* Logging callback, once called it just turn on the log_check flag */ +static int log_cb(struct cio_ctx *ctx, int level, const char *file, int line, + char *str) +{ + (void) ctx; + + printf("[cio-test-fs] %-60s => %s:%i\n", str, file, line); + return 0; +} + +/* Read a file into the buffer at most 'size' bytes. Return bytes read */ +static int read_file(const char *file, char *buf, size_t size) +{ + char *p = buf; + size_t total = 0; + ssize_t nb; + + int fd = open(file, O_RDONLY); + if (fd == -1) + return -1; + + while (1) { + nb = read(fd, p, size); + if (nb == 0) + break; + if (nb < 0) { + close(fd); + return -1; + } + p += nb; + size -= nb; + total += nb; + } + close(fd); + return total; +} + +/* Test API generating files to the file system and then scanning them back */ +static void test_memfs_write() +{ + int i; + int err; + int ret; + int n_files = 100; + int flags; + char *in_data; + size_t in_size; + char tmp[255]; + struct cio_ctx *ctx; + struct cio_stream *stream; + struct cio_chunk *chunk; + struct cio_chunk **carr; + struct cio_options cio_opts; + + /* Dummy break line for clarity on acutest output */ + printf("\n"); + + flags = CIO_CHECKSUM; + + cio_options_init(&cio_opts); + cio_opts.flags = flags; + + cio_opts.log_cb = log_cb; + cio_opts.flags = flags; + + /* Create main context */ + ctx = cio_create(&cio_opts); + TEST_CHECK(ctx != NULL); + + /* Try to create a file with an invalid stream */ + chunk = cio_chunk_open(ctx, NULL, "invalid", 0, 0, &err); + TEST_CHECK(chunk == NULL); + + /* Check invalid stream */ + stream = cio_stream_create(ctx, "", CIO_STORE_MEM); + TEST_CHECK(stream == NULL); + + /* Another invalid name */ + stream = cio_stream_create(ctx, "/", CIO_STORE_MEM); + TEST_CHECK(stream == NULL); + + /* Create valid stream */ + stream = cio_stream_create(ctx, "test-write", CIO_STORE_MEM); + TEST_CHECK(stream != NULL); + + /* + * Load sample data file and with the same content through multiple write + * operations generating other files. + */ + in_size = CIO_FILE_400KB_SIZE; + in_data = malloc(in_size); + if (!in_data) { + perror("calloc"); + exit(EXIT_FAILURE); + } + + ret = read_file(CIO_FILE_400KB, in_data, in_size); + if (ret == -1) { + cio_destroy(ctx); + exit(EXIT_FAILURE); + } + + /* Number of test files to create */ + n_files = 100; + + /* Allocate files array */ + carr = calloc(1, sizeof(struct cio_chunk) * n_files); + if (!carr) { + perror("calloc"); + exit(EXIT_FAILURE); + } + + + for (i = 0; i < n_files; i++) { + snprintf(tmp, sizeof(tmp), "api-test-%04i.txt", i); + carr[i] = cio_chunk_open(ctx, stream, tmp, CIO_OPEN, 1000000, &err); + + if (carr[i] == NULL) { + continue; + } + + cio_chunk_write(carr[i], in_data, in_size); + cio_chunk_write(carr[i], in_data, in_size); + + /* update metadata */ + //cio_meta_write(farr[i], tmp, len); + + /* continue appending data to content area */ + cio_chunk_write(carr[i], in_data, in_size); + cio_chunk_write(carr[i], in_data, in_size); + cio_chunk_write(carr[i], in_data, in_size); + } + + /* Release file data and destroy context */ + free(carr); + free(in_data); + + cio_scan_dump(ctx); + cio_destroy(ctx); +} + +TEST_LIST = { + {"memfs_write", test_memfs_write}, + { 0 } +}; diff --git a/src/fluent-bit/lib/chunkio/tests/stream.c b/src/fluent-bit/lib/chunkio/tests/stream.c new file mode 100644 index 000000000..0a86c1437 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/stream.c @@ -0,0 +1,87 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <chunkio/chunkio.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_scan.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_meta.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_utils.h> + +#include "cio_tests_internal.h" + +#define CIO_ENV "/tmp/cio-stream-test/" +#define CIO_FILE_400KB CIO_TESTS_DATA_PATH "/data/400kb.txt" + +/* Logging callback, once called it just turn on the log_check flag */ +static int log_cb(struct cio_ctx *ctx, int level, const char *file, int line, + char *str) +{ + (void) ctx; + + printf("[cio-test-stream] %-60s => %s:%i\n", str, file, line); + return 0; +} + +static void test_stream_delete() +{ + int i; + int ret; + int err; + int len; + char line[] = "this is a test line\n"; + struct cio_ctx *ctx; + struct cio_chunk *chunk; + struct cio_stream *stream; + struct cio_options cio_opts; + + cio_utils_recursive_delete("tmp"); + + cio_options_init(&cio_opts); + + cio_opts.root_path = "tmp"; + cio_opts.log_cb = log_cb; + cio_opts.log_level = CIO_LOG_DEBUG; + cio_opts.flags = CIO_CHECKSUM; + + /* Create a temporal storage */ + ctx = cio_create(&cio_opts); + stream = cio_stream_create(ctx, "test", CIO_STORE_FS); + chunk = cio_chunk_open(ctx, stream, "c", CIO_OPEN, 1000, &err); + TEST_CHECK(chunk != NULL); + if (!chunk) { + printf("cannot open chunk\n"); + exit(1); + } + + len = strlen(line); + for (i = 0; i < 1000; i++) { + ret = cio_chunk_write(chunk, line, len); + TEST_CHECK(ret == CIO_OK); + } + + cio_stream_delete(stream); + cio_destroy(ctx); +} + +TEST_LIST = { + {"stream_delete", test_stream_delete}, + { 0 } +}; diff --git a/src/fluent-bit/lib/chunkio/tests/test_utils.c b/src/fluent-bit/lib/chunkio/tests/test_utils.c new file mode 100644 index 000000000..95e8836ea --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/test_utils.c @@ -0,0 +1,18 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/src/fluent-bit/lib/chunkio/tests/test_utils.h b/src/fluent-bit/lib/chunkio/tests/test_utils.h new file mode 100644 index 000000000..ef4210575 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tests/test_utils.h @@ -0,0 +1,25 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIO_TESTS_UTILS_H +#define CIO_TESTS_UTILS_H + +int utils_recursive_delete(const char *dir); + +#endif diff --git a/src/fluent-bit/lib/chunkio/tools/CMakeLists.txt b/src/fluent-bit/lib/chunkio/tools/CMakeLists.txt new file mode 100644 index 000000000..0fe1845f6 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tools/CMakeLists.txt @@ -0,0 +1,5 @@ +set(src + cio.c) + +add_executable(cio ${src}) +target_link_libraries(cio chunkio-static) diff --git a/src/fluent-bit/lib/chunkio/tools/cio.c b/src/fluent-bit/lib/chunkio/tools/cio.c new file mode 100644 index 000000000..a27827653 --- /dev/null +++ b/src/fluent-bit/lib/chunkio/tools/cio.c @@ -0,0 +1,651 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <limits.h> +#include <signal.h> +#include <time.h> +#ifndef _MSC_VER +#include <pwd.h> +#endif +#ifdef __MACH__ +# include <mach/clock.h> +# include <mach/mach.h> +#endif + +#include <monkey/mk_core/mk_getopt.h> +#include <chunkio/chunkio_compat.h> + +#ifndef _MSC_VER +#define ANSI_RESET "\033[0m" +#define ANSI_BOLD "\033[1m" +#define ANSI_CYAN "\033[96m" +#define ANSI_MAGENTA "\033[95m" +#define ANSI_RED "\033[91m" +#define ANSI_YELLOW "\033[93m" +#define ANSI_BLUE "\033[94m" +#define ANSI_GREEN "\033[92m" +#define ANSI_WHITE "\033[97m" +#else +#define ANSI_RESET "" +#define ANSI_BOLD "" +#define ANSI_CYAN "" +#define ANSI_MAGENTA "" +#define ANSI_RED "" +#define ANSI_YELLOW "" +#define ANSI_BLUE "" +#define ANSI_GREEN "" +#define ANSI_WHITE "" +#endif + +#define ANSI_BOLD_CYAN ANSI_BOLD ANSI_CYAN +#define ANSI_BOLD_MAGENTA ANSI_BOLD ANSI_MAGENTA +#define ANSI_BOLD_RED ANSI_BOLD ANSI_RED +#define ANSI_BOLD_YELLOW ANSI_BOLD ANSI_YELLOW +#define ANSI_BOLD_BLUE ANSI_BOLD ANSI_BLUE +#define ANSI_BOLD_GREEN ANSI_BOLD ANSI_GREEN +#define ANSI_BOLD_WHITE ANSI_BOLD ANSI_WHITE + +#ifdef _MSC_VER +#define STDIN_FILENO _fileno( stdin ) +#define STDOUT_FILENO _fileno( stdout ) +#define STDERR_FILENO _fileno( stderr ) +#endif + +#define CIO_ROOT_PATH ".cio" +#define cio_print_signal(X) case X: \ + write (STDERR_FILENO, #X ")\n" , sizeof(#X ")\n")-1); \ + break; + +#define CIO_PERF_PATH "/tmp/cio-perf/" + +#define ONESEC_IN_NSEC 1000000000 + +#include <chunkio/chunkio.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_stream.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_meta.h> +#include <chunkio/cio_scan.h> +#include <chunkio/cio_utils.h> + +static void cio_help(int rc) +{ + printf("Usage: cio [-r PATH] OPTIONS\n\n"); + printf("Available Options\n"); + printf(" -r, --root[=PATH]\tset root path\n"); + printf(" -i, --stdin\t\tdump stdin data to stream/file\n"); + printf(" -s, --stream=STREAM\tset stream name\n"); + printf(" -m, --metadata=INFO\tset metadata\n"); + printf(" -M, --memory\t\trun in-memory mode\n"); + printf(" -l, --list\t\tlist environment content\n"); + printf(" -E, --extension\tset chunk extension filter\n"); + printf(" -F, --full-sync\tforce data flush to disk\n"); + printf(" -k, --checksum\tenable CRC32 checksum\n"); + printf(" -f, --filename=FILE\tset name of file to create\n"); + printf(" -p, --perf=FILE\trun performance test\n"); + printf(" -w, --perf-writes=N\tset number of writes for performance mode " + "(default: 5)\n"); + printf(" -e, --perf-files=N\tset number of files to create on " + "performance mode (default: 1000)\n"); + printf(" -S, --silent\t\tmake chunkio quiet during the operation\n"); + printf(" -v, --verbose\t\tincrease logging verbosity\n"); + printf(" -h, --help\t\tprint this help\n"); + exit(rc); +} + +static void cio_signal_handler(int signal) +{ + char s[] = "[cio] caught signal ("; + + /* write signal number */ + write(STDERR_FILENO, s, sizeof(s) - 1); + switch (signal) { + cio_print_signal(SIGINT); +#ifndef _MSC_VER + cio_print_signal(SIGQUIT); + cio_print_signal(SIGHUP); +#endif + cio_print_signal(SIGTERM); + cio_print_signal(SIGSEGV); + }; + + /* Signal handlers */ + switch (signal) { + case SIGINT: +#ifndef _MSC_VER + case SIGQUIT: + case SIGHUP: +#endif + case SIGTERM: + _exit(EXIT_SUCCESS); + case SIGSEGV: + abort(); + default: + break; + } +} + +void cio_bytes_to_human_readable_size(size_t bytes, + char *out_buf, size_t size) +{ + unsigned long i; + uint64_t u = 1024; + static const char *__units[] = { + "b", "K", "M", "G", + "T", "P", "E", "Z", "Y", NULL + }; + + for (i = 0; __units[i] != NULL; i++) { + if ((bytes / u) == 0) { + break; + } + u *= 1024; + } + if (!i) { + snprintf(out_buf, size, "%lu%s", (long unsigned int) bytes, __units[0]); + } + else { + float fsize = (float) ((double) bytes / (u / 1024)); + snprintf(out_buf, size, "%.1f%s", fsize, __units[i]); + } +} + +static void cio_signal_init() +{ + signal(SIGINT, &cio_signal_handler); +#ifndef _MSC_VER + signal(SIGQUIT, &cio_signal_handler); + signal(SIGHUP, &cio_signal_handler); +#endif + signal(SIGTERM, &cio_signal_handler); + signal(SIGSEGV, &cio_signal_handler); +} + + +static int log_cb(struct cio_ctx *ctx, int level, const char *file, int line, + char *str) +{ + char *dtitle = "chunkio"; + char *dcolor = ANSI_BLUE; + + /* messages from this own client are in yellow */ + if (*file == 't') { + dtitle = " cli "; + dcolor = ANSI_YELLOW; + } + + if (ctx->options.log_level > CIO_LOG_INFO) { + printf("%s[%s]%s %-60s => %s%s:%i%s\n", + dcolor, dtitle, ANSI_RESET, str, + dcolor, file, line, ANSI_RESET); + } + else { + printf("%s[%s]%s %s\n", dcolor, dtitle, ANSI_RESET, str); + } + + return 0; +} + +#ifndef _MSC_VER +static int cio_default_root_path(char *path, int size) +{ + int len; + struct passwd *pw; + + pw = getpwuid(getuid()); + if (!pw) { + perror("getpwuid"); + return -1; + } + + /* ~/.cio */ + len = snprintf(path, size, "%s/%s", + pw->pw_dir, CIO_ROOT_PATH); + if (len == -1) { + perror("snprintf"); + return -1; + } + + return 0; +} +#else +static int cio_default_root_path(char *path, int size) +{ + return -1; +} +#endif + +static void cio_timespec_get(struct timespec *t) +{ +#ifdef __MACH__ // macOS does not have timespec_get, use clock_get_time + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + t->tv_sec = mts.tv_sec; + t->tv_nsec = mts.tv_nsec; +#else + timespec_get(t, TIME_UTC); +#endif +} + +/* command/list: iterate root path and list content */ +static int cb_cmd_list(struct cio_ctx *ctx) +{ + cio_scan_dump(ctx); + return 0; +} + +/* command/stdin: read data from STDIN and dump it into stream/file */ +static int cb_cmd_stdin(struct cio_ctx *ctx, const char *stream, + int opt_buffer, + const char *fname, const char *metadata) +{ + int fd; + int ret; + int err; + int meta_len; + size_t total = 0; + ssize_t bytes; + char buf[1024*8]; + struct cio_stream *st; + struct cio_chunk *ch; + + /* Prepare stream and file contexts */ + st = cio_stream_create(ctx, stream, opt_buffer); + if (!st) { + cio_log_error(ctx, "cannot create stream\n"); + return -1; + } + + /* Open a file with a hint of 32KB */ + ch = cio_chunk_open(ctx, st, fname, CIO_OPEN, 1024*32, &err); + if (!ch) { + cio_log_error(ctx, "cannot create file"); + return -1; + } + + if (metadata) { + meta_len = strlen(metadata); + cio_meta_write(ch, (char *) metadata, meta_len); + } + + /* Catch up stdin */ + fd = dup(STDIN_FILENO); + if (fd == -1) { + perror("dup"); + cio_log_error(ctx, "cannot open standard input"); + return -1; + } + + do { + bytes = read(fd, buf, sizeof(buf) - 1); + if (bytes == 0) { + break; + } + else if (bytes == -1) { + perror("read"); + } + else { + ret = cio_chunk_write(ch, buf, bytes); + if (ret == -1) { + cio_log_error(ctx, "error writing to file"); + close(fd); + return -1; + } + total += bytes; + } + } while (bytes > 0); + + /* close stdin dup(2) */ + close(fd); + + /* synchronize changes to disk and close */ + cio_chunk_sync(ch); + cio_chunk_close(ch, CIO_FALSE); + + /* print some status */ + cio_bytes_to_human_readable_size(total, buf, sizeof(buf) - 1); + cio_log_info(ctx, "stdin total bytes => %lu (%s)", total, buf); + + return 0; +} + +static double time_to_double(struct timespec *t) +{ + return (double)(t->tv_sec) + ((double)t->tv_nsec/(double) ONESEC_IN_NSEC); +} + +static int time_diff(struct timespec *tm0, struct timespec *tm1, + struct timespec *out) +{ + + if (tm1->tv_sec >= tm0->tv_sec) { + out->tv_sec = tm1->tv_sec - tm0->tv_sec; + if (tm1->tv_nsec >= tm0->tv_nsec) { + out->tv_nsec = tm1->tv_nsec - tm0->tv_nsec; + } + else if(tm0->tv_sec == 0){ + /* underflow */ + return -1; + } + else{ + out->tv_nsec = ONESEC_IN_NSEC \ + + tm1->tv_nsec - tm0->tv_nsec; + out->tv_sec--; + } + } + else { + /* underflow */ + return -1; + } + + return 0; +} + +static void cb_cmd_perf(struct cio_ctx *ctx, int opt_buffer, char *pfile, + char *metadata, int writes, int files) +{ + int i; + int j; + int err; + int meta_len = 0; + int ret; + uint64_t bytes = 0; + double rate; + char *in_data; + size_t in_size; + char tmp[255]; + struct cio_stream *stream; + struct cio_chunk **carr; + struct timespec t1; + struct timespec t2; + struct timespec t_final; + + /* Create pref stream */ + stream = cio_stream_create(ctx, "test-perf", opt_buffer); + + /* + * Load sample data file and with the same content through multiple write + * operations generating other files. + */ + ret = cio_utils_read_file(pfile, &in_data, &in_size); + if (ret == -1) { + cio_destroy(ctx); + exit(EXIT_FAILURE); + } + + /* Allocate files array */ + carr = calloc(1, sizeof(struct cio_chunk) * files); + if (!carr) { + perror("calloc"); + exit(EXIT_FAILURE); + } + + if (metadata) { + meta_len = strlen(metadata); + } + + /* Perf-write test */ + cio_timespec_get(&t1); + for (i = 0; i < files; i++) { + snprintf(tmp, sizeof(tmp), "perf-test-%04i.txt", i); + carr[i] = cio_chunk_open(ctx, stream, tmp, CIO_OPEN, in_size, &err); + if (carr[i] == NULL) { + continue; + } + + if (meta_len > 0) { + cio_meta_write(carr[i], metadata, meta_len); + bytes += meta_len; + } + + for (j = 0; j < writes; j++) { + ret = cio_chunk_write(carr[i], in_data, in_size); + if (ret == -1) { + exit(1); + } + bytes += in_size; + } + cio_chunk_sync(carr[i]); + cio_chunk_close(carr[i], CIO_FALSE); + } + cio_timespec_get(&t2); + + /* Check timing */ + time_diff(&t1, &t2, &t_final); + + /* + * Write out the report + * ==================== + */ + cio_bytes_to_human_readable_size(bytes, tmp, sizeof(tmp) - 1); + printf("=== perf write === \n"); + printf("- crc32 checksum : %s\n", + ctx->options.flags & CIO_CHECKSUM ? "enabled" : "disabled"); + printf("- fs sync mode : %s\n", + ctx->options.flags & CIO_FULL_SYNC ? "full" : "normal"); + + cio_bytes_to_human_readable_size(in_size, tmp, sizeof(tmp) - 1); + printf("- file size : %s (%lu bytes)\n", tmp, in_size); + printf("- total files : %i\n", files); + printf("- file writes : %i\n", writes); + + cio_bytes_to_human_readable_size(bytes, tmp, sizeof(tmp) - 1); + printf("- bytes written : %s (%" PRIu64 " bytes)\n" , tmp, bytes); + printf("- elapsed time : %.2f seconds\n", time_to_double(&t_final)); + + rate = (double) (bytes / time_to_double(&t_final)); + cio_bytes_to_human_readable_size(rate, tmp, sizeof(tmp) - 1); + printf("- rate : %s per second (%.2f bytes)\n", tmp, rate); + + /* Release file data and destroy context */ + free(carr); + free(in_data); +} + +int main(int argc, char **argv) +{ + int ret = 0; + int opt; + int opt_silent = CIO_FALSE; + int opt_pwrites = 5; + int opt_pfiles = 1000; + int opt_buffer = CIO_STORE_FS; + int cmd_stdin = CIO_FALSE; + int cmd_list = CIO_FALSE; + int cmd_perf = CIO_FALSE; + int verbose = CIO_LOG_WARN; + int flags = 0; + char *chunk_ext = NULL; + char *perf_file = NULL; + char *fname = NULL; + char *stream = NULL; + char *metadata = NULL; + char *root_path = NULL; + char tmp[PATH_MAX]; + struct cio_ctx *ctx; + struct cio_options cio_opts; + + static const struct option long_opts[] = { + {"full-sync" , no_argument , NULL, 'F'}, + {"checksum" , no_argument , NULL, 'k'}, + {"extension" , required_argument, NULL, 'E'}, + {"list" , no_argument , NULL, 'l'}, + {"root" , required_argument, NULL, 'r'}, + {"silent" , no_argument , NULL, 'S'}, + {"stdin" , no_argument , NULL, 'i'}, + {"stream" , required_argument, NULL, 's'}, + {"metadata" , required_argument, NULL, 'm'}, + {"memory" , no_argument , NULL, 'M'}, + {"filename" , required_argument, NULL, 'f'}, + {"perf" , required_argument, NULL, 'p'}, + {"perf-writes", required_argument, NULL, 'w'}, + {"perf-files" , required_argument, NULL, 'e'}, + {"verbose" , no_argument , NULL, 'v'}, + {"version" , no_argument , NULL, 'V'}, + {"help" , no_argument , NULL, 'h'}, + }; + + /* Initialize signals */ + cio_signal_init(); + + while ((opt = getopt_long(argc, argv, "FkE:lr:p:w:e:Sis:m:Mf:vVh", + long_opts, NULL)) != -1) { + switch (opt) { + case 'F': + flags |= CIO_FULL_SYNC; + break; + case 'k': + flags |= CIO_CHECKSUM; + break; + case 'E': + chunk_ext = strdup(optarg); + break; + case 'l': + cmd_list = CIO_TRUE; + break; + case 'i': + cmd_stdin = CIO_TRUE; + break; + case 'r': + root_path = strdup(optarg); + break; + case 'p': + perf_file = strdup(optarg); + cmd_perf = CIO_TRUE; + break; + case 'w': + opt_pwrites = atoi(optarg); + break; + case 'e': + opt_pfiles = atoi(optarg); + break; + case 'S': + opt_silent = CIO_TRUE; + break; + case 's': + stream = strdup(optarg); + break; + case 'm': + metadata = strdup(optarg); + break; + case 'M': + opt_buffer = CIO_STORE_MEM; + break; + case 'f': + fname = strdup(optarg); + break; + case 'v': + verbose++; + break; + case 'V': + fprintf(stderr, "Chunk I/O v%s\n", cio_version()); + exit(0); + case 'h': + cio_help(EXIT_SUCCESS); + break; + default: + cio_help(EXIT_FAILURE); + } + } + + if (opt_buffer == CIO_STORE_FS && cmd_perf) { + root_path = strdup(CIO_PERF_PATH); + cio_utils_recursive_delete(CIO_PERF_PATH); + } + + /* Check root path, if not set, defaults to ~/.cio */ + if (opt_buffer == CIO_STORE_FS && !root_path) { + ret = cio_default_root_path(tmp, sizeof(tmp) - 1); + if (ret == -1) { + fprintf(stderr, + "[chunkio cli] cannot set default root path\n"); + cio_help(EXIT_FAILURE); + } + root_path = strdup(tmp); + } + + if (opt_silent == CIO_TRUE) { + verbose = 0; + } + + cio_options_init(&cio_opts); + + cio_opts.root_path = root_path; + cio_opts.flags = flags; + cio_opts.log_cb = log_cb; + cio_opts.log_level = verbose; + + /* Create CIO instance */ + ctx = cio_create(&cio_opts); + if (root_path) { + free(root_path); + } + + if (!ctx) { + exit(EXIT_FAILURE); + } + + /* Load */ + cio_load(ctx, chunk_ext); + cio_log_info(ctx, "root_path => %s", ctx->options.root_path); + + /* + * Process commands and options + */ + if (cmd_list == CIO_TRUE) { + ret = cb_cmd_list(ctx); + } + else if (cmd_stdin == CIO_TRUE) { + /* we need the stream and file names */ + if (!stream) { + fprintf(stderr, "[chunkio cli] missing stream name\n"); + cio_help(EXIT_FAILURE); + } + if (!fname) { + fprintf(stderr, "[chunkio cli] missing file name\n"); + free(stream); + cio_help(EXIT_FAILURE); + } + + ret = cb_cmd_stdin(ctx, stream, opt_buffer, fname, metadata); + } + else if (cmd_perf == CIO_TRUE) { + cb_cmd_perf(ctx, opt_buffer, perf_file, metadata, opt_pwrites, + opt_pfiles); + free(perf_file); + } + else { + cio_help(EXIT_FAILURE); + } + + free(chunk_ext); + free(stream); + free(fname); + free(metadata); + cio_destroy(ctx); + + return ret; +} |