Module:...::Finfo(3)

πŸ“¦ version 1.1.3, in alpine 3.24

πŸ’– Module::Generic::Finfo β€” File Info Object Class πŸ’–

okay so this is the Finfo(3) manual page, and the main character is Module::Generic::Finfo, aka the File Info Object Class. It's giving "object-oriented file info," and honestly? Obsessed. Let's get you fluent, bestie. ✨


✨ SYNOPSIS ✨

Here's the whole group-chat screenshot of how you use it:

use Module::Generic::Finfo qw( :all );
my $finfo = Module::Generic::Finfo->new( '/some/file/path.html' );
# Get access time as a DateTime object
$finfo->atime;
# Block site
$finfo->blksize;
# Number of blocks
$finfo->blocks;
if( $finfo->can_read )
{
    # Do something
}
# Can also use
$finfo->can_write;
$finfo->can_exec;
$finfo->csize;
# Inode change time as a DateTime object
$finfo->ctime;
$finfo->dev;
if( $finfo->exists )
{
    # Do something
}
print "File path is: ", $finfo->filepath;
if( $finfo->filetype == FILETYPE_NOFILE )
{
    # File does not exist
}
# Same as $finfo->filepath
print "File path is: ", $finfo->fname;
print "File group id is: ", $finfo->gid;
# Can also use $finfo->group which will yield the same result
$finfo->ino;
# or $finfo->inode;
if( $finfo->is_block )
{
    # Do something
}
elsif( $finfo->is_char )
{
    # Do something else
}
elsif( $finfo->is_dir )
{
    # It's a directory
}
elsif( $finfo->is_file )
{
    # It's a regular file
}
elsif( $finfo->is_link )
{
    # A file alias
}
elsif( $info->is_pipe )
{
    # A Unix pipe !
}
elsif( $finfo->is_socket )
{
    # It's a socket
}
elsif( ( $info->mode & 0100 ) )
{
    # Can execute
}
$finfo->mtime->strftime( '%A %d %B %Y %H:%m:%S' );
print "File base name is: ", $finfo->name;
printf "File has %d links\n", $finfo->nlink;
print "File permission in hexadecimal: ", $finfo->protection;
$finfo->rdev;
$finfo->size;
my $new_object = $finfo->stat( '/some/other/file.txt' );
# Get the user id
$finfo->uid;
# Or
$finfo->user;

🏷️ VERSION 🏷️

v0.5.3 β€” tiny version number, big file-info energy.


🌸 DESCRIPTION 🌸

This class provides a file info object oriented api.

The other big win? Even if you hand it a non-existing file, an object is still returned. Obviously, many of this module's methods will return an empty value since the file does not actually exist. No cap. 🫢


πŸ› οΈ METHODS πŸ› οΈ

Every method, every alias, every little detail. Let's go. πŸ’…

new

This instantiate an object that is used to access other key methods. It takes a file path.

atime

Returns the file last access time as a Module::Generic::DateTime object, which stringifies to its value in second since epoch. Module::Generic::DateTime is just a thin wrapper around DateTime to allow a DateTime to be used in comparison with another non DateTime value.

For example:

if( $finfo->atime > time() + 86400 )
{
    print( "You are traveling in the future\n" );
}

blksize

Returns the preferred I/O size in bytes for interacting with the file. You can also use block_size.

block_size

Alias for blksize.

blocks

Returns the actual number of system-specific blocks allocated on disk (often, but not always, 512 bytes each).

can_read

Returns true if the the effective user can read the file.

can_write

Returns true if the the effective user can write to the file.

can_exec

Returns true if the the effective user can execute the file. Same as execute.

can_execute

Returns true if the the effective user can execute the file. Same as exec.

csize

Returns the total size of file, in bytes. Same as size.

ctime

Returns the file inode change time as a Module::Generic::DateTime object, which stringifies to its value in second since epoch. Module::Generic::DateTime is just a thin wrapper around DateTime to allow a DateTime to be used in comparison with another non DateTime value.

dev

Returns the device number of filesystem. Same as dev.

device

Returns the device number of filesystem. Same as device.

exists

Returns true if the filetype is not FILETYPE_NOFILE.

filepath

Returns the file path as a string. Same as fname.

filetype

Returns the file type which is one of the CONSTANTS below.

fname

Returns the file path as a string. Same as filepath.

gid

