1 # This file was automatically generated by SWIG (http://www.swig.org).
4 # Do not make changes to this file unless you know what you are doing--modify
5 # the SWIG interface file instead.
9 use base qw(DynaLoader);
10 package Amanda::Utilc;
11 bootstrap Amanda::Util;
15 # ---------- BASE METHODS -------------
20 my ($classname,$obj) = @_;
21 return bless $obj, $classname;
31 my ($self,$field) = @_;
32 my $member_func = "swig_${field}_get";
33 $self->$member_func();
37 my ($self,$field,$newval) = @_;
38 my $member_func = "swig_${field}_set";
39 $self->$member_func($newval);
48 # ------- FUNCTION WRAPPERS --------
52 *get_original_cwd = *Amanda::Utilc::get_original_cwd;
53 *hexencode = *Amanda::Utilc::hexencode;
54 *hexdecode = *Amanda::Utilc::hexdecode;
55 *sanitise_filename = *Amanda::Utilc::sanitise_filename;
56 *quote_string = *Amanda::Utilc::quote_string;
57 *unquote_string = *Amanda::Utilc::unquote_string;
58 *expand_braced_alternates = *Amanda::Utilc::expand_braced_alternates;
59 *collapse_braced_alternates = *Amanda::Utilc::collapse_braced_alternates;
60 *split_quoted_strings = *Amanda::Utilc::split_quoted_strings;
61 *get_fs_usage = *Amanda::Utilc::get_fs_usage;
62 *fsync = *Amanda::Utilc::fsync;
63 *set_blocking = *Amanda::Utilc::set_blocking;
64 *weaken_ref = *Amanda::Utilc::weaken_ref;
65 *gettimeofday = *Amanda::Utilc::gettimeofday;
66 *openbsd_fd_inform = *Amanda::Utilc::openbsd_fd_inform;
67 *stream_server = *Amanda::Utilc::stream_server;
68 *stream_accept = *Amanda::Utilc::stream_accept;
69 *check_security = *Amanda::Utilc::check_security;
70 *set_pname = *Amanda::Utilc::set_pname;
71 *get_pname = *Amanda::Utilc::get_pname;
72 *set_ptype = *Amanda::Utilc::set_ptype;
73 *get_ptype = *Amanda::Utilc::get_ptype;
74 *set_pcontext = *Amanda::Utilc::set_pcontext;
75 *get_pcontext = *Amanda::Utilc::get_pcontext;
76 *safe_cd = *Amanda::Utilc::safe_cd;
77 *check_running_as = *Amanda::Utilc::check_running_as;
79 ############# Class : Amanda::Util::file_lock ##############
81 package Amanda::Util::file_lock;
82 use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
83 @ISA = qw( Amanda::Util );
88 my $self = Amanda::Utilc::new_file_lock(@_);
89 bless $self, $pkg if defined($self);
92 *lock = *Amanda::Utilc::file_lock_lock;
93 *lock_wr = *Amanda::Utilc::file_lock_lock_wr;
94 *lock_rd = *Amanda::Utilc::file_lock_lock_rd;
95 *unlock = *Amanda::Utilc::file_lock_unlock;
96 *locked = *Amanda::Utilc::file_lock_locked;
97 *write = *Amanda::Utilc::file_lock_write;
98 *data = *Amanda::Utilc::file_lock_data;
100 return unless $_[0]->isa('HASH');
101 my $self = tied(%{$_[0]});
102 return unless defined $self;
103 delete $ITERATORS{$self};
104 if (exists $OWNER{$self}) {
105 Amanda::Utilc::delete_file_lock($self);
106 delete $OWNER{$self};
112 my $ptr = tied(%$self);
118 my $ptr = tied(%$self);
123 # ------- VARIABLE STUBS --------
125 package Amanda::Util;
127 *RUNNING_AS_ANY = *Amanda::Utilc::RUNNING_AS_ANY;
128 *RUNNING_AS_ROOT = *Amanda::Utilc::RUNNING_AS_ROOT;
129 *RUNNING_AS_DUMPUSER = *Amanda::Utilc::RUNNING_AS_DUMPUSER;
130 *RUNNING_AS_DUMPUSER_PREFERRED = *Amanda::Utilc::RUNNING_AS_DUMPUSER_PREFERRED;
131 *RUNNING_AS_CLIENT_LOGIN = *Amanda::Utilc::RUNNING_AS_CLIENT_LOGIN;
132 *RUNNING_AS_UID_ONLY = *Amanda::Utilc::RUNNING_AS_UID_ONLY;
133 *CONTEXT_DEFAULT = *Amanda::Utilc::CONTEXT_DEFAULT;
134 *CONTEXT_CMDLINE = *Amanda::Utilc::CONTEXT_CMDLINE;
135 *CONTEXT_DAEMON = *Amanda::Utilc::CONTEXT_DAEMON;
136 *CONTEXT_SCRIPTUTIL = *Amanda::Utilc::CONTEXT_SCRIPTUTIL;
137 *AF_INET = *Amanda::Utilc::AF_INET;
138 *STREAM_BUFSIZE = *Amanda::Utilc::STREAM_BUFSIZE;
146 Amanda::Util - Runtime support for Amanda applications
148 =head1 Application Initialization
150 Application initialization generally looks like this:
152 use Amanda::Config qw( :init );
153 use Amanda::Util qw( :constants );
156 Amanda::Util::setup_application("myapp", "server", $CONTEXT_CMDLINE);
157 # .. command-line processing ..
158 Amanda::Config::config_init(...);
159 Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER);
161 Amanda::Util::finish_application();
165 =item setup_application($name, $type, $context)
167 Set up the operating environment for an application, without requiring
170 C<$name> is the name of the application, used in log messages, etc.
171 C<$type> is usualy one of "server" or "client". It specifies the
172 subdirectory in which debug logfiles will be created. C<$context>
173 indicates the usual manner in which this application is invoked; one
174 of C<$CONTEXT_CMDLINE> for a user-invoked command-line utility (e.g.,
175 C<amadmin>) which should send human-readable error messages to stderr;
176 C<$CONTEXT_DAEMON> for a program started by C<amandad>, e.g.,
177 C<sendbackup>; or C<$CONTEXT_SCRIPTUTIL> for a small program used from
178 shell scripts, e.g., C<amgetconf>
180 Based on C<$type> and C<$context>, this function does the following:
186 sets up debug logging;
190 configures internationalization
198 sets the current working directory to the debug or temporary
203 closes any unnecessary file descriptors as a security meaasure;
207 ignores C<SIGPIPE>; and
211 sets the appropriate target for error messages.
215 =item finish_setup($running_as_flags)
217 Perform final initialization tasks that require a loaded
218 configuration. Specifically, move the debug log into a
219 configuration-specific subdirectory, and check that the current userid
220 is appropriate for this applciation.
222 The user is specified by one of the following flags, which are
223 available in export tag C<:check_running_as_flags>:
225 $RUNNING_AS_ANY # any user is OK
226 $RUNNING_AS_ROOT # root
227 $RUNNING_AS_DUMPUSER # dumpuser, from configuration
228 $RUNNING_AS_DUMPUSER_PREFERRED # dumpuser, but client_login is OK too
229 $RUNNING_AS_CLIENT_LOGIN # client_login (--with-user at build time)
231 If the flag C<$RUNNING_AS_UID_ONLY> is bit-or'd into
232 C<$running_as_flags>, then the euid is ignored; this is used for
233 programs that expect to be setuid-root.
235 =item finish_application()
237 Remove old debug files.
238 All applications should call this before exiting.
240 =item get_original_cwd()
242 Return the original current directory with C<get_original_cwd>.
246 Print the version and exit. This is intended to be used in C<GetOptions> invocations, e.g.,
250 'version' => \&Amanda::Util::version_opt,
257 These functions read and write the entire requested size to a file
258 descriptor, even if the underlying syscall returns early. Note that
259 they do not operate on Perl file handles.
261 If fewer than C<$size> bytes are written, C<full_write> returns the
262 number of bytes actually written and sets C<$!> appropriately. When
263 reading, if fewer than C<$size> bytes are read due to a normal EOF,
264 then C<$!> is zero; otherwise, it contains the appropriate error
267 Unlike C<POSIX::read>, C<full_read> returns a scalar containing the
268 bytes it read from the file descriptor.
272 =item full_read($fd, $size)
274 =item full_write($fd, $buf, $size)
278 =head1 Miscellaneous Utilities
284 Return a "safe" environment hash. For non-setuid programs, this means
285 filtering out any localization variables.
287 =item get_fs_usage(file)
289 This is a wrapper around the Gnulib function of the same name. On success, it returns
292 blocksize Size of a block
293 blocks Total blocks on disk
294 bfree Free blocks available to superuser
295 bavail Free blocks available to non-superuser
296 bavail_top_bit_set 1 if fsu_bavail represents a value < 0
297 files Total file nodes
298 ffree Free file nodes
300 On failure, it returns nothing, and C<$!> should be set. If C<$!> is 0, then
301 this is a system which cannot measure usage without a C<disk> argument, which
302 this wrapper does not support.
304 =item is_pid_alive(pid)
306 Return 1 is the process with that pid is still alive.
308 =item weaken_ref($ref)
310 This is exactly the same as C<Scalar::Util::weaken>, but available in all
311 supported versions of perl.
315 Return the number of microseconds since the UNIX epoch.
319 Invoke the C<fsync> syscall.
321 =item set_blocking($fd, $blocking)
323 Set or clear the C<O_NONBLOCK> fd flag on $fd; returns a negative value on
324 failure, or 0 on success.
326 =item openbsd_fd_inform()
328 Due to a particularly poor user-space implementation of threading on OpenBSD,
329 executables that are run with nonstandard file descriptors open (fd > 2) find
330 those descriptors to be in a nonblocking state. This particularly affects
331 amandad services, which begin with several file descriptors in the 50's open.
333 This function "informs" the C library about these descriptors by making an
334 C<fcntl(fd, F_GETFL)> call. This is otherwise harmless, and is only perfomed
337 =item built_with_component($comp)
339 Returns true if Amanda was built with the given component. Component names are
340 in C<config/amanda/components.m4>.
346 These are thin wrappers over functions in C<common-src/stream.h> and other related
353 my $family = $Amanda::Util::AF_INET;
354 my $bufsize = $Amanda::Util::STREAM_BUFSIZE;
355 my ($listensock, $port) = Amanda::Util::stream_server(
356 $family, $bufsize, $bufsize, $priv);
358 This function creates a new socket and binds it to a port, returning both the
359 socket and port. If the socket is -1, then an error occurred and is available
360 in C<$!>. The constants C<$AF_INET> and C<$STREAM_BUFSIZE> are universally
361 used when calling this function. If the final argument, C<$priv>, is true,
362 then a the function opens a privileged port (below 1024).
366 my $sock = Amanda::Util::stream_accept(
367 $listen_sock, $timeout, $bufsize, $bufsize);
369 This function accepts a connection on a listening socket. If the connection is
370 not made within C<$timeout> seconds, or some other error occurs, then the
371 function returns -1. The bufsize arguments are applied to the new socket.
375 my $ok = Amanda::Util::check_security($socket, $userstr);
377 This function takes a socket descriptor and a string of the form C<"USER foo">
378 and performs BSD-style checks on that descriptor. These include verifying
379 round-trip DNS sanity; check that the user is in C<.rhosts> or C<.amandahosts>,
380 and checking that the remote port is reserved. Returns an error string on
381 error, or C<undef> on success.
385 =head1 String Utilities
389 =item quote_string($str)
391 Quote a string using Amanda's quoting algorithm. Strings with no
392 whitespace, control, or quote characters are returned unchanged. An
393 empty string is represented as the two-character string C<"">.
394 Otherwise, tab, newline, carriage return, form-feed, backslash, and
395 double-quote (C<">) characters are escaped with a backslash and the
396 string is surrounded by double quotes.
398 =item unquote_string($str)
400 Unquote a string as quoted with C<quote_string>.
402 =item skip_quoted_string($str)
404 my($q, $remaider) = skip_quoted_string($str)
406 Return the first quoted string and the remainder of the string, as separated by
407 any whitespace. Note that the remainder of the string does not include the
408 single separating whitespace character, but will include any subsequent
409 whitespace. The C<$q> is not unquoted.
411 =item C<split_quoted_strings($str)>
413 Split string on unquoted whitespace. Multiple consecutive spaces are I<not>
414 collapsed into a single space: C<"x y"> (with two spaces) parses as C<( "x",
415 "", "y")>. The strings are unquoted before they are returned. An empty string
416 is split into C<( "" )>. This method is generally used for parsing IPC messages,
417 where blank space is significant and well-controlled.
419 =item C<split_quoted_strings_friendly($str)>
421 Similar to C<split_quoted_strings>, but intended for user-friendly uses. In
422 particular, this function treats any sequence of zero or more whitespace
423 characters as a separator, rather than the more strict interpretation applied
424 by C<split_quoted_strings>. All of the strings are unquoted.
426 All of these quoting-related functions are available under the export
429 =item hexencode($str)
431 Encode a string using URI-style hexadecimal encoding.
432 Non-alphanumeric characters will be replaced with "%xx"
433 where "xx" is the two-digit hexadecimal representation of the character.
435 =item hexdecode($str)
437 Decode a string using URI-style hexadecimal encoding.
439 Both C<hexencode> and C<hexdecode> are available under the export tag C<:encoding>
441 =item expand_braced_alternates($str)
442 =item collapse_braced_alternates(\@list)
444 These two functions handle "braced alternates", which is a syntax
445 borrowed, partially, from shells. Comma-separated strings enclosed in
446 curly braces expand into multiple alternatives for the entire string.
449 "{foo,bar,bat}" [ "foo", "bar", "bat" ]
450 "foo{1,2}bar" [ "foo1bar", "foo2bar" ]
451 "foo{1\,2,3}bar" [ "foo1,2bar", "foo3bar" ]
452 "{a,b}-{1,2}" [ "a-1", "a-2", "b-1", "b-2" ]
454 Note that nested braces are not processed. Braces, commas, and
455 backslashes may be escaped with backslashes.
457 As a special case for numeric ranges, if the braces contain only digits
458 followed by two dots followed by more digits, and the digits sort in the
459 correct order, then they will be treated as a sequence. If the first number in
460 the sequence has leading zeroes, then all generated numbers will have that
461 length, padded with leading zeroes.
463 "tape-{01..10}" [ "tape-01", "tape-02", "tape-03", "tape-04",
464 "tape-05", "tape-06", "tape-07", "tape-08",
465 "tape-09", "tape-10" ]
467 On error, C<expand_braced_altnerates> returns undef. These two functions are
468 available in the export tag C<:alternates>.
470 =item generate_timestamp()
472 Generate a timestamp from the current time, obeying the
473 'USETIMESTAMPS' config parameter. The Amanda configuration must
476 =item sanitise_filename($fn)
478 "Santitises" a filename by replacing any characters that might have special
479 meaning to a filesystem with underscores. This operation is I<not> reversible,
480 and distinct input filenames I<may> produce identical output filenames.
482 =item unmarshal_tapespec($tapespec)
483 =item marshal_tapespec($filelist)
485 These functions convert between a tapespec -- formerly, and confusingly, called
486 a "tapelist" -- and a perl data structure like
488 [ $label1 => [ $filenum1, $filenum2, .. ],
489 $label2 => [ $filenum1, $filenum2, .. ],
492 Note that a non-tapespec C<$string> will be unmarshalled as C<[ $string, [] ]>.
498 Amanda provides a basic mechanism to lock a file and read its contents. This
499 uses operating-system facilities to acquire an advisory lock, so non-Amanda
500 applications are not prevented from modifying the file while it is locked.
502 To create a lock object, call the C<file_lock> constructor, passing the
505 my $fl = Amanda::Util::file_lock->new($filename)
507 then, three ways to lock the file:
509 $fl->lock_wr(); # take a write lock (exclusive)
510 $fl->lock_rd(); # take a read lock
511 $fl->lock(); # take a write lock and reads the contents of
512 # the file into memory.
514 they return -1 on failure, 0 if the lock is taken or 1 if the lock in not
515 taken (you can retry later).
517 to access the data in memory
519 my $state = $fl->data();
521 to change the file contents, call C<write>:
523 $fl->write($new_contents);
525 and unlock the lock with
529 Note that the file will be automatically unlocked if the C<file_lock> object is
532 =head1 Simple File Reading & Writing
534 For reading small files directly into memory with little code
535 overhead, we can use C<slurp>.
537 my $data = slurp $filename;
539 After processing the data, we can write it back to file with C<burp>. This
540 function always completely overwrites the file.
542 burp $filename, $header;
544 These functions can (and should) be exported to the main namespace
550 use Amanda::Debug qw(:init);
551 use Amanda::Config qw(:getconf);
554 use POSIX qw( :fcntl_h :errno_h );
555 use POSIX qw( strftime );
556 use Amanda::Constants;
559 # private package variables
564 sub setup_application {
565 my ($name, $type, $context) = @_;
568 croak("no name given") unless ($name);
569 croak("no type given") unless ($type);
570 croak("no context given") unless ($context);
572 # store these as perl values
575 $_pcontext = $context;
577 # and let the C side know about them too
580 set_pcontext($context);
582 safe_cd(); # (also sets umask)
585 # set up debugging, now that we have a name, type, and context
589 $SIG{'PIPE'} = 'IGNORE';
593 my ($running_as) = @_;
595 my $config_name = Amanda::Config::get_config_name();
598 dbrename($config_name, $_ptype);
601 check_running_as($running_as);
604 sub finish_application {
609 print "$_pname-$Amanda::Constants::VERSION\n";
614 push @EXPORT_OK, qw(get_original_cwd);
615 push @{$EXPORT_TAGS{"util"}}, qw(get_original_cwd);
620 delete @rv{qw(IFS CDPATH ENV BASH_ENV LANG)};
622 # delete all LC_* variables
623 for my $var (grep /^LC_/, keys %rv) {
631 push @EXPORT_OK, qw(running_as_flags_to_strings);
632 push @{$EXPORT_TAGS{"running_as_flags"}}, qw(running_as_flags_to_strings);
634 my %_running_as_flags_VALUES;
635 #Convert a flag value to a list of names for flags that are set.
636 sub running_as_flags_to_strings {
640 for my $k (keys %_running_as_flags_VALUES) {
641 my $v = $_running_as_flags_VALUES{$k};
643 #is this a matching flag?
644 if (($v == 0 && $flags == 0) || ($v != 0 && ($flags & $v) == $v)) {
649 #by default, just return the number as a 1-element list
657 push @EXPORT_OK, qw($RUNNING_AS_ANY);
658 push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_ANY);
660 $_running_as_flags_VALUES{"RUNNING_AS_ANY"} = $RUNNING_AS_ANY;
662 push @EXPORT_OK, qw($RUNNING_AS_ROOT);
663 push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_ROOT);
665 $_running_as_flags_VALUES{"RUNNING_AS_ROOT"} = $RUNNING_AS_ROOT;
667 push @EXPORT_OK, qw($RUNNING_AS_DUMPUSER);
668 push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_DUMPUSER);
670 $_running_as_flags_VALUES{"RUNNING_AS_DUMPUSER"} = $RUNNING_AS_DUMPUSER;
672 push @EXPORT_OK, qw($RUNNING_AS_DUMPUSER_PREFERRED);
673 push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_DUMPUSER_PREFERRED);
675 $_running_as_flags_VALUES{"RUNNING_AS_DUMPUSER_PREFERRED"} = $RUNNING_AS_DUMPUSER_PREFERRED;
677 push @EXPORT_OK, qw($RUNNING_AS_CLIENT_LOGIN);
678 push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_CLIENT_LOGIN);
680 $_running_as_flags_VALUES{"RUNNING_AS_CLIENT_LOGIN"} = $RUNNING_AS_CLIENT_LOGIN;
682 push @EXPORT_OK, qw($RUNNING_AS_UID_ONLY);
683 push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_UID_ONLY);
685 $_running_as_flags_VALUES{"RUNNING_AS_UID_ONLY"} = $RUNNING_AS_UID_ONLY;
687 #copy symbols in running_as_flags to constants
688 push @{$EXPORT_TAGS{"constants"}}, @{$EXPORT_TAGS{"running_as_flags"}};
690 push @EXPORT_OK, qw(pcontext_t_to_string);
691 push @{$EXPORT_TAGS{"pcontext_t"}}, qw(pcontext_t_to_string);
693 my %_pcontext_t_VALUES;
694 #Convert an enum value to a single string
695 sub pcontext_t_to_string {
698 for my $k (keys %_pcontext_t_VALUES) {
699 my $v = $_pcontext_t_VALUES{$k};
701 #is this a matching flag?
702 if ($enumval == $v) {
707 #default, just return the number
711 push @EXPORT_OK, qw($CONTEXT_DEFAULT);
712 push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_DEFAULT);
714 $_pcontext_t_VALUES{"CONTEXT_DEFAULT"} = $CONTEXT_DEFAULT;
716 push @EXPORT_OK, qw($CONTEXT_CMDLINE);
717 push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_CMDLINE);
719 $_pcontext_t_VALUES{"CONTEXT_CMDLINE"} = $CONTEXT_CMDLINE;
721 push @EXPORT_OK, qw($CONTEXT_DAEMON);
722 push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_DAEMON);
724 $_pcontext_t_VALUES{"CONTEXT_DAEMON"} = $CONTEXT_DAEMON;
726 push @EXPORT_OK, qw($CONTEXT_SCRIPTUTIL);
727 push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_SCRIPTUTIL);
729 $_pcontext_t_VALUES{"CONTEXT_SCRIPTUTIL"} = $CONTEXT_SCRIPTUTIL;
731 #copy symbols in pcontext_t to constants
732 push @{$EXPORT_TAGS{"constants"}}, @{$EXPORT_TAGS{"pcontext_t"}};
735 my ($fd, $count) = @_;
740 my $n_read = POSIX::read($fd, $b, $count);
741 if (!defined $n_read) {
742 next if ($! == EINTR);
744 } elsif ($n_read == 0) {
751 return join('', @bufs);
755 my ($fd, $buf, $count) = @_;
759 my $n_written = POSIX::write($fd, $buf, $count);
760 if (!defined $n_written) {
761 next if ($! == EINTR);
763 } elsif ($n_written == 0) {
767 $count -= $n_written;
768 $total += $n_written;
771 $buf = substr($buf, $n_written);
778 sub skip_quoted_string {
784 my $c = substr $str, $i, 1;
785 while ($c ne "" && !($iq == 0 && $c =~ /\s/)) {
788 } elsif ($c eq '\\') {
792 $c = substr $str, $i, 1;
794 my $quoted_string = substr $str, 0, $i;
795 my $remainder = undef;
796 if (length($str) > $i) {
797 $remainder = substr $str, $i+1;
800 return ($quoted_string, $remainder);
803 sub split_quoted_string_friendly {
810 (my $elt, $str) = skip_quoted_string($str);
811 push @result, unquote_string($elt);
812 $str =~ s/^\s+// if $str;
819 push @EXPORT_OK, qw(slurp);
821 push @EXPORT_OK, qw(burp);
823 push @EXPORT_OK, qw(safe_overwrite_file);
830 open my $fh, "<", $file or croak "can't open $file: $!";
839 open my $fh, ">", $file or croak "can't open $file: $!";
843 sub safe_overwrite_file {
844 my ( $filename, $contents ) = @_;
846 my $tmpfname = "$filename." . time;
847 open my $tmpfh, ">", $tmpfname or die "open: $!";
849 print $tmpfh $contents;
850 (fsync($tmpfh) == 0) or die "fsync: $!";
851 return rename $tmpfname, $filename;
855 push @EXPORT_OK, qw(hexencode hexdecode);
856 push @{$EXPORT_TAGS{"encoding"}}, qw(hexencode hexdecode);
858 push @EXPORT_OK, qw(quote_string unquote_string skip_quoted_string
859 sanitise_filename split_quoted_strings split_quoted_strings_friendly);
860 push @{$EXPORT_TAGS{"quoting"}}, qw(quote_string unquote_string skip_quoted_string
861 sanitise_filename split_quoted_strings split_quoted_strings_friendly);
863 push @EXPORT_OK, qw(expand_braced_alternates collapse_braced_alternates);
864 push @{$EXPORT_TAGS{"alternates"}}, qw(expand_braced_alternates collapse_braced_alternates);
867 sub generate_timestamp {
868 # this corresponds to common-src/timestamp.c's get_proper_stamp_from_time
869 if (getconf($CNF_USETIMESTAMPS)) {
870 return strftime "%Y%m%d%H%M%S", localtime;
872 return strftime "%Y%m%d", localtime;
876 sub built_with_component {
877 my ($component) = @_;
878 my @components = split / +/, $Amanda::Constants::AMANDA_COMPONENTS;
879 return grep { $_ eq $component } @components;
887 return 1 if $pid == $$;
889 my $Amanda_process = Amanda::Process->new(0);
891 $Amanda_process->load_ps_table();
892 my $alive = $Amanda_process->process_alive($pid);
897 push @EXPORT_OK, qw(weaken_ref);
899 push @EXPORT_OK, qw(stream_server stream_accept check_security);
901 push @EXPORT_OK, qw($AF_INET $STREAM_BUFSIZE);
902 push @{$EXPORT_TAGS{"constants"}}, qw($AF_INET $STREAM_BUFSIZE);
905 # these functions were verified to work similarly to those in
906 # common-src/tapelist.c - they pass the same tests, at least.
908 sub marshal_tapespec {
910 my @filelist = @$filelist; # make a copy we can wreck
914 my $label = shift @filelist;
915 my $files = shift @filelist;
917 $label =~ s/([\\:;,])/\\$1/g;
918 push @specs, "$label:" . join(",", @$files);
920 return join(";", @specs);
923 sub unmarshal_tapespec {
927 # detect a non-tapespec string for special handling; in particular, a string
928 # without an unquoted : followed by digits and commas at the end. The easiest
929 # way to do this is to replace every quoted character with a dummy, then look
930 # for the colon and digits.
932 $tmp =~ s/\\([\\:;,])/X/g;
933 if ($tmp !~ /:[,\d]+$/) {
934 # ok, it doesn't end with the right form, so unquote it and return it
936 $tapespec =~ s/\\([\\:;,])/$1/g;
937 return [ $tapespec, [ 0 ] ];
940 # use a lookbehind to mask out any quoted ;'s
941 my @volumes = split(/(?<!\\);/, $tapespec);
942 for my $vol (@volumes) {
943 my ($label, $files) = ($vol =~ /(.+):([\d,]+)/);
945 $label =~ s/\\([\\:;,])/$1/g;
946 push @filelist, $label;
948 my @files = split(/,/, $files);
949 @files = map { $_+0 } @files;
950 @files = sort { $a <=> $b } @files;
951 push @filelist, \@files;
959 fcntl(STDIN, F_GETFD, 0) or critical("Standard input is not open");
960 fcntl(STDOUT, F_GETFD, 0) or critical("Standard output is not open");
961 fcntl(STDERR, F_GETFD, 0) or critical("Standard error is not open");