Provided by: libparanoid-perl_2.10-1_all bug

NAME

       Paranoid::Filesystem - Filesystem Functions

VERSION

       $Id: lib/Paranoid/Filesystem.pm, 2.10 2022/03/08 00:01:04 acorliss Exp $

SYNOPSIS

         use Paranoid::Filesystem;

         $rv = pmkdir("/foo/{a1,b2}");

         $rv = preadDir("/tmp", @entries);
         $rv = psubdirs("/etc", @dirList);
         $rv = pfiles("/etc", @filesList);

         $rv = ptouch("/foo/*", $tstamp);
         $rv = ptouchR("/foo", $tstamp, $follow, %errors);
         $rv = pchmod("/foo", $perms);
         $rv = pchmodR("/foo", $perms, $follow, %errors);
         $rv = pchown("/foo", $user, $group);
         $rv = pchownR("/foo", $user, $group, $follow, %errors);

         $rv = prm("/foo");
         $rv = prmR("/foo", 1, %errors);

         $fullname = pwhich('ls');
         $cleaned  = pcleanPath($filename);
         $noLinks  = ptranslateLink("/etc/foo/bar.conf");
         $rv       = ptranslatePerms("ug+rwx");

         $filename = pwhich('ls');

DESCRIPTION

       This module provides a few functions to make accessing the filesystem a little easier,
       while instituting some safety checks.  If you want to enable debug tracing into each
       function you must set PDEBUG to at least 9.

       pcleanPath, ptranslateLink, and ptranslatePerms are only exported if this module is used
       with the :all target.

IMPORT LISTS

       This module exports the following symbols by default:

           preadDir psubdirs pfiles pmkdir prm prmR ptouch
           ptouchR pchmod pchmodR pchown pchownR pwhich

       The following specialized import lists also exist:

           List        Members
           --------------------------------------------------------
           all         @defaults ptranslateLink pcleanPath
                       ptranslatePerms

