Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 93 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
build_type: [Debug, Release]
include:
- os: ubuntu-latest
Expand All @@ -20,6 +20,9 @@ jobs:
- os: macos-latest
cc: clang
cxx: clang++
- os: windows-latest
cc: cl
cxx: cl

runs-on: ${{ matrix.os }}

Expand All @@ -39,12 +42,20 @@ jobs:
brew install clang-format zstd libsodium || true
# cmake is already available on macOS runners

- name: Set up environment
- name: Install dependencies (Windows)
if: matrix.os == 'windows-latest'
run: |
vcpkg install zstd:x64-windows libsodium:x64-windows
echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" >> $env:GITHUB_ENV

- name: Set up environment (non-Windows)
if: matrix.os != 'windows-latest'
run: |
echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV
echo "CXX=${{ matrix.cxx }}" >> $GITHUB_ENV

- name: Configure CMake
- name: Configure CMake (non-Windows)
if: matrix.os != 'windows-latest'
run: |
cmake -B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
Expand All @@ -53,16 +64,33 @@ jobs:
-DBFC_WITH_ZSTD=ON \
-DBFC_WITH_SODIUM=ON

- name: Build
- name: Configure CMake (Windows)
if: matrix.os == 'windows-latest'
run: |
cmake -B build `
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows `
-DBFC_WITH_ZSTD=ON `
-DBFC_WITH_SODIUM=ON `
-DBFC_BUILD_BENCHMARKS=OFF

- name: Build (non-Windows)
if: matrix.os != 'windows-latest'
run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)

- name: Build (Windows)
if: matrix.os == 'windows-latest'
run: cmake --build build --config ${{ matrix.build_type }} -j4

- name: Run tests
if: matrix.build_type == 'Debug'
run: |
cd build
ctest --output-on-failure --parallel $(nproc 2>/dev/null || sysctl -n hw.ncpu)
ctest --output-on-failure -C ${{ matrix.build_type }} --parallel 4

- name: Test CLI functionality
- name: Test CLI functionality (Unix)
if: matrix.os != 'windows-latest'
run: |
# Create test data
mkdir -p test_data
Expand Down Expand Up @@ -218,7 +246,66 @@ jobs:
rm -rf test.bfc test_data test_compressed.bfc test_fast.bfc test_balanced.bfc
rm -rf test_encrypted.bfc test_keyfile.bfc test_enc_comp.bfc test.key

- name: Test CLI functionality (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
# Create test data
New-Item -ItemType Directory -Force test_data\subdir | Out-Null
"Hello World" | Out-File -Encoding utf8 test_data\hello.txt
"Goodbye" | Out-File -Encoding utf8 test_data\bye.txt
"Nested file" | Out-File -Encoding utf8 test_data\subdir\nested.txt

# Locate the built binary (Debug or Release subfolder under bin)
$bfc = Get-ChildItem -Recurse build\bin -Filter bfc.exe | Select-Object -First 1 -ExpandProperty FullName
if (-not $bfc) { Write-Error "bfc.exe not found"; exit 1 }

# Basic CLI workflow
& $bfc create test.bfc test_data\
& $bfc list test.bfc
& $bfc info test.bfc
& $bfc verify test.bfc
& $bfc verify --deep test.bfc

# Compression
& $bfc create -c zstd test_compressed.bfc test_data\
& $bfc info test_compressed.bfc test_data\hello.txt
& $bfc verify test_compressed.bfc

# Extraction
New-Item -ItemType Directory -Force extract_test | Out-Null
Push-Location extract_test
& $bfc extract ..\test.bfc
if (Test-Path hello.txt) { Write-Output "hello.txt extracted" }
if (Test-Path bye.txt) { Write-Output "bye.txt extracted" }
if (Test-Path subdir\nested.txt) { Write-Output "nested.txt extracted" }
Pop-Location
Remove-Item -Recurse -Force extract_test

# Encryption
& $bfc create -e testpassword123 test_encrypted.bfc test_data\
& $bfc info test_encrypted.bfc
New-Item -ItemType Directory -Force extract_encrypted | Out-Null
Push-Location extract_encrypted
& $bfc extract -p testpassword123 ..\test_encrypted.bfc
if (Test-Path hello.txt) { Write-Output "hello.txt extracted from encrypted container" }
Pop-Location
Remove-Item -Recurse -Force extract_encrypted

# Wrong password should fail
New-Item -ItemType Directory -Force extract_fail | Out-Null
Push-Location extract_fail
$result = & $bfc extract -p wrongpassword ..\test_encrypted.bfc 2>&1; $ec = $LASTEXITCODE
if ($ec -ne 0) { Write-Output "Correctly failed with wrong password" }
Pop-Location
Remove-Item -Recurse -Force extract_fail

# Clean up
Remove-Item -Force test.bfc, test_data -Recurse -ErrorAction SilentlyContinue
Remove-Item -Force test_compressed.bfc, test_encrypted.bfc -ErrorAction SilentlyContinue

- name: Run benchmarks
if: matrix.os != 'windows-latest'
run: |
cd build/benchmarks
./benchmark_crc32c
Expand Down
115 changes: 111 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ jobs:
cc: clang
cxx: clang++
platform: macos
- os: windows-latest
arch: x86_64
cc: cl
cxx: cl
platform: windows

runs-on: ${{ matrix.os }}

Expand All @@ -51,7 +56,14 @@ jobs:
# Install create-dmg for DMG creation, zstd for compression, and libsodium for encryption
brew install create-dmg zstd libsodium

- name: Build Release
- name: Install dependencies (Windows)
if: matrix.platform == 'windows'
run: |
vcpkg install zstd:x64-windows libsodium:x64-windows
echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" >> $env:GITHUB_ENV

- name: Build Release (non-Windows)
if: matrix.platform != 'windows'
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
Expand All @@ -66,12 +78,32 @@ jobs:

cmake --build build --config Release -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)

