NAME

Module::Generic::File::Magic - File type and MIME detection with 3-level backend cascade

SYNOPSIS

use Module::Generic::File::Magic qw( :flags );

my $magic = Module::Generic::File::Magic->new( flags => MAGIC_MIME_TYPE ) ||
    die( Module::Generic::File::Magic->error );

# Which backend is active?
printf "Backend: %s\n", $magic->backend;    # xs, json, or file

# Detect from a file path
my $mime = $magic->from_file( '/path/to/archive.tar.gz' ) ||
    die( $magic->error );
# -> "application/gzip"

# Detect from an in-memory buffer
open( my $fh, '<:raw', '/path/to/file' ) or die( $! );
read( $fh, my $buf, 4096 );
close( $fh );
my $mime = $magic->from_buffer( $buf ) || die( $magic->error );

# Detect from an open filehandle
open( my $fh, '<:raw', '/path/to/file' ) or die( $! );
my $mime = $magic->from_filehandle( $fh ) || die( $magic->error );

# Convenience wrappers
my $type = $magic->mime_type_from_file( '/path/to/file' );
my $enc  = $magic->mime_encoding_from_file( '/path/to/file' );
my $full = $magic->mime_from_file( '/path/to/file' );
# -> "application/gzip; charset=binary"

# Control the read size for pure-Perl backends (default: 512 bytes)
my $magic2 = Module::Generic::File::Magic->new(
    flags    => MAGIC_MIME_TYPE,
    max_read => 1024,
) || die( Module::Generic::File::Magic->error );

# Change max_read at any time
$magic->max_read(1024);

# Procedural interface
use Module::Generic::File::Magic qw( :functions );
my $mime = magic_mime_type( '/path/to/file' );

VERSION

v0.1.0

DESCRIPTION

Module::Generic::File::Magic detects file types and MIME types using a three-level cascade, automatically selecting the best available backend:

Level 1 — xs (preferred)

libmagic.so.1 is loaded at runtime via dlopen(3) — no magic.h, no libmagic-dev package required at build time. Full libmagic accuracy and performance. The MAGIC_COMPRESS, MAGIC_SYMLINK, and all other flags are fully supported. compile(), check(), and list() are only available at this level.

Level 2 — json

libmagic is absent. The module loads lib/Module/Generic/File/magic.json (generated from the freedesktop.org shared-mime-info database, bundled with the distribution) and runs pure-Perl byte-pattern matching. Covers ~500 MIME types with magic signatures.

Level 3 — file

No pattern matched at level 2. Invokes file(1) in a subprocess as a last resort. from_buffer writes a temporary file via File::Temp.

The active backend is available via $magic->backend and the package variable $Module::Generic::File::Magic::BACKEND.

Note that within the json backend, a text-content heuristic is applied before falling through to file(1).

CONSTRUCTOR

new

my $magic = Module::Generic::File::Magic->new( %opts ) ||
    die( Module::Generic::File::Magic->error );
  • flags — integer bitmask (default: MAGIC_NONE)

  • magic_db — path to a custom .mgc database (xs backend only)

  • max_read — maximum bytes read from a file for pure-Perl backends (default: 512)

METHODS

backend

Returns the name of the active backend: "xs", "json", or "file". Note that the reported value is the top-level configured backend; the actual detection at runtime may cascade through multiple levels.

check( [ $filename ] )

Validates a magic database. xs backend only.

close

Releases the magic_t cookie. No-op on non-xs backends.

compile( $filename )

Compiles a magic source file into a .mgc database. xs backend only.

flags

Getter/setter for the libmagic flags bitmask.

from_buffer( $scalar )

Detects type from a raw byte scalar.

from_file( $path )

Detects type from a file path.

from_filehandle( $fh )

Detects type from an open filehandle.

list( [ $filename ] )

Prints magic database entries to stdout. xs backend only.

magic_db

Getter/setter for the custom magic database path (xs backend only).

max_read( [ $bytes ] )

Getter/setter for the maximum number of bytes read from a file when using pure-Perl backends. The default is 512 bytes, which covers all signatures in the bundled JSON database. Increase this value for formats whose signatures appear at large offsets (e.g. application/x-tar at offset 257).

mime_encoding_from_buffer / _from_file / _from_filehandle

Returns the charset (e.g. binary).

mime_from_buffer / _from_file / _from_filehandle

Returns e.g. application/gzip; charset=binary.

mime_type_from_buffer / _from_file / _from_filehandle

Returns e.g. application/gzip.

version

Returns the libmagic version string (e.g. "5.45"), or undef when not using the xs backend.

EXPORTED FUNCTIONS

use Module::Generic::File::Magic qw( :functions );
magic_from_buffer( $scalar [, $flags] )
magic_from_file( $path [, $flags] )
magic_mime_type( $path )
magic_mime_encoding( $path )

EXPORT TAGS

:flags, :functions, :all

FLAG CONSTANTS

MAGIC_NONE              No flags (default)
MAGIC_DEBUG             Print debug messages to stderr  [xs only]
MAGIC_SYMLINK           Follow symlinks
MAGIC_COMPRESS          Examine inside compressed files
MAGIC_DEVICES           Look at block/char device content  [xs only]
MAGIC_MIME_TYPE         Return MIME type
MAGIC_MIME_ENCODING     Return MIME charset
MAGIC_MIME              MAGIC_MIME_TYPE | MAGIC_MIME_ENCODING
MAGIC_CONTINUE          Return all matches  [xs only]
MAGIC_CHECK             Print warnings  [xs only]
MAGIC_PRESERVE_ATIME    Restore access time  [xs only]
MAGIC_RAW               Do not convert unprintable chars  [xs only]
MAGIC_ERROR             Treat ENOENT as real error  [xs only]
MAGIC_APPLE             Return Apple creator/type  [xs only]
MAGIC_EXTENSION         Return file extensions  [xs only]
MAGIC_NO_CHECK_*        Disable specific checks  [xs only]

Flags marked [xs only] are silently ignored on non-xs backends.

INSTALLATION

The only requirement for the xs backend is the libmagic1 runtime package:

# Debian / Ubuntu
sudo apt-get install libmagic1

# RPM-based
sudo yum install file-libs

# macOS (Homebrew)
brew install libmagic

No libmagic-dev or file-devel required. The module compiles and works on any system with a C compiler (the same one that built Perl).

FILES

  • lib/Module/Generic/File/magic.json

    Bundled magic signature database generated from the freedesktop.org shared-mime-info XML. Used by the json backend. To regenerate:

    perl scripts/gen_magic_json.pl [xml_path] [out_json_path]

AUTHOR

Jacques Deguest <jack@deguest.jp>

SEE ALSO

Module::Generic::Finfo, File::LibMagic, File::MimeInfo

The libmagic(3) man page.

COPYRIGHT & LICENSE

Copyright (c) 2026 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.