SUBROUTINES/METHODS

   pmkdir
         $rv = pmkdir("/foo/{a1,b2}");
         $rv = pmkdir("/foo", 0750);
         $rv = pmkdir("/foo", 0750, %errors);

       This function simulates a 'mkdir -p {path}', returning false if it fails for any reason
       other than the directory already being present.  The second argument (permissions) is
       optional, but if present should be an octal number.  Shell-style globs are supported as
       the path argument.

       If you need to make a directory that includes characters which would normally be
       interpreted as shell expansion characters you can offer a Paranoid::Glob object as the
       path argument instead.  Creating such an object while passing it a literal value will
       prevent any shell expansion from happening.

       This method also allows you to call pmkdir with a list of directories to create, rather
       than just relying upon shell expansion to construct the list.

   prm
         $rv = prm("/foo");
         $rv = prm("/foo", %errors);

       This function unlinks non-directories and rmdir's directories.

       File arguments are processed through Paranoid::Glob and expanded into multiple targets if
       globs are detected.  You can also use a Paranoid::Glob object with a multitude of entities
       to delete instead of a string.

       The optional second argument is a hash in which any error messages is stored (with the
       file/directory name as the key).  Attempting to delete something that's not present is not
       considered a failure.

   prmR
         $rv = prmR("/foo");
         $rv = prmR("/foo", 1);
         $rv = prmR("/foo", 1, %errors);

       This function works the same as prm but performs a recursive delete, similar to "rm -r" on
       the command line.  An optional second argument determines if symbolic links are followed
       and the targets also recursively deleted.

   preadDir
         $rv = preadDir("/tmp", @entries);
         $rv = preadDir("/tmp", @entries, 1);

       This function populates the passed array with the contents of the specified directory.  If
       there are any problems reading the directory the return value will be false and a string
       explaining the error will be stored in Paranoid::ERROR.

       All entries in the returned list will be prefixed with the directory name.  An optional
       third boolean argument can be given to filter out symlinks from the results.

   psubdirs
         $rv = psubdirs("/etc", @dirList);

       This function calls preadDir in the background and filters the list for directory (or
       symlinks to) entries.  It also returns a true if the command was processed with no
       problems, and false otherwise.

       Like preadDir an optional third boolean argument can be passed that causes symlinks to be
       filtered out.

   pfiles
         $rv = pfiles("/etc", @filesList);

       This function calls preadDir in the background and filters the list for file (or symlinks
       to) entries.  It also returns a true if the command was processed with no problems, and
       false otherwise.

       Like preadDir an optional third boolean argument can be passed that causes symlinks to be
       filtered out.

   pcleanPath
         $cleaned = pcleanPath($filename);

       This function takes a filename and cleans out any '.', '..', and '//+' occurrences within
       the path.  It does not remove '.' or '..' as the first path element, however, in order to
       preserve the root of the relative path.

       NOTE: this function does not do any checking to see if the passed filename/path actually
       exists or is valid in any way.  It merely removes the unnecessary artifacts from the
       string.

       If you're resolving an existing filename and want symlinks resolved to the real path as
       well you might be interested in Cwd's realpath function instead.

   ptranslateLink
         $noLinks = ptranslateLink("/etc/foo/bar.conf");

       This functions tests if passed filename is a symlink, and if so, translates it to the
       final target.  If a second argument is passed and evaluates to true it will check every
       element in the path and do a full translation to the final target.

       The final target is passed through pcleanPath beforehand to remove any unneeded path
       artifacts.  If an error occurs (like circular link references or the target being
       nonexistent) this function will return undef.  You can retrieve the reason for failure
       from Paranoid::ERROR.

       Obviously, testing for symlinks requires testing against the filesystem, so the target
       must be valid and present.

       Note: because of the possibility that relative links are being used (including levels of
       '..') all links are translated fully qualified from /.

   ptouch
         $rv = ptouch("/foo/*");
         $rv = ptouch("/foo/*", $tstamp);
         $rv = ptouch("/foo/*", $tstamp, %errors);

       Simulates the UNIX touch command.  Like the UNIX command this will create zero-byte files
       if they don't exist.  The time stamp is an integer denoting the time in UNIX epoch
       seconds.

       Shell-style globs are supported, as are Paranoid::Glob objects.

       The error message from each failed operation will be placed into the passed hash using the
       file name as the key.

   ptouchR
         $rv = ptouchR("/foo");
         $rv = ptouchR("/foo", $tstamp);
         $rv = ptouchR("/foo", $tstamp, $follow);
         $rv = ptouchR("/foo", $tstamp, $follow, %errors);

       This function works the same as ptouch, but offers one additional argument (the third
       argument), boolean, which indicates whether or not the command should follow symlinks.

       You cannot use this function to create new, non-existant files, this only works to update
       an existing directory heirarchy's mtime.

   ptranslatePerms
         $rv = ptranslatePerms("ug+rwx");

       This translates symbolic mode notation into an octal number.  It fed invalid permissions
       it will return undef.  It understands the following symbols:

         u            permissions apply to user
         g            permissions apply to group
         o            permissions apply to all others
         r            read privileges
         w            write privileges
         x            execute privileges
         s            setuid/setgid (depending on u/g)
         t            sticky bit

       EXAMPLES

         # Add user executable privileges
         $perms = (stat "./foo")[2];
         chmod $perms | ptranslatePerms("u+x"), "./foo";

         # Remove all world privileges
         $perms = (stat "./bar")[2];
         chmod $perms ^ ptranslatePerms("o-rwx"), "./bar";

       NOTE: If this function is called with a numeric representation of permissions, it will
       return them as-is.  This allows for this function to be called indiscriminately where you
       might be given permissions in either format, but ultimately want them only in numeric
       presentation.

   pchmod
         $rv = pchmod("/foo", $perms);
         $rv = pchmod("/foo", $perms, %errors);

       This function takes a given permission and applies it to every file given to it.  The
       permission can be an octal number or symbolic notation (see ptranslatePerms for
       specifics).  If symbolic notation is used the permissions will be applied relative to the
       current permissions on each file.  In other words, it acts exactly like the chmod program.

       File arguments are processed through Paranoid::Glob and expanded into multiple targets if
       globs are detected. or you can hand it a glob object directly.

       The error message from each failed operation will be placed into the passed hash using the
       filename as the key.

       The return value will be true unless any errors occur during the actual chmod operation
       including attempting to set permissions on non-existent files.

   pchmodR
         $rv = pchmodR("/foo", $perms);
         $rv = pchmodR("/foo", $perms, $follow);
         $rv = pchmodR("/foo", $perms, $follow, %errors);

       This function works the same as pchmod, but offers one additional argument (the third
       argument), boolean, which indicates whether or not the command should follow symlinks.

   pchown
         $rv = pchown("/foo", $user);
         $rv = pchown("/foo", $user, $group);
         $rv = pchown("/foo", $user, $group, %errors);

       This function takes a user and/or a named group or ID and applies it to every file given
       to it.  If either the user or group is undefined it leaves that portion of ownership
       unchanged.

       File arguments are processed through Paranoid::Glob and expanded into multiple targets if
       globs are detected, or you can hand it a populated glob object directly.

       The error message from each failed operation will be placed into the passed hash using the
       filename as the key.

       The return value will be true unless any errors occur during the actual chown operation
       including attempting to set permissions on non-existent files.

   pchownR
         $rv = pchownR("/foo", $user);
         $rv = pchownR("/foo", $user, $group);
         $rv = pchownR("/foo", $user, $group, $follow);
         $rv = pchownR("/foo", $user, $group, $follow, %errors);

       This function works the same as pchown, but requires one additional argument (the fourth
       argument), boolean, which indicates whether or not the command should follow symlinks.

   pwhich
         $fullname = pwhich('ls');

       This function tests each directory in your path for a binary that's both readable and
       executable by the effective user.  It will return only one match, stopping the search on
       the first match.  If no matches are found it will return undef.

