Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
92 changes: 77 additions & 15 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,49 +20,68 @@ jobs:
- os: macos-latest
cc: clang
cxx: clang++
- os: windows-latest
cc: cl
cxx: cl

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

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up C environment (non-Linux)
if: runner.os != 'Linux'
uses: aminya/setup-cpp@v1
with:
compiler: ${{ runner.os == 'Windows' && 'msvc' || 'clang' }}
vcvarsall: ${{ runner.os == 'Windows' }}
cmake: true
ninja: true

- name: Install dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake clang-format clang-tidy libzstd-dev libsodium-dev
sudo apt-get install -y build-essential cmake ninja-build clang-format clang-tidy libzstd-dev libsodium-dev

- name: Install dependencies (macOS)
if: matrix.os == 'macos-latest'
if: runner.os == 'macOS'
run: |
brew install clang-format zstd libsodium || true
# cmake is already available on macOS runners
brew install clang-format zstd libsodium ninja || true

- name: Set up environment
- name: Install dependencies (Windows)
if: runner.os == 'Windows'
shell: bash
run: |
echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV
echo "CXX=${{ matrix.cxx }}" >> $GITHUB_ENV
vcpkg install zstd:x64-windows libsodium:x64-windows
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> "$GITHUB_ENV"

- name: Configure CMake
shell: bash
run: |
TOOLCHAIN_ARG=""
if [ "${{ runner.os }}" == "Windows" ]; then
TOOLCHAIN_ARG="-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows -DBFC_BUILD_BENCHMARKS=OFF"
fi
cmake -B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DCMAKE_C_COMPILER=${{ matrix.cc }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \
-DBFC_WITH_ZSTD=ON \
-DBFC_WITH_SODIUM=ON
-DBFC_WITH_SODIUM=ON \
$TOOLCHAIN_ARG

- name: Build
run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)
run: cmake --build build --config ${{ matrix.build_type }} -j4

- name: Run tests
if: matrix.build_type == 'Debug'
shell: bash
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 +237,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: runner.os == 'Windows'
shell: bash
run: |
BFC=$(find build/bin -name "bfc.exe" | head -1)
[ -z "$BFC" ] && { echo "bfc.exe not found"; exit 1; }

mkdir -p test_data/subdir
echo "Hello World" > test_data/hello.txt
echo "Goodbye" > test_data/bye.txt
echo "Nested file" > test_data/subdir/nested.txt

"$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" info test_compressed.bfc test_data/hello.txt
"$BFC" verify test_compressed.bfc

mkdir extract_test && cd extract_test
"$OLDPWD/$BFC" extract ../test.bfc
[ -f hello.txt ] && echo "hello.txt extracted"
[ -f bye.txt ] && echo "bye.txt extracted"
[ -f subdir/nested.txt ] && echo "nested.txt extracted"
cd ..

"$BFC" create -e testpassword123 test_encrypted.bfc test_data/
mkdir extract_enc && cd extract_enc
"$OLDPWD/$BFC" extract -p testpassword123 ../test_encrypted.bfc
[ -f hello.txt ] && echo "hello.txt extracted from encrypted container"
cd ..

mkdir extract_fail && cd extract_fail
"$OLDPWD/$BFC" extract -p wrongpassword ../test_encrypted.bfc 2>&1 && true
[ $? -ne 0 ] && echo "Correctly failed with wrong password" || true
cd ..

rm -rf test_data test.bfc test_compressed.bfc test_encrypted.bfc extract_enc extract_fail

- 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