NAME¶
Paranoid::Filesystem - Filesystem Functions
VERSION¶
$Id: Filesystem.pm,v 0.20 2011/12/20 02:45:21 acorliss Exp $
SYNOPSIS¶
use Paranoid::Filesystem;
$rv = pmkdir("/foo", 0750);
$rv = prm(\%errors, "/foo", "/bar/*");
$rv = prmR(\%errors, "/foo/*");
$rv = preadDir("/etc", \@dirList);
$rv = psubdirs("/etc", \@dirList);
$rv = pfiles("/etc", \@filesList);
$rv = pglob("/usr/*", \@matches); # deprecated
$rv = pglob(\%errors, \@matches, @globs);
$noLinks = ptranslateLink("/etc/foo/bar.conf");
$cleaned = pcleanPath($filename);
$rv = ptouch(\%errors, $epoch, @files);
$rv = ptouchR(1, \%errors, $epoch, @files);
$rv = ptranslatePerms("ug+rwx");
$rv = pchmod(\%errors, "ug+rw", "/foo", "./bar*");
$rv = pchmodR(1, \%errors, $perms, @files);
$rv = pchown(\%errors, $user, $group, @files);
$rv = pchownR(1, \%errors, $user, $group, @files);
$fullname = 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.
NOTE: Previous versions of this module used the rather restrictive
filename regexes for detainting arguments. This is now handled by the
Paranoid::Glob module, which detaints to pretty much everything a filesystem
can handle. Many of what used to be fatal errors are no longer so.
Programmatic errors are still fatal, but errors which may be due to user input
are safely errored out, allowing program execution to continue.
SUBROUTINES/METHODS¶
pmkdir¶
$rv = pmkdir("/foo", 0750);
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 boolean true 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(\%errors, "/foo", "/bar/*");
This function unlinks non-directories and rmdir's directories. File arguments
are processed through
pglob and expanded into multiple targets if globs
are detected.
The error message from each failed operation will be placed into the passed hash
ref using the filename as the key.
NOTE: If you ask it to delete something that's not there it will silently
succeed. After all, not being there is what you wanted anyway, right?
prmR¶
$rv = prmR(\%errors, "/foo/*");
This function works the same as
prm but performs a recursive delete,
similar to "rm -r" on the command line.
preadDir¶
$rv = preadDir("/etc", \@dirList);
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 '//+'
occurences 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 /.
pglob¶
$rv = pglob("/usr/*", \@matches);
$rv = pglob(\%errors, \@matches, @globs);
This function populates the passed array ref with any matches to the shell glob
function. This differs from that function, however, in that it only returns
those files or directories that actually exist on the filesystem.
* Expanding wildcard (can be zero-length)
? Single character wildcard (mandatory character)
[a-z] Character class
{foo,bar} Ellipsis list
This returns a false if there is any problem processing the request, such as if
there is an illegal globbing construct in the request or other types of
errors.
Paranoid::ERROR will store a string explaining the failure, as
well as an associated value in the passed hash reference (in the latter
calling incarnation).
Two forms of the function call are supported, primarily for backward
compatibility purposes. The latter is the preferred incarnation.
NOTE: This function is now just a wrapper around Paranoid::Glob. It may
be advantageous for you to use it directly in lieu of
pglob.
ptouch¶
$rv = ptouch(\%errors, $epoch, @files);
Simulates the UNIX touch command. Like the UNIX command this will create
zero-byte files if they don't exist. The first argument is the timestamp to
apply to targets. If undefined it will default to the current value of
time().
Shell-style globs are supported.
The error message from each failed operation will be placed into the passed hash
ref using the filename as the key.
ptouchR¶
$rv = ptouchR(1, \%errors, $epoch, @files);
This function works the same as
ptouch, but requires one additional
argument (the first 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";
pchmod¶
$rv = pchmod(\%errors, "ug+rw", "/foo", "./bar*");
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
pglob and expanded into multiple
targets if globs are detected.
The error message from each failed operation will be placed into the passed hash
ref 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(1, \%errors, $perms, @files);
This function works the same as
pchmod, but requires one additional
argument (the first argument), boolean, which indicates whether or not the
command should follow symlinks.
pchown¶
$rv = pchown(\%errors, $user, $group, @files);
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
pglob and expanded into multiple
targets if globs are detected.
The error message from each failed operation will be placed into the passed hash
ref 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(1, \%errors, $user, $group, @files);
This function works the same as
pchown, but requires one additional
argument (the first 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
- Carp
- o
- Cwd
- o
- Errno
- o
- Fcntl
- o
- Paranoid
- o
- Paranoid::Debug
- o
- Paranoid::Input
- o
- Paranoid::Glob
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 licensed under the same terms as Perl, itself. Please see
http://dev.perl.org/licenses/ for more information.
(c) 2005, Arthur Corliss (corliss@digitalmages.com)