diff --git a/.github/workflows/ctest.yml b/.github/workflows/ctest.yml
index 191cefb2..afa88013 100644
--- a/.github/workflows/ctest.yml
+++ b/.github/workflows/ctest.yml
@@ -16,7 +16,7 @@ jobs:
fail-fast: false
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
+ os: [ubuntu-latest, windows-latest, macos-13]
build_type: [Debug, Release]
c_compiler: [gcc, clang, cl]
bit7z_auto_format: [OFF, ON]
@@ -39,7 +39,7 @@ jobs:
c_compiler: clang
cpp_compiler: clang++
use_system_7zip: OFF
- - os: macos-latest
+ - os: macos-13
c_compiler: clang
cpp_compiler: clang++
use_system_7zip: OFF
@@ -63,21 +63,29 @@ jobs:
bit7z_use_system_codepage: ON
- os: ubuntu-latest
bit7z_path_sanitization: ON
- - os: macos-latest
+ - os: macos-13
c_compiler: cl
- - os: macos-latest
+ - os: macos-13
c_compiler: gcc
- - os: macos-latest
+ - os: macos-13
bit7z_use_native_string: ON
- - os: macos-latest
+ - os: macos-13
bit7z_auto_prefix_long_paths: ON
- - os: macos-latest
+ - os: macos-13
bit7z_use_system_codepage: ON
- - os: macos-latest
+ - os: macos-13
bit7z_path_sanitization: ON
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
+
+ - name: Fix kernel mmap rnd bits
+ shell: bash
+ if: ${{ runner.os == 'Linux' && matrix.build_type == 'Debug' }}
+ # Asan in llvm 14 provided in ubuntu 22.04 is incompatible with
+ # high-entropy ASLR in much newer kernels that GitHub runners are
+ # using leading to random crashes: https://reviews.llvm.org/D148280
+ run: sudo sysctl vm.mmap_rnd_bits=28
- name: Set reusable strings
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
@@ -121,9 +129,10 @@ jobs:
- name: Build 7z.so for tests (macOS)
shell: bash
- if: matrix.os == 'macos-latest'
+ if: matrix.os == 'macos-13'
run: |
git clone --depth 1 https://github.com/rikyoz/7-Zip ${{ github.workspace }}/../7-zip
+ sed -i '' 's/-Wno-poison-system-directories/-Wno-poison-system-directories -Wno-declaration-after-statement\r/' ${{ github.workspace }}/../7-zip/CPP/7zip/warn_clang_mac.mak
cd ${{ github.workspace }}/../7-zip/CPP/7zip/Bundles/Format7zF/
make -j -f ../../cmpl_mac_x64.mak
cp b/m_x64/7z.so ${{ github.workspace }}/bin/x64/7z.so
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0127820e..a3cc671f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,10 +2,10 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-cmake_minimum_required( VERSION 3.11 )
+cmake_minimum_required( VERSION 3.14 )
project( bit7z
- VERSION 4.0.6
+ VERSION 4.0.7
DESCRIPTION "A C++ static library offering a clean and simple interface to the 7-zip/p7zip shared libraries"
HOMEPAGE_URL "https://github.com/rikyoz/bit7z/" )
set( CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON" )
diff --git a/README.md b/README.md
index d5554a11..3e6d9fc7 100644
--- a/README.md
+++ b/README.md
@@ -286,11 +286,11 @@ add_subdirectory( ${CMAKE_SOURCE_DIR}/third_party/bit7z )
target_link_libraries( ${YOUR_TARGET} PRIVATE bit7z )
```
-The library is highly customizable: for a detailed list of the available build options, please refer to the [wiki](https://github.com/rikyoz/bit7z/wiki/Building-the-library).
+The library is highly customizable: for a detailed list of the available build options, please refer to the [wiki](https://github.com/rikyoz/bit7z/wiki/Building-the-library#%EF%B8%8F-build-options).
-### π 7-zip Version
+### π 7-zip Version
-While configuring bit7z via CMake, it automatically downloads the latest version of 7-zip currently supported by the library.
+While configuring bit7z via CMake, it automatically downloads the latest version of 7-zip supported by the library.
Optionally, you can specify a different version of 7-zip via the CMake option `BIT7Z_7ZIP_VERSION` (e.g., `-DBIT7Z_7ZIP_VERSION="22.01"`).
@@ -300,16 +300,26 @@ Please note that, in general, it is best to use the same version of 7-zip of the
#### Using 7-zip v23.01 on Linux and macOS
+By default, bit7z is compatible with the `7z.so` from 7-zip v23.01 and later.
+
+If you plan to use the `7z.so` from p7zip or 7-zip v22.01 and earlier instead, you have two ways to make bit7z compatible:
+
++ Configure bit7z with the CMake option `-DBIT7Z_USE_LEGACY_IUNKNOWN=ON`; _or_
++ Configure bit7z for 7-zip v22.01 (i.e., `-DBIT7Z_7ZIP_VERSION="22.01"`).
+
- Expand for more details!
+ Expand for more details
-_On Linux and macOS_, 7-zip v23.01 introduced breaking changes to the IUnknown interface. If you build bit7z for such a version of 7-zip (the default), it will not support using the shared libraries from previous versions of 7-zip (or from p7zip). Conversely, bit7z made for earlier versions of 7-zip or for p7zip is incompatible with the shared libraries from 7-zip v23.01 and later.
+_On Linux and macOS_, 7-zip v23.01 introduced breaking changes to the IUnknown interface.
+As a result, if you build bit7z for such a version of 7-zip (the default), it will not support using the shared libraries from previous versions of 7-zip (or from p7zip).
+Conversely, bit7z made for earlier versions of 7-zip or for p7zip is incompatible with the shared libraries from 7-zip v23.01 and later.
-You can build the shared libraries of 7-zip v23.01 in a backward-compatible mode by defining the macro `Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN`. If this is your case, you can build bit7z for v23.01 using the option `BIT7Z_USE_LEGACY_IUNKNOWN` (in this case, bit7z will be compatible also with previous versions of 7-zip/p7zip).
+You can build the shared libraries of 7-zip v23.01 in a backward-compatible mode by defining the macro `Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN`.
+If this is your case, you'll need to enable the `BIT7Z_USE_LEGACY_IUNKNOWN` to make bit7z work (in this case, bit7z will be compatible also with previous versions of 7-zip/p7zip).
-### π String Encoding
+### πΊοΈ String Encoding
By default, bit7z follows the [UTF-8 Everywhere Manifesto](http://utf8everywhere.org/) to simplify the use of the library within cross-platform projects.
In short, this means that:
@@ -374,6 +384,6 @@ Older versions (v3.x and earlier) of bit7z were released under the [GNU General
-Copyright © 2014 - 2023 Riccardo Ostani (
@rikyoz)
+Copyright © 2014 - 2024 Riccardo Ostani (
@rikyoz)
diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake
index 7fd8b764..49498016 100644
--- a/cmake/Dependencies.cmake
+++ b/cmake/Dependencies.cmake
@@ -30,7 +30,7 @@ endif()
if( NOT USE_STANDARD_FILESYSTEM OR NOT STANDARD_FILESYSTEM_COMPILES OR BIT7Z_BUILD_TESTS )
CPMAddPackage( NAME ghc_filesystem
GITHUB_REPOSITORY rikyoz/filesystem
- GIT_TAG c0dcd0b090da7dffc74b124a6f164f54dbbb5ccb
+ GIT_TAG 983650f374699e3979f9cdefe13ddff60bd4ac68
DOWNLOAD_ONLY YES )
if( ghc_filesystem_ADDED )
message( STATUS "ghc::filesystem source code available at ${ghc_filesystem_SOURCE_DIR}" )
diff --git a/include/bit7z/bit7z.hpp b/include/bit7z/bit7z.hpp
index fd103d3a..ac3afd8e 100644
--- a/include/bit7z/bit7z.hpp
+++ b/include/bit7z/bit7z.hpp
@@ -10,7 +10,9 @@
#ifndef BIT7Z_HPP
#define BIT7Z_HPP
+#include "bitarchiveeditor.hpp"
#include "bitarchivereader.hpp"
+#include "bitarchivewriter.hpp"
#include "bitexception.hpp"
#include "bitfilecompressor.hpp"
#include "bitfileextractor.hpp"
diff --git a/include/bit7z/bitarchiveeditor.hpp b/include/bit7z/bitarchiveeditor.hpp
index 0d8da12a..0e47ddb4 100644
--- a/include/bit7z/bitarchiveeditor.hpp
+++ b/include/bit7z/bitarchiveeditor.hpp
@@ -20,6 +20,11 @@ using std::vector;
using EditedItems = std::unordered_map< uint32_t, BitItemsVector::value_type >;
+enum struct DeletePolicy : std::uint8_t {
+ ItemOnly,
+ RecurseDirs
+};
+
/**
* @brief The BitArchiveEditor class allows creating new file archives or updating old ones.
* Update operations supported are the addition of new items,
@@ -132,18 +137,40 @@ class BIT7Z_MAYBE_UNUSED BitArchiveEditor final : public BitArchiveWriter {
void updateItem( const tstring& itemPath, istream& inStream );
/**
- * @brief Marks the item at the given index as deleted.
+ * @brief Marks as deleted the item at the given index.
+ *
+ * @note By default, if the item is a folder, only its metadata is deleted, not the files within it.
+ * If instead the policy is set to DeletePolicy::RecurseDirs,
+ * then the items within the folder will also be deleted.
*
- * @param index the index of the item to be deleted.
+ * @param index the index of the item to be deleted.
+ * @param policy the policy to be used when deleting items.
+ *
+ * @throws BitException if the index is invalid.
*/
- void deleteItem( uint32_t index );
+ void deleteItem( uint32_t index, DeletePolicy policy = DeletePolicy::ItemOnly );
/**
- * @brief Marks the item at the given path (in the archive) as deleted.
+ * @brief Marks as deleted the archive's item(s) with the specified path.
+ *
+ * @note By default, if the marked item is a folder, only its metadata will be deleted, not the files within it.
+ * To delete the folder contents as well, set the `policy` to `DeletePolicy::RecurseDirs`.
+ *
+ * @note The specified path must not begin with a path separator.
+ *
+ * @note A path with a trailing separator will _only_ be considered if
+ * the policy is DeletePolicy::RecurseDirs, and will only match folders;
+ * with DeletePolicy::ItemOnly, no item will match a path with a trailing separator.
+ *
+ * @note Generally, archives may contain multiple items with the same paths.
+ * If this is the case, all matching items will be marked as deleted according to the specified policy.
*
* @param itemPath the path (in the archive) of the item to be deleted.
+ * @param policy the policy to be used when deleting items.
+ *
+ * @throws BitException if the specified path is empty or invalid, or if no matching item could be found.
*/
- void deleteItem( const tstring& itemPath );
+ void deleteItem( const tstring& itemPath, DeletePolicy policy = DeletePolicy::ItemOnly );
/**
* @brief Applies the requested changes (i.e., rename/update/delete operations) to the input archive.
@@ -164,6 +191,8 @@ class BIT7Z_MAYBE_UNUSED BitArchiveEditor final : public BitArchiveWriter {
auto hasNewData( uint32_t index ) const noexcept -> bool override;
auto hasNewProperties( uint32_t index ) const noexcept -> bool override;
+
+ void markItemAsDeleted( uint32_t index );
};
} // namespace bit7z
diff --git a/include/bit7z/bitarchiveitem.hpp b/include/bit7z/bitarchiveitem.hpp
index 671af111..1300d1a4 100644
--- a/include/bit7z/bitarchiveitem.hpp
+++ b/include/bit7z/bitarchiveitem.hpp
@@ -53,6 +53,14 @@ class BitArchiveItem : public BitGenericItem {
*/
BIT7Z_NODISCARD auto path() const -> tstring override;
+ /**
+ * @note Same as path(), but returning a native string (i.e., std::wstring on Windows, std::string elsewhere).
+ *
+ * @return the path of the item in the archive, if available or inferable from the name, or an empty string
+ * otherwise.
+ */
+ BIT7Z_NODISCARD auto nativePath() const -> native_string;
+
/**
* @return the uncompressed size of the item.
*/
diff --git a/include/bit7z/bitoutputarchive.hpp b/include/bit7z/bitoutputarchive.hpp
index 2d14bfb2..5c53cfbe 100644
--- a/include/bit7z/bitoutputarchive.hpp
+++ b/include/bit7z/bitoutputarchive.hpp
@@ -166,13 +166,10 @@ class BitOutputArchive {
* @brief Adds all the files inside the given directory path that match the given wildcard filter.
*
* @param inDir the directory where to search for files to be added to the output archive.
- * @param filter (optional) the wildcard filter to be used for searching the files.
- * @param recursive (optional) recursively search the files in the given directory
- * and all of its subdirectories.
+ * @param filter the wildcard filter to be used for searching the files.
+ * @param recursive recursively search the files in the given directory and all of its subdirectories.
*/
- void addFiles( const tstring& inDir,
- const tstring& filter = BIT7Z_STRING( "*" ),
- bool recursive = true );
+ void addFiles( const tstring& inDir, const tstring& filter, bool recursive );
/**
* @brief Adds all the files inside the given directory path that match the given wildcard filter.
diff --git a/src/bitarchiveeditor.cpp b/src/bitarchiveeditor.cpp
index 92880848..2bbe1f67 100644
--- a/src/bitarchiveeditor.cpp
+++ b/src/bitarchiveeditor.cpp
@@ -90,32 +90,98 @@ void BitArchiveEditor::updateItem( const tstring& itemPath, std::istream& inStre
mEditedItems[ findItem( itemPath ) ] = std::make_unique< StdInputItem >( inStream, itemPath ); //-V108
}
-void BitArchiveEditor::deleteItem( uint32_t index ) {
+void BitArchiveEditor::deleteItem( uint32_t index, DeletePolicy policy ) {
if ( index >= inputArchiveItemsCount() ) {
throw BitException( "Cannot delete item at index " + std::to_string( index ),
make_error_code( BitError::InvalidIndex ) );
}
- mEditedItems.erase( index );
- setDeletedIndex( index );
+
+ markItemAsDeleted( index );
+
+ const auto& deletedItem = inputArchive()->itemAt( index );
+ if ( !deletedItem.isDir() || policy == DeletePolicy::ItemOnly ) {
+ return;
+ }
+
+ const auto deletedPath = deletedItem.nativePath() + fs::path::preferred_separator;
+ if ( deletedPath.size() <= 1 ) { // The original path was empty
+ return;
+ }
+
+ for ( const auto& item: *inputArchive() ) {
+ if ( starts_with( item.nativePath(), deletedPath ) ) {
+ markItemAsDeleted( item.index() );
+ }
+ }
+}
+
+/**
+ * Determines if the given itemPath is within the specified base directory.
+ *
+ * @param itemPath The path to the item to be checked.
+ * @param isDir A boolean indicating whether the itemPath represents a directory.
+ * @param base The base directory against which the itemPath is checked.
+ *
+ * @return true if the itemPath is located within the base directory, false otherwise.
+ */
+inline auto isInsidePath( const fs::path& itemPath, bool isDir, const fs::path& base ) -> bool {
+ const auto relativePath = itemPath.lexically_relative( base ).native();
+ /* The relative path of the item with respect to the base directory can be:
+ * 1) A single dot component;
+ * 2) A path not starting with a dot-dot component (i.e., the item is inside the base path);
+ * 3) A path starting with a dot-dot component (i.e., the item is outside the base path).
+ *
+ * This function is called after having evaluated itemPath == base to false;
+ * also, 7-Zip reports folder paths without trailing separators.
+ * Hence, the first case can be restricted further to only the case
+ * where the base path has a trailing path separator: this means that if
+ * the relative path is a single dot, the item must be a folder to be considered inside the base path.
+ *
+ * The remaining cases 2 and 3 are checked as follows:
+ * - Either the relative path doesn't start with two dots (and then the item is inside the base path) or
+ * - It starts with two dots, but it is not a dot-dot component (e.g., a normal filename starting with two dots).
+ */
+ return ( relativePath != BIT7Z_NATIVE_STRING( "." ) || isDir ) &&
+ ( !starts_with( relativePath, BIT7Z_NATIVE_STRING( ".." ) ) ||
+ ( relativePath.size() > 2 && !isPathSeparator( relativePath[ 2 ] ) ) );
}
-void BitArchiveEditor::deleteItem( const tstring& itemPath ) {
- auto res = std::find_if( inputArchive()->cbegin(), inputArchive()->cend(),
- // Note: we don't use auto for the parameter type to support compilation with GCC 4.9
- [ &, this ]( const BitArchiveItemOffset& archiveItem ) {
- if ( archiveItem.path() == itemPath ) {
- mEditedItems.erase( archiveItem.index() );
- setDeletedIndex( archiveItem.index() );
- return true;
- }
- return false;
- } );
- if ( res == inputArchive()->cend() ) {
- throw BitException( "Could not mark the item as deleted",
+void BitArchiveEditor::deleteItem( const tstring& itemPath, DeletePolicy policy ) {
+ // The path to be deleted must be relative to the root of the archive.
+ if ( itemPath.empty() || isPathSeparator( itemPath.front() ) ) {
+ throw BitException( "Could not mark any path as deleted",
+ std::make_error_code( std::errc::invalid_argument ), itemPath );
+ }
+
+ bool deleted = false;
+
+ // Normalized form of the path to be deleted inside the archive.
+ const auto deletedPath = tstring_to_path( itemPath ).lexically_normal();
+ for ( const auto& item: *inputArchive() ) {
+ const fs::path path = item.nativePath();
+
+ // The current item is marked as deleted if either:
+ // - it is lexicographically equivalent to the path to be deleted; or
+ // - we need to recursively delete directories,
+ // and the path of the item is (lexicographically) inside the path to be deleted.
+ if ( path == deletedPath ||
+ ( policy == DeletePolicy::RecurseDirs && isInsidePath( path, item.isDir(), deletedPath ) ) ) {
+ markItemAsDeleted( item.index() );
+ deleted = true;
+ }
+ }
+
+ if ( !deleted ) {
+ throw BitException( "Could not mark any path as deleted",
std::make_error_code( std::errc::no_such_file_or_directory ), itemPath );
}
}
+void BitArchiveEditor::markItemAsDeleted( uint32_t index ) {
+ mEditedItems.erase( index );
+ setDeletedIndex( index );
+}
+
void BitArchiveEditor::setUpdateMode( UpdateMode mode ) {
if ( mode == UpdateMode::None ) {
throw BitException( "Cannot set update mode to UpdateMode::None",
diff --git a/src/bitarchiveitem.cpp b/src/bitarchiveitem.cpp
index aabdadd9..ae957f58 100644
--- a/src/bitarchiveitem.cpp
+++ b/src/bitarchiveitem.cpp
@@ -63,6 +63,15 @@ auto BitArchiveItem::path() const -> tstring {
return path.getString();
}
+auto BitArchiveItem::nativePath() const -> native_string {
+ BitPropVariant path = itemProperty( BitProperty::Path );
+ if ( path.isEmpty() ) {
+ path = itemProperty( BitProperty::Name );
+ return path.isEmpty() ? native_string{} : path.getNativeString();
+ }
+ return path.getNativeString();
+}
+
auto BitArchiveItem::size() const -> uint64_t {
const BitPropVariant size = itemProperty( BitProperty::Size );
return size.isEmpty() ? 0 : size.getUInt64();
diff --git a/src/bitarchivereader.cpp b/src/bitarchivereader.cpp
index ac75fb78..74e1334b 100644
--- a/src/bitarchivereader.cpp
+++ b/src/bitarchivereader.cpp
@@ -49,9 +49,12 @@ auto BitArchiveReader::archiveProperties() const -> map< BitProperty, BitPropVar
return result;
}
-auto BitArchiveReader::items() const -> vector< BitArchiveItemInfo > {
- vector< BitArchiveItemInfo > result;
- for ( uint32_t i = 0; i < itemsCount(); ++i ) {
+auto BitArchiveReader::items() const -> std::vector< BitArchiveItemInfo > {
+ const auto count = itemsCount();
+
+ std::vector< BitArchiveItemInfo > result;
+ result.reserve( count );
+ for ( uint32_t i = 0; i < count; ++i ) {
BitArchiveItemInfo item( i );
for ( uint32_t j = kpidNoProperty; j <= kpidCopyLink; ++j ) {
// We cast property twice (here and in archiveProperty), to make the code is easier to read.
@@ -61,7 +64,7 @@ auto BitArchiveReader::items() const -> vector< BitArchiveItemInfo > {
item.setProperty( property, propertyValue );
}
}
- result.push_back( item );
+ result.push_back( std::move( item ) );
}
return result;
}
diff --git a/src/bititemsvector.cpp b/src/bititemsvector.cpp
index 6f58ed78..d98a3f5c 100644
--- a/src/bititemsvector.cpp
+++ b/src/bititemsvector.cpp
@@ -38,9 +38,10 @@ void BitItemsVector::indexDirectory( const fs::path& inDir,
void BitItemsVector::indexPaths( const std::vector< tstring >& inPaths, IndexingOptions options ) {
const auto symlinkPolicy = options.followSymlinks ? SymlinkPolicy::Follow : SymlinkPolicy::DoNotFollow;
- for ( const auto& filePath : inPaths ) {
+ for ( const auto& inputPath : inPaths ) {
+ const auto filePath = tstring_to_path( inputPath );
const FilesystemItem item{ filePath,
- options.retainFolderStructure ? tstring_to_path( filePath ) : fs::path{},
+ options.retainFolderStructure ? filePath : fs::path{},
symlinkPolicy };
indexItem( item, options );
}
diff --git a/src/internal/fsutil.cpp b/src/internal/fsutil.cpp
index 6f8858ec..6b8c127d 100644
--- a/src/internal/fsutil.cpp
+++ b/src/internal/fsutil.cpp
@@ -303,10 +303,6 @@ auto fsutil::get_file_attributes_ex( const fs::path& filePath,
constexpr auto kLongPathPrefix = BIT7Z_NATIVE_STRING( R"(\\?\)" );
-inline auto starts_with( const native_string& str, const native_string& prefix ) -> bool {
- return str.size() >= prefix.size() && str.compare( 0, prefix.size(), prefix ) == 0;
-}
-
auto fsutil::should_format_long_path( const fs::path& path ) -> bool {
constexpr auto kMaxDosFilenameSize = 12;
diff --git a/src/internal/stringutil.hpp b/src/internal/stringutil.hpp
index 2ac190bb..21d39aae 100644
--- a/src/internal/stringutil.hpp
+++ b/src/internal/stringutil.hpp
@@ -74,6 +74,34 @@ inline auto path_to_wide_string( const fs::path& path ) -> std::wstring {
#endif
}
+inline auto starts_with( const native_string& str, const native_string& prefix ) -> bool {
+ return str.rfind( prefix, 0 ) == 0;
+}
+
+/**
+ * Checks if the given character is a valid path separator on the target platform.
+ *
+ * @note On Windows, both / and \ are considered as path separators.
+ * On other platforms, only / is considered a path separator.
+ *
+ * @param character the character value to be checked.
+ *
+ * @return true if the character is a valid path separator on the target platform, false otherwise.
+ */
+inline auto isPathSeparator( char character ) -> bool {
+#ifdef _WIN32
+ return character == '/' || character == '\\';
+#else
+ return character == '/';
+#endif
+}
+
+#ifdef _WIN32
+inline auto isPathSeparator( wchar_t character ) -> bool {
+ return character == L'/' || character == L'\\';
+}
+#endif
+
} // namespace bit7z
#endif //STRINGUTIL_HPP
diff --git a/tests/src/test_dateutil.cpp b/tests/src/test_dateutil.cpp
index 1519fe7e..86e25753 100644
--- a/tests/src/test_dateutil.cpp
+++ b/tests/src/test_dateutil.cpp
@@ -10,7 +10,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
-#if !defined(__GNUC__) || __GNUC__ >= 5
+#if !defined(__GNUC__) || __GNUC__ >= 5 || defined(__clang__)
#include
#include
@@ -23,7 +23,7 @@ using namespace bit7z;
struct DateConversionTest {
const char* name;
- std::time_t dateTime;
+ std::int64_t dateTime; // Using std::int64_t instead of std::time_t to use 64-bit time on x86
FILETIME fileTime;
};
@@ -36,7 +36,6 @@ TEST_CASE( "fsutil: Date conversions", "[fsutil][date functions]" ) {
DateConversionTest{ "1 January 1970, 00:00", 0, { 3577643008, 27111902 } } );
DYNAMIC_SECTION( "Date: " << testDate.name ) {
-
#ifndef _WIN32
SECTION( "From std::time_t to FILETIME" ) {
auto output = time_to_FILETIME( testDate.dateTime );
@@ -45,20 +44,17 @@ TEST_CASE( "fsutil: Date conversions", "[fsutil][date functions]" ) {
}
#endif
- SECTION( "From FILETIME...") {
- std::time_t output{};
#ifndef _WIN32
- SECTION( "...to std::filesystem::file_time_type" ) {
- auto result = FILETIME_to_file_time_type( testDate.fileTime );
- output = std::time_t{ duration_cast< seconds >( result.time_since_epoch() ).count() };
- }
+ SECTION( "From FILETIME to std::filesystem::file_time_type" ) {
+ auto result = FILETIME_to_file_time_type( testDate.fileTime );
+ auto output = duration_cast< seconds >( result.time_since_epoch() ).count();
+ REQUIRE( output == testDate.dateTime );
+ }
#endif
- SECTION( "...to bit7z::time_type" ) {
- auto result = FILETIME_to_time_type( testDate.fileTime );
- output = bit7z::time_type::clock::to_time_t( result );
- }
-
+ SECTION( "From FILETIME to bit7z::time_type" ) {
+ auto result = FILETIME_to_time_type( testDate.fileTime );
+ auto output = bit7z::time_type::clock::to_time_t( result );
REQUIRE( output == testDate.dateTime );
}
}