NAME
Module::Generic::Finfo - File Info Object Class
SYNOPSIS
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
DESCRIPTION
This class provides a file info object oriented api.
The other advantage is that even if a non-existing file is provided, an object is returned. Obviously many of this module's methods will return an empty value since the file does not actually exist.
METHODS
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"
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.
is_link
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.
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 use "basename" in File::Basename on the value returned by "fname"
nlink
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
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
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
THREAD & PROCESS SAFETY
Module::Generic::Finfo is designed to be fully thread-safe and process-safe, ensuring data integrity across Perl ithreads and mod_perl’s threaded Multi-Processing Modules (MPMs) such as Worker or Event. It leverages Module::Generic::Global for thread-safe management of system-wide state and maintains per-object state for file metadata.
Key considerations for thread and process safety:
Shared Variables
The
has_local_tz
value in "_datetime", indicating system timezone support, is stored in Module::Generic::Global’slocal_tz
namespace as a system-wide global (accessed vialocal_tz =
'system'>). This is shared across allModule::Generic::*
modules (e.g., Module::Generic::Finfo, Module::Generic::DateTime) to avoid redundant timezone checks. Access is protected by thread locks, ensuring thread-safe initialization and retrieval: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, ensuring negligible risk of collisions with unrelated modules.File Metadata
File metadata (e.g., "filepath", internal
_data
array) is stored per-object, ensuring 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 as they operate on per-object state. "_datetime" uses DateTime and DateTime::Format::Strptime, both 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, requiring no additional synchronisation. 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). Users should callModule::Generic::Global->cleanup_register
in mod_perl handlers to clear shared state after requests, preventing memory leaks. - - Thread-Unsafe Functions
-
Avoid Perl functions like "localtime" in perlfunc or "getgrgid" in perlfunc (used in "group") in threaded MPMs, as they may affect all threads. Module::Generic::Finfo mitigates this by caching results in per-object state. Consult perlthrtut and mod_perl documentation for details.
Process Safety
File operations (e.g., "stat" in perlfunc in "init", "reset") are process-safe, relying on system-level calls. The shared
has_local_tz
is managed by Module::Generic::Global, ensuring consistent access 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 & LICENSE
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.