- name: Run tests
- name: Build Release (Windows)
if: matrix.platform == 'windows'
run: |
cmake -B build `
-DCMAKE_BUILD_TYPE=Release `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows `
-DBFC_WITH_ZSTD=ON `
-DBFC_WITH_SODIUM=ON `
-DBFC_BUILD_BENCHMARKS=OFF
cmake --build build --config Release -j4

- name: Run tests (non-Windows)
if: matrix.platform != 'windows'
run: |
cd build
ctest --output-on-failure

- name: Test CLI functionality
- name: Run tests (Windows)
if: matrix.platform == 'windows'
run: |
cd build
ctest --output-on-failure -C Release

- name: Test CLI functionality (non-Windows)
if: matrix.platform != 'windows'
run: |
# Create test data
mkdir -p test_data
Expand Down Expand Up @@ -158,11 +190,50 @@ jobs:
rm -rf test.bfc test_data test_compressed.bfc test_fast.bfc test_balanced.bfc
rm -rf test_encrypted.bfc test_keyfile.bfc test_enc_comp.bfc test.key

- name: Test CLI functionality (Windows)
if: matrix.platform == 'windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force test_data\subdir | Out-Null
"Hello World" | Out-File -Encoding utf8 test_data\hello.txt
"Goodbye" | Out-File -Encoding utf8 test_data\bye.txt
"Nested file" | Out-File -Encoding utf8 test_data\subdir\nested.txt

$bfc = Get-ChildItem -Recurse build\bin -Filter bfc.exe | Select-Object -First 1 -ExpandProperty FullName
if (-not $bfc) { Write-Error "bfc.exe not found"; exit 1 }

& $bfc create test.bfc test_data\
& $bfc list test.bfc
& $bfc info test.bfc
& $bfc verify test.bfc
& $bfc verify --deep test.bfc

& $bfc create -c zstd test_compressed.bfc test_data\
& $bfc verify test_compressed.bfc

New-Item -ItemType Directory -Force extract_test | Out-Null
Push-Location extract_test
& $bfc extract ..\test.bfc
if (Test-Path hello.txt) { Write-Output "hello.txt extracted" }
Pop-Location
Remove-Item -Recurse -Force extract_test

& $bfc create -e testpassword123 test_encrypted.bfc test_data\
New-Item -ItemType Directory -Force extract_enc | Out-Null
Push-Location extract_enc
& $bfc extract -p testpassword123 ..\test_encrypted.bfc
if (Test-Path hello.txt) { Write-Output "hello.txt extracted from encrypted container" }
Pop-Location
Remove-Item -Recurse -Force extract_enc

Remove-Item -Recurse -Force test_data, test.bfc, test_compressed.bfc, test_encrypted.bfc -ErrorAction SilentlyContinue

- name: Get version
id: get_version
run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

- name: Create release package
- name: Create release package (non-Windows)
if: matrix.platform != 'windows'
run: |
VERSION=${{ steps.get_version.outputs.version }}
PACKAGE_NAME=bfc-${VERSION#v}-${{ matrix.platform }}-${{ matrix.arch }}
Expand Down Expand Up @@ -216,6 +287,42 @@ jobs:
# Create tarball
tar -czf ${PACKAGE_NAME}.tar.gz ${PACKAGE_NAME}

- name: Create release package (Windows)
if: matrix.platform == 'windows'
shell: pwsh
run: |
$version = "${{ steps.get_version.outputs.version }}"
$versionNoV = $version.TrimStart('v')
$pkgName = "bfc-$versionNoV-windows-x86_64"

New-Item -ItemType Directory -Force $pkgName | Out-Null

# Find and copy binaries
$bfcExe = Get-ChildItem -Recurse build\bin -Filter bfc.exe | Select-Object -First 1 -ExpandProperty FullName
Copy-Item $bfcExe "$pkgName\bfc.exe"
Copy-Item (Get-ChildItem -Recurse build\lib -Filter bfc.lib | Select-Object -First 1 -ExpandProperty FullName) "$pkgName\bfc.lib"
Copy-Item (Get-ChildItem -Recurse build\lib -Filter bfc.dll -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName) "$pkgName\bfc.dll" -ErrorAction SilentlyContinue

# Copy headers and docs
Copy-Item include\bfc.h "$pkgName\"
Copy-Item README.md "$pkgName\"
Copy-Item LICENSE "$pkgName\"

# Create install script
@'
@echo off
echo Installing BFC...
copy bfc.exe "%ProgramFiles%\bfc\bfc.exe" 2>nul || (
mkdir "%ProgramFiles%\bfc"
copy bfc.exe "%ProgramFiles%\bfc\bfc.exe"
)
copy bfc.h "%ProgramFiles%\bfc\bfc.h"
echo BFC installed to %ProgramFiles%\bfc
'@ | Out-File -Encoding ascii "$pkgName\install.bat"

# Create ZIP
Compress-Archive -Path $pkgName -DestinationPath "$pkgName.zip"

- name: Create DEB and RPM packages (Linux only)
if: matrix.platform == 'linux'
run: |
Expand Down
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0 -fsanitize=address,undefined")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -DNDEBUG")

if(BFC_COVERAGE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
endif()
elseif(MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /WX /wd4996")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od /Zi /RTC1")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O2 /DNDEBUG")
# Disable sanitizers on MSVC (not supported the same way)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()

# Find dependencies
Expand Down
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A high-performance, single-file container format for storing files and directori
- **Optional compression** - ZSTD compression with intelligent content analysis
- **Optional encryption** - ChaCha20-Poly1305 AEAD with Argon2id key derivation
- **Integrity validation** - CRC32C checksums with hardware acceleration
- **Cross-platform** - Works on Linux, macOS, FreeBSD, and other Unix systems
- **Cross-platform** - Works on Linux, macOS, FreeBSD, and Windows (MSVC/MinGW-w64)
- **Crash-safe writes** - Atomic container creation with index at EOF
- **Memory efficient** - Optimized for large containers and small memory footprint

Expand Down Expand Up @@ -46,14 +46,14 @@ cmake --build build

### Prerequisites

- C17 compatible compiler (GCC 7+, Clang 6+)
- C17 compatible compiler (GCC 7+, Clang 6+, or MSVC 2019+)
- CMake 3.15+
- POSIX-compliant system

**Optional dependencies:**
- ZSTD library for compression support
- libsodium for encryption support
- pkg-config (or pkgconf on FreeBSD) for dependency detection
- pkg-config (or pkgconf on FreeBSD/Linux) for dependency detection on Unix
- vcpkg for dependency management on Windows

### Build from source

Expand Down Expand Up @@ -87,6 +87,32 @@ cmake -B build -DCMAKE_BUILD_TYPE=Release -DBFC_WITH_ZSTD=ON -DBFC_WITH_SODIUM=O
make -C build
```

**Windows (MSVC) setup:**

```powershell
# Install dependencies via vcpkg
vcpkg install zstd:x64-windows libsodium:x64-windows

# Configure with vcpkg toolchain
cmake -B build `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows `
-DBFC_WITH_ZSTD=ON `
-DBFC_WITH_SODIUM=ON

# Build
cmake --build build --config Release

# Run
.\build\bin\Release\bfc.exe create archive.bfc path\to\files\
```

> **Windows notes:**
> - Symlink creation requires Developer Mode or elevated privileges; symlinks stored in
> containers are extracted as regular files on Windows without Developer Mode.
> - FUSE mount (`BFC_WITH_FUSE`) is not supported on Windows.
> - MinGW-w64 is also supported; use the standard Unix cmake/make flow with the MinGW generator.

### Build options

```bash
Expand Down
Loading
Loading