A Modern C++23 Wrapper for libmagic
Bringing the power of the Unix file command to modern C++
Libmagicxx is a modern C++23 wrapper library for the battle-tested libmagic β the same library that powers the Unix file command used by millions of developers worldwide. Rather than reinventing the wheel, libmagicxx brings libmagic's decades of file type detection expertise into the modern C++ ecosystem with an elegant, type-safe interface.
| libmagic (C API) | libmagicxx (C++23 Wrapper) |
|---|---|
| Manual resource management | RAII with automatic cleanup |
| Error codes and global state | std::expected and exceptions |
| Raw C strings | std::string and std::string_view |
| Procedural API | Object-oriented Magic class |
| No type safety | Strong typing with concepts |
| Manual flag handling | Type-safe Flags and Parameters enums |
| Single file identification | Batch directory and container identification |
| No progress feedback | Built-in progress tracking for batch operations |
| Manual state checking | IsOpen(), IsDatabaseLoaded(), IsValid() queries |
| One parameter at a time | Bulk GetParameters() / SetParameters() |
π Why a wrapper? libmagic is the gold standard for content-based file detection, maintained for decades and used in countless production systems. Libmagicxx doesn't replace itβit makes it accessible to modern C++ developers with the safety and ergonomics they expect.
- Why Use Libmagicxx?
- What Libmagicxx Adds
- Supported Platforms
- Quick Start
- Installation
- Usage with CMake
- Magic States
- CMake Package Variables
- Examples
- Documentation
- Contributing
- Security
- License
- Disclaimer
You need libmagic's capabilities, but want modern C++:
| Your Need | Libmagicxx Solution |
|---|---|
| π Security | Use libmagic's proven detection to validate file uploads |
| π¨ Media Processing | Route files to correct handlers based on true content type |
| π File Management | Leverage decades of magic database refinements |
| β‘ Developer Experience | Write idiomatic C++23 instead of C-style code |
| π‘οΈ Safety | Automatic resource management prevents leaks and errors |
Wraps libmagic's C API with modern features:
std::expectedfor elegant error handling- Concepts and constraints for type safety
- RAII for automatic resource management
Clean, intuitive interface:
Magic magic{Magic::Flags::Mime};
auto type = magic.IdentifyFile("document.pdf");
// Returns: "application/pdf"First-class CMake support:
find_package(Magicxx REQUIRED)
target_link_libraries(app Recognition::Magicxx)- β Linux (x86_64) β GCC & Clang
- β Windows (x86_64) β MinGW & Clang
- π¦ DEB, RPM, and NSIS installers
- π libmagic Power β Access libmagic features through a clean C++ interface
- π‘οΈ Memory Safe β No manual
magic_open/magic_closecalls to forget - π§ͺ Extensively Tested β 600+ unit tests (shared and static libs tested independently)
- π§ Flexible Configuration β All 30 libmagic flags exposed as type-safe enums
- π Progress Tracking β Shared progress tracker for monitoring batch operations
- ποΈ Database Support β Easy loading of custom magic definition files
| Platform | Architecture | Compilers | Package Formats |
|---|---|---|---|
| π§ Linux | x86_64 | GCC, Clang | .deb, .rpm |
| πͺ Windows | x86_64 | MinGW-w64, Clang | .exe (NSIS) |
Get up and running in under a minute:
# 1. Download the latest release for your platform
# β https://github.com/oguztoraman/libmagicxx/releases/latest
# 2. Install (Linux example)
sudo apt install ./libmagicxx-*-linux-x86_64.deb # Debian/Ubuntu
sudo dnf install ./libmagicxx-*-linux-x86_64.rpm # Fedora/RHEL
# 3. Use in your project (see CMake integration below)π§ Debian/Ubuntu (APT)
sudo apt install ./libmagicxx-<version>-linux-x86_64.debπ§ Fedora/RHEL (DNF)
sudo dnf install ./libmagicxx-<version>-linux-x86_64.rpmπͺ Windows (NSIS Installer)
- Download
libmagicxx-<version>-windows-x86_64.exe - Run the installer
- Follow the on-screen instructions
- Add the installation directory to your
PATHif needed
π§ Build from Source
git clone https://github.com/oguztoraman/libmagicxx.git
cd libmagicxx
python ./scripts/launch_container.py # Pulls pre-built container from GHCR
./scripts/initialize.sh
./scripts/workflows.sh -p linux-x86_64-clang -cTo build the container locally instead: python ./scripts/launch_container.py --local
See CONTRIBUTING.md for detailed build instructions.
π¦ Download: Latest Release | All Releases
Add to your CMakeLists.txt:
find_package(Magicxx REQUIRED)
target_link_libraries(your_project
PRIVATE Recognition::Magicxx # Shared library
# or
PRIVATE Recognition::MagicxxStatic # Static library
)#include <print>
#include <iostream>
#include <magic.hpp>
int main()
{
using namespace Recognition;
// Create a Magic instance with MIME type detection
Magic magic{Magic::Flags::Mime};
// Identify a file's type
auto result = magic.IdentifyFile("mystery_file");
std::println(std::cout, "File type: {}", result);
// Example output: "application/pdf; charset=binary"
}#include <magic.hpp>
#include <future>
#include <thread>
using namespace Recognition;
using namespace std::chrono_literals;
// Combine multiple flags for detailed output
Magic detailed{
Magic::Flags::MimeType |
Magic::Flags::MimeEncoding |
Magic::Flags::ContinueSearch
};
// Use custom database
Magic custom{Magic::Flags::None};
custom.LoadDatabaseFile("/path/to/custom.mgc");
// Track progress for batch file identification
Magic magic{Magic::Flags::Mime};
auto tracker = Utility::MakeSharedProgressTracker();
// Start identification in background thread
auto future = std::async([&magic, tracker] {
return magic.IdentifyFiles("/large/directory", tracker);
});
// Monitor progress in main thread
while (!tracker->IsCompleted()) {
std::println("Progress: {}", tracker->GetCompletionPercentage().ToString());
std::this_thread::sleep_for(100ms);
}
auto results = future.get();The Magic class follows a clear state machine model:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Magic State Diagram β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Constructor() Constructor(flags) β
β β β β
β βΌ βΌ β
β ββββββββββββββ Open(flags) ββββββββββββββ ββββββββββββββ β
β β CLOSED βββββββββββββββ>β OPENED β<βββββββββ VALID β β
β ββββ¬ββββββββββ ββββ¬βββββββ¬βββ Open βββββββββββ¬βββ β
β β β² β² β β² β (flags) β² β β
β ββββββ β β βββββ β β β
β Close() β β Open(flags) β β β
β β β β β β
β β βββββββββββββββββββββββββ β β
β β LoadDatabaseFile() β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββ β
β Close() β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| State | IsOpen() |
IsDatabaseLoaded() |
IsValid() |
Can Identify Files? |
|---|---|---|---|---|
| Closed | β false |
β false |
β false |
β No |
| Opened | β
true |
β false |
β false |
β No |
| Valid | β
true |
β
true |
β
true |
β Yes |
π‘ Tip: Use the convenience constructorsβthey automatically open and load the default database, putting you directly in the Valid state!
After find_package(Magicxx), these variables are available:
| Variable | Description |
|---|---|
MAGICXX_FOUND |
β
TRUE if Libmagicxx was found |
MAGICXX_VERSION |
Version string (e.g., "9.1.1") |
MAGICXX_SHARED_LIB_AVAILABLE |
Shared library availability |
MAGICXX_STATIC_LIB_AVAILABLE |
Static library availability |
MAGICXX_INCLUDE_DIR |
Path to headers |
MAGICXX_LIB_DIR |
Path to libraries |
MAGICXX_LICENSE_DIR |
Path to license files |
MAGICXX_DOC_DIR |
Path to documentation |
MAGICXX_CMAKE_DIR |
Path to CMake config |
MAGICXX_DEFAULT_DATABASE_DIR |
Path to magic database |
Explore real-world usage patterns in the examples:
| Example | Description |
|---|---|
| Basic Identify | File identification with exception handling |
| Noexcept Identify | Non-throwing API with std::expected |
| Directory Identify | Batch identification of files in a directory |
| Custom Flags/Parameters | Configuring flags and tuning parameters |
| Check and Compile | Database validation and compilation |
| Progress Tracking | Monitoring batch operations with progress tracker |
| Container Identify | Identify specific files from a container |
| Lifecycle Management | Manual state transitions and queries |
| Version and All Parameters | Get version and bulk parameter operations |
The comprehensive documentation includes:
| Section | Description |
|---|---|
| Modules | Core API, Exceptions, Utility, String Conversions |
| Classes | Magic, MagicException, Percentage, ProgressTracker |
| Examples | 9 runnable examples with detailed explanations |
| Style Guides | C++ and CMake coding conventions |
| Project Docs | Contributing, Security, Code of Conduct, Changelog |
We welcome contributions of all kinds! Whether you're fixing bugs, adding features, improving documentation, or suggesting enhancementsβyour help makes Libmagicxx better for everyone.
Found a security vulnerability? Please report it responsibly.
Libmagicxx is licensed under the GNU Lesser General Public License v3.0.
This means you can:
- β Use it in commercial projects
- β Link to it from proprietary software
- β Modify and distribute it (under LGPL terms)
See COPYING.LESSER for the full license text.
Third-Party Licenses
| Component | License |
|---|---|
| file/libmagic | BSD-2-Clause |
| GoogleTest | BSD-3-Clause |
| libgnurx | LGPL-2.1-or-later |
This project is a personal hobby project developed independently. It is not affiliated with, endorsed by, or created on behalf of any employer, company, or organization. No proprietary or confidential information was used in its development.
Made with β€οΈ for the C++ community