DEPENDENCIES

       o   Cwd

       o   Errno

       o   Fcntl

       o   Paranoid

       o   Paranoid::Debug

       o   Paranoid::Glob

       o   Paranoid::Input

       o   Paranoid::IO

       o   Paranoid::Process

BUGS AND LIMITATIONS

       ptranslateLink is probably pointless for 99% of the uses out there, you're better off
       using Cwd's realpath function instead.  The only thing it can do differently is
       translating a single link itself, without translating any additional symlinks found in the
       preceding path.  But, again, you probably won't want that in most circumstances.

       All of the *R recursive functions have the potential to be very expensive in terms of
       memory usage.  In an attempt to be fast (and reduce excessive function calls and stack
       depth) it utilizes Paranoid::Glob's recurse method.  In essence, this means that the
       entire directory tree is loaded into memory at once before any operations are performed.

       For the most part functions meant to simulate userland programs try to act just as those
       programs would in a shell environment.  That includes filtering arguments through shell
       globbing expansion, etc.  Should you have a filename that should be treated as a literal
       string you should put it into a Paranoid::Glob object as a literal first, and then hand
       the glob to the functions.

AUTHOR

       Arthur Corliss (corliss@digitalmages.com)

LICENSE AND COPYRIGHT

       This software is free software.  Similar to Perl, you can redistribute it and/or modify it
       under the terms of either:

         a)     the GNU General Public License
                <https://www.gnu.org/licenses/gpl-1.0.html> as published by the
                Free Software Foundation <http://www.fsf.org/>; either version 1
                <https://www.gnu.org/licenses/gpl-1.0.html>, or any later version
                <https://www.gnu.org/licenses/license-list.html#GNUGPL>, or
         b)     the Artistic License 2.0
                <https://opensource.org/licenses/Artistic-2.0>,

       subject to the following additional term:  No trademark rights to "Paranoid" have been or
       are conveyed under any of the above licenses.  However, "Paranoid" may be used fairly to
       describe this unmodified software, in good faith, but not as a trademark.

       (c) 2005 - 2020, Arthur Corliss (corliss@digitalmages.com) (tm) 2008 - 2020, Paranoid Inc.
       (www.paranoid.com)