Merge pull request 'develop-libmagic' (#10) from develop-libmagic into master

This commit is contained in:
Bart Beumer 2025-04-13 19:16:50 +00:00
commit 37dcda3d96
13 changed files with 233 additions and 12 deletions

22
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,22 @@
FROM alpine:3.21.3
# Install tools required for building.
RUN apk update && \
apk add --no-cache \
autoconf \
bash \
boost-build \
build-base \
cmake \
gdb \
git \
libstdc++ \
libtool \
linux-headers \
ninja \
m4 \
perl \
python3 \
py3-pip && \
pip install --break-system-packages conan && \
conan profile detect

View File

@ -0,0 +1,19 @@
{
"name": "C++",
"build": {
"dockerfile": "Dockerfile"
},
// Configure tool-specific properties.
"customizations": {
"vscode": {
"settings": {},
"extensions": [
"ms-vscode.cpptools",
"twxs.cmake",
"ms-vscode.cmake-tools",
"konicy.conan-extension"
]
}
}
}

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
/build
# ---> C++
# Prerequisites
*.d

View File

@ -4,3 +4,4 @@ project(all)
enable_testing()
add_subdirectory(bmrshared)
add_subdirectory(bmrshared-magic)

View File

@ -0,0 +1,2 @@
add_subdirectory(lib)
add_subdirectory(tst)

View File

@ -0,0 +1,26 @@
// GNU Lesser General Public License v3.0
// Copyright (c) 2025 Bart Beumer <bart@4beumer.nl>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License v3.0 as published by
// the Free Software Foundation.
//
#include <filesystem>
#include <magic.h>
namespace bmrshared
{
class magic_file_info final
{
public:
explicit magic_file_info(const std::filesystem::path& path);
~magic_file_info();
std::string get_mime(const std::filesystem::path& path) const;
private:
magic_t m_magic_cookie;
};
} // namespace bmrshared

View File

@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.20)
find_package(libmagic 5.45 REQUIRED)
project(bmrshared-magic)
add_library(
${PROJECT_NAME}
magic_file_info.cpp
)
set_property(
TARGET ${PROJECT_NAME}
PROPERTY CXX_STANDARD 20
)
target_include_directories(
${PROJECT_NAME}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include
)
target_link_libraries(
${PROJECT_NAME}
PUBLIC
libmagic::libmagic
)
install(
FILES ${CONAN_LIBMAGIC_PACKAGE_FOLDER}/res/magic.mgc
DESTINATION bin
)

View File

@ -0,0 +1,59 @@
// GNU Lesser General Public License v3.0
// Copyright (c) 2025 Bart Beumer <bart@4beumer.nl>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License v3.0 as published by
// the Free Software Foundation.
//
#include <bmrshared/magic_file_info.hpp>
namespace bmrshared
{
magic_file_info::magic_file_info(const std::filesystem::path& path)
: m_magic_cookie(nullptr)
{
bool load_ok = false;
m_magic_cookie = magic_open(MAGIC_MIME_TYPE);
if (m_magic_cookie != nullptr && std::filesystem::is_regular_file(path))
{
load_ok = (magic_load(m_magic_cookie, path.native().c_str()) == 0);
}
if (m_magic_cookie && !load_ok)
{
magic_close(m_magic_cookie);
m_magic_cookie = nullptr;
}
if (!load_ok)
{
throw std::runtime_error("Could not initialize libmagic.");
}
}
magic_file_info::~magic_file_info()
{
magic_close(m_magic_cookie);
}
std::string magic_file_info::get_mime(const std::filesystem::path& path) const
{
std::string mime;
if (std::filesystem::is_regular_file(path))
{
const char* file_name = path.native().c_str();
const char* magic_full = nullptr;
if (file_name != nullptr)
{
magic_full = magic_file(m_magic_cookie, file_name);
}
if (magic_full != nullptr)
{
mime = magic_full;
}
}
return mime;
}
} // namespace bmrshared

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.20)
find_package(GTest REQUIRED)
include(GoogleTest)
project(bmrshared-magic-test)
add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
add_executable(
${PROJECT_NAME}
test_magic.cpp
)
set_property(
TARGET ${PROJECT_NAME}
PROPERTY CXX_STANDARD 20
)
target_link_libraries(
${PROJECT_NAME}
PUBLIC
bmrshared-magic
GTest::gtest_main
)

View File

@ -0,0 +1,26 @@
// GNU Lesser General Public License v3.0
// Copyright (c) 2025 Bart Beumer <bart@4beumer.nl>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License v3.0 as published by
// the Free Software Foundation.
//
#include <bmrshared/magic_file_info.hpp>
#include <gtest/gtest.h>
namespace
{
constexpr std::string_view magic_file_location = "/usr/local/bin/magic.mgc";
}
TEST(test_magic, no_throw_on_query)
{
bmrshared::magic_file_info mfi(magic_file_location);
EXPECT_NO_THROW(mfi.get_mime(magic_file_location));
}
TEST(test_magic, throw_on_wrong_magic_file)
{
EXPECT_THROW(bmrshared::magic_file_info mfi(""), std::exception);
EXPECT_THROW(bmrshared::magic_file_info mfi("/etc/hostname"), std::exception);
}

View File

@ -26,8 +26,3 @@ target_link_libraries(
GTest::gmock
)
install(
TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)

20
conanfile.py Normal file
View File

@ -0,0 +1,20 @@
import os
from conan import ConanFile
from conan.tools.files import copy
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps
class HelloConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
requires = "boost/1.84.0", "gtest/1.14.0", "libmagic/5.45"
generators = "CMakeDeps"
build_policy = "*"
def generate(self):
# We need to find the folder of libmagic and supply it to cmake so that
# we can deploy the magic file.
libmagic = self.dependencies["libmagic"]
tc = CMakeToolchain(self)
tc.variables["CONAN_LIBMAGIC_PACKAGE_FOLDER"] = libmagic.package_folder
tc.generate()

View File

@ -1,7 +0,0 @@
[requires]
boost/1.84.0
gtest/1.14.0
[generators]
CMakeDeps
CMakeToolchain