Returns the numeric group ID of file's owner. Same as group.

group

Returns the numeric group ID of file's owner. Same as gid.

ino

Alias for ino. (Yes, that's the whole sentence. The docs are doing a little mirror thing, and we respect it.)

inode

Returns the inode number.

is_block

Returns true if this is a block file, false otherwise.

is_char

Returns true if this is a character file, false otherwise.

is_dir

Returns true if this is a directory, false otherwise.

is_file

Returns true if this is a regular file, false otherwise.

Returns true if this is a symbolic link, false otherwise.

is_pipe

Returns true if this is a pipe, false otherwise.

is_socket

Returns true if this is a socket, false otherwise.

mime_type

my $mime = $finfo->mime_type;
print "MIME type: $mime\n"; # e.g., "text/plain"

This guesses the file mime type and returns it as a scalar object.

If File::MMagic::XS is installed, it will use it, otherwise, it will use File::MMagic.

If an error occurs, it will set an exception object, and return an empty list in list context, or undef in scalar context. So, y'know, handle your errors, bestie.

mode

Returns the file mode. This is equivalent to the mode & 07777, ie without the file type bit.

So you could do something like:

if( $finfo->mode & 0100 )
{
    print( "Owner can execute\n" );
}
if( $finfo->mode & 0001 )
{
    print( "Everyone can execute too!\n" );
}

mode_n2s

Takes a numeric mode (e.g., 0644) of a file or directory, and returns a human-readable string (e.g., "rw-r--r--"). Returns undef if the mode is invalid:

my $mode_str = $finfo->mode_n2s( 0644 );
print "Mode: $mode_str\n"; # "rw-r--r--"

mode_s2n

Takes a mode string (e.g., "rw-r--r--") of a file or directory, and converts it to octal mode (e.g., 0644). Returns undef if the mode string is invalid:

my $mode_num = $finfo->mode_s2n( "rw-r--r--" );
print "Numeric mode: $mode_num\n"; # 0644

mtime

Returns the file last modify time as a Module::Generic::DateTime object, which stringifies to its value in second since epoch. Module::Generic::DateTime is just a wrapper around DateTime to allow a DateTime to be used in comparison with another non DateTime value.

name

Returns the file base name. So if the file is /home/john/www/some/file.html this would return file.html.

Interesting to note that "name" in APR::Finfo which is advertised as returning the file base name, actually returns just an empty string. With this module, this uses a workaround to provide the proper value. It uses basename in File::Basename on the value returned by fname.

Returns the number of (hard) links to the file.

permission

Returns the file permission as a 4 digits octal value, such as 0755 or 0644.

protection

(No description in the docs β€” just a name and a dream. We're keeping it exactly as listed.)

rdev

Returns the device identifier (special files only).

reset

Force Module::Generic::Finfo to reload the filesystem information of the underlying file or directory.

size

Returns the total size of file, in bytes. Same as csize.

stat

Provided with a file path and this returns a new Module::Generic::Finfo object.

user

Returns the numeric user ID of file's owner. Same as uid.

uid

Returns the numeric user ID of file's owner. Same as user.


🌈 CONSTANTS 🌈

These are the file-type constants, bestie. filetype is one of them. 🫢

FILETYPE_NOFILE

File type constant to indicate the file does not exist.

FILETYPE_REG

Regular file.

FILETYPE_DIR

The element is a directory.

FILETYPE_CHR

The element is a character block.

FILETYPE_BLK

A block device.

FILETYPE_PIPE

The file is a FIFO or a pipe.

FILETYPE_LNK

The file is a symbolic link.

FILETYPE_SOCK

The file is a (unix domain) socket.

FILETYPE_UNKFILE

The file is of some other unknown type or the type cannot be determined.


πŸŽ€ SERIALISATION πŸŽ€

Serialisation by CBOR, Sereal and Storable::Improved (or the legacy Storable) is supported by this package. To that effect, the following subroutines are implemented: FREEZE, THAW, STORABLE_freeze and STORABLE_thaw.

Serialisation is supported, periodt. πŸ’…

πŸ’… THREAD & PROCESS SAFETY πŸ’…

Okay bestie, this is the part where Module::Generic::Finfo flexes its ✨stability✨ β€” it’s designed to be fully thread-safe and process-safe, so your data stays intact across Perl ithreads and mod_perl’s threaded Multi-Processing Modules (MPMs) like Worker or Event. It uses Module::Generic::Global for thread-safe management of system-wide state, and it keeps per-object state for file metadata. No cap, it’s giving responsible icon behavior 🫢

Key considerations for thread and process safety:

  • Shared Variables

The has_local_tz value in _datetime, which tells you whether the system timezone is supported, is stored in Module::Generic::Global’s local_tz namespace as a system-wide global (accessed via "local_tz =" 'system'>). This is shared across all Module::Generic::* modules (e.g., Module::Generic::Finfo, Module::Generic::DateTime) to avoid redundant timezone checks. Access is protected by thread locks, so initialization and retrieval stay thread-safe:

use threads;
my $finfo = Module::Generic::Finfo->new( "example.txt" );
my $atime = $finfo->atime; # Sets shared has_local_tz
my $dt = Module::Generic::DateTime->new( DateTime->now );
$dt->epoch; # Reuses has_local_tz

The local_tz namespace is highly specific, so the risk of collisions with unrelated modules is negligible.

  • File Metadata

File metadata (e.g., filepath, the internal _data array) is stored per-object, so each thread or process operates on its own instance without shared-state conflicts:

use threads;
my @threads = map
{
    threads->create(sub
    {
        my $finfo = Module::Generic::Finfo->new( "example.txt" );
        $finfo->size; # Thread-safe, per-object state
        return(1);
    });
} 1..5;
$_->join for @threads;
  • External Libraries

Methods like mime_type use File::MMagic::XS or File::MMagic, which are thread-safe because they operate on per-object state. _datetime uses DateTime and DateTime::Format::Strptime, and both are thread-safe when combined with Module::Generic::Global’s locking for has_local_tz.

  • Serialisation

Serialisation methods (FREEZE, THAW) operate on per-object state, making them thread-safe for use with CBOR::XS, Sereal, or Storable::Improved:

use threads;
use Sereal;
my $finfo = Module::Generic::Finfo->new( "example.txt" );
my $encoded = Sereal::encode_sereal( $finfo ); # Thread-safe
  • mod_perl Considerations
    • Prefork MPM β€” File metadata and has_local_tz are isolated per-process, so no extra synchronisation is needed. System-level operations (e.g., stat in reset) are process-safe.
    • Threaded MPMs (Worker/Event) β€” The local_tz namespace is protected by Module::Generic::Global’s synchronisation (lock in perlfunc for ithreads, APR::ThreadRWLock in rare non-threaded Perl cases). You should call Module::Generic::Global->cleanup_register in mod_perl handlers to clear shared state after requests and prevent memory leaks.
    • Thread-Unsafe Functions β€” Avoid Perl functions like localtime in perlfunc or getgrgid in perlfunc (used in group) in threaded MPMs, because they may affect all threads. Module::Generic::Finfo mitigates this by caching results in per-object state. Consult perlthrtut at http://perldoc.perl.org/perlthrtut.html and the mod_perl documentation at https://perl.apache.org/docs/2.0/user/coding/coding.html#Thread_environment_Issues for details.
  • Process Safety

File operations (e.g., stat in perlfunc in init, reset) are process-safe because they rely on system-level calls. The shared has_local_tz is managed by Module::Generic::Global, which keeps access consistent across processes:

use POSIX qw( fork );
my $pid = fork();
if( $pid == 0 )
{
    my $finfo = Module::Generic::Finfo->new( "example.txt" );
    $finfo->atime; # Safe, uses shared has_local_tz
    exit;
}
waitpid( $pid, 0 );

For debugging in threaded or multi-process environments, use platform-specific commands (e.g., on Linux):

ls -l /proc/$$/fd  # List open file descriptors

See your operating system’s documentation for equivalent commands.


πŸ‘‘ AUTHOR πŸ‘‘

Jacques Deguest <jack@deguest.jp>

CPAN ID: jdeguest

https://gitlab.com/jackdeguest/Module-Generic


πŸ¦‹ SEE ALSO πŸ¦‹

Module::Generic::File, Module::Generic


Copyright (c) 2021-2024 DEGUEST Pte. Ltd.

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


That’s the whole vibe, bestie β€” source says perl v5.42.2, dated 2026-02-15, and this page is officially closed like a group chat after everyone says goodnight πŸ’…βœ¨πŸ«Ά

πŸ“¦ where this page comes from