NAME
File::Value - routines to manipulate file name or content as a single value
SYNOPSIS
use File::Value; # to import routines into a Perl script
($msg = file_value(">pid_file", $pid)) # Example: store a file value
and die "pid_file: $msg\n";
($msg = file_value("<pid_file", $pid)) # Example: read a file value
and die "pid_file: $msg\n";
snag_dir($dirname); # attempt to create directory $dirname
snag_file($filename); # attempt to create file $filename
($num, $name) = # return number and name of node created
snag_version( # with lowest numbered available version
$template, { # base name with possible terminal digits
as_dir => undef, # create as a directory (default file)
no_type_mismatch => 0, # complain if mismatch (default don't)
mknextcopy => 0 }); # copy unnumbered file (default don't)
list_high_version($template); # report highest version found
list_low_version($template); # report lowest version found
DESCRIPTION
These are general purpose routines that support the treatment of a file's contents or a file's name as a single data value.
FUNCTIONS
file_value( $file, $value, $how, $maxlen )
Copy contents of file $file to or from a string $value, returning the empty string on success or an error message on failure. To copy $value to $file, start $file with ">" or ">>". To copy $file to $value, start $file with "<". The optional $how parameter qualifies how the copy will be done: "trim" (default) trims whitespace from either end, "untaint" removes various suspicious characters that might cause security problems (no guarantees), and "raw" does no processing at all. The optional parameter $maxlen dictates the maximum number of octets that will be copied. It defaults for sanity to 4GB; use a value of 0 (zero) to remove even that limit.
snag_file( $filename ), snag_dir( $dirname )
The snag_file() and snag_dir() routines try to create directory or file $node. Return "" on successful creation, "1" if $node already exists, else an error message. We check existence only if the creation attempt fails, which permits efficient handling of race conditions. For example,
$msg = -e $node ? "1" # either branch can return "1"
: snag_file($node); # race lost if this returns "1"
if ($msg eq "1") {
$fname = snag_version("$node.v1");
}
checks existence before calling us, avoiding subroutine and system call overhead, and it can rely on the "1" return to detect a lost race and take appropriate action. Generally returns strings, so the caller must check with string comparison (ne, eq instead of !=, ==).
snag_version( $template, $options )
Create the lowest numbered available version of a file or directory that is higher than the highest existing version, and return a two-element array containing the number and name of the node that was obtained, or (-1, $error_msg) on failure. The $options argument is an optional hash reference in which the following keys are recognized:
as_dir => undef, # create node as dir (default is to
# infer it from $template if possible)
no_type_mismatch => 0, # complain if mismatch (default don't)
mknextcopy => 0, # copy unnumbered file (default don't)
If no numbered version exists, the version that will be created will be a file, or a directory if as_dir
is true (default is false unless the original node was a directory). If no_type_mismatch
is true (default is false), it is an error if the type of the highest version (file or directory) is different from the requested type. If a race condition is detected, snag_version will try again with the next higher version number, but won't do this more than a few times. If mknextcopy
is true (default false), the new node will receive a copy of the unnumbered file corresponding to $template (it is an error if it does not exist already as an unnumbered file).
The $template parameter is used to search for and create numbered versions. If it doesn't end in a digit substring ($digits), the digit "1" is assumed. The length of $digits determines the minimum width of the version number, zero-padded if necessary, and the value of $digits is the first version number to use if no numbered versions exist. Examples:
$template="x"; # x1, x2, ..., x9, x10, ..., x101, ...
$template="x.3"; # x.3, x.4, ..., x.101, x.102, ...
$template="v001"; # v001, v002, ..., v101, ..., v1001, ...
One common use case calls for version numbers only when the file or directory that you want to create already exists. For $name="foo",
if (($msg = snag_file($name)) eq 1)
{ ($n, $name) = snag_version("$name-"); }
creates foo, foo-1, foo-2, foo-3 etc. Another common use case calls for version numbers on every version. For example, if versions v996, v997, v998 currently exist, running
($n, $name) = snag_version("v001");
will then create v999, v1000, v1001, etc.
list_high_version( $template )
Return the number and name of the highest numbered existing version of $template (defaults to ""), where numbered versions have the form /$template\d+$/, eg, "v" for v001, v02, v3, or "foo.v" for foo.v1, ..., foo.v129 . Return (-1, undef) if no numbered versions exist.
list_low_version( $template )
Similar to list_high_version(), but return the number and name of the lowest numbered existing version.
SEE ALSO
touch(1)
AUTHOR
John A. Kunze, jak at ucop.edu
COPYRIGHT AND LICENSE
Copyright 2009-2010 UC Regents. Open source BSD license.