Fink::Services(3) Fink documentation Fink::Services(3)NAMEFink::Services - functions for text processing and system interaction
DESCRIPTION
These functions handle a variety of text (file and string) parsing and
system interaction tasks.
Functions
No functions are exported by default. You can get whichever ones you
need with things like:
use Fink::Services '&read_config';
use Fink::Services qw(&execute &expand_percent);
read_config
my $config = read_config $filename;
my $config = read_config $filename, \%defaults;
Reads a fink.conf file given by $filename into a new Fink::Config
object and initializes Fink::Config globals from it. If %defaults
is given they will be used as defaults for any keys not in the
config file. The new object is returned.
read_properties
my $property_hash = read_properties $filename;
my $property_hash = read_properties $filename, $opts;
Reads a text file $filename and returns a ref to a hash of its
fields. See the description of read_properties_lines for more
information.
If $filename cannot be read, program will die with an error
message.
read_properties_var
my $property_hash = read_properties_var $filename, $string;
my $property_hash = read_properties_var $filename, $string, $opts;
Parses the multiline text $string and returns a ref to a hash of
its fields. See the description of read_properties_lines for more
information. The string $filename is used in parsing-error messages
but the file is not accessed.
read_properties_lines
my $property_hash = read_properties_lines $filename, @lines;
my $property_hash = read_properties_lines $filename, $opts, @lines;
This is function is not exported. You should use
read_properties_var, read_properties, or read_properties_multival
instead.
Parses the list of text strings @lines and returns a ref to a hash
of its fields. The string $filename is used in parsing-error
messages but the file is not accessed.
See the Fink Packaging Manual, section 2.2 "File Format" for
information about the format of @lines text.
If errors are encountered while parsing @lines, messages are sent
to STDOUT, but whatever (possibly incorrect) parsing is returned
anyway. The following situations are checked:
More than one occurance of a key. In this situation, the last
occurance encountered in @lines is the one returned. Note that the
same key can occur in the main package and/or different splitoff
packages, up to one time in each.
Use of RFC-822-style multilining (whitespace indent of second and
subsequent lines). This notation has been deprecated in favor of
heredoc notation.
Any unknown/invalid syntax.
Reaching the end of @lines while a heredoc multiline value is
still open.
Note that no check is made for the validity of the fields being in
the file in which they were encountered. The filetype (fink.conf,
*.info, etc.) is not necessarily known and this routine is used for
many different filetypes.
Multiline values (including all the lines of fields in a splitoff)
are returned as a single multiline string (i.e., with embedded \n),
not as a ref to another hash or array.
The following options can be put in an $opts hash:
case_sensitive
If true, fields are treated in a case-sensitive manner. If
false (including undef), field case is ignored (and
cannonicalized to lower-case). Defaults to false.
remove_space
If true, will do doing python-style leading whitespace removal,
on both the top level and any heredocs. In this technique, the
first line of a heredoc establishes the number of whitespace
characters that are removed from subsequent lines. Defaults to
false.
This option also DOES NOT allow RFC-822 multi-line syntax.
read_properties_multival
my $property_hash = read_properties_multival $filename;
my $property_hash = read_properties_multival $filename, $opts;
Reads a text file $filename and returns a ref to a hash of its
fields, with each value being a ref to a list of values for that
field. See the description of read_properties_multival_lines for
more information.
If $filename cannot be read, program will die with an error
message.
read_properties_multival_var
my $property_hash = read_properties_multival_var $filename, $string;
my $property_hash = read_properties_multival_var $filename, $string, $opts;
Parses the multiline text $string and returns a ref to a hash of
its fields, with each value being a ref to a list of values for
that field. See the description of read_properties_multival_lines
for more information. The string $filename is used in parsing-error
messages but the file is not accessed.
read_properties_multival_lines
my $property_hash = read_properties_multival_lines $filename, @lines;
my $property_hash = read_properties_multival_lines $filename, $opts, @lines;
This is function is not exported. You should use
read_properties_var, read_properties, read_properties_multival, or
read_properties_multival_var instead.
Parses the list of text strings @lines and returns a ref to a hash
of its fields, with each value being a ref to a list of values for
that field. The string $filename is used in parsing-error messages
but the file is not accessed.
The function is similar to read_properties_lines, with the
following differences:
Multiline values are can only be given in RFC-822 style notation,
not with heredoc.
No sanity-checking is performed. Lines that could not be parsed
are silently ignored.
Multiple occurances of a field are allowed.
Each hash value is a ref to a list of key values instead of a
simple value string. The list is in the order the values appear in
@lines.
execute
my $retval = execute $script;
my $retval = execute $script, %options;
Executes the (possibly multiline) script $script.
If $script appears to specify an interpreter (i.e., the first line
begins with #!) the whole thing is stored in a temp file which is
made chmod +x and executed. If the tempfile could not be created,
the program dies with an error message. If executing the script
fails, the tempfile is not deleted and the failure code is
returned.
If $script does not specify an interpreter, each line is executed
individually. In this latter case, the first line that fails causes
further lines to not be executed and the failure code is returned.
Blank lines and lines beginning with # are ignored, and any line
ending with \ is joined to the following line.
In either case, each command to be executed (either the shell
script tempfile or individual lines of the simple script) is
printed on STDOUT before being executed by a system() call.
The optional %options are given as option=>value pairs. The
following options are known:
quiet
If the option 'quiet' is not given or its value is false and
the command failed, a message including the return code is sent
to STDOUT.
nonroot_okay
If the value of the option 'nonroot_okay' is true, fink was run
with the --build-as-nobody flag, drop to user=nobody when
running the actual commands.
delete_tempfile
Whether to delete temp-files that are created. The following
values are known:
· -1
Always delete
· 0 (or not passed)
Delete if script was successful, do not delete if it failed
· 1
Never delete
ignore_INT
If true, ignore SIGINT (control-C interrupt) while executing.
Note that this applies to the $script as a whole, not to each
individual line in it.
prepare_script
my $is_tempfile = prepare_script \$script $drop_root;
Given a ref to a scalar containing a (possibly multiline) script,
parse it according to the *Script field rules and leave it in
ready-to-run form. There will be no trailing newline. Note that the
scalar $script is changed! Save a copy if you want to see the
original.
If the first line begins with #! (with optional leading
whitespace), dump the whole script (with leading whitespace on the
#! line removed) into a tempfile. Die if there was a problem
creating the tempfile. Return true and leave $script set to the
fullpathname of the tempfile.
Otherwise, remove leading whitespace from each line, join
consecutive lines that end with \ as a continuation character,
remove blank lines and lines beginning with #. Return false and
leave $script set to the parsed script. If there was nothing left
after parsing, $script is set to undef.
$drop_root is a boolean (e.g. from execute()) to indicate whether
we're building as root or not.
expand_percent
my $string = expand_percent $template;
my $string = expand_percent $template, \%map;
my $string = expand_percent $template, \%map, $err_info;
my $string = expand_percent $template, \%map, $err_info, $err_action;
Performs percent-expansion on the given multiline $template
according to %map (if one is defined). This is a wrapper around
percent_expand2; see the documentation for that function for more
information about percent-expansion.
The value of $err_action determines what happens if the string
cannot be successfully and fully percent-expanded. The following
values are known:
0 (or undef or not specified)
die with error message
1 print error message but ignore
2 silently ignore
If given, $err_info will be appended to the error message. "Ignore"
in this context means the unknown % is left intact in the string.
expand_percent2
my $string = expand_percent2 $template, \%map;
my $string = expand_percent2 $template, \%map, %options;
Performs percent-expansion on the given multiline $template
according to %map. If a line in $template begins with # (possibly
preceeded with whitespace) it is treated as a comment and no
expansion is performed on that line.
The %map is a hash where the keys are the strings to be replaced
(not including the percent char). The mapping can be recursive
(i.e., a value that itself has a percent char), and multiple
substitution passes are made to deal with this situation. Recursing
is currently limitted to a single additional level (only (up to)
two passes are made). If there are still % chars left after the
recursion, that means $template needs more passes (beyond the
recursion limit) or there are % patterns in $template that are not
in %map.
To get an actual percent char in the string, protect it as %% in
$template (similar to printf()). This occurs whether or not there
is a %map. This behavior is implemented internally in the
function, so you should not have ('%'=>'%') in %map. Pecent-
delimited percent chars are left-associative (again as in
printf()).
Expansion keys are not limitted to single letters, however, having
one expansion key that is the beginning of a longer one (d and dir)
will cause unpredictable results (i.e., "a" and "arch" is bad but
"c" and "arch" is okay).
Curly-braces can be used to explicitly delimit a key. If both %f
and %foo exist, one should use %{foo} and %{f} to avoid ambiguity.
The following %options are known:
err_action=>$s (optional)
The value of the err_action option determines what happens if
the string cannot be successfully and fully percent-expanded.
The following err_action string values are known:
"die" (or no err_action option given)
Die with error message
"warn"
Print error message but continue, returning a partially-
processed string
"ignore"
Silently ignore, returning a partially-processed string
"undef"
Print error message and return undef
err_info=>$s (optional)
The string $s will be appended to the error message.
filename
my $file = filename $source_field;
Treats $source_field as a URL or "mirror:" construct as might be
found in Source: fields of a .info file and returns just the
filename (skips URL proto/host or mirror-type, and directory
hierarchy). Note that the presence of colons in the filename will
break this function.
version_cmp
my $bool = version_cmp $fullversion1, $op, $fullversion2;
Compares the two debian version strings $fullversion1 and
$fullversion2 according to the binary operator $op. Each version
string is of the form epoch:version-revision (though one or more of
these components may be omitted as usual--see the Debian Policy
Manual, section 5.6.11 "Version" for more information). The
operators are those used in the debian-package world: << and >> for
strictly-less-than and strictly-greater-than, <= and >= for less-
than-or-equal-to and greater-than-or-equal-to, and = for equal-to.
The results of the basic comparison (similar to the perl <=> and
cmp operators) are cached in a package variable so repeated queries
about the same two version strings does not require repeated
parsing and element-by-element comparison. The result is cached in
both the order the packages are given and the reverse, so these
later requests can be either direction.
raw_version_cmp
my $cmp = raw_version_cmp $item1, $item2;
This is function is not exported. You should use version_cmp
instead.
Compare $item1 and $item2 as debian epoch or version or revision
strings and return -1, 0, 1 as for the perl <=> or cmp operators.
latest_version
my $latest = latest_version @versionstrings;
Given a list of one or more debian version strings, return the one
that is the highest. See the Debian Policy Manual, section 5.6.11
"Version" for more information.
sort_versions
my @sorted = sort_versions @versionstrings;
Given a list of one or more debian version strings, return the list
sorted lowest-to-highest. See the Debian Policy Manual, section
5.6.11 "Version" for more information.
parse_fullversion
my ($epoch, $version, $revision) = parse_fullversion $versionstring;
Parses the given $versionstring of the form epoch:version-revision
and returns a list of the three components. Epoch and revision are
each optional and default to zero if absent. Epoch must contain
only numbers and revision must not contain any hyphens.
If there is an error parsing $versionstring, () is returned.
collapse_space
my $pretty_text = collapse_space $original_text;
Collapses whitespace inside a string. All whitespace sequences are
converted to a single space char. Newlines are removed. Leading and
trailing whitespace is removed.
pkglist2lol
my $struct = pkglist2lol $pkglist;
Takes a string representing a pkglist field and returns a ref to a
list of lists of strings representing each pkg. The elements of the
list referenced by $struct are joined by logical AND (commas in
$pkglist). The pkgs in each list referenced by an element of
@$struct are joined by logical OR (delimited by vertical-bar within
a comma- delimited cluster). Leading and trailing whitespace are
removed from each pkg, and null pkgs are removed. A ref to an array
is always returned, though it may contain no elements. Each element
of @$struct is always an array ref, even if that list only has one
element; none of these will have no elements. A new $struct is
returned on each call, so changing one returned value does not
afect the data returned by another call or the underlying data.
For example,
pkglist2lol( 'foo | quux (>= 1.0-1), bar' )
returns
[
[ "foo", "quux (>= 1.0-1)" ],
[ "bar" ]
]
lol2pkglist
my $pkglist = lol2pkglist $struct;
Given a ref to a list of lists of pkgs, reconstitute the Debian
pkglist string. Blank/whitespace-only/undef elements are removed.
The return is always defined (though it may be null). $struct is
not modified.
cleanup_lol
cleanup_lol $struct;
Given a ref to a list of lists of pkgs, remove useless entries from
the top-level list:
Null entries (undef)
Refs to lists representing duplicate OR clusters (first one found
is kept)
file_MD5_checksum (deprecated)
my $md5 = file_MD5_checksum $filename;
Returns the MD5 checksum of the given $filename. Uses /sbin/md5 if
it is available, otherwise uses the first md5sum in PATH. The
output of the chosen command is read via an open() pipe and matched
against the appropriate regexp. If the command returns failure or
its output was not in the expected format, the program dies with an
error message.
Note: this method is deprecated; use Fink::Checksum->new('MD5')
instead.
gcc_selected
my $selected = gcc_selected;
Finds the version of GCC currently selected with gcc_select.
Returns the version of GCC selected, eg: 4.0.0 . Yields a false
value if the current selection cannot be determined.
enforce_gcc
my $gcc = enforce_gcc($message);
my $gcc = enforce_gcc($message, $gcc_abi);
Check to see if the gcc version optionally supplied in $gcc_abi is
the same as the default GCC ABI for the installed version of Mac OS
X or Darwin. If it is not, we return the value for the default GCC
ABI.
If it is, or if $gcc_abi is not supplied, then we check to see if
the gcc version obtained from /usr/sbin/gcc_select agrees with the
expected (default) gcc version corresponding to the installed
version of Mac OS X or Darwin. If the versions agree, the common
value is returned. If they do not agree, we print $message and
exit fink.
The strings CURRENT_SYSTEM, INSTALLED_GCC, and EXPECTED_GCC, within
$message are converted to appropriate values.
Sample message:
This package must be compiled with GCC EXPECTED_GCC, but you
currently have GCC INSTALLED_GCC selected. To correct this
problem, you may need to install a more recent version of the
Developer Tools (Apple's Xcode).
get_osx_vers
my $os_x_version = get_osx_vers();
Returns OS X major and minor versions (if that's what this platform
appears to be, as indicated by being able to run /usr/bin/sw_vers).
The output of that command is parsed and cached in a global
configuration option in the Fink::Config package so that multiple
calls to this function do not result in repeated spawning of
sw_vers processes.
get_osx_vers_long
my $os_x_version = get_osx_vers_long();
Returns full OS X version (if that's what this platform appears to
be, as indicated by being able to run /usr/bin/sw_vers). The output
of that command is parsed and cached in a global configuration
option in the Fink::Config package so that multiple calls to this
function do not result in repeated spawning of sw_vers processes.
get_darwin_equiv
my $os_x_version = get_darwin_equiv($kernel_major_version);
For a given kernel major version (i.e., the "8" of "8.6.1"), return
the OS X version expected to be used on it. Returns undef if it
couldn't be determined.
get_kernel_vers
my $kernel_version = get_kernel_vers();
Returns the major version of the local kernel.
get_system_perl_version
my $perlversion = get_system_perl_version;
Returns the version of perl in that is /usr/bin/perl by running a
program with it to return its $^V variable. The value is cached, so
multiple calls to this function do not result in repeated spawning
of perl processes.
get_path
my $path_to_file = get_path $filename;
Returns the full pathname of the first executable occurance of
$filename in PATH. The correct platform-dependent pathname
separator is used. This is an all-perl routine that emulates
'which' in csh.
count_files
my $number_of_files = &count_files($path, $regexp);
Returns the number of files in $path. If $regexp is set only files
matching the regexp are returned.
eval_conditional
my $bool = &eval_conditional($expr, $where);
Evaluates the logical expression passed as a string in $expr and
returns its logical value. If there is a parsing error, abort and
print a message (including $where) is printed. Two syntaxes are
supported:
string1 op string2
The two strings are compared using one of the operators defined
as a key in the %compare_subs package-global. The three
components may be separated from each other by "some
whitespace" for legibility.
string
"False" indicates the string is null (has no non-whitespace
characters). "True" indicates the string is non-null.
Leading and trailing whitespace is ignored. The strings themselves
cannot contain whitespace or any of the op operators (no quoting,
delimiting, or protection syntax is implemented).
call_queue_clear
call_queue_add
&call_queue_clear;
# some loop {
&call_queue_add \@call;
# }
&call_queue_clear;
This implements a primitive function/method call queue for
potential future parallelization. Using this model, there is a
single queue. One calls call_queue_clear to make sure there are no
calls left from a previous queue usage, then call_queue_add to add
calls to the queue, then call_queue_clear to make sure all the
calls are complete.
call_queue_clear blocks until there are no calls pending.
call_queue_add blocks until there is an agent available to handle
the call, then hands it off to the agent. Each call is specified by
a ref to a list having one of two forms:
[ $object, $method, @params ]
In this form, a call will be made to the specified $method name
(given as a string, i.e., a symbolic ref) of (blessed) object
$obj, that is, $object->$method(@params).
[ \&function, @params ]
In this form, a call will be made to function &function
(unblessed CODE ref), that is, &$function(@params).
In both cases, the thing is called with parameter list @params (if
given, otherwise an empty list). Return values are discarded. The
lis @call will be clobbered. Unless you are extremely careful to
check the underlying function or method for thread safety and the
use of whatever var are declared "shared", you should not expect
sane results if your functions and methods change parameters passed
by reference, (object) instance variables, or other runtime data
structures.
lock_wait
my $fh = lock_wait $file, %options;
my ($fh, $timedout) = do_lock $file, %options;
Acquire a lock on file $file, waiting until the lock is available
or a timeout occurs.
Returns a filehandle, which must be closed in order to relinquish
the lock. This filehandle can be read from or written to. If
unsuccessful, returns false.
In list context, also returns whether the operation timed out.
The %options hash can contain the following keys:
exclusive => $exclusive
If present and true, an exclusive write lock will be obtained.
Otherwise, a shared read lock will be obtained.
Any number of shared locks can coexist, and they can all be
used for reading. However, an exclusive lock cannot coexist
with any other lock, exclusive or shared, and it is required
for writing.
timeout => $timeout
If running as non-root user, the locking operation will time-
out if the lock cannot be obtained for $timeout seconds. An
open filehandle (which must be closed) will still be returned.
This option has no effect on the root user.
By default, $timeout is 300, so that a user will not get stuck
when root refuses to relinquish the lock. To disable timeouts,
pass zero for $timeout.
root_timeout => $timeout
Just like 'timeout', but the timeout applies to the root user
as well. This option overrides 'timeout'.
quiet => $quiet
If present and true, no messages will be printed by this
function.
desc => $desc
A description of the process that the lock is synchronizing.
This is used in messages printed by this function, eg: "Waiting
for $desc to finish".
no_block => $no_block
If present and true, lock_wait will forget the 'wait' part of
its name. If the lock cannot be acquired immediately, failure
will be returned.
dpkg_lockwait
my $path = dpkg_lockwait;
Returns path to dpkg-lockwait, or dpkg (see lockwait_executable for
more information).
aptget_lockwait
my $path = aptget_lockwait;
Returns path to apt-get-lockwait, or apt-get (see
lockwait_executable for more information).
lockwait_executable
my $path = lockwait_executable($basename);
Finds an executable file named $basename with "-lockwait" appended
in the current PATH. If found, returns the full path to it. If not,
returns just the given $basename. The *-lockwait executables are
wrappers around the parent executables, but only a single instance
of them can run at a time. Other calls to any of the *-lockwait
executables wait until no other instances of them are running
before launching the parent executable.
store_rename
my $success = store_rename $ref, $file;
Store $ref in $file using Storable. Use a
write-to-temp-and-atomically- rename strategy, to prevent
corruption. Return true on success.
spec2struct
my $spec_struct = spec2struct($spec_string);
my $spec_struct = spec2struct($spec_string, $where);
Turn a package specification such as 'foo (>= 1.0)' into a
structural form.
The hash returned always contains the field 'package', and
optionally contains the fields 'version' and 'relation' to indicate
a version restriction.
The $where field is used in case of error, to indicate to the user
where the error occurred.
On error, an exception is thrown.
spec2string
my $spec_string = spec2string($spec_struct);
my $spec_string = spec2string($spec_struct, $where);
Reverse spec2struct. On error, an exception is thrown.
get_options
get_options $command, $optiondesc, $args;
get_options $command, $optiondesc, $args, %optional;
Convenience method to parse arguments for a Fink command.
Standard errors such as invalid options and --help are handled
automagically.
The $command parameter should simply contain the name of the
current Fink command, eg: 'index'.
The $optiondesc array-ref should contain sub-arrays describing
options. Each sub-array should contain, in order:
* Two items which could be passed to Getopt::Long::GetOptions.
* A third item with descriptive text appropriate for the --help
option. If no help should be printed for this option, pass undef.
* An optional fourth item, with a suitable name for the option's
value if it takes a value.
Eg: [ 'option|o' => \$opt, 'Descriptive text', 'value' ]
It is not necessary to include the --help item, it will be added
automatically.
The $args array-ref should contain the list of command-line
arguments to be examined for options. The array will be modified to
remove the arguments found, make a copy if you want to retain the
original list.
The following elements of %optional are available:
helpformat
If the standard help format is not good enough for your
purposes, a custom format can be defined. This is simply a
string, with a some special constructs:
%opts{opt1,opt2,...} Prints the default usage and description for the
given options 'opt1', 'opt2', etc.
%all{} Prints the default usage and description for all
options.
%align{opt,desc} Prints the option 'opt' and its description 'desc',
aligned with other options.
%align{opt,desc,optspace}
Prints the option 'opt' and its description 'desc',
aligned such that the option part takes up a width
of optspace characters.
%intro{ex,...} Print a help introduction, with 'ex' as a very short
generic example of calling this command, such as:
'[options] [packages]'. With multiple examples, will
print one per line.
%% Print a literal percent character.
Percent can also be used to escape comma and curly brackets inside an
expansion.
validate
If the options can be invalid under unusual circumstances, pass
in a code-ref here which will validate the results of option-
parsing. This code-ref should return one of the $VALIDATE_*
constants.
It is guaranteed that $VALIDATE_OK is a false value, and other
$VALIDATE_* are true.
optwidth
The width of the screen given to showing the options (as
opposed to their descriptions). The default should usually be
fine.
If an option has the form "foo!", then a --no-foo help string will
also be created as part of %all{}. Other special features of Getopt
may be adopted in the future
find_subpackages
my @package_names = find_subpackages(__PACKAGE__);
Find the sub-packages of a package. For example, the package
Foo::Bar could have sub-packages Foo::Bar::Baz,
Foo::Bar::Two::Levels, etc.
A list of package-names will be returned, with each package having
already been require'd. One can then call new, or some other class
method, to create new objects of a sub-package.
apt_available
my $bool = apt_available;
Check if apt-get seems usable on this system.
ensure_fink_bld
ensure_fink_bld;
If the current user database does not contain the fink-bld user,
add one.
add_user
add_user($user, $group, $name, $home);
Creates a new user group in the DirectoryServices database. If a
group with name $group doesn't exist, then the group is created as
well. In this case, for convenience, the group will be given the
same id as the user. Returns true on success.
create_ds_entry
create_ds_entry($path, $key => $value,...);
Create an entry in the DirectoryServices database. Returns whether
or not it succeeded.
edit_ds_entry
edit_ds_entry($path, $key => $value,...);
Edit an entry in the DirectoryServices database. Returns whether or
not it succeeded.
check_id_unused
check_id_unused($id,$mode);
Tests whether an input is used either as a user id or as a group
id. $mode should be one of "uid", "gid" or "both"
is_accessible
my ($status,$dir) = is_accessible($path, $octmode);
Example:
my ($status,$dir) = is_accessible("/sw/src/fink.build", "05");
Check whether a path is accessible via the octal mode in $octmode
(not limited to just that mode, so "05" will satisfy e.g. 555, 755,
777, etc.).
Returns a status value of:
0: when only directories or empty entries are in the path, i.e.
it's a path one
could create with 'mkdir -p' 1: we've hit a nondirectory file
Also returns the first path element which is not a world-readable
and executable directory, or the empty string if $path terminates .
select_legal_path
my $status = &select_legal_path ($fink_conf_field, $dir_to_check,
$interactive) ;
Currently $fink_conf_field can be 'Buildpath' or 'FetchAltDir'.
$dir_to_check is the directory to check, unsurprisingly. If
$interactive is true then run the prompts, e.g. for Configure.pm If
it's not set then skip them, e.g. for Engine.pm .
Returns an empty string to indicate an error.
Example:
my $status = select_legal_path ("Buildpath",'',1) ;
Fink 0.36.3.1 2013-12-30 Fink::Services(3)