// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #include &); static string_view call(const magic_t &, const int &flags, const mutable_buffer &, const const_buffer &); } ircd::magic::init::init() { if(unlikely(!(cookie = ::magic_open(flags)))) throw error{"magic_open() failed"}; //TODO: conf; TODO: windows static const char *const paths[] { "/usr/local/share/misc/magic.mgc", "/usr/share/misc/magic.mgc", nullptr }; for(const char *const *path{paths}; *path; ++path) if(magic_check(cookie, *path) == 0) if(magic_load(cookie, *path) == 0) return; throw error { "Failed to open any magic database" }; } ircd::magic::init::~init() noexcept { ::magic_close(cookie); } ircd::string_view ircd::magic::description(const mutable_buffer &out, const const_buffer &buffer) { return call(cookie, MAGIC_NONE, out, buffer); } ircd::string_view ircd::magic::extensions(const mutable_buffer &out, const const_buffer &buffer) { return call(cookie, MAGIC_EXTENSION, out, buffer); } ircd::string_view ircd::magic::mime_encoding(const mutable_buffer &out, const const_buffer &buffer) { return call(cookie, MAGIC_MIME_ENCODING, out, buffer); } ircd::string_view ircd::magic::mime_type(const mutable_buffer &out, const const_buffer &buffer) { return call(cookie, MAGIC_MIME_TYPE, out, buffer); } ircd::string_view ircd::magic::mime(const mutable_buffer &out, const const_buffer &buffer) { return call(cookie, MAGIC_MIME, out, buffer); } ircd::string_view ircd::magic::call(const magic_t &cookie, const int &flags, const mutable_buffer &out, const const_buffer &buffer) { return call(cookie, flags, out, [&cookie, &buffer] { return magic_buffer(cookie, data(buffer), size(buffer)); }); } ircd::string_view ircd::magic::call(const magic_t &cookie, const int &ours, const mutable_buffer &out, const std::function &closure) { const auto &theirs{magic::flags}; const unwind reset{[&theirs, &cookie] { set_flags(cookie, theirs); }}; set_flags(cookie, ours); string_view str { closure() }; if(!str) { throw_on_error(cookie); str = "application/octet-stream"_sv; } return { data(out), copy(out, str) }; } void ircd::magic::set_flags(const magic_t &cookie, const int &flags) { if(magic_setflags(cookie, flags) == -1) throw_on_error(cookie); } void ircd::magic::throw_on_error(const magic_t &cookie) { const char *const errstr { ::magic_error(cookie) }; if(errstr) throw error { "%s", errstr }; assert(magic_errno(cookie) == 0); } int ircd::magic::version() { return ::magic_version(); } __attribute__((constructor)) static void ircd_magic_version_check() { if(unlikely(MAGIC_VERSION != ircd::magic::version())) { fprintf(stderr, "FATAL: linked libmagic version %d != compiled magic.h version %d.\n", ircd::magic::version(), MAGIC_VERSION); std::terminate(); } }