From: Bdale Garbee Date: Wed, 22 Oct 2008 00:27:49 +0000 (+0200) Subject: commit untracked files ... confusing X-Git-Tag: debian/2.6.1p1-1~39 X-Git-Url: https://git.gag.com/?p=debian%2Famanda;a=commitdiff_plain;h=6ba576375c19b829b2a13dbe6562eedd2716b9ea commit untracked files ... confusing --- diff --git a/DEVELOPING b/DEVELOPING new file mode 100644 index 0000000..8ba7d32 --- /dev/null +++ b/DEVELOPING @@ -0,0 +1,53 @@ +Notes For Developers +==================== + +This document describes a few basic tasks for managing the codebase; +see http://wiki.zmanda.com/ for more detailed developer-oriented +documentation. + +Adding Gnulib Modules +--------------------- + +Edit the clearly marked section in gnulib/regenerate/regenerate, +then re-run that script as directed below. + +Updating Gnulib +--------------- + +This should probably be done after most releases, so that we have +adequate time to uncover any bugs or problems in the new gnulib before +we make another release. + +To update the gnulib files included with Amanda, you'll first need a +CVS checkout of gnulib; let's call it $GNULIB_CO. Then, in the root +of the Amanda source, run + + GNULIB_TOOL=$GNULIB_CO/gnulib-tool ./gnulib/regenerate/regenerate + +Use 'svn status' to figure out what changed, and 'svn add' / 'svn rm' +to inform Subversion. Then re-run autogen, configure, make, and test +the result. If all is well, commit. + +Updating Libtool +---------------- + +Libtool includes such useful files as config/config.guess. +Occasionally (probably right after a release), these files should be +updated. On a machine with libtool installed, simply run + libtoolize --force --copy + +Then use 'svn status' to see what changed, test it out, and commit. + +Updating Gettext +---------------- + +The gettext library contains a significant number of files. Assuming +you have the proper version of gettext installed, these files can be +updated by running + + po/reautopoint + +and then adjusting as appropriate with 'svn add' / 'svn rm', testing, +and committing. Note that this script post-processes the results of +autopoint rather extensively, and will probably need to be adjusted +for a new version of autopoint. diff --git a/UPGRADING b/UPGRADING new file mode 100644 index 0000000..4e012b7 --- /dev/null +++ b/UPGRADING @@ -0,0 +1,69 @@ +Upgrading +========= + +This file describes the process for ugprading Amanda from a previous +version. In general, the Amanda development team aims for seamless +upgrades. In the rare cases where an upgrade requires other changes +on your system, they are described in this file. + +The file is organized from oldest to newest. Please follow all of +the directions, in order, for the range of versions over which you +are upgrading. + +See also http://wiki.zmanda.com/index.php/Version_compatibility for notes +on the compatibility of various versions of Amanda. + +Upgrading from pre-2.4.0 +------------------------ + +Amanda 2.4.0 has introduced a major incompatibility in the Amanda protocol. +This means that pre-2.4.0 clients won't interoperate with a 2.4.0 server, nor +will 2.4.0 clients interoperate with pre-2.4.0 servers. You have to upgrade +them all at the same time. + +To ease the upgrade process Amanda has, from release 2.4.0 on, a configure flag +(--with-testing) that will cause Amanda to use alternate service names (Amanda- +test) instead of the standard ones. This allows you to keep using your old +version of Amanda while you test the new one. + +Depending upon the version of Amanda you are upgrading from, Amanda may use a +different database library to store the backup information, and the new Amanda +may not be able to read the old Amanda database files. In this case, you will +want to do something like the following: + +Before the upgrade (using the old version of amadmin): + + # cd /var/AMANDA/CONFIG + # amadmin CONFIG export > zzz + # mkdir backup + # mv curinfo* backup + + +and after the upgrade (using the new version of amadmin): + + # cd /var/AMANDA/CONFIG + # amadmin CONFIG import < zzz + + +and a month :-) after you are happy with the new version: + + # cd /var/AMANDA/CONFIG + # rm -rf backup + + +After 2.4.0, the structure of the directory holding the index files was changed +to have three levels instead of being flat. This greatly reduces the number of +files in a given directory, which was a problem for some systems. + +The new layout is: + + [indexdir]/hostname/filesystem/YYYYMMDD_L.gz + +where hostname and filesystem are "sanitized" versions of the names from +disklist, i.e. '/' characters are converted to '_' and so on. This new naming +convention matches the one used for the text formatted database. + +A script is available to convert the flat directory structure to the new +layout: + + http://www.amanda.org/2.4-conv/msg00428.html diff --git a/amplot/amplot.sh b/amplot/amplot.sh new file mode 100644 index 0000000..fe47bcc --- /dev/null +++ b/amplot/amplot.sh @@ -0,0 +1,202 @@ +#!@SHELL@ +# Amanda, The Advanced Maryland Automatic Network Disk Archiver +# Copyright (c) 1992-1998 University of Maryland at College Park +# All Rights Reserved. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of U.M. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. U.M. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Author: Olafur Gudumundsson, (ogud@tis.com) Trusted Information Systems +# Formerly at: Systems Design and Analysis Group +# Computer Science Department +# University of Maryland at College Park +# +# Amplot: a program to generate postscript plots of each nights amanda +# performance +# +# Author: Olafur Gudmundsson (ogud@tis.com) +# Creation Date: April 1992 +# Last modified: April 1995 +# Input: list of amdumps +# Output: Plot of amdump files as either gnuplots on the screen or +# Postscript files +# + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +confdir=@CONFIG_DIR@ + +# add sbin and ucb dirs +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb" +export PATH + +# we use a different version of the compression variable than amanda itself. +COMPRESS=@AMPLOT_COMPRESS@ + +# Function to check that awk can do command-line variable +# substitution. If no, then exit; if yes, set $AVARFLAG +# to the commandline switch used to introduce a variable. This +# check used to be performed at build time in configure; it's +# now performed at runtime. +test_awk() { + local tmpfile result + tmpfile=`mktemp /tmp/amplot.XXXXXX` + echo 'BEGIN{print i; exit}' > ${tmpfile} + result=`$AWK -f ${tmpfile} i=xx | wc -c` + if test "$result" -le 1; then + result=`$AWK -f ${tmpfile} -v i=xx | wc -c` + if test "$result" -le 1; then + echo "$AWK does not support command-line variable assignment; amplot cannot run" >&2 + rm -fr $tmpfile + exit 1 + else + AVARFLAG=-v + fi + else + AVARFLAG='' + fi + + rm -fr $tmpfile +} + +# Function to search for gnuplot and ensure it's working. This +# first tries the location detected/configured when amanda was built, +# then tries 'gnuplot', assuming it's in the user's path. If no +# working gnuplot executable is found, it exits with an error. The +# variable $GNUPLOT is set to the resulting executable. +find_gnuplot() { + if test "x$GNUPLOT" = "x"; then + # look for it in the user's PATH + GNUPLOT=gnuplot + fi + + if ${GNUPLOT} --version 2>/dev/null | grep '^gnuplot' >/dev/null; then + : # looks OK + else + echo "${GNUPLOT} was not found; amplot cannot run" + exit 1 + fi +} + +# check our environment, using functions from above +test_awk +find_gnuplot + +if [ $# -eq 0 ] ; then + _ 'Usage: %s [-c] [-e] [-g] [-l] [-p] [-t hours] \n' $0 + _ '%s generates plot for screen with fixed dimensions\n' $0 + _ ' -c Compress the input amdump files after plotting\n' + _ ' -e Extends x (time) axes if needed\n' + _ ' -g Run gnuplot directly no postscript file generated DEFAULT\n' + _ ' -l Landscape mode suitable for printing\n' + _ ' -p Postscript output (color)\n' + _ ' -b The postscipt will be b/w\n' + _ ' -t T Set the right edge of the plot to be T hours\n' + exit 1 +fi + +tmp_files="bandw_free disk_alloc dump_idle finished run_queue tape_* title" + +my_plot=$amlibexecdir/amplot.g +paper=0 +gnuplot=1 +cmpres=0 +para="" +maxtime=4 +bw=0 + +# setting up the parameters to pass to [gn]awk +while :; do + case "$1" in + -c) cmpres=1; shift;; + -e) para=$para"$AVARFLAG extend=1 "; shift;; + -g) gnuplot=1; shift;; + -l) paper=1; para=$para"$AVARFLAG paper=1 "; shift;; + -p) gnuplot=0; shift;; + -b) bw=1; shift;; + -t) shift + if test "$#" -eq 0; then + _ '%s: no argument for -t option\n' $0 1>&2 + exit 5 + fi + maxtime="$1"; shift;; + *) break;; + esac +done +if [ $# -eq 0 ] ; then + _ '%s: no input files\n' $0 1>&2 + exit 5 +fi +para=$para"$AVARFLAG maxtime=$maxtime" + +if [ $gnuplot -eq 1 ] ; then + my_plot=$my_plot"p" # use the plot prog that pauses + plot=" -geometry 800x700+40+0" + para=$para"$AVARFLAG gnuplot=1 " + _ "Displaying graph on the screen, for next graph" + + if [ "$paper" -eq 1 ] ; then + _ '%s: -l requires -p flag at the same time\n' $0 1>&2 + exit 6 + fi + if [ "$bw" -eq 1 ] ; then + _ '%s: -b requires -p flag at the same time\n' $0 1>&2 + exit 6 + fi +fi + +if [ $bw -eq 1 ]; then + para=$para" bw=1" +fi + +list=""; # files to compress at the end + +for i in ${1+"$@"} # for all the input files +do + f="$i"; + if [ ! -f "$f" ] ; then + f=`ls "$i" "$i".*[zZ] 2>/dev/null` + fi + if [ -f "$f" ] ; then # found file + disp=`$AWK -f $amlibexecdir/amcat.awk $AVARFLAG f="$f"` + if [ -z "$disp" ] ; then + _ 'Do not know how to [gz|z]cat this file\n' + else + /bin/rm -f $tmp_files + $disp "$f" | $AWK -f $amlibexecdir/amplot.awk $para + $GNUPLOT $plot $my_plot + if [ $disp = "cat" -a $cmpres -eq 1 ] ; then + list=$list" "$f + fi + fi + else # check if file has been compressed + _ 'No such file %s or %s\n' "$i" "$i.*[zZ]" + fi +done + +/bin/rm -f $tmp_files + +if [ "$list" != "" ] ; then # now compress the files we worked on +# comment out next line if you do not want compression at the end + _ 'Compressing %s\n' "$list" + $COMPRESS $list +fi +exit 0 diff --git a/changer-src/chg-chio.pl b/changer-src/chg-chio.pl new file mode 100644 index 0000000..56bb358 --- /dev/null +++ b/changer-src/chg-chio.pl @@ -0,0 +1,488 @@ +#! @PERL@ -w + +# Catch for sh/csh on systems without #! ability. +eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}' + & eval 'exec @PERL@ -S $0 $argv:q' + if 0; + +# +# This changer script controls tape libraries on operating systems that have a +# chgio program +# DSL 7000 on FreeBSD is an example +# +# The changer being used is a n tape juke, that can be used with 1, n-1 or n +# tapes in the juke. The special slot is slot n. The script does not +# make assumptions about the number of slots, except that the special slot +# is the highest number. The slot is special in the sense that it contains the +# the only tape if the juke contains 1 tape and contains no tape if the juke +# contains n-1 tapes. See getCurrentTape. +# +# Furthermore, the script uses drive 0 and assumes that the device is able to +# figure itself how to move a type from slot m to drive 0 if asked to do so and +# multiple pickers are present. +# +# The numbering of the slots is by the way from 1 to n with slots. The chio +# program returns the slot numbers numbered from 0 to n-1 however. +# +# This script is built up out of bits and pieces of the other scripts +# and no credits are claimed. Most notably the chg-rth.pl script was used. That +# script was written by Erik Frederick, . +# +# Permission to freely use and distribute is granted (by me and was granted by +# the original authors). +# +# Nick Hibma - nick.hibma@jrc.it +# + +require 5.001; + +($progname = $0) =~ s#/.*/##; + +use English; +use Getopt::Long; + +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'}; +$ENV{'PATH'} = "/usr/bin:/usr/sbin:/sbin:/bin"; + +$| = 1; + +if (-d "@AMANDA_DBGDIR@") { + $logfile = "@AMANDA_DBGDIR@/changer.debug"; +} else { + $logfile = "/dev/null"; +} +die "$progname: cannot open $logfile: $ERRNO\n" + unless (open (LOG, ">> $logfile")); + +# +# get the information from the configuration file +# + +$prefix="@prefix@"; +$prefix=$prefix; # avoid warnings about possible typo +$exec_prefix="@exec_prefix@"; +$exec_prefix=$exec_prefix; # Ditto +$sbindir="@sbindir@"; +if ( "@USE_VERSION_SUFFIXES@" eq "yes" ) { + $SUF = "-@VERSION@"; +} else { + $SUF = ""; +} + +chomp ($tapeDevice = `$sbindir/amgetconf$SUF tapedev 2>&1`); +die "tapedev not found in amanda.conf" + if !$tapeDevice or $tapeDevice eq "" or + $tapeDevice =~ m/no such parameter/; +chomp ($changerDevice = `$sbindir/amgetconf$SUF changerdev 2>&1`); +chomp $changerDevice; +die "changerdev not found in amanda.conf" + if !$changerDevice or $changerDevice eq "" or + $changerDevice =~ m/no such parameter/; + +# +# Initialise a few global variables +# + +@slots = (); +@drives = (); +$max_slot = 0; +$max_drive = 0; +$nr_tapes = 0; + +@dow = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); +@moy = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); + +sub do_time { + my (@t); + my ($r); + + ### + # Get the local time for the value. + ### + + @t = localtime (time ()); + + ### + # Return the result. + ### + + $r = sprintf "%s %s %2d %2d:%02d:%02d %4d", + $dow[$t[6]], + $moy[$t[4]], + $t[3], + $t[2], $t[1], $t[0], + 1900 + $t[5]; + + return $r; +} + +sub getCurrentTape { + print LOG &do_time(), ": enter: getCurrentTape\n"; + + # + # Determines the slot number for the tape that is currently in the + # drive. getTapeParams and getTapeStatus should have been called. + # If there is no tape in the drive, no current tape, 0 is returned. + # + + my($slot, $i); + + if ( !$drives[0] ) { # drive empty + $i = 0; + } elsif ( $nr_tapes == 1 ) { # one tape -> comes from slot max_slot + $i = $max_slot; + } else { # find first empty slot + $i = 0; + while ( $i < $#slots and $slots[$i] ) { + $i++ + } + $i++; + } + + print LOG &do_time(), ": leave: getCurrentTape: $i\n"; + return $i; +} + +sub getTapeStatus { + print LOG &do_time(), ": enter: getTapeStatus\n"; + + # + # Sets $nr_tapes, @slots, @drives, $current_tape + # + + my($type,$num,$status); + + print LOG &do_time(), ": running: @CHIO@ -f $changerDevice status\n"; + if ( !(open(FH,"@CHIO@ -f $changerDevice status|")) ) { + print "$progname: '@CHIO@ -f $changerDevice status' failed, $!\n"; + exit(2); + } + + # + # This routine requires the format of the output of 'chio status' to + # be as follows: + # picker 0: + # slot 0: + # slot 1: + # slot 2: + # (etc.) + # drive 0: + + + @slots=(); + @drives=(); + + while( defined ($line = ) ) { + chomp( $line ); + print LOG &do_time(), ": $line\n"; + next unless $line =~ m/(\w+)\s+(\d+):\s*<([^>]+)>/; + ($type,$num,$status) = ($1,$2,$3); + if ( $type =~ m/slot/i ) { + $slots[$num] = ( $status =~ m/full/i ) ? 1 : 0; + if ($slots[ $num ]) { $nr_tapes++ } + } elsif ( $type =~ m/drive/i ) { + $drives[$num] = 0; + if ( $status =~ m/full/i ) { + $drives[$num] = 1; + $nr_tapes++; + } + } else { + # ignore 'picker', empty ones, etc... + } + } + close(FH); + + if ( $nr_tapes == 0 ) { + print "$progname: No tapes in changer!\n"; + exit(2); + } + + $currentTape = &getCurrentTape(); + + print LOG &do_time(), ": leave: getTapeStatus: $nr_tapes\n"; + return($nr_tapes); +} + +sub getTapeParams { + print LOG &do_time(), ": enter: getTapeParams\n"; + + # + # Requests information on the number of slots, pickers and drives + # from the changer. + # + + my($max_slot,$max_drive,$max_picker); + + print LOG &do_time(), ": running: @CHIO@ -f $changerDevice params\n"; + if ( !open(FH,"@CHIO@ -f $changerDevice params|") ) { + print "$progname: '@CHIO@ -f $changerDevice params' failed, $!\n"; + exit(2); + } + + # + # the format of the output of 'chio params' should be + # /dev/ch0: 8 slots, 1 drive, 1 picker + # /dev/ch0: current picker: 0 + # + + $max_slot = 0; + $max_picker = -1; + $max_drive = 0; + + while( defined ($line = ) ) { + chomp $line; + print LOG &do_time(), ": $line\n"; + $max_slot = $1 if $line =~ m/(\d+) slot/i; + $max_drive = $1 if $line =~ m/(\d+) drive/i; + $max_picker = $1 if $line =~ m/(\d+) picker/i; + + } + close(FH); + if ( $max_drive == 0 or $max_picker == -1 ) { + print "$progname: No drive or picker ? ($max_drive/$max_picker)\n"; + exit(2); + } + + print LOG &do_time(), ": leave: getTapeParams: $max_slot, $max_drive, $max_picker\n"; + return ($max_slot, $max_drive, $max_picker); +} + +sub testTape { + my($tape) = @_; + + # + # Check a few parameters to avoid the most serious problems + # + + return + if $currentTape == $tape; + + if( $slots[$tape-1] == 0 ) { + print " $progname: no tape in slot requested\n"; + exit(1); + } + if( $tape > $max_slot ) { + print $tape," $progname: requested a tape > $max_slot\n"; + exit(2); + } + if( $tape < 1 ) { + print $tape," $progname: requested a tape < 1\n"; + exit(2); + } + return; +} + +sub Load { + my($tape) = @_; + print LOG &do_time(), ": enter: Load: $tape\n"; + + # + # Load tape $tape into drive 0 + # + + print LOG &do_time(), ": running: @CHIO@ -f $changerDevice move slot ", $tape - 1, " drive 0\n"; + if ( system("@CHIO@ -f $changerDevice move slot ".($tape-1)." drive 0") ) { + print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape into drive 0\n"; + exit(2); + } + + # wait for tape to load + $count = 1800; + while ( $count > 0 && + system("$MT $MTF $tapeDevice status > /dev/null 2>&1" ) ) { + print LOG &do_time(), ": waiting for tape to load\n"; + sleep 30; + $count -= 30; + } + + print LOG &do_time(), ": leave: Load\n"; +} + +sub Unload { + my($tape) = @_; + print LOG &do_time(), ": enter: Unload: $tape\n"; + + # + # Unload the tape from drive 0 and put it into the slot specified by + # $tape. + # + + # + # Ecrix AutoPAK devices (based on the Spectra Logics 215 changer) + # can lock up if you try to move a tape from a drive to an open slot + # without first rewinding and ejecting the tape. This appears to + # occur when the operation times out and the ch driver sends a device + # or bus reset. Ecrix claims this is about to be fixed with a new + # firmware rev but for now it's safest to just explicitly eject + # the tape before moving the cartridge. + # + if ( system ("$MT $MTF $tapeDevice offline") ) { + print "$progname: Warning, failed to eject the tape with '$MT $MTF $tapeDevice offline'\n"; + # NB: not fatal; let chio try it's thing + } + + if ( system("@CHIO@ -f $changerDevice move drive 0 slot ".($tape-1)." ") ) { + print "$progname: cannot '@CHIO@ -f $changerDevice move' tape $tape from drive 0\n"; + exit(2); + } + print LOG &do_time(), ": leave: Unload\n"; +} + +sub changeTape { + my($tape) = @_; + print LOG &do_time(), ": enter: changeTape: $tape\n"; + + # + # Unload current tape and load a new tape from slot $tape. + # + + if ($tape != $currentTape) { + + &testTape($tape); + + if( $currentTape != 0 ) { + &Unload($currentTape); + } + &Load($tape); + $currentTape = $tape; + } + print LOG &do_time(), ": leave: changeTape\n"; +} + + +# +# Main program +# + +# +# Initialise +# + +($max_slot, $max_drive) = &getTapeParams(); + +$opt_slot = 0; # perl -w fodder +$opt_info = 0; # perl -w fodder +$opt_reset = 0; # perl -w fodder +$opt_eject = 0; # perl -w fodder + +GetOptions("slot=s", "info", "reset", "eject"); + +$nr_tapes = &getTapeStatus(); + +# +# Before we do anything with the tape changer we'll have to rewind the tape +# + +if (-x "$sbindir/ammt$SUF") { + $MT="$sbindir/ammt$SUF"; + $MTF="-f"; +} elsif (-x "@MT@") { + $MT="@MT@"; + $MTF="@MT_FILE_FLAG@"; +} else { + print LOG &do_time(), ": mt program not found\n"; + print " mt program not found\n"; + exit(1); +} +print LOG &do_time(), ": MT -> $MT $MTF\n"; + +system ("$MT $MTF $tapeDevice rewind") + unless $currentTape == 0; + + +if ( $opt_slot ) { + if ( $opt_slot =~ /first/ ) { + &changeTape(1); + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape $tapeDevice\n"; + } + if ( $opt_slot =~ /last/ ) { + &changeTape($max_slot); + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape $tapeDevice\n"; + } + if ( $opt_slot =~ /current/ ) { + &changeTape($currentTape); + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape $tapeDevice\n"; + } + if ( $opt_slot =~ /next/ ) { + $tape = $currentTape+1; + if ( $tape > $max_slot ) { + $tape = 1; + } + while ( $slots[$tape-1] == 0 ) { # there is at least 1 + if ( ++$tape > $max_slot ) { + $tape = 1; + } + } + &changeTape($tape); + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape $tapeDevice\n"; + } + if ( $opt_slot =~ /prev/ ) { + $tape = $currentTape-1; + if ( $tape < 1 ) { + $tape = $max_slot; + } + while ( $slots[$tape-1] == 0 ) { # there is at least 1 + if ( --$tape < 1 ) { + $tape = $max_slot; + } + } + &changeTape($tape); + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape $tapeDevice\n"; + } + if ( $opt_slot =~ /^\d+$/ ) { + &changeTape($opt_slot); + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape $tapeDevice\n"; + } + if ( $opt_slot =~ /advance/ ) { + $tape=$currentTape+1; + if ( $tape > $max_slot ) { + $tape = 1; + } + if ( $currentTape ) { + &Unload($currentTape); + } + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape , /dev/null\n"; + } + + exit 0; +} + +if ( $opt_info ) { + if ( $currentTape == 0 ) { + &Load(1); # load random tape + $currentTape = 1; + } + + print LOG &do_time(), ": $currentTape $max_slot 1\n"; + print "$currentTape $max_slot 1\n"; + exit 0; +} + +if ( $opt_reset ) { + &changeTape(1); + print LOG &do_time(), ": $currentTape $tapeDevice\n"; + print "$currentTape $tapeDevice\n"; + exit 0; +} + +if ( $opt_eject ) { + if ( $currentTape ) { + &Unload($currentTape); + print "0 $tapeDevice\n"; + exit 0; + } else { + print "$progname: drive was not loaded\n"; + exit 1; + } +} + +print "$progname: No command was received. Exiting.\n"; +exit 1; diff --git a/changer-src/chg-chs.sh b/changer-src/chg-chs.sh new file mode 100644 index 0000000..8679711 --- /dev/null +++ b/changer-src/chg-chs.sh @@ -0,0 +1,393 @@ +#!@SHELL@ +# +# Amanda, The Advanced Maryland Automatic Network Disk Archiver +# Copyright (c) 1991-1998 University of Maryland at College Park +# All Rights Reserved. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of U.M. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. U.M. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Author: James da Silva, Systems Design and Analysis Group +# Computer Science Department +# University of Maryland at College Park +# + +# +# chg-chs.sh - chs tape changer script +# + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +pname="chg-chs" + +# add sbin and ucb dirs +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb" +export PATH + +if [ -d "@AMANDA_DBGDIR@" ]; then + logfile=@AMANDA_DBGDIR@/changer.debug +else + logfile=/dev/null +fi + +CHS=@CHS@ + +USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" +if test "$USE_VERSION_SUFFIXES" = "yes"; then + SUF="-@VERSION@" +else + SUF= +fi + +ourconf=`amgetconf$SUF changerfile` +changerdev=`amgetconf$SUF changerdev` +if test -n "$changerdev" && test x"$changerdev" != x/dev/null; then + CHS="$CHS -f$changerdev" +fi + +# read in some config parameters + +if [ \! -f $ourconf ]; then + answer=`_ ' %s: %s does not exist' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +firstslot=`awk '$1 == "firstslot" {print $2}' $ourconf 2>/dev/null` +if [ "$firstslot" = "" ]; then + answer=`_ ' %s: firstslot not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +lastslot=`awk '$1 == "lastslot" {print $2}' $ourconf 2>/dev/null` +if [ "$lastslot" = "" ]; then + answer=`_ ' %s: lastslot not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +nslots=`expr $lastslot - $firstslot + 1` + +gravity=`awk '$1 == "gravity" {print $2}' $ourconf 2>/dev/null` +if [ "$gravity" = "" ]; then + answer=`_ ' %s: gravity not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +needeject=`awk '$1 == "needeject" {print $2}' $ourconf 2>/dev/null` +if [ "$needeject" = "" ]; then + answer=`_ ' %s: needeject not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +multieject=`awk '$1 == "multieject" {print $2}' $ourconf 2>/dev/null` +if [ "$multieject" = "" ]; then + echo `_ 'Note -> multieject not specified in %s' "$ourconf"` >> $logfile + multieject=0 +fi + +ejectdelay=`awk '$1 == "ejectdelay" {print $2}' $ourconf 2>/dev/null` +if [ "$ejectdelay" = "" ]; then + echo `_ 'Note -> ejectdelay not specified in %s' "$ourconf"` >> $logfile + ejectdelay=0 +fi + +ourstate=`awk '$1 == "statefile" {print $2}' $ourconf 2>/dev/null` +if [ "$ourstate" = "" ]; then + answer=`_ ' %s: statefile not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +# read in state: only curslot and curloaded at the present time + +curslot=`awk '$1 == "curslot" {print $2}' $ourstate 2>/dev/null` +if [ "$curslot" = "" ]; then + curslot=$firstslot +fi + +curloaded=`awk '$1 == "curloaded" {print $2}' $ourstate 2>/dev/null` +if [ "$curloaded" = "" ]; then + curloaded=0 +fi + + +# process the command-line + +# control vars to avoid code duplication: not all shells have functions! +usage=0 +checkgravity=0 +ejectslot=0 +loadslot=0 +slotempty=0 + +if [ $# -ge 1 ]; then command=$1; else command="-usage"; fi + +case "$command" in + +-info) # return basic information about changer + + backwards=`expr 1 - $gravity` + answer="$curslot $nslots $backwards" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + ;; + +-reset) # reset changer + + checkgravity=0 + loadslot=1 + newslot=$firstslot + + # XXX put changer-specific reset here, if applicable + ;; + +-eject) # eject tape if loaded + + checkgravity=0 + loadslot=0 + newslot=$curslot + ejectslot=1 + + if [ $curloaded -eq 0 ]; then + answer=`_ '%s %s: slot already empty' "$curslot" "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi + ;; + +-slot) # change to slot + + checkgravity=1 + loadslot=1 + + slotparm=$2 + case "$slotparm" in + [0-9]*) + newslot=$slotparm + if [ \( $newslot -gt $lastslot \) -o \ + \( $newslot -lt $firstslot \) ]; then + answer =`_ '%s %s: no slot %s: legal range is %s ... %s' "$newslot" "$pname" "$newslot" "$firstslot" "$lastslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi + ;; + current) + newslot=$curslot + ;; + first) + newslot=$firstslot + ;; + last) + newslot=$lastslot + ;; + next|advance) + newslot=`expr $curslot + 1` + if [ $newslot -gt $lastslot ]; then + newslot=$firstslot + fi + if [ $slotparm = advance ]; then + loadslot=0 + fi + ;; + prev) + newslot=`expr $curslot - 1` + if [ $newslot -lt $firstslot ]; then + newslot=$lastslot + fi + ;; + *) + answer=`_ ' %s: bad slot name "%s"' "$pname" "$slotparm"` + echo `_ 'Exit ->'` "$answer" >> $logfile + echo $answer + exit 1 + ;; + esac + ;; +*) + usage=1 + ;; +esac + + +if [ $usage -eq 1 ]; then + answer=`_ ' usage: %s {-reset | -slot [|current|next|prev|advance]}' "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + + +# check for legal move + +if [ \( $checkgravity -eq 1 \) -a \( $gravity -ne 0 \) ]; then + if [ \( $newslot -lt $curslot \) -o \( "$slotparm" = "prev" \) ] + then + answer=`_ '%s %s: cannot go backwards in gravity stacker' "$newslot" "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi +fi + +# get tape device name + +device=`awk '$1 == "slot" && $2 == '$newslot' {print $3}' $ourconf 2>/dev/null` +if [ "$device" = "" ]; then + answer=`_ '%s %s: slot %s device not specified in %s' "$newslot" "$pname" "$newslot" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +# check if load needs an eject first + +if [ \( $needeject -eq 1 \) -a \( $loadslot -eq 1 \) -a \ + \( $curloaded -eq 1 \) -a \( $newslot -ne $curslot \) ]; then + ejectslot=1 +fi + + +if [ $ejectslot -eq 1 ]; then # eject the tape from the drive + + # XXX put changer-specific load command here, if applicable + + curloaded=0 # unless something goes wrong + slotempty=0 + + # generically, first check that the device is there + + if [ ! -c $device ]; then + answer=`_ '%s %s: %s: not a device file' "$newslot" "$pname" "$device"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + + # if multiple eject is required, do it now + if [ $multieject -eq 1 ]; then + loopslot=$curslot + while [ $loopslot -lt $newslot ]; do + try_eject_device $device + if [ $? -ne 0 ]; then + answer=`_ '%s %s: %s: unable to change slot %s' "$newslot" "$pname" "$device" "$loopslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + loopslot=`/usr/bin/expr $loopslot + 1` + done + fi + + # second, try to unload the device + try_eject_device $device + $CHS deselect -d1 -s$curslot >/dev/null 2>&1 + if [ $? -ne 0 ]; then + # + # XXX if the changer-specific eject command can distinguish + # betweeen "slot empty" and more serious errors, return 1 + # for the first case, 2 for the second case. Generically, + # we just presume an error signifies an empty slot. + # + #slotempty=1 + answer=`_ ' %s: tape unload to slot %s failed' "$pname" "$curslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + else + sleep $ejectdelay + fi +fi + +if [ \( $loadslot -eq 1 \) -a \( \( $curloaded -ne 1 \) -o \( \( $curloaded -eq 1 \) -a \( $newslot -ne $curslot \) \) \) ]; then # load the tape from the slot + + # XXX put changer-specific load command here, if applicable + + curloaded=1 # unless something goes wrong + slotempty=0 + + # generically, first check that the device is there + + if [ ! -c $device ]; then + answer=`_ '%s %s: %s: not a device file' "$newslot" "$pname" "$device"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + + $CHS select -s$newslot -d1 >/dev/null 2>&1 + if [ $? -ne 0 ]; then + answer=`_ ' %s: tape load from slot %s failed' "$pname" "$newslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + sleep 60 + + # second, try to rewind the device + amdevcheck_status $device + if [ $? -ne 0 ]; then + # + # XXX if the changer-specific load command can distinguish + # betweeen "slot empty" and more serious errors, return 1 + # for the first case, 2 for the second case. Generically, + # we just presume an error signifies an empty slot. + # + slotempty=1 + curloaded=0 + fi +fi + +# update state + +echo "# $pname state cache: DO NOT EDIT!" > $ourstate +echo curslot $newslot >> $ourstate +echo curloaded $curloaded >> $ourstate + +# return slot info + +if [ $slotempty -eq 1 ]; then + answer=`_ ' %s: %s slot is empty' "$pname" "$newslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 +fi + +if [ "$command" = -slot -a "$slotparm" = advance ]; then + device=/dev/null +fi + +answer="$newslot $device" +echo `_ 'Exit ->'` $answer >> $logfile +echo $answer +exit 0 diff --git a/changer-src/chg-disk.sh b/changer-src/chg-disk.sh new file mode 100644 index 0000000..bdce74a --- /dev/null +++ b/changer-src/chg-disk.sh @@ -0,0 +1,319 @@ +#! @SHELL@ +# +# Amanda, The Advanced Maryland Automatic Network Disk Archiver +# Copyright (c) 1991-1999 University of Maryland at College Park +# All Rights Reserved. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of U.M. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. U.M. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Author: Jean-Christian SIMONETTI, System and Network Engineer +# Wanadoo Portails +# Sophia Antipolis, France +# +# This changer script is based on a directory structure like: +# slot_root_dir -| +# |- info +# |- data -> slot1 +# |- slot1 +# |- slot2 +# |- ... +# |- slotn +# where 'slot_root_dir' is the tapedev 'file:xxx' parameter and 'n' +# is the LASTSLOT value of your changerfile config file. If LASTSLOT is +# not defined, the value of the tapecycle parameter is used. +# +# To use this driver, just put the line 'tpchanger "chg-disk"' in your +# amanda.conf. +# +# Example of use (amanda.conf): +# --- cut here --- +# tapedev "file:/BACKUP2/slots/" +# changerdev "/dev/null" +# changerfile "chg-disk" +# tpchanger "chg-disk" +# changerfile "/usr/local/amanda/etc/changer" +# tapetype HARD-DISK +# define tapetype HARD-DISK { +# length 12000 mbytes +# } +# --- cut here --- +# +# Example changerfile (chg-disk.conf): +# --- cut here --- +# LASTSLOT=12 +# --- cut here --- +# +# The number of slot is equal to your LASTSLOT or tapecycle. +# You must create the slots and data directory. +# + + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +# add sbin and ucb dirs +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb" +export PATH + +USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" +if test "$USE_VERSION_SUFFIXES" = "yes"; then + SUF="-@VERSION@" +else + SUF= +fi + +MYNAME=$0 + +TAPE=`amgetconf$SUF tapedev` +if test X"$TAPE" = X""; then + echo `_ ' tapedev not specified in amanda.conf.'` + exit 2 +fi +SLOTDIR=`echo $TAPE | sed 's/^file://'` + +isinteger() { + # should be exactly one arg + [ $# = 1 ] || return 1 + # if arg is null, no expr needed + [ "${1}" = '' ] && return 1 + # expr will return 0 on match + expr "$1" : '[0-9][0-9]*$' > /dev/null 2>&1 +} + +# Need rwx access to the virtual tape itself. +if ! test -d $SLOTDIR; then + echo `_ ' Virtual-tape directory %s does not exist.' "$SLOTDIR"` + exit 2 +fi +if ! test -w $SLOTDIR; then + echo `_ ' Virtual-tape directory %s is not writable.' "$SLOTDIR"` + exit 2 +fi + + +# need rwx access to directory of changer file +CHANGERFILE=`amgetconf$SUF changerfile` +conf_match=`expr "$CHANGERFILE" : .\*\.conf\$` +if [ $conf_match -ge 6 ]; then + CONFIGFILE=$CHANGERFILE + CHANGERFILE=`echo $CHANGERFILE | sed 's/.conf$//g'` +else + CONFIGFILE=$CHANGERFILE.conf +fi + +CFDir=`dirname ${CHANGERFILE}` +[ -d ${CFDir} -a -r ${CFDir} -a -w ${CFDir} -a -x ${CFDir} ] || + { echo `_ " %s: need 'rwx' access to '%s'" "$MYNAME" "$CFDir"` ; exit 2 ; } + +# check or create changer metadata files +ACCESSFILE=$CHANGERFILE-access +[ -f $ACCESSFILE -a -r $ACCESSFILE -a -w $ACCESSFILE ] || + echo 0 > $ACCESSFILE || + { echo `_ " %s: could not access or create '%s'" "$MYNAME" "$ACCESSFILE"` ; exit 2; } +CLEANFILE=$CHANGERFILE-clean +[ -f $CLEANFILE -a -r $CLEANFILE -a -w $CLEANFILE ] || + echo 0 > $CLEANFILE || + { echo `_ " %s: could not access or create '%s'" "$MYNAME" "$CLEANFILE"` ; exit 2 ; } +SLOTFILE=$CHANGERFILE-slot +[ -f $SLOTFILE -a -r $SLOTFILE -a -w $SLOTFILE ] || + echo 0 > $SLOTFILE || + { echo `_ " %s: could not access or create '%s'" "$MYNAME" "$SLOTFILE"` ; exit 2; } + +# read and check metadata +ACCESSCOUNT=`cat $ACCESSFILE` +isinteger $ACCESSCOUNT || { ACCESSCOUNT=0 ; echo 0 > $ACCESSFILE ; } +CLEANCOUNT=`cat $CLEANFILE` +isinteger $CLEANCOUNT || { CLEANCOUNT=0 ; echo 0 > $CLEANFILE ; } + +FIRSTSLOT=1 +LASTSLOT=`amgetconf$SUF tapecycle` +if test -r $CONFIGFILE; then + . $CONFIGFILE +fi +CURSLOT=0 +CLEANSLOT=$LASTSLOT +NSLOT=`expr $LASTSLOT - $FIRSTSLOT + 1` + +load() { + WHICHSLOT=$1; + # unload should have been called, but just in case ... + [ -h $SLOTDIR/data ] && unload + ln -s $SLOTDIR/slot$WHICHSLOT $SLOTDIR/data + echo $WHICHSLOT > $SLOTFILE +} + +unload() { + rm -f $SLOTDIR/data + echo "0" > $SLOTFILE +} + +readstatus() { + CURSLOT=`cat $SLOTFILE` +} + +loadslot() { + WHICHSLOT=$1 + + TYPE=string # default if not numeric + isinteger $WHICHSLOT && TYPE=digit + + readstatus + NEWSLOT=0 + if [ $WHICHSLOT = "current" ]; then + if [ $CURSLOT -le 0 ]; then + load $FIRSTSLOT + echo "$FIRSTSLOT $TAPE" + exit 0 + else + echo "$CURSLOT $TAPE" + exit 0 + fi + elif [ $WHICHSLOT = "next" -o $WHICHSLOT = "advance" ]; then + NEWSLOT=`expr $CURSLOT + 1` + [ $NEWSLOT -gt $LASTSLOT ] && NEWSLOT=$FIRSTSLOT + elif [ $WHICHSLOT = "prev" ]; then + NEWSLOT=`expr $CURSLOT - 1` + [ $NEWSLOT -lt $FIRSTSLOT ] && NEWSLOT=$LASTSLOT + elif [ $WHICHSLOT = "first" ]; then + NEWSLOT=$FIRSTSLOT + elif [ $WHICHSLOT = "last" ]; then + NEWSLOT=$LASTSLOT + elif [ $TYPE = "digit" ]; then + if [ $WHICHSLOT -ge $FIRSTSLOT -a $WHICHSLOT -le $LASTSLOT ]; then + NEWSLOT=$WHICHSLOT + else + echo `_ '%s illegal slot' "$WHICHSLOT"` + exit 1 + fi + elif [ $WHICHSLOT = "clean" ]; then + NEWSLOT=$CLEANSLOT + else + echo `_ '%s illegal request' "$WHICHSLOT"` + exit 1 + fi + if [ $NEWSLOT = $CURSLOT ]; then + echo "$CURSLOT $TAPE" + exit 0 + fi + if [ $NEWSLOT = $CLEANSLOT ]; then + expr ${CLEANCOUNT:=0} + 1 > $CLEANFILE + echo 0 > $ACCESSFILE + else + expr ${ACCESSCOUNT:=0} + 1 > $ACCESSFILE + if [ $ACCESSCOUNT -gt $LASTSLOT ]; then + $MYNAME -slot clean >/dev/null + fi + fi + + readstatus + if [ $CURSLOT -ne 0 ]; then + unload + fi + + if [ $WHICHSLOT = "advance" ]; then + echo "$NEWSLOT /dev/null" + exit 0 + fi + load $NEWSLOT + echo "$NEWSLOT $TAPE" + exit 0 +} + +info() { + readstatus + echo "$CURSLOT $NSLOT 1" + exit 0 +} + +reset() { + readstatus + [ $CURSLOT -gt 0 ] && unload + load $FIRSTSLOT + echo "$FIRSTSLOT $tape" + exit 0 +} + +eject() { + readstatus + if [ $CURSLOT -le 0 ]; then + echo `_ '0 Drive was not loaded'` + exit 1 + else + unload + echo $CURSLOT + exit 0 + fi +} + + +while [ $# -ge 1 ];do + case $1 in + -slot) + shift + loadslot $* + ;; + -clean) + shift + loadslot clean + ;; + -current) + shift + loadslot current + ;; + -next) + shift + loadslot next + ;; + -advance) + shift + loadslot advance + ;; + -prev) + shift + loadslot prev + ;; + -first) + shift + loadslot first + ;; + -last) + shift + loadslot last + ;; + -info) + shift + info + ;; + -reset) + shift + reset + ;; + -eject) + shift + eject + ;; + *) + echo `_ ' Unknown option %s' "$1"` + exit 2 + ;; + esac +done + diff --git a/changer-src/chg-iomega.pl b/changer-src/chg-iomega.pl new file mode 100644 index 0000000..56a1329 --- /dev/null +++ b/changer-src/chg-iomega.pl @@ -0,0 +1,290 @@ +#! @PERL@ -w + +# Catch for sh/csh on systems without #! ability. +eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}' + & eval 'exec @PERL@ -S $0 $argv:q' + if 0; + +# +# This changer script is designed for IOMEGA or JAZZ disks of various sizes +# as well as any other removable disk media. +# +# This is a PURELY MANUAL changer. It requests insertion of disk media via +# messages on /dev/tty. So it cannot be used via crontab. +# +# Make sure you comply with any of the following. +# - Add statements +# tpchanger "chg-iomega" +# tapedev "file:" +# # (e.g. tapedev "file:/mnt/iomega" ) +# tapetype IOMEGA +# +# +# define tapetype IOMEGA { +# comment "IOMega 250 MB floppys" +# length 250 mbytes +# filemark 100 kbytes +# speed 1 mbytes +# } +# to your /etc/amanda//amanda.conf file +# - Add entry to /etc/fstab to specify mount point of removable disk +# and make this disk mountable by any user. +# - Format all disks, add a "data" sub directory and label all disks +# by a call to amlabel. +# - Be aware that as of version 2.4.4p1, amanda can't handle backups that are +# larger than the size of the removable disk media. So make sure +# /etc/amanda//disklist specifies chunks smaller than the +# disk size. +# +# This script is built up out of bits and pieces of other scripts, in +# particular chg-chio.pl. That script was written by +# Nick Hibma - nick.hibma@jrc.it +# +# Permission to freely use and distribute is granted (by me and was granted by +# the original authors). +# +# Christoph Pospiech +# + +require 5.001; + +($progname = $0) =~ s#/.*/##; + +use English; +use Getopt::Long; + +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'}; +$ENV{'PATH'} = "/usr/bin:/usr/sbin:/sbin:/bin"; + +$| = 1; + +if (-d "@AMANDA_DBGDIR@") { + $logfile = "@AMANDA_DBGDIR@/changer.debug"; +} else { + $logfile = "/dev/null"; +} +die "$progname: cannot open $logfile: $ERRNO\n" + unless (open (LOG, ">> $logfile")); + + +# +# get the information from the configuration file +# + +$prefix="@prefix@"; +$prefix=$prefix; # avoid warnings about possible typo +$exec_prefix="@exec_prefix@"; +$exec_prefix=$exec_prefix; # Ditto +$sbindir="@sbindir@"; +if ( "@USE_VERSION_SUFFIXES@" eq "yes" ) { + $SUF = "-@VERSION@"; +} else { + $SUF = ""; +} + +chomp ($tapeDevice = `$sbindir/amgetconf$SUF tapedev 2>&1`); +die "tapedev not found in amanda.conf" + if !$tapeDevice or $tapeDevice eq "" or + $tapeDevice =~ m/no such parameter/; +chomp ($changerDevice = `$sbindir/amgetconf$SUF changerdev 2>&1`); +chomp $changerDevice; +die "changerdev not found in amanda.conf" + if !$changerDevice or $changerDevice eq "" or + $changerDevice =~ m/no such parameter/; + +# +# Initialise a few global variables +# + +$current_label = ""; +#$current_slot = 0; +$max_slot = 1; + +@dow = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); +@moy = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); + +sub do_time { + my (@t); + my ($r); + + ### + # Get the local time for the value. + ### + + @t = localtime (time ()); + + ### + # Return the result. + ### + + $r = sprintf "%s %s %2d %2d:%02d:%02d %4d", + $dow[$t[6]], + $moy[$t[4]], + $t[3], + $t[2], $t[1], $t[0], + 1900 + $t[5]; + + return $r; +} + + +sub is_mounted { + my $device = shift @_; + my ($directory) = ($device =~ m/file\:(.*)$/); + if ( -d "$directory/data" ) { return 1;} + else {return 0;} +} + +sub request { + my $label = shift @_; + my $answer; + open (TTY, "+= 5) { + print LOG &do_time(), ": disk not found\n"; + print "disk not found\n"; + exit 1; + } else { + print LOG &do_time(), ": 1 $tapeDevice\n"; + print "1 $tapeDevice\n"; + exit 0; + } +} + +if ( $opt_label ) { + print LOG &do_time(), ": label $opt_label requested\n"; + # no operation + print LOG &do_time(), ": 1 $tapeDevice\n"; + print "1 $tapeDevice\n"; + exit 0; +} + +print "$progname: No command was received. Exiting.\n"; +exit 1; diff --git a/changer-src/chg-juke.sh b/changer-src/chg-juke.sh new file mode 100755 index 0000000..9e3809b --- /dev/null +++ b/changer-src/chg-juke.sh @@ -0,0 +1,267 @@ +#!@SHELL@ + +# chg-juke +# +# This assumes we have possibly rait-striped drives in several +# jukeboxes, controlled by the Fermilab "juke" package +# +# So we could have 3 drives in 3 jukeboxes: +# changerscript="chg-juke" +# changerfile=/some/file +# tapedev="rait:/dev/nst{1,2,3}" +# changerdev="myjuke{0,1,2}" +# Or, if the jukebox has multiple drives: +# changerscript="chg-juke" +# changerfile=/some/file +# tapedev="rait:/dev/nst{1,2,3}" +# changerdev="myjuke" +# We need therefore to generate lists with csh to expand the tapedev +# and changerdev, and deal with the possibility that there are several +# jukeboxes and several drives in each jukebox involved. + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + + +# +# debugging... +# +if [ -d "@AMANDA_DBGDIR@" ]; then + DBGFILE=@AMANDA_DBGDIR@/changer.debug +else + DBGFILE=/dev/null +fi +exec 2>$DBGFILE +echo `_ 'args:'` $0 $* >&2 +set -x + +# +# the usual config fun +# + +USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" +if test "$USE_VERSION_SUFFIXES" = "yes"; then + SUF="-@VERSION@"; +else + SUF= +fi +getconf=$sbindir/amgetconf$SUF + +# +# make sure we can find JUKE later +# +JUKE_DIR=/usr/local +# Fermilab specific +if [ -f /usr/local/etc/setups.sh ] +then + . /usr/local/etc/setups.sh + setup juke +fi + +# add sbin, ucb, and the JUKE_DIR to PATH +PATH="$PATH:$JUKE_DIR/bin:/usr/sbin:/sbin:/usr/ucb" +export PATH JUKE_DIR + +build_drivelists() { + # + # figure out which drives are in which jukebox + # + count=0 + for juke in $jlist + do + for d in $dlist + do + if juke list -j $juke drive $d | grep 'drive [0-9]' >&2 + then + eval "drives_in_$juke=\"\$drives_in_$juke $d\"" + fi + done + done +} + +unload_drive_n_clean() { + + # + # $1 is whether to clean it + # + cleanit=$1 + + # + # if the drive is ONLINE, mt unload it + # + if amdevcheck_status $tapedev; then + try_eject_device $tapedev + fi + + # + # unload any tapes present, maybe load/unload a cleaning cartridge + # + for juke in $jlist + do + eval "jdlist=\"\$drives_in_$juke\"" + for drive in $jdlist + do + juke unload -j $juke drive $drive >&2 || true + if juke list -j $juke drive $drive | grep '(empty)' >&2 + then + : + else + echo `_ '%s %s unable to empty preceding tape from drive %s' "$slot" "$tapedev" "$drive"` + exit 1 + fi + + if $cleanit + then + juke load -j $juke drive $drive clean + sleep 120 + juke unload -j $juke drive $drive + fi + done + done +} + +load_drives() { + # + # load slots. If it's a stripe, load several... + # + for juke in $jlist + do + eval "jdlist=\"\$drives_in_$juke\"" + jndrives=`echo $jdlist | wc -w` + count=0 + for drive in $jdlist + do + rslot=`expr $newslot '*' $jndrives + $count` + juke load -j $changerdev drive $drive slot $rslot >&2 + if juke list -j $changerdev drive $drive | grep '(empty)' >&2 + then + echo `_ '$slot $tapedev unable to load tape into drive' "$slot" "$tapedev"` + exit 1 + fi + count=`expr $count + 1` + done + done + + # + # wait for drive(s) to come online + # + count=0 + until amdevcheck_status $tapedev; do + count=`expr $count + 1` + if [ $count -gt 24 ] + then + echo `_ '%s %s never came online' "$slot" "$tapedev"` + exit 1 + fi + sleep 5 + done +} + + +ONLINEREGEX="ONLINE|READY|sense[_ ]key[(]0x0[)]|sense key error = 0|^er=0$" + +# +# get config variables +# +changerfile=`$getconf changerfile` + tapedev=`$getconf tapedev` + changerdev=`$getconf changerdev` + dlist=`csh -c "echo $tapedev" | sed -e 's/rait://g' -e 's/tape://g'` + ndrives=`echo $dlist | wc -w` + jlist=`csh -c "echo $changerdev"` + njukes=`echo $jlist | wc -w` + totalslots=`for juke in $jlist ; do juke list -j $juke; done | + grep -v '^clean' | + grep 'slot [0-9]' | + wc -l` + +if [ $ndrives -gt 1 ] +then + # + # if it's a 3 tape stripe and we have 30 actual slots + # we only have 10 virtual slots... + # + totalslots=`expr $totalslots / $ndrives` +fi + +build_drivelists + +# +# get current slot if we have one +# +if [ -f "$changerfile" ] +then + slot="`cat $changerfile`" +else + slot=0 + echo $slot > $changerfile +fi + +# +# We treat -reset just like -slot 0 +# +if [ x$1 = 'x-reset' ] +then + set : -slot 0 + shift +fi + +case x$1 in + +x-slot) + + # + # handle special slots... + # + case "$2" in + current) newslot=$slot ; load=true;; + next) newslot=`expr $slot + 1`; load=true;; + advance) newslot=`expr $slot + 1`; load=false;; + prev) newslot=`expr $slot - 1`; load=true;; + first) newslot=0 ; load=true;; + last) newslot=-1 ; load=true;; + *) newslot=$2 ; load=true;; + esac + + if [ $newslot = "clean" ] + then + unload_drive_n_clean true + else + if [ 0 -gt $newslot ] + then + newslot=`expr $totalslots - 1` + fi + + if [ $totalslots -le $newslot ] + then + newslot=0 + fi + + echo $newslot > $changerfile + slot=$newslot + + if $load + then + unload_drive_n_clean false + load_drives + fi + fi + + echo $slot $tapedev + ;; + +x-info) + echo $slot $totalslots 1 + exit 0 + ;; + +x-eject) + unload_drive_n_clean false + echo $slot $tapedev + ;; +esac + +exit $rc diff --git a/changer-src/chg-manual.sh b/changer-src/chg-manual.sh new file mode 100644 index 0000000..d480de9 --- /dev/null +++ b/changer-src/chg-manual.sh @@ -0,0 +1,323 @@ +#!@SHELL@ +# +# Exit Status: +# 0 Alles Ok +# 1 Illegal Request +# 2 Fatal Error +# + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +amlibexecdir=@amlibexecdir@ +. ${amlibexecdir}/chg-lib.sh + +# +# Changer config file (changerfile) +# +# resend_mail=900 # 15 minutes +# timeout_mail=604800 # 7 days +# request="tty" # Use the tty to ask the user to change tape. +# # Can't be use by cron +# request="email" # Send an email to ask the user to change tape. +# request="tty_email" # Use the tty if it exist or send an email. +# #Default is "tty_email" +# mtx_binary="/path/to/mtx" # path of 'mtx'; default is value discovered by +# # configure +# +# + + +if [ -d "@AMANDA_DBGDIR@" ]; then + logfile=@AMANDA_DBGDIR@/changer.debug +else + logfile=/dev/null +fi + +myname=$0 + +EGREP='@EGREP@' + +if ! error=`try_find_mt`; then + echo $error + exit 2 +fi + +MAILER=@MAILER@ +ONLINEREGEX="ONLINE|READY|sense[_ ]key[(]0x0[)]|sense key error = 0|^er=0$|, mt_erreg: 0x0|^Current Driver State: at rest$" +REPORTTO=`amgetconf mailto` +tape=`amgetconf tapedev` + +if [ -z "$tape" ]; then + echo `_ ' tapedev not specified in amanda.conf.'` + exit 2 +fi + +ORG=`amgetconf ORG` + +firstslot=1 +lastslot=99 +resend_mail=900 # 15 minutes +timeout_mail=604800 # 7 days + +changerfile=`amgetconf changerfile` + +conf_match=`expr "$changerfile" : .\*\.conf\$` +if [ $conf_match -ge 6 ]; then + configfile=$changerfile + changerfile=`echo $changerfile | sed 's/.conf$//g'` +else + configfile=$changerfile.conf +fi + +cleanfile=$changerfile-clean +accessfile=$changerfile-access +slotfile=$changerfile-slot +[ ! -f $cleanfile ] && echo 0 > $cleanfile +[ ! -f $accessfile ] && echo 0 > $accessfile +[ ! -f $slotfile ] && echo $firstslot > $slotfile +cleancount=`cat $cleanfile` +accesscount=`cat $accessfile` +slot=`cat $slotfile` + +# define these functions early so that they can be overridden in changerfile.conf + +request_tty() { + if > /dev/tty; then + echo -n `_ 'Insert tape into slot %s and press return' "$1"` > /dev/tty + read ANSWER < /dev/tty + else + echo -n `_ 'no /dev/tty to ask to change tape'` + exit 1 + fi +} + +### +# If $changerfile exists, source it into this script. One reason is to +# override the request() function above which gets called to request +# that a tape be mounted. Here is an alternate versions of request() +# that does things more asynchronous: +# +request_email() { + # Send E-mail about the mount request and wait for the drive + # to go ready by checking the status once a minute. Repeat + # the E-mail once an hour in case it gets lost. + timeout=0 + gtimeout=$timeout_mail + while true;do + if [ $gtimeout -le 0 ]; then + echo -n `_ 'timeout waiting for tape online'` + exit 1; + fi + if [ $timeout -le 0 ]; then + msg=`_ 'insert Amanda tape into slot %s (%s)' "$1" "$tape"` + subject=`_ '%s AMANDA TAPE MOUNT REQUEST FOR SLOT %s' "$ORG" "$1"` + echo "$msg" | $MAILER -s "$subject" $REPORTTO + timeout=$resend_mail + fi + echo `_ ' -> status %s' "$tape"` >> $logfile + if amdevcheck_status $tape; then + break + fi + sleep 60 + timeout=`expr $timeout - 60` + gtimeout=`expr $gtimeout - 60` + done +} + +request_tty_email() { + if > /dev/tty; then + echo -n `_ 'Insert tape into slot %s and press return' "$1"` > /dev/tty + read ANSWER < /dev/tty + else + request_email "$1" + fi +} + +request() { + if [ X"$request" = X"tty" ]; then + request_tty "$1" + else if [ X"$request" = X"email" ]; then + request_email "$1" + else + request_tty_email "$1" + fi + fi +} + +# source the changer configuration file (see description, top of file) +if [ -f $configfile ]; then + . $configfile +fi + +# adjust MTX, if necessary +test -n "${mtx_binary}" && MTX="${mtx_binary}" + +# check that MAILER is defined +if test -z "$MAILER"; then + if test x"$request" = x"email" || test x"$request" = x"tty-email"; then + answer=`_ " %s: Can't send email because MAILER is not defined" "$myname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi +fi + +# + +eject() { + echo `_ ' -> status %s' "$tape"` >> $logfile + if amdevcheck_status $tape; then + echo `_ ' -> offline %s' "$tape"` >> $logfile + try_eject_device $tape + answer="$slot $tape" + code=0 + else + answer=`_ ' %s: Drive was not loaded' "$myname"` + code=1 + fi + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit $code +} + +# + +reset() { + echo `_ ' -> status %s' "$tape"` >> $logfile + if amdevcheck_status $tape; then + answer="$slot $tape" + else + answer="0 $tape" + fi + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 +} + +# load # + +loadslot() { + echo `_ ' -> status %s' "$tape"` >> $logfile + # amdevcheck returns zero if the tape exists. + amdevcheck_status $tape; + tape_status=$? + + whichslot=$1 + case $whichslot in + current) + load=$slot + [ $load -eq 0 ] && load=$firstslot + [ $load -gt $lastslot ] && load=$firstslot + [ $load -lt $firstslot ] && load=$lastslot + ;; + next|advance) + load=`expr $slot + 1` + [ $load -gt $lastslot ] && load=$firstslot + ;; + prev) + load=`expr $slot - 1` + [ $load -lt $firstslot ] && load=$lastslot + ;; + first) + load=$firstslot + ;; + last) + load=$lastslot + ;; + [0-9]|[0-9][0-9]) + if [ $1 -lt $firstslot -o $1 -gt $lastslot ]; then + answer=`_ ' %s: slot must be %s .. %s' "$myname" "firstslot" "$lastslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi + load=$1 + ;; + *) + answer=`_ ' %s: illegal slot: %s' "$myname" "$1"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + ;; + esac + # + if [ $tape_status -eq 0 -a $load = $slot ];then + # already loaded + answer="$slot $tape" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + fi + + expr $accesscount + 1 > $accessfile + + if [ $tape_status -eq 0 ]; then + echo `_ " -> offline %s" "$tape"` >> $logfile + try_eject_device $tape + tape_status=1 + fi + if [ $whichslot = advance ]; then + tape=/dev/null + else + echo `_ ' -> load %s' "$load"` >> $logfile + while true; do + request $load + echo `_ ' -> status %s' "$tape"` >> $logfile + if amdevcheck_status $tape; then + break; + fi + done + fi + echo $load > $slotfile + answer="$load $tape" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 +} + +# + +info() { + echo `_ ' -> status %s' "$tape"` >> $logfile + if amdevcheck_status $tape; then + answer="$slot $lastslot 1" + else + answer="0 $lastslot 1" + fi + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 +} + +# +# main part +# + +echo `gettext "args ->"` "$@" >> $logfile +while [ $# -ge 1 ];do + case $1 in + -slot) + shift + loadslot $* + ;; + -info) + shift + info + ;; + -reset) + shift + reset + ;; + -eject) + shift + eject + ;; + *) + fmt`gettext " %s: Unknown option %s\n"` + printf $fmt $myname $1 + exit 2 + ;; + esac +done + +exit 0 diff --git a/changer-src/chg-mcutil.sh b/changer-src/chg-mcutil.sh new file mode 100644 index 0000000..16b56f1 --- /dev/null +++ b/changer-src/chg-mcutil.sh @@ -0,0 +1,578 @@ +#!@SHELL@ +# +# Author: Robert Dege +# +# +# version 1.2 +# ----------- +# fixed last_cleaned file so that if it doesn't exist, it gets created with current date, not '0,0' +# fixed a bug that was reporting the wrong slot # to amcheck +# +# version 1.1 +# ----------- +# amverify was failing when using -slot current. Fixed exit $code from 1 -> 0. +# removed useless $current variables from movetape() function. +# +# +# +# Exit Status: +# 0 Alles Ok +# 1 Illegal Request +# 2 Fatal Error +# + + +# +# Set Path so that it includes Amanda binaries, and access to tapechanger & drive programs +# +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +# add sbin and ucb dirs +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb" +export PATH + + +# +# Define Suffix for amanda binaries +# +USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" +if test "$USE_VERSION_SUFFIXES" = "yes"; then + SUF="-@VERSION@" +else + SUF= +fi + +# +# Load configuration data from the config file +# + +ourconf=`amgetconf$SUF changerfile` +myname=$0 + + +if [ ! -f "$ourconf" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): %s not found as listed in amanda.conf' "$code" "$ourconf"` 1>&2 + exit $code +fi + + +# grab mcutil info +tmpval1=`grep ^mcutil $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^mcutil $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): mcutil not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + MCUTIL=$tmpval2 +else + MCUTIL=$tmpval1 +fi + + +# grab tape info +tmpval1=`grep ^tape $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^tape $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): tape not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + tape=$tmpval2 +else + tape=$tmpval1 +fi + + +# grab firstslot info +tmpval1=`grep ^firstslot $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^firstslot $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): firstslot not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + firstslot=$tmpval2 +else + firstslot=$tmpval1 +fi + + +# grab lastslot info +tmpval1=`grep ^lastslot $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^lastslot $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): lastslot not specified in %s' "$code" "$ourconf"` 1>&2 +elif [ -z "$tmpval1" ]; then + lastslot=$tmpval2 +else + lastslot=$tmpval1 +fi + + +# grab use_cleaning info +tmpval1=`grep ^use_cleaning $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^use_cleaning $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): use_cleaning not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + use_cleaning=$tmpval2 +else + use_cleaning=$tmpval1 +fi + + +# grab cleanslot info +tmpval1=`grep ^cleanslot $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^cleanslot $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): cleanslot not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + cleanslot=$tmpval2 +else + cleanslot=$tmpval1 +fi + + +# grab cleansleep info +tmpval1=`grep ^cleansleep $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^cleansleep $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): cleansleep not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + cleansleep=$tmpval2 +else + cleansleep=$tmpval1 +fi + + +# grab cleanme info +tmpval1=`grep ^cleanme $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^cleanme $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): cleanme not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + cleanme=$tmpval2 +else + cleanme=$tmpval1 +fi + + +# grab cleanfile info +tmpval1=`grep ^cleanfile $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^cleanfile $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): cleanfile not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + cleanfile=$tmpval2 +else + cleanfile=$tmpval1 +fi + + +# grab lastfile info +tmpval1=`grep ^lastfile $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^lastfile $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): lastfile not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + lastfile=$tmpval2 +else + lastfile=$tmpval1 +fi + + +# grab currentslot info +tmpval1=`grep ^currentslot $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^currentslot $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): currentslot not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + currentslot=$tmpval2 +else + currentslot=$tmpval1 +fi + + +# grab logfile info +tmpval1=`grep ^logfile $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^logfile $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): logfile not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + logfile=$tmpval2 +else + logfile=$tmpval1 +fi + +[ ! -w $logfile ] && logfile=/dev/null + + +# grab slot0source info +tmpval1=`grep ^slot0source $ourconf | awk -F\ '{print $2}'` +tmpval2=`grep ^slot0source $ourconf | awk -F= '{print $2}'` +if [ -z "$tmpval1" ] && [ -z "$tmpval2" ]; then + code=2 + echo `_ 'Command Line ->'` $myname $@ + echo `_ 'Exit(%s): slot0source not specified in %s' "$code" "$ourconf"` 1>&2 + exit $code +elif [ -z "$tmpval1" ]; then + slot0source=$tmpval2 +else + slot0source=$tmpval1 +fi + + + +# +# Verify currentslot contains a value +# +if [ ! -f $currentslot ] || [ `cat $currentslot` -lt $firstslot ];then + readstatus + echo $used > $currentslot +fi + +current=`cat $currentslot` + + +# Start logging to $logfile +echo "\n\n==== `date` ====" >> $logfile +echo `_ 'Command Line ->'` $myname $@ >> $logfile + + +# +# is Use Cleaning activated? +# +if [ $use_cleaning -eq 1 ]; then + curday=`date +%j` + curyear=`date +%Y` + + [ ! -f $cleanfile ] && echo 0 > $cleanfile + [ ! -f $lastfile ] && echo $curday,$curyear > $lastfile + + +# +# Check to see when tape drive was last cleaned +# output warning message if it's been too long +# Currently, if it's been more than 45days, then +# an error message is displayed everytime the +# script is called, until the clean parameter +# is run +# + cleaned=`cat $cleanfile` + lastcleaned=`cut -d, -f1 $lastfile` + yearcleaned=`cut -d, -f2 $lastfile` + + if [ `expr $curday - $lastcleaned` -lt 0 ];then + diffday=`expr $curday - $lastcleaned + 365` + diffyear=`expr $curyear - $yearcleaned - 1` + else + diffday=`expr $curday - $lastcleaned` + diffyear=`expr $curyear - $yearcleaned` + fi + + if [ $diffday -gt $cleanme ] || [ $diffyear -ge 1 ];then + if [ $diffyear -ge 1 ];then + echo `_ "Warning, it's been %s year(s) & %s day(s) since you last cleaned the tape drive!" "$diffyear" "$diffday"` + else + echo `_ "Warning, it's been %s day(s) since you last cleaned the tape drive!" "$diffday"` + fi + fi + +fi + + +# +# Read if there is a tape in the tape drive +# If so, determine what slot is the tape from +# +readstatus() { + echo `_ "querying tape drive....."` >> $logfile + used=`expr \`$MCUTIL -e drive | tr = \] | cut -d\] -f2\` - $slot0source` + echo `_ " Done"` >> $logfile + + # Give changer a chance to reset itself + sleep 3 +} + + +# +# If tape is in the drive, eject it +# +eject() { + echo `_ "tape drive eject was called"` >> $logfile + + readstatus + + if [ $used -ge $firstslot ];then + $MCUTIL -m drive slot:$used + code=$? + else + code=1 + fi + + if [ $code -eq 0 ];then + answer=`_ 'Cartridge %s successfully ejected from %s' "$used" "$tape"` + echo `_ "Exit(%s): %s" "$code" "$answer"` >> $logfile + echo $current $answer #For amtape output + return $code + elif [ $code -eq 1 ];then + answer=`_ "No Cartridge in Tape Drive"` + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + echo $current $answer #For amtape output + exit $code + else + answer=`_ 'Tape abnormally failed'` + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + echo $current $answer #For amtape output + exit $code + fi +} + + +# +# reset tape drive to a current state. +# This involves ejecting the current tape (if occupied) +# and inserting the tape in $firstslot +# +reset() { + echo `_ 'tape drive reset was called'` >> $logfile + + readstatus + + if [ $used -ge $firstslot ];then + eject + fi + + res=`$MCUTIL -m slot:$firstslot drive` + code=$? + + + if [ $code -eq 0 ];then + echo $firstslot > $currentslot + answer=`_ '%s - Tape drive was successfully reset' "$firstslot"` + elif [ $code -eq 1 ];then + answer=`_ '%s - Tape drive reset failed\nCommand -> %s' "$firstslot" "$res"` + else + code=2 + answer=`_ '%s - Tape abnormally failed -> %s' "$firstslot" "$res"` + fi + + echo `_ 'Exit(%s): slot %s' "$code" "$answer"` >> $logfile + echo $firstslot #For amtape output + exit $code +} + + + + +# +# Load a specific cartridge into the changer +# +loadslot() { + echo `_ "loadslot was called"` >> $logfile + + readstatus + + whichslot=$1 + + case $whichslot in + current) + if [ $current -ge $firstslot ];then + load=$current + else + load=$used + fi + + movetape + ;; + next|advance) + [ $used -lt $firstslot ] && used=$current + + load=`expr $used + 1` + [ $load -gt $lastslot ] && load=$firstslot + + if [ $whichslot = advance ];then + echo $load > $currentslot + code=0 + answer=`_ 'advancing to slot %s' "$load"` + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + echo $load $code + exit $code + else + movetape + fi + ;; + prev) + [ $used -lt $firstslot ] && used=$current + + load=`expr $used - 1` + [ $load -lt $firstslot ] && load=$lastslot + movetape + ;; + first) + load=$firstslot + movetape + ;; + last) + load=$lastslot + movetape + ;; + [$firstslot-$lastslot]) + load=$1 + movetape + ;; + clean) + if [ use_cleaning -eq 1 ];then + current=$cleanslot + eject + $MCUTIL slot:$cleanslot drive + sleep $cleansleep + echo "$curday,$curyear" > $lastfile + echo `expr $cleaned + 1` > $cleanfile + reset + else + code=1 + answer=`_ "Cleaning not enabled in config"` + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + echo $cleanslot $answer + exit $code + fi + ;; + *) + code=1 + answer=`_ '"%s" invalid menu option' "$whichslot"` + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + echo "$answer" + exit $code + ;; + esac +} + + +# +# sub-function that slot calls to actually eject the tape +# & load in the correct slot cartridge +# +movetape() { + + # If the requested slot is already loaded in the tape drive + if [ $load -eq $used ]; then + code=0 + answer=`_ 'slot %s is already loaded' "$load"` + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + echo $load $tape # For amtape output + exit $code + elif [ $used -ge $firstslot ];then + current=$load + eject + else + echo $load $tape # For amtape output + fi + + echo `_ 'Loading slot %s into Tape drive' "$load"` >> $logfile + $MCUTIL -m slot:$load drive + code=$? + + if [ $code -eq 0 ];then + echo $load > $currentslot + answer=`_ 'Cartridge %s successfully loaded in Tape drive' "$load"` + else + answer=`_ 'Cartridge %s failed to load in Tape drive' "$load"` + fi + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + exit $code +} + + +info() { + echo `_ 'tape drive info was called'` >> $logfile + + readstatus + + if [ $used -lt 0 ];then + used=0 + fi + + code=0 + answer="$used $lastslot 1" + echo `_ 'Exit(%s): %s' "$code" "$answer"` >> $logfile + echo "$answer" + exit $code +} + + + case $1 in + -slot) + shift + loadslot $* + ;; + -device) + echo $tape + ;; + -info) + shift + info + ;; + -reset) + shift + reset + ;; + -eject) + shift + eject + ;; + --help|-help) + echo `_ '-slot {current|next|previous|first|last|%s-%s|clean}' "$firstslot" "$lastslot"` + echo `_ ' current - show contents of current slot'` + echo `_ ' next - load tape from next slot'` + echo `_ ' previous - load tape from previous slot'` + echo `_ ' first - load tape from first slot'` + echo `_ ' last - load tape from last slot'` + echo `_ ' %s - %s - load tape from slot ' "$firstslot" "$lastslot"` + echo `_ ' clean - Clean the drive'` + echo `_ '-device : Show current tape device'` + echo `_ '-reset : Reset changer to known state'` + echo `_ '-eject : Eject current tape from drive'` + echo `_ '-info : Output {current slot | # of slots | can changer go backwards}'` + echo `_ '-help : Display this help'` + ;; + *) + echo `_ " %s -{slot|device|reset|eject|help}" "$myname"` + ;; + esac diff --git a/changer-src/chg-mtx.sh b/changer-src/chg-mtx.sh new file mode 100644 index 0000000..173f20e --- /dev/null +++ b/changer-src/chg-mtx.sh @@ -0,0 +1,273 @@ +#!@SHELL@ +# +# Exit Status: +# 0 Alles Ok +# 1 Illegal Request +# 2 Fatal Error +# + +# source utility functions and values from configure +prefix=@prefix@ +exec_prefix=@exec_prefix@ +amlibexecdir=@amlibexecdir@ +. ${amlibexecdir}/chg-lib.sh + +if [ -d "@AMANDA_DBGDIR@" ]; then + logfile=@AMANDA_DBGDIR@/changer.debug +else + logfile=/dev/null +fi + +myname=$0 + +tape=`amgetconf tapedev` +if [ -z "$tape" ]; then + echo " tapedev not specified in amanda.conf"; + exit 2; +fi + +TAPE=`amgetconf changerdev`; export TAPE # for mtx command +if [ -z "$TAPE" ]; then + echo " changerdev not specified in amanda.conf"; + exit 2; +fi + +if [ "$tape" = "/dev/null" -o "$TAPE" = "/dev/null" ]; then + echo " Both tapedev and changerdev must be specified in config file"; + exit 2; +fi + +MTX=@MTX@ + +if [ -x $sbindir/ammt$SUF ]; then + MT=$sbindir/ammt$SUF + MTF=-f +elif [ -x "@MT@" ]; then + MT=@MT@ + MTF=@MT_FILE_FLAG@ +else + answer=" $myname: mt program not found" + code=1 + echo "Exit -> $answer" >> $logfile + echo "$answer" + exit $code +fi +echo MT "->" $MT $MTF >> $logfile + +if [ -x $sbindir/amdd$SUF ]; then + DD=$sbindir/amdd$SUF +elif [ -x "@DD@" ]; then + DD=@DD@ +else + answer=" $myname: dd program not found" + code=1 + echo "Exit -> $answer" >> $logfile + echo "$answer" + exit $code +fi +echo DD "->" $DD >> $logfile + +firstslot=1 +lastslot=5 +# counted from 1 !!! +cleanslot=6 + +changerfile=`amgetconf changerfile` + +cleanfile=$changerfile-clean +accessfile=$changerfile-access +[ ! -f $cleanfile ] && echo 0 > $cleanfile +[ ! -f $accessfile ] && echo 0 > $accessfile +cleancount=`cat $cleanfile` +accesscount=`cat $accessfile` +# + +readstatus() { + used=`$MTX -s | + sed -n 's/Drive: No tape Loaded/-1/p;s/Drive: tape \(.\) loaded/\1/p'` + + if [ -z "$used" ]; then + used="-1"; + fi +} + + +eject() { + readstatus + if [ $used -gt 0 ];then + $MTX -u $used + answer="0 $tape" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + else + answer=`_ ' %s: Drive was not loaded' "$myname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi +} + +reset() { + readstatus + if [ $used -gt 0 ];then + $MTX -u $used + fi + res=`$MTX -l 1` + if [ $? -eq 0 ];then + answer="1 $tape" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + else + answer="1 $res" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi +} +# +# +loadslot() { + readstatus + echo " -> loaded $used" >> $logfile + whichslot=$1 + case $whichslot in + current) + if [ $used -lt 0 ];then + $MTX -l 1 + used=1 + fi + answer="$used $tape" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + ;; + next|advance) + load=`expr $used + 1` + [ $load -gt $lastslot ] && load=$firstslot + ;; + prev) + load=`expr $used - 1` + [ $load -lt $firstslot ] && load=$lastslot + ;; + first) + load=$firstslot + ;; + last) + load=$lastslot + ;; + [$firstslot-$lastslot]) + load=$1 + ;; + clean) + load=$cleanslot + ;; + *) + answer=`_ ' %s: illegal request: "%s"' "$myname" "$whichslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + ;; + esac + + if [ $load = $used ]; then + answer="$used $tape" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + fi + + if [ $load = $cleanslot ]; then + expr $cleancount + 1 > $cleanfile + echo 0 > $accessfile + else + expr $accesscount + 1 > $accessfile + if [ $accesscount -gt 9 ]; then + $myname -slot clean >/dev/null + fi + fi + + # Slot 6 might contain an ordinary tape rather than a cleaning + # tape. A cleaning tape auto-ejects; an ordinary tape does not. + # We therefore have to read the status again to check what + # actually happened. + readstatus + + + if [ $used -gt 0 ];then + echo " -> unload $used" >> $logfile + res=`$MTX -u $used` + status=$? + echo " -> status $status" >> $logfile + echo " -> res $res" >> $logfile + if [ $status -ne 0 ];then + answer=`_ ' %s: %s' "$myname" "$res"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + fi + if [ $whichslot = advance ];then + answer="$load /dev/null" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + fi + echo `_ ' -> load %s' "$load"` >> $logfile + res=`$MTX -l $load` + status=$? + echo `_ ' -> status %s' "$status"` >> $logfile + echo `_ ' -> result %s' "$res"` >> $logfile + if [ $status -eq 0 ];then + amdevcheck_status $tape + answer="$load $tape" + code=0 + else + answer="$load $res" + code=2 + fi + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit $code +} +# +info() { + readstatus + echo " -> info $used" >> $logfile + if [ $used -lt 0 ];then + used=0 + fi + answer="$used $lastslot 1" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 +} +# +echo Args "->" "$@" >> $logfile +while [ $# -ge 1 ];do + case $1 in + -slot) + shift + loadslot $* + ;; + -info) + shift + info + ;; + -reset) + shift + reset + ;; + -eject) + shift + eject + ;; + *) + answer=`_ ' %s: Unknown option %s' "$myname" "$1"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + ;; + esac +done diff --git a/changer-src/chg-multi.sh b/changer-src/chg-multi.sh new file mode 100644 index 0000000..ddb5301 --- /dev/null +++ b/changer-src/chg-multi.sh @@ -0,0 +1,421 @@ +#! @SHELL@ +# +# Amanda, The Advanced Maryland Automatic Network Disk Archiver +# Copyright (c) 1991-1999 University of Maryland at College Park +# All Rights Reserved. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of U.M. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. U.M. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Author: James da Silva, Systems Design and Analysis Group +# Computer Science Department +# University of Maryland at College Park +# + +# +# chg-multi.sh - generic tape changer script +# + +# source utility functions and values from configure +prefix=@prefix@ +exec_prefix=@exec_prefix@ +amlibexecdir=@amlibexecdir@ +. ${amlibexecdir}/chg-lib.sh + +pname="chg-multi" + +if [ -d "@AMANDA_DBGDIR@" ]; then + logfile=@AMANDA_DBGDIR@/changer.debug +else + logfile=/dev/null +fi + +echo `_ "arguments ->"` "$@" >> $logfile + +ourconf=`amgetconf changerfile` + +if ! error=try_find_mt; then + echo $error + exit 2 +fi + +EXPR=expr +# EXPR=/usr/local/bin/expr # in case you need a more powerful expr... + +# read in some config parameters + +if [ ! -f "$ourconf" ]; then + answer=`_ ' %s: %s does not exist' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +firstslot=`awk '$1 == "firstslot" {print $2}' $ourconf 2>/dev/null` +if [ -z "$firstslot" ]; then + answer=`_ ' %s: firstslot not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +lastslot=`awk '$1 == "lastslot" {print $2}' $ourconf 2>/dev/null` +if [ -z "$lastslot" ]; then + answer=`_ ' %s: lastslot not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +nslots=`$EXPR $lastslot - $firstslot + 1` + +gravity=`awk '$1 == "gravity" {print $2}' $ourconf 2>/dev/null` +if [ -z "$gravity" ]; then + answer=`_ ' %s: gravity not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +needeject=`awk '$1 == "needeject" {print $2}' $ourconf 2>/dev/null` +if [ -z "$needeject" ]; then + answer=`_ ' %s: needeject not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +multieject=`awk '$1 == "multieject" {print $2}' $ourconf 2>/dev/null` +if [ -z "$multieject" ]; then + echo `_ 'Note: setting multieject to a default of zero'` >> $logfile + multieject=0 +fi + +ejectdelay=`awk '$1 == "ejectdelay" {print $2}' $ourconf 2>/dev/null` +if [ -z "$ejectdelay" ]; then + echo `_ 'Note: setting ejectdelay to a default of zero'` >> $logfile + ejectdelay=0 +fi + +posteject=`awk '$1 == "posteject" {print $2}' $ourconf 2>/dev/null` +if [ -z "$posteject" ]; then + echo `_ 'Note: setting posteject to a default of "true"'` >> $logfile + posteject=true +fi + +ourstate=`awk '$1 == "statefile" {print $2}' $ourconf 2>/dev/null` +if [ -z "$ourstate" ]; then + answer=`_ ' %s: statefile not specified in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +# needeject and multieject are incompatible +if [ $needeject -eq 1 ] && [ $multieject -eq 1 ] ; then + answer=`_ ' %s: needeject and multieject cannot be both enabled in %s' "$pname" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + +# read in state: only curslot and curloaded at the present time + +curslot=`awk '$1 == "curslot" {print $2}' $ourstate 2>/dev/null` +if [ -z "$curslot" ]; then + curslot=$firstslot +fi + +curloaded=`awk '$1 == "curloaded" {print $2}' $ourstate 2>/dev/null` +if [ -z "$curloaded" ]; then + curloaded=0 +fi + + +# process the command-line + +# control vars to avoid code duplication: not all shells have functions! +usage=0 +checkgravity=0 +ejectslot=0 +loadslot=0 +slotempty=0 +ejectonly=0 + +if [ $# -ge 1 ]; then command=$1; else command="-usage"; fi + +case "$command" in + +-info) # return basic information about changer + + backwards=`$EXPR 1 - $gravity` + answer="$curslot $nslots $backwards" + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 0 + ;; + +-reset) # reset changer. Actually, we only reset changer state. We + # trust that the operator has reloaded a stack and reset the + # hardware. In most cases, we do not want to actually do + # anything: if the operator has done something with the + # hardware, we have no way to know what the actual current + # slot is. If the hardware state has not changed, and what is + # really wanted is to load the first slot, use "slot first" + # instead + + checkgravity=0 + loadslot=1 + newslot=$firstslot + curslot=$firstslot + # XXX put changer-specific reset here, if applicable + ;; + +-eject) # eject tape if loaded. Note that if multieject is set, this + # only can make sense if the position is last and gravity 1 + + checkgravity=0 + loadslot=0 + newslot=$curslot + ejectslot=1 + ejectonly=1 + if [ $multieject -eq 1 ] && \ + ([ $gravity -eq 0 ] || [ $curslot -ne $lastslot ]) ; then + # Can't do this: if we eject, the stacker is going to + # load the next tape, and our state will be botched + answer=`_ '%s %s: Cannot use -eject with multieject/nogravity/notlastslot' "$curslot" "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi + if [ $curloaded -eq 0 ]; then + answer=`_ '%s %s: slot already empty' "$curslot" "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi + ;; + +-slot) # change to slot + + checkgravity=1 + loadslot=1 + + slotparm=$2 + case "$slotparm" in + [0-9]*) + newslot=$slotparm + if [ $newslot -gt $lastslot ] || \ + [ $newslot -lt $firstslot ] ; then + answer=`_ '%s %s: no slot %s: legal range is %s ... %s' "$newslot" "$pname" "$newslot" "$firstslot" "$lastslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi + ;; + current) + newslot=$curslot + ;; + first) + newslot=$firstslot + ;; + last) + newslot=$lastslot + ;; + next|advance) + newslot=`$EXPR $curslot + 1` + if [ $newslot -gt $lastslot ]; then + newslot=$firstslot + fi + if [ $slotparm = advance ]; then + loadslot=0 + fi + ;; + prev) + newslot=`$EXPR $curslot - 1` + if [ $newslot -lt $firstslot ]; then + newslot=$lastslot + fi + ;; + *) + answer=`_ ' %s: bad slot name "%s"' "$pname" "$slotparm"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + ;; + esac + ;; +*) + usage=1 + ;; +esac + + +if [ $usage -eq 1 ]; then + answer=`_ ' usage: %s {-reset | -slot [|current|next|prev|advance] | -info | -eject}' "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 +fi + + +# check for legal move + +if [ $checkgravity -eq 1 ] && [ $gravity -ne 0 ] ; then + if [ $newslot -lt $curslot ] || [ "$slotparm" = "prev" ] ; then + answer=`_ '%s %s: cannot go backwards in gravity stacker' "$newslot" "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 + fi +fi + +# Do the 'mt offline' style of stacker control if applicable +if [ $multieject -eq 1 ] && [ $loadslot -eq 1 ] && [ $newslot -ne $curslot ] +then + # XXX put changer-specific load command here, if applicable + + curloaded=0 # unless something goes wrong + slotempty=0 + + while [ $curslot -ne $newslot ]; do + device=`awk '$1 == "slot" && $2 == '$curslot' {print $3}' $ourconf 2>/dev/null` + if [ "$device" = "" ]; then + answer=`_ '%s %s: slot %s device not specified in %s' "$curslot" "$pname" "$curslot" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + echo `_ ' -> offline'` "$device" >> $logfile + if ! try_eject_device $device; then + answer=`_ '%s %s: %s: unable to change to slot %s' "$newslot" "$pname" "$device" "$curslot"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + [ $ejectdelay -gt 0 ] && sleep $ejectdelay + echo `_ ' -> running'` $posteject $device >> $logfile + $posteject $device >> $logfile 2>&1 + status=$? + if [ $status -ne 0 ]; then + answer=`_ '%s %s: %s %s failed: %s' "$newslot" "$pname" "$posteject" "$device" "$status"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + curslot=`$EXPR $curslot + 1` + if [ $curslot -gt $lastslot ] ; then + curslot=$firstslot + fi + done +fi + +if [ $ejectonly -eq 1 ] \ + || ([ $needeject -eq 1 ] \ + && [ $loadslot -eq 1 ] \ + && [ $curloaded -eq 1 ] \ + && [ $newslot -ne $curslot ]) +then + # XXX put changer-specific load command here, if applicable + + curloaded=0 # unless something goes wrong + slotempty=0 + + # try to unload the current device + device=`awk '$1 == "slot" && $2 == '$curslot' {print $3}' $ourconf 2>/dev/null` + if [ "$device" = "" ]; then + answer=`_ '%s %s: slot %s device not specified in %s' "$curslot" "$pname" "$curslot" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + echo `_ ' -> offline'` $device >> $logfile + try_eject_device $device + if [ $? -ne 0 ]; then + # + # XXX if the changer-specific eject command can distinguish + # betweeen "slot empty" and more serious errors, return 1 + # for the first case, 2 for the second case. Generically, + # we just presume an error signifies an empty slot. + # + slotempty=1 + else + [ $ejectonly -eq 0 ] && [ $ejectdelay -gt 0 ] && sleep $ejectdelay + echo `_ ' -> running '` $posteject $device >> $logfile + $posteject $device >> $logfile 2>&1 + status=$? + if [ $status -ne 0 ]; then + answer=`_ '%s %s: %s %s failed: %s' "$newslot" "$pname" "$posteject" "$device" "$status"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + fi +fi + +if [ $loadslot -eq 1 ]; then # load the tape from the slot + + # XXX put changer-specific load command here, if applicable + + curloaded=1 # unless something goes wrong + slotempty=0 + curslot=$newslot + + # try to rewind the device + device=`awk '$1 == "slot" && $2 == '$curslot' {print $3}' $ourconf 2>/dev/null` + if [ "$device" = "" ]; then + answer=`_ '%s %s: slot %s device not specified in %s' "$curslot" "$pname" "$curslot" "$ourconf"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 2 + fi + amdevcheck_status $device + if [ $? -ne 0 ]; then + # + # XXX if the changer-specific load command can distinguish + # betweeen "slot empty" and more serious errors, return 1 + # for the first case, 2 for the second case. Generically, + # we just presume an error signifies an empty slot. + # + slotempty=1 + curloaded=0 + fi +fi + +# update state + +echo `_ '# multi-changer state cache: DO NOT EDIT!'` > $ourstate +echo curslot $newslot >> $ourstate +echo curloaded $curloaded >> $ourstate + +# return slot info + +if [ $slotempty -eq 1 ]; then + answer=`_ '%s %s: slot is empty' "$newslot" "$pname"` + echo `_ 'Exit ->'` $answer >> $logfile + echo $answer + exit 1 +fi + +if [ "$command" = -slot -a "$slotparm" = advance ]; then + device=/dev/null +fi + +answer="$newslot $device" +echo `_ 'Exit ->'` $answer >> $logfile +echo $answer +exit 0 diff --git a/changer-src/chg-null.sh b/changer-src/chg-null.sh new file mode 100644 index 0000000..04ebb47 --- /dev/null +++ b/changer-src/chg-null.sh @@ -0,0 +1,101 @@ +#!@SHELL@ +# +# Exit Status: +# 0 Alles Ok +# 1 Illegal Request +# 2 Fatal Error +# + +# try to hit all the possibilities here +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +debugdir=@AMANDA_DBGDIR@ + +# add sbin and ucb dirs +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb" +export PATH + +if [ -d "$debugdir" ] +then + logfile=$debugdir/changer.debug +else + logfile=/dev/null +fi +exec 2> $logfile +set -x + +USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" +if test "$USE_VERSION_SUFFIXES" = "yes"; then + SUF="-@VERSION@" +else + SUF= +fi + +myname=$0 + +EGREP='@EGREP@' + +firstslot=1 +totalslots=200 + +changerfile=`amgetconf$SUF changerfile` + +tapedev=`amgetconf$SUF tapedev` + +cleanfile=$changerfile-clean +accessfile=$changerfile-access +slotfile=$changerfile-slot +[ ! -f $cleanfile ] && echo 0 > $cleanfile +[ ! -f $accessfile ] && echo 0 > $accessfile +[ ! -f $slotfile ] && echo $firstslot > $slotfile +cleancount=`cat $cleanfile` +accesscount=`cat $accessfile` +slot=`cat $slotfile` + +rc=0 + +case x$1 in + +x-slot) + + # + # handle special slots... + # + case "$2" in + current) newslot=$slot ; load=true;; + next) newslot=`expr $slot + 1`; load=true;; + advance) newslot=`expr $slot + 1`; load=false;; + prev) newslot=`expr $slot - 1`; load=true;; + first) newslot=0 ; load=true;; + last) newslot=-1 ; load=true;; + *) newslot=$2 ; load=true;; + esac + + if [ 0 -gt $newslot ] + then + newslot=`expr $totalslots - 1` + fi + + if [ $totalslots -le $newslot ] + then + newslot=0 + fi + echo $newslot > $changerfile-slot + slot=$newslot + echo $slot $tapedev + ;; + +x-info) + echo $slot $totalslots 1 + ;; + +x-eject) + echo $slot $tapedev + ;; +esac + +exit $rc diff --git a/changer-src/chg-rait.sh b/changer-src/chg-rait.sh new file mode 100644 index 0000000..757661f --- /dev/null +++ b/changer-src/chg-rait.sh @@ -0,0 +1,217 @@ +#!@SHELL@ + +# chg-rait +# +# This assumes we have rait-striped drives in several +# other amanda changer configs. +# +# so we have a changerfile that lists other changers and +# changer files. +# nchangers=3 +# tpchanger_1="chg-mtx" +# changerdev_1="/dev/mtx1" +# changerfile_1="/some/file1" +# tapedev_1="/some/dev" +# tpchanger_2="chg-mtx" +# changerdev_2="/dev/mtx2" +# changerfile_2="/some/file2" +# tapedev_2="/some/dev" +# tpchanger_3="chg-mtx" +# changerdev_3="/dev/mtx3" +# changerfile_3="/some/file3" +# tapedev_3="/some/dev" +# +# the tapedev_n entries are only needed if the changer script in question +# uses tapedev. +# + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +# add sbin and ucb dirs +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb" +export PATH + +# +# debugging... +# +if [ -d "@AMANDA_DBGDIR@" ]; then + DBGFILE=@AMANDA_DBGDIR@/rait-changer.debug + KIDDEBUG=@AMANDA_DBGDIR@/changer.debug + WORK=@AMANDA_DBGDIR@/chgwork$$ +else + DBGFILE=/dev/null + KIDDEBUG=/dev/null + WORK=/tmp/chgwork$$ +fi + +exec 2>$DBGFILE +echo `_ "arguments: "` $0 $* >&2 +set -x + +USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" +if test "$USE_VERSION_SUFFIXES" = "yes"; then + SUF="-@VERSION@"; +else + SUF= +fi +getconf=$sbindir/amgetconf$SUF + + +changerfile=`$getconf changerfile` +. $changerfile + +# +# get config items that other changers use to put in our +# fake amanda.conf files. +# +org=`$getconf ORG` +mailto=`$getconf mailto` + +# +# make a working directory (with amanda.conf) for each changer, and start the +# changer script in background for each one +# + +i=1 +while [ $i -le $nchangers ] +do + eval tpchanger=\$tpchanger_$i + eval changerdev=\$changerdev_$i + eval changerfile=\$changerfile_$i + eval tapedev=\$tapedev_$i + + mkdir -p $WORK/$i + cd $WORK/$i + + cat >> amanda.conf < exitcode + ) > stdout 2>stderr & + + i=`expr $i + 1` +done + +wait + +# +# once they've all finished, collect up the results +# + +myexit=0 +myslot=-1 +mymax=65536 +myflag=1 +mydev="" +mysep="{" + +case x$1 in +x-slot|x-reset|x-eject|x-search|x-label) + + # + # read slot number and device from each + # slot numbers must match(?!), and is our resulting slot number + # resulting device is {dev1,dev2,...} from each one + # + i=1 + while [ $i -le $nchangers ] + do + read exitcode < $WORK/$i/exitcode + read n dev < $WORK/$i/stdout + echo -------------- >&2 + cat $WORK/$i/stderr >&2 + cat $KIDDEBUG >&2 + echo -------------- >&2 + + if [ "$exitcode" != 0 ] + then + myexit=$exitcode + fi + if [ $myslot = -1 ] + then + myslot=$n + fi + if [ $n != $myslot ] + then + # synch error! + myexit=1 + echo `_ 'stackers are out of synch, issue a reset'` >&2 + fi + mydev="$mydev$mysep$dev" + mysep="," + + i=`expr $i + 1` + done + mydev="rait:$mydev}" + echo $myslot $mydev + ;; +x-info) + # + # read info from each + # slot numbers must match(?!), and is our resulting slot number + # minimum max slots is our resulting max slots + # if any can't go backwards, the aggregate can't either + # + i=1 + while [ $i -le $nchangers ] + do + read exitcode < $WORK/$i/exitcode + read n max flag < $WORK/$i/stdout + echo -------------- >&2 + cat $WORK/$i/stderr >&2 + cat $KIDDEBUG >&2 + echo -------------- >&2 + + if [ "$exitcode" != 0 ] + then + myexit=$exitcode + fi + if [ $myslot = -1 ] + then + myslot=$n + fi + if [ $n != $myslot ] + then + # synch error! + myexit=1 + echo `_ 'stackers are out of synch, issue a -reset'` >&2 + fi + if [ $max -lt $mymax ] + then + mymax=$max + fi + if [ $flag = 0 ] + then + myflag=0 + fi + i=`expr $i + 1` + done + echo $myslot $mymax $myflag + +esac + +# +# clean up work directories +# +rm -rf $WORK + +exit $myexit diff --git a/changer-src/chg-rth.pl b/changer-src/chg-rth.pl new file mode 100644 index 0000000..9f75559 --- /dev/null +++ b/changer-src/chg-rth.pl @@ -0,0 +1,307 @@ +#!@PERL@ + +# Catch for sh/csh on systems without #! ability. +eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}' + & eval 'exec @PERL@ -S $0 $argv:q' + if 0; + +# rth-changer - +# A tape changer script for the Robotic Tape Handling system OEM'd +# by Andataco (RTH-406) for use with Amanda, the Advanced Maryland +# Network Disk Archiver. +# +# Author: Erik Frederick 1/10/97 +# edf@tyrell.mc.duke.edu +# +# This changer script controls the HP c1553 tape drive via a +# Peripheral Vision Inc. SCSI control subsystem that interprets +# commands sent on the SCSI bus. It may work with other tape drives +# containing the PVI board. +# +# Permission to freely use and distribute is granted. +# + +require 5.001; + +use Getopt::Long; + +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'}; +$ENV{'PATH'} = "/usr/bin:/usr/sbin:/sbin:/bin"; + +$pname = "rth-changer"; + +$prefix="@prefix@"; +$prefix=$prefix; # avoid warnings about possible typo +$exec_prefix="@exec_prefix@"; +$exec_prefix=$exec_prefix; # ditto +$sbindir="@sbindir@"; +$amlibexecdir="@amlibexecdir@"; +if ("@USE_VERSION_SUFFIXES@" eq "yes") { + $suf = "-@VERSION@"; +} else { + $suf = ""; +} + +if (-x "$sbindir/ammt$SUF") { + $MT="$sbindir/ammt$SUF"; + $MTF="-f"; +} elsif (-x "@MT@") { + $MT="@MT@"; + $MTF="@MT_FILE_FLAG@"; +} else { + print " $pname: mt program not found\n"; + exit(1); +} + +$tapeDevice=`$sbindir/amgetconf$SUF tapedev`; +die "tapedev not found in amanda.conf" + if !$tapeDevice or $tapeDevice eq "" or + $tapeDevice =~ m/no such parameter/; + +sub getCurrentTape { + + if (!sysopen(RTH, $tapeDevice, 2)) { + print "$currentTape $pname: error in opening `$tapeDevice' for getting current tape: $!\n"; + exit(2); + } + if (syswrite(RTH, "Rd_ElS", 6) != 6) { + print "$currentTape $pname: error in writing `Rd_ElS' to `$tapeDevice': $!\n"; + exit(2); + } + if (!close(RTH)) { + print "$currentTape $pname: error in closing `$tapeDevice' for getting current tape: $!\n"; + exit(2); + } + + if (!sysopen(RTH, $tapeDevice, 2)) { + print "$currentTape $pname: error in opening `$tapeDevice' for getting current tape: $!\n"; + exit(2); + } + if (sysread(RTH, $status, 136) != 136) { + print "$currentTape $pname: error in reading rth status.\n"; + exit(2); + } + if (!close(RTH)) { + print "$currentTape $pname: error in closing `$tapeDevice' for getting current tape: $!\n"; + exit(2); + } + + @statusBits=unpack("c*",$status); + + if( ($statusBits[18] == 0x1) || ($statusBits[18]== 0x9)) { + return ($statusBits[27]-1); + } + + return (0); +} + + +sub getTapeStatus { + + if (!sysopen(RTH, $tapeDevice, 2)) { + print "$currentTape $pname: error in opening `$tapeDevice' for getting tape status: $!\n"; + exit(2); + } + if (syswrite(RTH, "Rd_ElS", 6) != 6) { + print "$currentTape $pname: error in writing `Rd_ElS' to `$tapeDevice': $!\n"; + exit(2); + } + if (!close(RTH)) { + print "$currentTape $pname: error in closing `$tapeDevice' for getting tpae status: $!\n"; + exit(2); + } + + if (!sysopen(RTH, $tapeDevice, 2)) { + print "$currentTape $pname: error in opening `$tapeDevice' for getting tape status: $!\n"; + exit(2); + } + if (sysread(RTH, $status, 136) != 136) { + print "$currentTape $pname: error in reading rth status for tape $currentTape.\n"; + exit(2); + } + if (!close(RTH)) { + print "$currentTape $pname: error in closing `$tapeDevice' for getting tape status: $!\n"; + exit(2); + } + + @statusBits=unpack("c*",$status); + + $curTape=0; + for($i=42;$i<187;$i+=16) { + if($statusBits[$i] == 0x9) { + $slots[$curTape] = 1; + } + else { + $slots[$curTape] = 0; + } + $curTape++; + } + + return (@slots); +} + +sub rthLoad { + my($tape) = @_; + + $command = sprintf "GeT%d", $tape; + if (!sysopen(RTH, $tapeDevice, 2)) { + print "$currentTape $pname: error in opening `$tapeDevice' for loading tape: $!\n"; + exit(2); + } + if (syswrite(RTH, $command, 4) != 4) { + print "$currentTape $pname: error in loading tape by writing `$command' to `$tapeDevice': $!\n"; + exit(2); + } + if (!close (RTH)) { + print "$currentTape $pname: error in closing `$tapeDevice' when trying to load tape: $!\n"; + exit(2); + } +} + +sub rthUnload { + my($tape) = @_; + + $command = sprintf "PuT%d", $tape; + if (!sysopen(RTH, $tapeDevice, 2)) { + print "$currentTape $pname: error in opening `$tapeDevice' for unloading tape: $!\n"; + exit(2); + } + if (syswrite(RTH, $command, 4) != 4) { + print "$currentTape $pname: error in unloading tape by writing `$command' to `$tapeDevice': $!\n"; + exit(2); + } + if (!close (RTH)) { + print "$currentTape $pname: error in closing `$tapeDevice' when trying to unload tape: $!\n"; + exit(2); + } +} + +sub testTape { + my($tape) = @_; + + @slots=getTapeStatus(); + + if($currentTape == $tape) { + return; + } + + if($slots[$tape-1] == 0) { + print " $pname: no tape in slot requested\n"; + exit(1); + } + if($tape>6) { + print $tape," $pname: requested a tape > 6\n"; + exit(2); + } + if($tape<1) { + print $tape," $pname: requested a tape < 1\n"; + exit(2); + } + return; +} + +sub changeTape { + my($tape) = @_; + + if($tape==$currentTape) { + return; + } + + testTape($tape); + + if($currentTape==0) { + rthLoad($tape); + $currentTape=$tape; + return; + } + else { + rthUnload($currentTape); + rthLoad($tape); + $currentTape=$tape; + } +} + + +$result = &GetOptions("slot=s", "info", "reset", "eject"); + +system($MT, 'rewind'); + +$nSlots=6; +$firstTape=1; +$lastTape=6; +$currentTape=getCurrentTape(); + +if($opt_slot) { + if($opt_slot =~ /first/) { + changeTape(1); + print $currentTape, " ", $tapeDevice, "\n"; + } + if($opt_slot =~ /last/) { + changeTape(6); + print $currentTape, " ", $tapeDevice, "\n"; + } + if($opt_slot =~ /current/) { + changeTape($currentTape); + print $currentTape, " ", $tapeDevice, "\n"; + } + if($opt_slot =~ /next/) { + $tape=$currentTape+1; + if ($tape>6) { + $tape=1; + } + changeTape($tape); + print $currentTape, " ", $tapeDevice,"\n"; + } + if($opt_slot =~ /prev/) { + $tape=$currentTape-1; + if($tape<1) { + $tape=6; + } + changeTape($tape); + print $currentTape, " ", $tapeDevice,"\n"; + } + if($opt_slot =~ /\d/) { + changeTape($opt_slot); + print $currentTape, " ", $tapeDevice,"\n"; + } + if($opt_slot =~ /advance/) { + $tape=$currentTape+1; + if ($tape>6) { + $tape=1; + } + if($currentTape) { + rthUnload($currentTape); + } + print $currentTape, " ", "/dev/null","\n"; + } + + exit 0; +} + +if($opt_info) { + + print $currentTape, " 6 1\n"; + + exit 0; +} + +if($opt_reset) { + changeTape(1); + print $currentTape, " ",$tapeDevice,"\n"; + exit 0; +} + +if($opt_eject) { + if($currentTape) { + rthUnload($currentTape); + print "0 ",$tapeDevice,"\n"; + exit 0; + } + else { + print "0 $pname: drive was not loaded\n"; + exit 1; + } +} + +print "$pname: No command was received. Exiting.\n"; +exit 1; diff --git a/changer-src/chg-zd-mtx.sh b/changer-src/chg-zd-mtx.sh new file mode 100644 index 0000000..36236da --- /dev/null +++ b/changer-src/chg-zd-mtx.sh @@ -0,0 +1,1379 @@ +#!@SHELL@ +# +# Exit Status: +# 0 Alles Ok +# 1 Illegal Request +# 2 Fatal Error +# +# Contributed by Eric DOUTRELEAU +# This is supposed to work with Zubkoff/Dandelion version of mtx +# +# Modified by Joe Rhett +# to work with MTX 1.2.9 by Eric Lee Green http://mtx.sourceforge.net +# +# Modified by Jason Hollinden on 13-Feb-2001 +# to work with MTX 1.2.10, >9 slots, has barcode support, and works with +# multiple configs at once. +# NOTE: Only tested the 2 additions with an ADIC Scalar 100. + +################################################################################ +# Here are the things you need to do and know to configure this script: +# +# * Figure out what the robot device name is and what the tape drive +# device name is. They will be different! +# +# You cannot send robot commands to a tape drive and vice versa. +# Both should respond to "mtx -f /dev/... inquiry". Hopefully, +# that output will make it obvious which is which. +# +# For instance, here is what mtx has to say about my current robot: +# +# Product Type: Medium Changer +# Vendor ID: 'ATL ' +# Product ID: 'ACL2640 206 ' +# Revision: '2A5A' +# Attached Changer: No +# +# and here is what it says about a tape drive: +# +# Product Type: Tape Drive +# Vendor ID: 'Quantum ' +# Product ID: 'DLT4000 ' +# Revision: 'CD50' +# Attached Changer: No +# +# Note the "Product Type" value makes it clear which is which. +# +# If it is not obvious, "mf -f /dev/... rewind" should be happy when +# talking to a (loaded) tape drive but the changer should give some +# kind of error. Similarly, "mtx -f /dev/... status" should show good +# results with the changer but fail with a tape drive device name. +# +# Once you have this figured out, set "changerdev" in amanda.conf +# to the changer device and "tapedev" to the tape device. +# +# * Find out what the first and last storage slots are. Running +# "mtx -f /dev/... status" should give you something like this +# (although the output will vary widely based on the version of mtx +# and the specifics of your robot): +# +# Storage Changer /dev/changer:1 Drives, 9 Slots ( 0 Import/Export ) +# Data Transfer Element 0:Empty +# Storage Element 1:Full :VolumeTag=SR0001 +# Storage Element 2:Full :VolumeTag=SR0002 +# Storage Element 3:Full :VolumeTag=SR0003 +# Storage Element 4:Full :VolumeTag=SR0004 +# Storage Element 5:Full :VolumeTag=SR0005 +# Storage Element 6:Full :VolumeTag=SR0006 +# Storage Element 7:Full :VolumeTag=SR0007 +# Storage Element 8:Full :VolumeTag=SR0008 +# Storage Element 9:Full :VolumeTag=SR0009 +# Storage Element 10 IMPORT/EXPORT:Full :VolumeTag=SR0009 +# +# This says the first storage slot (element) is "1" and the last +# is "9". If you allocate the entire robot to Amanda, you do not need +# to set the "firstslot" or "lastslot" configuration file variables -- +# the script will compute these values for you. +# +# You do not have to allocate all of the slots for Amanda use, +# but whatever slots you use must be contiguous (i.e. 4 through 9 +# in the above would be OK but 1, 2, 5, 6, 9 would not). The one +# exception to this is that if one of the slots contains a cleaning +# cartridge, it may be in any slot (Amanda will just skip over it if +# it is between firstslot and lastslot). +# +# * Speaking of cleaning cartridges, if you have a storage slot dedicated +# to one, figure out what slot it is in. That slot number will go in +# the "cleanslot" variable. +# +# Also, decide if you want the changer script to automatically run +# the cleaning tape through the drive after every so many mounts, +# and how many mounts you want to do between cleanings. If you +# want the script to do this, set the "autoclean" variable to 1 and +# the "autocleancount" to the number of mounts between cleanings. +# If you do not want to do automatic cleanings (including not having +# a cleaning cartridge in the robot), set "autoclean" to 0. +# +# Note that only a count of mounts is used to determine when it is +# time to clean. The script does not try to detect if the drive is +# requesting cleaning, or how much the drive was used on a given +# mount. +# +# * If you tell Amanda about a cleaning cartridge, whether for automatic +# operation or manual (amtape clean), you must also tell +# the script how long it takes to run the cleaning cycle. It is +# impossible for the script to determine when the cleaning operation +# is done, so the "cleancycle" variable is the number of seconds +# the longest cleaning operation takes (you'll just have to figure +# this out by watching it a few times, or maybe finding it in a tape +# drive hardware manual). The script will sleep for this length of +# time whenever the cleaning tape is referenced. The default is 120 +# seconds (two minutes). +# +# * Figure out the drive slot number. By default, it is set to 0. +# In the example above, the tape drive ("Data Transfer Element") +# is in slot 0. If your drive slot is not 0, you +# need to set the drive slot number with the "driveslot" variable. +# +# * Figure out whether your robot has a barcode reader and whether +# your version of mtx supports it. If you see "VolumeTag" entries +# in the "mtx -f /dev/xxx status" output you did above, you have +# a reader and mtx can work with it, so you may set the "havereader" +# variable to 1. The default is 0 (do not use a reader). +# +# * Pick any tape to load and then determine if the robot can put it +# away directly or whether an "offline" must be done first. +# +# With the tape still mounted and ready, try to put the tape away +# with "mtx". If you get some kind of error, which is the most +# common response, try "mt -f /dev/... offline", wait for the drive +# to unload and make sure the robot takes no action on its own to +# store the tape. Assuming it does not, try the "mtx" command again +# to store the tape. +# +# If you had to issue the "mt -f /dev/... offline" before you could +# use "mtx" to store the tape, set the "offline_before_unload" +# variable to 1. If "mtx" unloaded the drive and put the tape away +# all by itself, set it to 0. +# +# * Some drives and robots require a small delay between unloading the +# tape and instructing the robot to move it back to storage. +# For instance, if you try to grab the tape too soon on an ATL robot +# with DLT tape drives, it will rip the leader out of the drive and +# require sincerely painful hardware maintenance. +# +# If you need a little delay, set the "unloadpause" variable to +# the number of seconds to wait before trying to take a tape from +# a drive back to storage. The default is 0. +# +# * Some drives also require a short pause after loading, or the drive +# will return an I/O error during a test to see if it's online (which +# this script uses "mt rewind" to test). My drives don't recover from +# this, and must be reloaded before they will come online after failing +# such a test. For this reason there is an "initial_poll_delay" +# variable which will pause for a certain number of seconds before +# looping through the online test for the first time. The default is 0. +#### + +#### +# Now you are ready to set up the variables in the changer configuration +# file. +# +# All variables are in "changerfile".conf where "changerfile" is set +# in amanda.conf. For example, if amanda.conf has: +# +# changerfile="/etc/amanda/Dailyset1/CHANGER" +# or changerfile="/etc/amanda/Dailyset1/CHANGER.conf" +# +# the variables must be in "/etc/amanda/Dailyset1/CHANGER.conf". +# The ".conf" is appended only if it's not there". +# +# If "changerfile" is a relative path, it is relative to the directory +# that contains amanda.conf. That also happens to be the directory Amanda +# makes current before running this script. +# +# Here is a commented out example file with all the variables and showing +# their default value (if any): +#### +# firstslot=? #### First storage slot (element) -- required +# lastslot=? #### Last storage slot (element) -- required +# cleanslot=-1 #### Slot with cleaner tape -- default is "-1" +# #### Set negative to indicate no cleaner available +# driveslot=0 #### Drive slot number. Defaults to 0 +# #### Use the 'Data Transfer Element' you want +# +# # Do you want to clean the drive after a certain number of accesses? +# # NOTE - This is unreliable, since 'accesses' aren't 'uses', and we +# # have no reliable way to count this. A single amcheck could +# # generate as many accesses as slots you have, plus 1. +# # ALSO NOTE - many modern tape loaders handle this automatically. +# +# autoclean=0 #### Set to '1' or greater to enable +# +# autocleancount=99 #### Number of access before a clean. +# +# cleancycle=120 #### Time (seconds) to clean drive (default 120) +# +# havereader=0 #### If you have a barcode reader, set to 1. +# +# offline_before_unload=0 #### Does your robot require an +# #### 'mt offline' before mtx unload? +# +# poll_drive_ready=NN #### Time (seconds) between tests to see if +# #### the tape drive has gone ready (default: 3). +# +# max_drive_wait=NN #### Maximum time (seconds) to wait for the +# #### tape drive to become ready (default: 120). +# +# initial_poll_delay=NN #### initial delay after load before polling for +# #### readiness +# +#### + +#### +# Now it is time to test the setup. Do all of the following in the +# directory that contains the amanda.conf file, and do all of it as +# the Amanda user. +# +# * Run this: +# +# .../chg-zd-mtx -info +# echo $? #### (or "echo $status" if you use csh/tcsh) +# +# You should get a single line from the script like this (the actual +# numbers will vary): +# +# 5 9 1 1 +# +# The first number (5) is the "current" slot. This may or may not be +# the slot actually loaded at the moment (if any). It is the slot +# Amanda will try to use next. +# +# The second number (9) is the number of slots. +# +# The third number will always be "1" and indicates the changer is +# capable of going backward. +# +# The fourth number is optional. If you set $havereader to 1, it +# will be "1", otherwise it will not be present. +# +# The exit code ($? or $status) should be zero. +# +# * Run this: +# +# .../chg-zd-mtx -reset +# echo $? +# +# The script should output a line like this: +# +# 1 /dev/rmt/0mn +# +# The number at the first should match $firstslot. The device name +# after that should be your tape device. +# +# The exit code ($? or $status) should be zero. +# +# * Run this: +# +# .../chg-zd-mtx -slot next +# echo $? +# +# The script should output a line like this: +# +# 2 /dev/rmt/0mn +# +# The number at the first should be one higher than $firstslot. +# The device name after that should be your tape device. +# +# The exit code ($? or $status) should be zero. +# +# * Run this: +# +# .../chg-zd-mtx -slot current +# echo $? +# +# Assuming the tape is still loaded from the previous test, the +# robot should not move and the script should report the same thing +# the previous command did. +# +# * If you continue to run "-slot next" commands, the robot should load +# each tape in turn then wrap back around to the first when it +# reaches $lasttape. If $cleanslot is within the $firstslot to +# $lastslot range, the script will skip over that entry. +# +# * Finally, try some of the amtape commands and make sure they work: +# +# amtape reset +# amtape slot next +# amtape slot current +# +# * If you set $havereader non-zero, now would be a good time to create +# the initial barcode database: +# +# amtape update +#### + +################################################################################ +# To debug this script, first look in @AMANDA_DBGDIR@. The script +# uses one of two log files there, depending on what version of Amanda +# is calling it. It may be chg-zd-mtx.YYYYMMDD*.debug, or it may be +# changer.debug.driveN where 'N' is the drive number. +# +# If the log file does not help, try running the script, **as the Amanda +# user**, in the amanda.conf directory with whatever set of args the log +# said were used when you had a problem. If nothing else useful shows up +# in the output, try running the script with the DEBUG environment variable +# set non-null, e.g.: +# +# env DEBUG=yes .../chg-zd-mtx ... +################################################################################ + +# source utility functions and values from configure +prefix=@prefix@ +exec_prefix=@exec_prefix@ +amlibexecdir=@amlibexecdir@ +. ${amlibexecdir}/chg-lib.sh + +test -n "$DEBUG" && set -x +TMPDIR="@AMANDA_TMPDIR@" +DBGDIR="@AMANDA_DBGDIR@" + +argv0=$0 +myname=`expr "$argv0" : '.*/\(.*\)'` + +config=`pwd 2>/dev/null` +config=`expr "$config" : '.*/\(.*\)'` + +### +# Functions to write a new log file entry and append more log information. +### + +ds=`date '+%H:%M:%S' 2>/dev/null` +if [ $? -eq 0 -a -n "$ds" ]; then + logprefix=`echo "$ds" | sed 's/./ /g'` +else + logprefix="" +fi + +LogAppend() { + if [ -z "$logprefix" ]; then + echo "$@" >> $DBGFILE + else + echo "$logprefix" "$@" >> $DBGFILE + fi +} + +Log() { + if [ -z "$logprefix" ]; then + echo "===" "`date`" "===" >> $DBGFILE + echo "$@" >> $DBGFILE + else + ds=`date '+%H:%M:%S' 2>/dev/null` + echo "$ds" "$@" >> $DBGFILE + fi +} + +### +# Common exit function. +# +# $1 = exit code +# $2 = slot result +# $3 = additional information (error message, tape devive, etc) +### + +internal_call=0 +Exit() { + if [ $internal_call -gt 0 ]; then + call_type=Return + else + call_type=Exit + fi + code=$1 + shift + exit_slot=$1 + shift + exit_answer="$@" + Log $call_type "($code) -> $exit_slot $@" + echo "$exit_slot" "$@" + if [ $call_type = Return ]; then + return $code + fi + amgetconf dbclose.$argv0:$DBGFILE > /dev/null 2>&1 + exit $code +} + +### +# Function to run another command and log it. +### + +Run() { + Log `_ 'Running: %s' "$*"` + rm -f $stdout $stderr + "$@" > $stdout 2> $stderr + exitcode=$? + Log `_ 'Exit code: %s' "$exitcode"` + if [ -s $stdout ] + then + LogAppend Stdout: + cat $stdout >> $DBGFILE + fi + if [ -s $stderr ] + then + LogAppend Stderr: + cat $stderr >> $DBGFILE + fi + cat $stdout + cat $stderr 1>&2 + return $exitcode +} + +### +# Return success if the arg is numeric. +### + +IsNumeric() { + test -z "$1" && return 1 + x="`expr "$1" : '\([-0-9][0-9]*\)' 2>/dev/null`" + return `expr X"$1" != X"$x"` +} + +### +# Run $MTX status unless the previous output is still valid. +### + +mtx_status_valid=0 +get_mtx_status() { + test -n "$DEBUG" && set -x + if [ $mtx_status_valid -ne 0 ]; then + return 0 + fi + rm -f $mtx_status + Run $MTX status > $mtx_status 2>&1 + status=$? + if [ $status -eq 0 ]; then + mtx_status_valid=1 + fi + return $status +} + +### +# Determine the slot currently loaded. Set $loadedslot to the slot +# currently loaded, or "-1", and $loadedbarcode to the corresponding +# barcode (or nothing). +### + +get_loaded_info() { + test -n "$DEBUG" && set -x + get_mtx_status + + set x `sed -n ' +/^Data Transfer Element:Empty/ { + s/.*/-1/p + q +} +/^Data Transfer Element '$driveslot':Empty/ { + s/.*/-1/p + q +} +/^Data Transfer Element:Full (Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^ ]*\)/ { + s/.*(Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^ ]*\)/\1 \2/p + q +} +/^Data Transfer Element '$driveslot':Full (Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^ ]*\)/ { + s/.*(Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^ ]*\)/\1 \2/p + q +} +/^Data Transfer Element '$driveslot':Full (Unknown Storage Element Loaded):VolumeTag *= *\([^ ]*\)/ { + s/.*:VolumeTag *= *\([^ ]*\)/-2 \1/p + q +} +/^Data Transfer Element:Full (Storage Element \([0-9][0-9]*\) Loaded)/ { + s/.*(Storage Element \([0-9][0-9]*\) Loaded).*/\1/p + q +} +/^Data Transfer Element '$driveslot':Full (Storage Element \([0-9][0-9]*\) Loaded)/ { + s/.*Storage Element \([0-9][0-9]*\) Loaded.*/\1/p + q +} +/^Data Transfer Element '$driveslot':Full (Unknown Storage Element Loaded)/ { + s/.*/-2/p + q +} +' < $mtx_status 2>&1` + shift # get rid of the "x" + loadedslot=$1 + loadedbarcode=$2 + if [ -z "$loadedslot" ]; then + Exit 2 \ + `_ ''` \ + "could not determine current slot, are you sure your drive slot is $driveslot" + return $? # in case we are internal + fi + + #Use the current slot if it's empty and we don't know which slot is loaded' + if [ $loadedslot -eq -2 ]; then + set x `sed -n ' +{ + /^.*Storage Element '$currentslot':Empty/ { + s/.*Storage Element \([0-9][0-9]*\):Empty/\1/p + q + } + /^.*Storage Element '$currentslot':Full/ { + s/.*Storage Element \([0-9][0-9]*\):Full/-2/p + q + } + /^.*Storage Element '$currentslot' IMPORT\/EXPORT:Empty/ { + s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Empty/\1/p + q + } + /^.*Storage Element '$currentslot' IMPORT\/EXPORT:Full/ { + s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Full/-2/p + q + } +} +' < $mtx_status 2>& 1` + shift # get rid of the "x" + loadedslotx=$1 + if [ ! -z $loadedslotx ]; then + loadedslot=$loadedslotx + fi + fi + + #Use the first empty slot if we don't know which slot is loaded' + if [ $loadedslot -eq -2 ]; then + set x `sed -n ' +{ + /^.*Storage Element \([0-9][0-9]*\):Empty/ { + s/.*Storage Element \([0-9][0-9]*\):Empty/\1/p + q + } + /^.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Empty/ { + s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Empty/\1/p + q + } +} +' < $mtx_status 2>& 1` + shift # get rid of the "x" + loadedslot=$1 + fi + + if IsNumeric "$loadedslot" ; then + : + else + Exit 2 \ + `_ ''` \ + "currently loaded slot ($loadedslot) not numeric" + return $? # in case we are internal + fi + Log `_ 'STATUS -> currently loaded slot = %s' "$loadedslot"` + LogAppend `_ ' -> currently loaded barcode = "%s"' "$loadedbarcode"` +} + +### +# Get a list of slots between $firstslot and $lastslot, if they are set. +# If they are not set, set them to the first and last slot seen on the +# assumption the entire robot is to be used (???). +### + +slot_list= +get_slot_list() { + test -n "$DEBUG" && set -x + if [ -n "$slot_list" ]; then + return + fi + get_mtx_status + slot_list=`sed -n ' +/^Data Transfer Element:Full (Storage Element \([0-9][0-9]*\) Loaded)/ { + s/.*(Storage Element \([0-9][0-9]*\) Loaded).*/\1/p +} +/^Data Transfer Element '$driveslot':Full (Storage Element \([0-9][0-9]*\) Loaded)/ { + s/.*Storage Element \([0-9][0-9]*\) Loaded.*/\1/p +} +/^Data Transfer Element '$driveslot':Full (Unknown Storage Element Loaded)/ { + : loop + n + /^.*Storage Element \([0-9][0-9]*\):Full/ { + s/.*Storage Element \([0-9][0-9]*\):Full.*/\1/p + b loop + } + /^.*Storage Element \([0-9][0-9]*\):Empty/ { + s/.*Storage Element \([0-9][0-9]*\):Empty/\1/p + } +} +/^.*Storage Element \([0-9][0-9]*\):Full/ { + s/.*Storage Element \([0-9][0-9]*\):Full.*/\1/p +} +/^.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Full/ { + s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Full.*/\1/p +} +' < $mtx_status 2>&1 | grep -v "^${cleanslot}\$" | sort -n` + slot_list=`echo $slot_list` # remove the newlines + if [ $firstslot -lt 0 -o $lastslot -lt 0 ]; then + last=$lastslot + for slot in $slot_list; do + if [ $firstslot -lt 0 ]; then + Log `_ 'SLOTLIST -> firstslot set to %s' "$slot"` + firstslot=$slot + fi + if [ $lastslot -lt 0 ]; then + last=$slot + fi + done + if [ $lastslot -lt 0 -a $last -ge 0 ]; then + Log `_ 'SLOTLIST -> lastslot set to %s' "$last"` + lastslot=$last + fi + if [ $firstslot -lt 0 ]; then + Exit 2 \ + `_ ''` \ + `_ 'cannot determine first slot'` + return $? # in case we are internal + elif [ $lastslot -lt 0 ]; then + Exit 2 \ + `_ ''` \ + `_ 'cannot determine last slot'` + return $? # in case we are internal + fi + fi + amanda_slot_list= + for slot in $slot_list; do + if [ $slot -ge $firstslot -a $slot -le $lastslot ]; then + amanda_slot_list="$amanda_slot_list $slot" + fi + done + if [ -z "$amanda_slot_list" ]; then + Exit 2 \ + `_ ''` \ + "no slots available" + return $? # in case we are internal + fi + slot_list="$amanda_slot_list" +} + +DBGFILE=`amgetconf dbopen.$argv0 2>/dev/null` +if [ -z "$DBGFILE" ] +then + DBGFILE=/dev/null # will try this again below +fi + +changerfile=`amgetconf changerfile 2>/dev/null` +if [ -z "$changerfile" ]; then + Exit 2 \ + `_ ''` \ + "changerfile must be specified in amanda.conf" +fi + +rawtape=`amgetconf tapedev 2>/dev/null` +if [ -z "$rawtape" ]; then + Exit 2 \ + `_ ''` \ + "tapedev may not be empty" +fi +tape=`tape_device_filename "$rawtape"` +if [ -z "$tape" ]; then + Exit 2 \ + ` _ ''` \ + "tapedev $rawtape is not a tape device." +elif [ $tape = "/dev/null" -o `expr "$tape" : 'null:'` -eq 5 ]; then + Exit 2 \ + `_ ''` \ + "tapedev ($tape) may not be the null device" +fi +# Confusingly, TAPE is the name of the changer device... +TAPE=`amgetconf changerdev 2>/dev/null` +if [ -z "$TAPE" ]; then + Exit 2 \ + `_ ''` \ + "changerdev may not be empty" +elif [ $TAPE = "/dev/null" ]; then + Exit 2 \ + `_ ''` \ + "changerdev ($TAPE) may not be the null device" +fi +export TAPE # for mtx command + +CHANGER=$TAPE +export CHANGER # for mtx command + +#### Set up the various config files. + +conf_match=`expr "$changerfile" : .\*\.conf\$` +if [ $conf_match -ge 6 ]; then + configfile=$changerfile + changerfile=`echo $changerfile | sed 's/.conf$//g'` +else + configfile=$changerfile.conf +fi + +if [ ! -e $configfile ]; then + Exit 2 \ + `_ ''` \ + "configuration file \"$configfile\" doesn't exist" +fi +if [ ! -f $configfile ]; then + Exit 2 \ + `_ ''` \ + "configuration file \"$configfile\" is not a file" +fi + +cleanfile=$changerfile-clean +accessfile=$changerfile-access +slotfile=$changerfile-slot +labelfile=$changerfile-barcodes +[ ! -s $cleanfile ] && echo 0 > $cleanfile +[ ! -s $accessfile ] && echo 0 > $accessfile +[ ! -s $slotfile ] && echo -1 > $slotfile +[ ! -f $labelfile ] && > $labelfile +cleancount=`cat $cleanfile` +accesscount=`cat $accessfile` + +test -z "$MT" && Exit 2 "" "No mt command defined" +test ! -f "$MT" && Exit 2 "" "mt command ($MT) doesn't exist" +test -z "$MTX" && Exit 2 "" "No mtx command defined" +test ! -f "$MTX" && Exit 2 "" "mtx command ($MTX) doesn't exist" + +#### Dig out of the config file what is needed + +varlist= +varlist="$varlist firstslot" +varlist="$varlist lastslot" +varlist="$varlist cleanslot" +varlist="$varlist cleancycle" +varlist="$varlist OFFLINE_BEFORE_UNLOAD" # old name +varlist="$varlist offline_before_unload" +varlist="$varlist unloadpause" +varlist="$varlist AUTOCLEAN" # old name +varlist="$varlist autoclean" +varlist="$varlist autocleancount" +varlist="$varlist havereader" +varlist="$varlist driveslot" +varlist="$varlist poll_drive_ready" +varlist="$varlist initial_poll_delay" +varlist="$varlist max_drive_wait" + +for var in $varlist +do + val="`cat $configfile 2>/dev/null | sed -n ' +# Ignore comment lines (anything starting with a #). +/^[ ]*#/d +# Find the first var=val line in the file, print the value and quit. +/^[ ]*'$var'[ ]*=[ ]*\([^ ][^ ]*\).*/ { + s/^[ ]*'$var'[ ]*=[ ]*\([^ ][^ ]*\).*/\1/p + q +} +'`" + eval $var=\"$val\" +done + +# Deal with driveslot first so we can get DBGFILE set if we are still +# using the old amgetconf. + +if [ -z "$driveslot" ]; then + driveslot=0; +fi + +# Get DBGFILE set if it is not already. + +if [ $DBGFILE = /dev/null ]; then + if [ -d "$DBGDIR" ]; then + DBGFILE=$DBGDIR/changer.debug.drive$driveslot + else + DBGFILE=/dev/null + fi + Log `_ '=== Start %s ===' "\`date\`"` +fi +if [ -z "$driveslot" ]; then + Exit 2 \ + `_ ''` \ + `_ 'cannot determine drive slot from %s' "$tape"` +fi + +stdout=$TMPDIR/$myname.1.$$ +stderr=$TMPDIR/$myname.2.$$ +mtx_status=$TMPDIR/$myname.status.$$ +trap "rm -f $stdout $stderr $mtx_status" 0 # exit cleanup + +Log `_ 'Using config file %s' "$configfile"` + +# Log the argument list. + +Log `_ "Arg info:"` +LogAppend "\$# = $#" +i=0 +LogAppend "\$$i = \"$argv0\"" +for arg in "$@"; do + i=`expr $i + 1` + LogAppend "\$$i = \"$arg\"" +done + +# Set the default config values for those not in the file. Log the +# results and make sure each is valid (numeric). + +firstslot=${firstslot:-'-1'} # default: mtx status +lastslot=${lastslot:-'-1'} # default: mtx status +cleanslot=${cleanslot:-'-1'} # default: -1 +cleancycle=${cleancycle:-'120'} # default: two minutes +if [ -z "$offline_before_unload" -a -n "$OFFLINE_BEFORE_UNLOAD" ]; then + offline_before_unload=$OFFLINE_BEFORE_UNLOAD # (old name) +fi +offline_before_unload=${offline_before_unload:-'0'} # default: 0 +unloadpause=${unloadpause:-'0'} # default: 0 +if [ -z "$autoclean" -a -n "$AUTOCLEAN" ]; then + autoclean=$AUTOCLEAN # (old name) +fi +autoclean=${autoclean:-'0'} # default: 0 +autocleancount=${autocleancount:-'99'} # default: 99 +havereader=${havereader:-'0'} # default: 0 +poll_drive_ready=${poll_drive_ready:-'3'} # default: three seconds +initial_poll_delay=${initial_poll_delay:-'0'} # default: zero zeconds +max_drive_wait=${max_drive_wait:-'120'} # default: two minutes + +# check MT and MTX for sanity +if test "${MTX:0:1}" = "/"; then + if ! test -f "${MTX}"; then + Exit 2 \ + `_ ''` \ + `_ "mtx binary at '%s' not found" "$MTX"` + fi + if ! test -x "${MTX}"; then + Exit 2 \ + `_ ''` \ + `_ "mtx binary at '%s' is not executable" "$MTX"` + fi +else + # try running it to see if the shell can find it + "$MTX" >/dev/null 2>/dev/null + if test $? -eq 127 -o $? -eq 126; then + Exit 2 \ + `_ ''` \ + `_ "Could not run mtx binary at '%s'" "$MTX"` + fi +fi + +error=`try_find_mt` +if test $? -ne 0; then + Exit 2 '' $error +fi + +get_slot_list + +Log `_ "Config info:"` +for var in $varlist; do + if [ $var = "OFFLINE_BEFORE_UNLOAD" ]; then + continue # old name + elif [ $var = "AUTOCLEAN" ]; then + continue # old name + fi + eval val=\"'$'$var\" + if [ -z "$val" ]; then + Exit 2 \ + `_ ''` \ + `_ '%s missing in %s' "$var" "$configfile"` + fi + if IsNumeric "$val" ; then + : + else + Exit 2 \ + `_ ''` \ + `_ '%s (%s) not numeric in %s' "$var" "$val" "$configfile"` + fi + LogAppend $var = \"$val\" +done + +# Run the rest of the config file sanity checks. + +if [ $firstslot -gt $lastslot ]; then + Exit 2 \ + `_ ''` \ + `_ 'firstslot (%s) greater than lastslot (%s) in %s' "$firstslot" "$lastslot" "$configfile"` +fi +if [ $autoclean -ne 0 -a $cleanslot -lt 0 ]; then + Exit 2 \ + `_ ''` \ + `_ 'autoclean set but cleanslot not valid (%s)' "$cleanslot"` +fi + +# Set up the current slot + +currentslot=`cat $slotfile` +if IsNumeric "$currentslot" ; then + if [ $currentslot -lt $firstslot ]; then + Log `_ 'SETUP -> current slot %s less than %s ... resetting to %s' "$currentslot" "$firstslot" "$firstslot"` + currentslot=$firstslot + elif [ $currentslot -gt $lastslot ]; then + Log `_ 'SETUP -> current slot %s greater than %s ... resetting to %s' "$currentslot" "$lastslot" "$lastslot"` + currentslot=$lastslot + fi +else + Log `_ 'SETUP -> contents of %s (%s) invalid, setting current slot to first slot (%s)' "$slotfile" "$currentslot" "$firstslot"` + currentslot=$firstslot +fi + +found_current=0 +first_slot_in_list=-1 +next_slot_after_current=-1 +for slot in $slot_list; do + if [ $first_slot_in_list -lt 0 ]; then + first_slot_in_list=$slot # in case $firstslot is missing + fi + if [ $slot -eq $currentslot ]; then + found_current=1 + break + elif [ $slot -gt $currentslot ]; then + next_slot_after_current=$slot # $currentslot is missing + break + fi +done +if [ $found_current -eq 0 ]; then + if [ $next_slot_after_current -lt 0 ]; then + new_currentslot=$first_slot_in_list + else + new_currentslot=$next_slot_after_current + fi + Log `_ 'WARNING -> current slot %s not available, setting current slot to next slot (%s)' "$currentslot" "$new_currentslot"` + currentslot=$new_currentslot +fi + +# More routines. + +### +# Eject the current tape and put it away. +### + +eject() { + test -n "$DEBUG" && set -x + Log `_ 'EJECT -> ejecting tape from %s' "$tape"` + get_loaded_info + if [ $loadedslot -gt 0 ]; then + Log `_ 'EJECT -> moving tape from drive %s to storage slot %s' "$driveslot" "$loadedslot"` + if [ $offline_before_unload -ne 0 ]; then + Run try_eject_device $tape + fi + sleep $unloadpause + result=`Run $MTX unload $loadedslot $driveslot 2>&1` + status=$? + Log `_ ' -> status %s, result "%s"' "$status" "$result"` + mtx_status_valid=0 + if [ $status -ne 0 ]; then + answer="$result" + code=2 + else + answer="$rawtape" + code=0 + fi + else + answer=`_ 'Drive was not loaded'` + code=1 + fi + Exit $code "$loadedslot" "$answer" + return $? # in case we are internal +} + +### +# Reset the robot back to the first slot. +### + +reset() { + test -n "$DEBUG" && set -x + Log `_ 'RESET -> loading tape from slot %s to drive %s (%s)' "$firstslot" "$driveslot" "$tape"` + # Call loadslot without doing it as an internal and let it finish + # things up. + loadslot $firstslot + # NOTREACHED + Exit 2 `_ ''` `_ 'reset: should not get here'` + return $? # in case we are internal +} + +### +# Unload the current tape (if necessary) and load a new one (unless +# "advance"). If no tape is loaded, get the value of "current" from +# $slotfile. +### + +loadslot() { + test -n "$DEBUG" && set -x + if [ $# -lt 1 ]; then + Exit 2 `_ ''` `_ 'Missing -slot argument'` + return $? # in case we are internal + fi + whichslot=$1 + Log `_ 'LOADSLOT -> load drive %s (%s) from slot %s' "$driveslot" "$tape" "$whichslot"` + + numeric=`echo $whichslot | sed 's/[^0-9]//g'` + case $whichslot in + current|prev|next|advance) + find_slot=$currentslot + ;; + first) + find_slot=$firstslot + ;; + last) + find_slot=$lastslot + ;; + $numeric) + find_slot=$numeric + ;; + clean) + find_slot=$cleanslot + ;; + *) + Exit 2 `_ ''` `_ 'Illegal slot: "%s"' "$whichslot"` + return $? # in case we are internal + ;; + esac + + # Find the requested slot in the slot list. By loading the "set" + # command with multiple copies, we guarantee that if the slot is + # found, we can look both forward and backward without running + # off the end. Putting $cleanslot at the end allows us to find + # that slot since it is not in $slot_list. + get_slot_list + set x $slot_list $slot_list $slot_list $cleanslot + shift # get rid of the "x" + prev_slot=$1 + shift + while [ $# -gt 0 ]; do + if [ $1 -eq $find_slot ]; then + break + fi + prev_slot=$1 + shift + done + if [ $# -le 0 ]; then + Exit 2 \ + `_ ''` \ + `_ 'Cannot find slot %s in slot list (%s)' "$find_slot " "$slot_list"` + return $? # in case we are internal + fi + + # Determine the slot to load. + case $whichslot in + next|advance) + shift + loadslot=$1 + ;; + prev) + loadslot=$prev_slot + ;; + *) + loadslot=$find_slot + esac + + # If the desired slot is already loaded, we are done. Only update + # current slot if this is not the cleaning slot. + get_loaded_info + if [ $loadslot = $loadedslot ]; then + if [ $loadslot -ne $cleanslot ]; then + rm -f $slotfile + echo $loadslot > $slotfile + fi + Exit 0 "$loadedslot" "$rawtape" + return $? # in case we are internal + fi + if [ $loadedslot -eq -2 ]; then + Exit 0 "$loadedslot" "$rawtape" + return $? # in case we are internal + fi + + # If we are loading the cleaning tape, bump the cleaning count + # and reset the access count. Otherwise, bump the access count + # and see if it is time to do a cleaning. + if [ $loadslot = $cleanslot ]; then + rm -f $cleanfile $accessfile + expr $cleancount + 1 > $cleanfile + echo 0 > $accessfile + else + rm -f $accessfile + expr $accesscount + 1 > $accessfile + if [ $autoclean -ne 0 -a $accesscount -gt $autocleancount ] + then + internal_call=`expr $internal_call + 1` + loadslot clean > /dev/null 2>&1 + status=$? + internal_call=`expr $internal_call - 1` + if [ $status -ne 0 ]; then + Exit $status "$loadslot" "$exit_answer" + return $? # in case we are internal + fi + + # Slot $cleanslot might contain an ordinary tape + # rather than a cleaning tape. A cleaning tape + # *MIGHT* auto-eject; an ordinary tape does not. + # We therefore have to read the status again to + # check what actually happened. + mtx_status_valid=0 + get_loaded_info + fi + fi + + # Unload whatever tape is in the drive. + internal_call=`expr $internal_call + 1` + eject > /dev/null 2>&1 + status=$? + internal_call=`expr $internal_call - 1` + if [ $status -gt 1 ]; then + Exit $status "$exit_slot" "$exit_answer" + return $? # in case we are internal + fi + + # If we were doing an "advance", we are done. + if [ $whichslot = advance ]; then + if [ $loadslot -ne $cleanslot ]; then + rm -f $slotfile + echo $loadslot > $slotfile + fi + Exit 0 "$loadslot" "/dev/null" + return $? # in case we are internal + fi + + # Load the tape, finally! + Log `_ "LOADSLOT -> loading tape from slot %s to drive %s (%s)" "$loadslot" "$driveslot" "$tape"` + result=`Run $MTX load $loadslot $driveslot 2>&1` + status=$? + Log `_ ' -> status %s, result "%s"' "$status" "$result"` + mtx_status_valid=0 + if [ $status -ne 0 ]; then + Exit 2 "$loadslot" "$result" + return $? # in case we are internal + fi + + ### + # Cleaning tapes never go "ready", so instead we just sit here + # for "long enough" (as determined empirically by the user), + # then return success. + ### + if [ $loadslot -eq $cleanslot ]; then + Run sleep $cleancycle + Exit 0 "$loadslot" "$rawtape" + return $? # in case we are internal + fi + + ### + # Wait for the drive to go online. + ### + waittime=0 + ready=0 + sleep $initial_poll_delay + while [ $waittime -lt $max_drive_wait ]; do + amdevcheck_status $tape + if [ $? -eq 0 ]; then + ready=1 + break + fi + sleep $poll_drive_ready + waittime=`expr $waittime + $poll_drive_ready` + done + if [ $ready -eq 0 ]; then + Exit 2 "$loadslot" `_ 'Drive not ready after %s seconds, rewind said "%s"' "$max_drive_wait" "$result"` + return $? # in case we are internal + fi + + if [ $loadslot -ne $cleanslot ]; then + rm -f $slotfile + echo $loadslot > $slotfile + fi + Exit 0 "$loadslot" "$rawtape" + return $? # in case we are internal +} + +### +# Return information about how the changer is configured and the current +# state of the robot. +### + +info() { + test -n "$DEBUG" && set -x + get_loaded_info + get_slot_list + Log `_ 'INFO -> first slot: %s' "$firstslot"` + LogAppend `_ ' -> current slot: %s' "$currentslot"` + LogAppend `_ ' -> loaded slot: %s' "$loadedslot"` + LogAppend `_ ' -> last slot: %s' "$lastslot"` + LogAppend `_ ' -> slot list: %s' "$slot_list"` + LogAppend `_ ' -> can go backwards: 1'` + LogAppend `_ ' -> havereader: %s' "$havereader"` + + ### + # Check if a barcode reader is configured or not. If so, it + # passes the 4th item in the echo back to amtape signifying it + # can search based on barcodes. + ### + reader= + if [ $havereader -eq 1 ]; then + reader=1 + fi + + if [ $currentslot -lt $firstslot -o $currentslot -gt $lastslot ]; then + currentslot=$firstslot # what "current" will get + fi + numslots=`expr $lastslot - $firstslot + 1` + Exit 0 "$currentslot" "$numslots 1 $reader" + return $? # in case we are internal +} + +### +# Read the labelfile and scan for a particular entry. +### + +read_labelfile() { + labelfile_entry_found=0 + labelfile_label= + labelfile_barcode= + + lbl_search=$1 + bc_search=$2 + + line=0 + while read lbl bc junk; do + line=`expr $line + 1` + if [ -z "$lbl" -o -z "$bc" -o -n "$junk" ]; then + Log `_ 'ERROR -> Line %s malformed: %s %s %s' "$line" "$lbl" "$bc" "$junk"` + LogAppend `_ ' -> Remove %s and run "%s %s update"' "$labelfile" "$sbindir/amtape" "$config"` + Exit 2 \ + `_ ''` \ + `_ 'Line %s malformed in %s: %s %s %s' "$line" "$labelfile" "$lbl" "$bc" "$junk"` + return $? # in case we are internal + fi + if [ $lbl = "$lbl_search" -o $bc = "$bc_search" ]; then + if [ $labelfile_entry_found -ne 0 ]; then + Log `_ 'ERROR -> Duplicate entries: %s line %s' "$labelfile" "$line"` + LogAppend `_ ' -> Remove %s and run "%s %s update"' "$labelfile" "$sbindir/amtape" "$config"` + Exit 2 \ + `_ ''` \ + `_ 'Duplicate entries: %s line %s' "$labelfile" "$line"` + return $? # in case we are internal + fi + labelfile_entry_found=1 + labelfile_label=$lbl + labelfile_barcode=$bc + fi + done +} + +### +# Adds the label and barcode for the currently loaded tape to the +# barcode file. Return an error if the database is messed up. +### + +addlabel() { + test -n "$DEBUG" && set -x + if [ $# -lt 1 ]; then + Exit 2 `_ ''` `_ 'Missing -label argument'` + return $? # in case we are internal + fi + tapelabel=$1 + if [ $havereader -eq 0 ]; then + Exit 2 `_ ''` `_ 'Not configured with barcode reader'` + return $? # in case we are internal + fi + get_loaded_info + if [ $loadedslot -lt 0 ]; then + Exit 1 `_ ''` `_ 'No tape currently loaded'` + return $? # in case we are internal + fi + if [ -z "$loadedbarcode" ]; then + Exit 1 `_ ''` `_ 'No barcode found for tape %s.' $tapelabel` + return $? # in case we are internal + fi + Log `_ 'LABEL -> Adding label "%s" with barcode "%s" for slot %s into %s' "$tapelabel" "$loadedbarcode" "$loadedslot" "$labelfile"` + read_labelfile "$tapelabel" "$loadedbarcode" < $labelfile + if [ $labelfile_entry_found -ne 0 ]; then + lf_val= + if [ "$labelfile_barcode" != "$loadedbarcode" ]; then + lf_type=label + lf_val=$tapelabel + val_type=barcode + old_val=$labelfile_barcode + new_val=$loadedbarcode + elif [ "$labelfile_label" != "$tapelabel" ]; then + lf_type=barcode + lf_val=$loadedbarcode + val_type=label + old_val=$labelfile_label + new_val=$tapelabel + fi + if [ -n "$lf_val" ]; then + LogAppend `_ 'ERROR -> !!! Label database corrupted !!!'` + LogAppend `_ ' -> "%s" conflicts with new %s "%s" for %s "%s"' "$old_val" "$val_type" "$new_val" "$lf_type" "$lf_val"` + Exit 2 \ + `_ ''` \ + `_ '%s: "%s" conflicts with new %s "%s" for %s "%s"' "$tapelabel" "$old_val" "$val_type" "$new_val" "$lf_type" "$lf_val"` + return $? # in case we are internal + fi + LogAppend `_ " -> already synced"` + else + echo "$tapelabel $loadedbarcode" >> $labelfile + LogAppend `_ ' -> appended %s entry: %s %s' "$labelfile" "$tapelabel" "$loadedbarcode"` + fi + Exit 0 "$loadedslot" "$rawtape" + return $? # in case we are internal +} + +### +# Look for a label in the barcode file. If found, locate the slot it's +# in by looking for the barcode in the mtx output, then load that tape. +### + +searchtape() { + test -n "$DEBUG" && set -x + if [ $# -lt 1 ]; then + Exit 2 `_ ''` `_ 'Missing -search argument'` + return $? # in case we are internal + fi + tapelabel=$1 + if [ $havereader -eq 0 ]; then + Exit 2 `_ ''` `_ 'Not configured with barcode reader'` + return $? # in case we are internal + fi + Log `_ 'SEARCH -> Hunting for label "%s"' "$tapelabel"` + read_labelfile "$tapelabel" "" < $labelfile + if [ $labelfile_entry_found -eq 0 ]; then + LogAppend `_ ' -> !!! label "%s" not found in %s !!!' "$tapelabel" "$labelfile"` + LogAppend `_ ' -> Remove %s and run "%s %s update"' "$labelfile" "$sbindir/amtape" "$config"` + Exit 2 \ + `_ ''` \ + `_ '%s: label "%s" not found in %s' "$tapelabel" "$tapelabel" "$labelfile"` + return $? # in case we are internal + fi + LogAppend `_ ' -> barcode is "%s"' "$labelfile_barcode"` + get_mtx_status + foundslot=`sed -n ' +/VolumeTag *= *'$labelfile_barcode' *$/ { + s/.*Storage Element \([0-9][0-9]*\).*/\1/p + q +} +' < $mtx_status` + LogAppend `_ ' -> foundslot is %s' "$foundslot"` + if [ -z "$foundslot" ]; then + LogAppend `_ 'ERROR -> !!! Could not find slot for barcode "%s"!!!' "$labelfile_barcode"` + LogAppend `_ ' -> Remove %s and run "%s %s update"' "$labelfile" "$sbindir/amtape" "$config"` + Exit 2 \ + `_ ''` \ + `_ 'barcode "%s" not found in mtx status output' "$labelfile_barcode"` + return $? # in case we are internal + fi + # Call loadslot without doing it as an internal and let it finish + # things up. + loadslot $foundslot + # NOTREACHED + Exit 2 `_ ''` `_ 'searchtape: should not get here'` + return $? # in case we are internal +} + +### +# Program invocation begins here +### + +if [ $# -lt 1 ]; then + Exit 2 `_ ''` `_ 'Usage: %s -command args' "$myname"` +fi +cmd=$1 +shift +case "$cmd" in +-slot) + loadslot "$@" + ;; +-info) + info "$@" + ;; +-reset) + reset "$@" + ;; +-eject) + eject "$@" + ;; +-label) + addlabel "$@" + ;; +-search) + searchtape "$@" + ;; +-clean) + loadslot clean + ;; +*) + Exit 2 `_ ''` `_ 'unknown option: %s' "$cmd"` + ;; +esac + +Exit 2 `_ ''` `_ '%s: should not get here' "$myname"` diff --git a/client-src/patch-system.sh b/client-src/patch-system.sh new file mode 100644 index 0000000..fe7f634 --- /dev/null +++ b/client-src/patch-system.sh @@ -0,0 +1,152 @@ +#! @SHELL@ +# +# patch inetd.conf and services +# originally by Axel Zinser (fifi@hiss.han.de) +# + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" +if test "$USE_VERSION_SUFFIXES" = "yes"; then + SUF="-@VERSION@" +else + SUF= +fi + +SERVICE_SUFFIX="@SERVICE_SUFFIX@" + +USER="@CLIENT_LOGIN@" + +INETDCONF=/etc/inetd.conf +[ ! -f $INETDCONF ] && INETDCONF=/usr/etc/inetd.conf + +SERVICES=/etc/services +[ ! -f $SERVICES ] && SERVICES=/usr/etc/services + +ENABLE_AMANDAD=true + +case `uname -n` in +"@DEFAULT_SERVER@" | "@DEFAULT_SERVER@".*) + ENABLE_INDEX=true + ENABLE_TAPE=true + ;; +*) + ENABLE_INDEX=false + ENABLE_TAPE=false + ;; +esac + +CLIENT_PORT=10080 +KCLIENT_PORT=10081 +INDEX_PORT=10082 +TAPE_PORT=10083 + +while [ $# != 0 ]; do + case "$1" in + --service-suffix=*) + SERVICE_SUFFIX=`echo $1 | sed -e 's/[^=]*=//'`;; + --version-suffix=*) + SUF=`echo $1 | sed -e 's/[^=]*=//'`;; + --inetd=*) + INETDCONF=`echo $1 | sed -e 's/[^=]*=//' -e 's%^$%/dev/null%'`;; + --services=*) + SERVICES=`echo $1 | sed -e 's/[^=]*=//' -e 's%^$%/dev/null%'`;; + --libexecdir=?*) + libexecdir=`echo $1 | sed -e 's/[^=]*=//'`;; + --user=?*) + USER=`echo $1 | sed -e 's/[^=]*=//'`;; + --enable-client) + ENABLE_AMANDAD=true;; + --disable-client) + ENABLE_AMANDAD=false;; + --enable-index) + ENABLE_INDEX=true;; + --disable-index) + ENABLE_INDEX=false;; + --enable-tape) + ENABLE_TAPE=true;; + --disable-tape) + ENABLE_TAPE=false;; + --client-port=?*) + CLIENT_PORT=`echo $1 | sed -e 's/[^=]*=//'`;; + --kclient-port=?*) + KCLIENT_PORT=`echo $1 | sed -e 's/[^=]*=//'`;; + --index-port=?*) + INDEX_PORT=`echo $1 | sed -e 's/[^=]*=//'`;; + --tape-port=?*) + TAPE_PORT=`echo $1 | sed -e 's/[^=]*=//'`;; + --usage | --help | -h) + echo `_ 'call this script with zero or more of the following arguments:'` + echo `_ '--version-suffix=: append to program names [%s]' "$SUF"` + echo `_ '--service-suffix=: append to service names [%s]' "$SERVICE_SUFFIX"` + echo `_ '--libexecdir=: where daemons should be looked for [%s]' "$libexecdir"` + echo `_ '--inetd=: full pathname of inetd.conf [%s]' "$INETDCONF"` + echo `_ '--services=: full pathname of services [%s]' "$SERVICES"` + echo `_ '\tan empty pathname or /dev/null causes that file to be skipped'` + echo `_ '--user=: run deamons as this user [%s]' "$USER"` + echo `_ '--enable/disable-client: enable/disable amandad [%s]' \`$ENABLE_AMANDAD && echo enabled || echo disabled\`` + echo `_ '--enable/disable-index: enable/disable index server [%s]' \`$ENABLE_INDEX && echo enabled || echo disabled\`` + echo `_ '--enable/disable-tape: enable/disable tape server [%s]' \`$ENABLE_TAPE && echo enabled || echo disabled\`` + echo `_ '--client-port=: amandad port number [%s]' "$CLIENT_PORT"` + echo `_ '--kclient-port=: kamandad port number [%s]' "$KCLIENT_PORT"` + echo `_ '--index-port=: index server port number [%s]' "$INDEX_PORT"` + echo `_ '--tape-port=: tape server port number [%s]' "$TAPE_PORT"` + exec true;; + *) + echo `_ '%s: invalid argument %s. run with -h for usage\n' "$0" "$1"` >&2 + exec false;; + esac + shift +done + +if [ "$SERVICES" = /dev/null ]; then : +elif [ -f "$SERVICES" ]; then + TEMP="$SERVICES.new" + { + egrep < "$SERVICES" -v "^(amanda|kamanda|amandaidx|amidxtape)${SERVICE_SUFFIX}[ ]" + echo "amanda${SERVICE_SUFFIX} ${CLIENT_PORT}/udp" + echo "amanda${SERVICE_SUFFIX} ${CLIENT_PORT}/tcp" + echo "kamanda${SERVICE_SUFFIX} ${KCLIENT_PORT}/udp" + echo "amandaidx${SERVICE_SUFFIX} ${INDEX_PORT}/tcp" + echo "amidxtape${SERVICE_SUFFIX} ${TAPE_PORT}/tcp" + } > "$TEMP" + if diff "$SERVICES" "$TEMP" >/dev/null 2>/dev/null; then + echo `_ '%s is up to date' "$SERVICES"` + else + cp "$TEMP" "$SERVICES" || echo `_ 'cannot patch %s' "$SERVICES"` + fi + rm -f "$TEMP" +else + echo `_ '%s not found!' "$SERVICES"` +fi +if [ "$INETDCONF" = /dev/null ]; then : +elif [ -f "$INETDCONF" ]; then + err=`_ 'warning: %s/amandad%s does not exist' "$libexecdir" "$SUF"` + $ENABLE_AMANDAD && test ! -f $libexecdir/amandad$SUF && echo "$err" >&2 + err=`_ 'warning: %s/amindexd%s does not exist' "$libexecdir" "$SUF"` + $ENABLE_INDEX && test ! -f $libexecdir/amindexd$SUF && echo "$err" >&2 + err=`_ 'warning: %s/amidxtaped%s does not exist' "$libexecdir" "$SUF"` + $ENABLE_TAPE && test ! -f $libexecdir/amidxtaped$SUF && echo "$err" >&2 + TEMP="$INETDCONF.new" + { + egrep < "$INETDCONF" -v "^(amanda|amandaidx|amidxtape)${SERVICE_SUFFIX}[ ]" + $ENABLE_AMANDAD && echo "amanda${SERVICE_SUFFIX} dgram udp wait $USER $libexecdir/amandad$SUF amandad$SUF" + $ENABLE_INDEX && echo "amandaidx${SERVICE_SUFFIX} stream tcp nowait $USER $libexecdir/amindexd$SUF amindexd$SUF" + $ENABLE_TAPE && echo "amidxtape${SERVICE_SUFFIX} stream tcp nowait $USER $libexecdir/amidxtaped$SUF amidxtaped$SUF" + } > "$TEMP" + if diff "$INETDCONF" "$TEMP" >/dev/null 2>/dev/null; then + fmt="%s is up to date\n" + printf $fmt $INETDCONF + else + fmt="cannot patch %s\n" + cp "$TEMP" "$INETDCONF" || printf $fmt $INETDCONF + fi + rm -f "$TEMP" +else + fmt="%s not found!\n" + printf $fmt $INETDCONF +fi diff --git a/common-src/amaespipe.sh b/common-src/amaespipe.sh new file mode 100755 index 0000000..8d3aa1c --- /dev/null +++ b/common-src/amaespipe.sh @@ -0,0 +1,90 @@ +#! @SHELL@ +# +# Copyright (c) 2005 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com +# + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +# add sbin and ucb dirs +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb" +export PATH + +# wrapper script to use aespipe +# based on bz2aespipe distributed by aespipe from +# http://loop-aes.sourceforge.net/ +# FILE FORMAT +# 10 bytes: constant string 'bz2aespipe' +# 10 bytes: itercountk digits +# 1 byte: '0' = AES128, '1' = AES192, '2' = AES256 +# 1 byte: '0' = SHA256, '1' = SHA384, '2' = SHA512, '3' = RMD160 +# 24 bytes: random seed string +# remaining bytes are aespipe encrypted + +# These definitions are only used when encrypting. +# Decryption will autodetect these definitions from archive. +ENCRYPTION=AES256 +HASHFUNC=SHA256 +ITERCOUNTK=100 +WAITSECONDS=1 +AMANDA_HOME=~@CLIENT_LOGIN@ +GPGKEY="$AMANDA_HOME/.gnupg/am_key.gpg" +FDNUMBER=3 + +if test x$1 = x-d ; then + # decrypt + n=`head -c 10 - | tr -d -c 0-9a-zA-Z` + if test x${n} != xbz2aespipe ; then + echo `_ 'bz2aespipe: wrong magic - aborted'` >/dev/tty + exit 1 + fi + itercountk=`head -c 10 - | tr -d -c 0-9` + if test x${itercountk} = x ; then itercountk=0; fi + n=`head -c 1 - | tr -d -c 0-9` + encryption=AES128 + if test x${n} = x1 ; then encryption=AES192; fi + if test x${n} = x2 ; then encryption=AES256; fi + n=`head -c 1 - | tr -d -c 0-9` + hashfunc=SHA256 + if test x${n} = x1 ; then hashfunc=SHA384; fi + if test x${n} = x2 ; then hashfunc=SHA512; fi + if test x${n} = x3 ; then hashfunc=RMD160; fi + seedstr=`head -c 24 - | tr -d -c 0-9a-zA-Z+/` + aespipe -K ${GPGKEY} -p ${FDNUMBER} -e ${encryption} -H ${hashfunc} -S ${seedstr} -C ${itercountk} -d +else + # encrypt + echo -n bz2aespipe + echo ${ITERCOUNTK} | awk '{printf "%10u", $1;}' + n=`echo ${ENCRYPTION} | tr -d -c 0-9` + aesstr=0 + if test x${n} = x192 ; then aesstr=1; fi + if test x${n} = x256 ; then aesstr=2; fi + n=`echo ${HASHFUNC} | tr -d -c 0-9` + hashstr=0 + if test x${n} = x384 ; then hashstr=1; fi + if test x${n} = x512 ; then hashstr=2; fi + if test x${n} = x160 ; then hashstr=3; fi + seedstr=`head -c 18 /dev/urandom | uuencode -m - | head -n 2 | tail -n 1` + echo -n ${aesstr}${hashstr}${seedstr} + aespipe -K ${GPGKEY} -p ${FDNUMBER} -e ${ENCRYPTION} -H ${HASHFUNC} -S ${seedstr} -C ${ITERCOUNTK} -w ${WAITSECONDS} +fi +exit 0 diff --git a/common-src/amanda-sh-lib.sh.in b/common-src/amanda-sh-lib.sh.in new file mode 100644 index 0000000..0c82190 --- /dev/null +++ b/common-src/amanda-sh-lib.sh.in @@ -0,0 +1,49 @@ +# Shell library containing functions and definitions common to amanda's +# shell scripts and wrappers. + +# Include this file as follows: +# prefix="@prefix@" +# exec_prefix="@exec_prefix@" +# amlibexecdir="@amlibexecdir@" +# . "${amlibexecdir}/amanda-sh-lib.sh" + +#### +# Configure variables + +GREP="@GREP@" +EGREP="@EGREP@" +GETTEXT="@GETTEXT@" +GNUPLOT="@GNUPLOT@" +GNUTAR="@GNUTAR@" +STAR="@STAR@" +SAMBA_CLIENT="@SAMBA_CLIENT@" +GZIP="@GZIP@" +SORT="@SORT@" +MAILER="@MAILER@" +PERL="@PERL@" +AWK="@AWK@" + +#### +# Set up PATH for finding amanda executables + +PATH="@sbindir@:@amlibexecdir@:$PATH" + +#### +# Gettext + +# use as follows: +# echo `_ "%s: '%s' is not executable" "$myname" "$binpath"` +# NOTE: use a text editor with shell syntax hilighting to avoid +# quoting errors! + +if test -n "$GETTEXT"; then + _() { + fmt=`$GETTEXT -d amanda "$1"` + shift + printf "$fmt" $* + } +else + _() { + printf "$@" + } +fi diff --git a/common-src/amcrypt-ossl-asym.sh b/common-src/amcrypt-ossl-asym.sh new file mode 100644 index 0000000..bec5269 --- /dev/null +++ b/common-src/amcrypt-ossl-asym.sh @@ -0,0 +1,188 @@ +#!@SHELL@ +# +# amcrypt-ossl-asym.sh - asymmetric crypto helper using OpenSSL +# Usage: amcrypt-ossl-asym.sh [-d] +# +# Copyright © 2006 Ben Slusky +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# +# Keys can be generated with the standard OpenSSL commands, e.g.: +# +# $ openssl genrsa -aes128 -out backup-privkey.pem 1024 +# Generating RSA private key, 1024 bit long modulus +# [...] +# Enter pass phrase for backup-privkey.pem: +# Verifying - Enter pass phrase for backup-privkey.pem: +# +# $ openssl rsa -in backup-privkey.pem -pubout -out backup-pubkey.pem +# Enter pass phrase for backup-privkey.pem: +# Writing RSA key +# + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +# change these as needed +OPENSSL= # whatever's in $PATH +CIPHER=aes-256-cbc # see `openssl help` for more ciphers +AMANDA_HOME=~@CLIENT_LOGIN@ +RANDFILE=$AMANDA_HOME/.rnd +export RANDFILE +PASSPHRASE=$AMANDA_HOME/.am_passphrase # optional +PRIVKEY=$AMANDA_HOME/backup-privkey.pem +PUBKEY=$AMANDA_HOME/backup-pubkey.pem + +# where might openssl be? +PATH=/bin:/usr/bin:/usr/local/bin:/usr/ssl/bin:/usr/local/ssl/bin:/opt/csw/bin +export PATH +MAGIC='AmAnDa+OpEnSsL' +ME=`basename "$0"` +WORKDIR="/tmp/.${ME}.$$" + + +# first things first +if [ -z "${OPENSSL:=`which openssl`}" ]; then + echo `_ '%s: %s not found' "${ME}" "openssl"` >&2 + exit 1 +elif [ ! -x "${OPENSSL}" ]; then + echo `_ "%s: can't execute %s (%s)" "${ME}" "openssl" "${OPENSSL}"` >&2 + exit 1 +fi + +if [ -n "${PASSPHRASE}" ]; then + # check the openssl version. if it's too old, we have to handle + # the pass phrase differently. + OSSL_VERSION=`eval \"${OPENSSL}\" version |cut -d\ -f2` + case "${OSSL_VERSION}" in + ''|0.[0-8].*|0.9.[0-6]*|0.9.7|0.9.7[a-c]*) + echo `_ '%s: %s is version %s' "${ME}" "${OPENSSL}" "${OSSL_VERSION}"` >&2 + echo `_ '%s: Using pass phrase kluge for OpenSSL version >=0.9.7d' "${ME}"` >&2 + PASS_FROM_STDIN=yes + ;; + esac +fi + +mkdir -m 700 "${WORKDIR}" +if [ $? -ne 0 ]; then + echo `_ '%s: failed to create temp directory' "${ME}"` >&2 + exit 1 +fi +# ignore SIGINT +trap "" 2 +trap "rm -rf \"${WORKDIR}\"" 0 1 3 15 + +# we'll need to pad the datastream to a multiple of the cipher block size +# prior to encryption and decryption. 96 bytes (= 768 bits) should be good +# for any cipher. +pad() { + perl -pe 'BEGIN { $bs = 96; $/ = \8192 } $nbytes = ($nbytes + length) % $bs; END { print "\0" x ($bs - $nbytes) }' +} + +encrypt() { + # generate a random printable cipher key (on one line) + echo `"${OPENSSL}" rand -base64 80` >"${WORKDIR}/pass" + + # encrypt the cipher key using the RSA public key + "${OPENSSL}" rsautl -encrypt -in "${WORKDIR}/pass" -out "${WORKDIR}/pass.ciphertext" -pubin -inkey "${PUBKEY}" -pkcs + [ $? -eq 0 ] || return 1 + + # print magic + printf "%s" "${MAGIC}" + + # print the encrypted cipher key, preceded by size + ls -l "${WORKDIR}/pass.ciphertext" | awk '{ printf("%-10d", $5) }' + cat "${WORKDIR}/pass.ciphertext" + + # encrypt data using the cipher key and print + pad | "${OPENSSL}" enc "-${CIPHER}" -nopad -e -pass "file:${WORKDIR}/pass" -nosalt + [ $? -eq 0 ] || return 1 +} + +decrypt() { + # read magic + magicsize=`printf "%s" "${MAGIC}" | wc -c | sed 's/^ *//'` + magic=`dd bs=$magicsize count=1 2>/dev/null` + if [ "$magic" != "${MAGIC}" ]; then + echo `_ '%s: bad magic' "${ME}"` >&2 + return 1 + fi + + # read size of encrypted cipher key + n=`dd bs=10 count=1 2>/dev/null` + [ $n -gt 0 ] 2>/dev/null + if [ $? -ne 0 ]; then + echo `_ '%s: bad header' "${ME}"` >&2 + return 1 + fi + + # read the encrypted cipher key + dd "of=${WORKDIR}/pass.ciphertext" bs=$n count=1 2>/dev/null + + # decrypt the cipher key using the RSA private key + if [ "${PASS_FROM_STDIN}" = yes ]; then + "${OPENSSL}" rsautl -decrypt -in "${WORKDIR}/pass.ciphertext" -out "${WORKDIR}/pass" -inkey "${PRIVKEY}" -pkcs < "${PASSPHRASE}" + else + "${OPENSSL}" rsautl -decrypt -in "${WORKDIR}/pass.ciphertext" -out "${WORKDIR}/pass" -inkey "${PRIVKEY}" ${PASSARG} -pkcs 3< "${PASSPHRASE}" + fi + [ $? -eq 0 ] || return 1 + + # use the cipher key to decrypt data + pad | "${OPENSSL}" enc "-${CIPHER}" -nopad -d -pass "file:${WORKDIR}/pass" -nosalt + + # N.B.: in the likely event that we're piping to gzip, the above command + # may return a spurious error if gzip closes the output stream early. + return 0 +} + +if [ "$1" = -d ]; then + if [ -z "${PRIVKEY}" ]; then + echo `_ '%s: must specify private key for decryption' "${ME}"` >&2 + exit 1 + elif [ ! -r "${PRIVKEY}" ]; then + echo `_ "%s: can't read private key from %s" "${ME}" "${PRIVKEY}"` >&2 + exit 1 + fi + + if [ -n "${PASSPHRASE}" -a -e "${PASSPHRASE}" -a -r "${PASSPHRASE}" ]; then + PASSARG='-passin fd:3' + else + PASSPHRASE=/dev/null + fi + + decrypt + if [ $? -ne 0 ]; then + echo `_ '%s: decryption failed' "${ME}"` >&2 + exit 1 + fi +else + if [ -z "${PUBKEY}" ]; then + echo `_ '%s: must specify public key for encryption' "${ME}"` >&2 + exit 1 + elif [ ! -r "${PUBKEY}" ]; then + echo `_ "%s: can't read public key from %s" "${ME}" "${PUBKEY}"` >&2 + exit 1 + fi + + encrypt + if [ $? -ne 0 ]; then + echo `_ '%s: encryption failed' "${ME}"` >&2 + exit 1 + fi +fi diff --git a/common-src/amcrypt-ossl.sh b/common-src/amcrypt-ossl.sh new file mode 100644 index 0000000..edab131 --- /dev/null +++ b/common-src/amcrypt-ossl.sh @@ -0,0 +1,47 @@ +#!@SHELL@ +# +# amcrypt-ossl.sh - crypto helper using OpenSSL +# Usage: amcrypt-ossl.sh [-d] +# + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +# change these as needed +OPENSSL= # whatever's in $PATH +CIPHER=aes-256-cbc # see `openssl help` for more ciphers +AMANDA_HOME=~@CLIENT_LOGIN@ +RANDFILE=$AMANDA_HOME/.rnd +export RANDFILE +PASSPHRASE=$AMANDA_HOME/.am_passphrase # required + +# where might openssl be? +PATH=/bin:/usr/bin:/usr/local/bin:/usr/ssl/bin:/usr/local/ssl/bin:/opt/csw/bin +export PATH +ME=`basename "$0"` + +if [ -z "${OPENSSL:=`which openssl`}" ]; then + echo `_ '%s: openssl not found' "${ME}"` >&2 + exit 1 +elif [ ! -x "${OPENSSL}" ]; then + echo `_ "%s: can't execute %s (%s)" "${ME}" "openssl" "${OPENSSL}"` >&2 + exit 1 +fi + +# we'll need to pad the datastream to a multiple of the cipher block size prior +# to encryption. 96 bytes (= 768 bits) should be good for any cipher. +pad() { + perl -pe 'BEGIN { $bs = 96; $/ = \8192 } $nbytes = ($nbytes + length) % $bs; END { print "\0" x ($bs - $nbytes) }' +} + +if [ "$1" = -d ]; then + # decrypt + "${OPENSSL}" enc -d "-${CIPHER}" -nopad -salt -pass fd:3 3< "${PASSPHRASE}" +else + # encrypt + pad | "${OPENSSL}" enc -e "-${CIPHER}" -nopad -salt -pass fd:3 3< "${PASSPHRASE}" +fi + diff --git a/common-src/amcrypt.sh b/common-src/amcrypt.sh new file mode 100755 index 0000000..82e1ea6 --- /dev/null +++ b/common-src/amcrypt.sh @@ -0,0 +1,47 @@ +#!@SHELL@ +# +# Original wrapper by Paul Bijnens +# +# worked by Stefan G. Weichinger +# to enable gpg-encrypted dumps via aespipe +# also worked by Matthieu Lochegnies for server-side encryption + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +amlibexecdir="@amlibexecdir@" +. "${amlibexecdir}/amanda-sh-lib.sh" + +# add sbin and ucb dirs, as well as csw (blastwave) +PATH="$PATH:/usr/sbin:/sbin:/usr/ucb:/opt/csw/bin" +export PATH + +AMANDA_HOME=~@CLIENT_LOGIN@ +AM_AESPIPE=@sbindir@/amaespipe +AM_PASSPHRASE=$AMANDA_HOME/.am_passphrase + +AESPIPE=`which aespipe` + +if [ $? -ne 0 ] ; then + echo `_ '%s: %s was not found in %s' "$0" "aespipe" "$PATH"` >&2 + exit 2 +fi + +if [ ! -x $AESPIPE ] ; then + echo `_ '%s: %s is not executable' "$0" "aespipe"` >&2 + exit 2 +fi + +if [ ! -x $AM_AESPIPE ] ; then + echo `_ '%s: %s was not found' "$0" "$AM_AESPIPE"` >&2 + exit 2 +fi +if [ ! -x $AM_AESPIPE ] ; then + echo `_ '%s: %s is not executable' "$0" "$AM_AESPIPE"` >&2 + exit 2 +fi + +$AM_AESPIPE "$@" 3< $AM_PASSPHRASE + +rc=$? +exit $rc diff --git a/common-src/amcryptsimple.pl b/common-src/amcryptsimple.pl new file mode 100755 index 0000000..05e50e5 --- /dev/null +++ b/common-src/amcryptsimple.pl @@ -0,0 +1,141 @@ +#!@PERL@ -w +# +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com +# + + + +# Run perl. +eval '(exit $?0)' && eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' + & eval 'exec /usr/bin/perl -S $0 $argv:q' + if 0; + +use Time::Local; + +my $AMANDA='@CLIENT_LOGIN@'; + +my $ddebug = 1; # set to 1 to print signal debug to stderr + +my $sigint_seen = 0; +my $sigpipe_seen = 0; +my $sighup_seen = 0; +my $sigill_seen = 0; +my $sigterm_seen = 0; +my $sigsegv_seen = 0; +my $sigquit_seen = 0; +my $sigfpe_seen = 0; + +$AMANDA_HOME = (getpwnam($AMANDA) )[7] || die "Cannot find $AMANDA home directory\n" ; +$AM_PASS = "$AMANDA_HOME/.am_passphrase"; + +unless ( -e $AM_PASS ) { + die "secret key $AM_PASS not found\n"; +} + + +$ENV{'PATH'} = '/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/csw/bin'; + +$ENV{'GNUPGHOME'} = "$AMANDA_HOME/.gnupg"; + + +sub encrypt() { + system "gpg --batch --no-secmem-warning --disable-mdc --symmetric --cipher-algo AES256 --passphrase-fd 3 3<$AM_PASS"; +} + +sub decrypt() { + system "gpg --batch --quiet --no-mdc-warning --decrypt --passphrase-fd 3 3<$AM_PASS"; +} + +sub int_catcher { + $sigint_seen = 1; +} + +sub pipe_catcher { + $sigpipe_seen = 1; +} + +sub hup_catcher { + $sighup_seen = 1; +} + +sub ill_catcher { + $sigill_seen = 1; +} + +sub term_catcher { + $sigterm_seen = 1; +} + +sub segv_catcher { + $sigsegv_seen = 1; +} + +sub quit_catcher { + $sigquit_seen = 1; +} + +sub fpe_catcher { + $sigfpe_seen = 1; +} + +#main + +$SIG{'INT'} = 'int_catcher'; +$SIG{'PIPE'} = 'pipe_catcher'; +$SIG{'HUP'} = 'hup_catcher'; +$SIG{'ILL'} = 'ill_catcher'; +$SIG{'TERM'} = 'term_catcher'; +$SIG{'SEGV'} = 'segv_catcher'; +$SIG{'QUIT'} = 'quit_catcher'; +$SIG{'FPE'} = 'FPE_catcher'; + + +if ( $#ARGV > 0 ) { + die "Usage: $0 [-d]\n"; +} + +if ( $#ARGV==0 && $ARGV[0] eq "-d" ) { + decrypt(); +} +else { + encrypt(); +} + +if ( $ddebug ) { + if ( $sigint_seen ) { print STDERR "strange sigint seen = $sigint_seen\n"; } + if ( $sigpipe_seen ) { print STDERR "strange sigpipe seen = $sigpipe_seen\n"; } + if ( $sighup_seen ) { print STDERR "strange sighup seen = $sighup_seen\n"; } + if ( $sigill_seen ) { print STDERR "strange sigill seen = $sigill_seen\n"; } + + if ( $sigterm_seen ) { print STDERR "strange sigterm seen = $sigterm_seen\n"; } + if ( $sigsegv_seen ) { print STDERR "strange sigsegv seen = $sigsegv_seen\n"; } + if ( $sigquit_seen ) { print STDERR "strange sigquit seen = $sigquit_seen\n"; } + if ( $sigfpe_seen ) { print STDERR "strange sigfpe seen = $sigfpe_seen\n"; } + +} + +$SIG{'INT'} = 'DEFAULT'; +$SIG{'PIPE'} = 'DEFAULT'; +$SIG{'HUP'} = 'DEFAULT'; +$SIG{'ILL'} = 'DEFAULT'; +$SIG{'TERM'} = 'DEFAULT'; +$SIG{'SEGV'} = 'DEFAULT'; +$SIG{'QUIT'} = 'DEFAULT'; +$SIG{'FPE'} = 'DEFAULT'; + diff --git a/common-src/amflock-flock.c b/common-src/amflock-flock.c new file mode 100644 index 0000000..82001c3 --- /dev/null +++ b/common-src/amflock-flock.c @@ -0,0 +1,52 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1998 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +/* moved from amflock.c by Dustin J. Mitchell */ + +#include "amanda.h" + +static int +flock_lock( + int fd, + G_GNUC_UNUSED char *resource) +{ + return flock(fd, LOCK_EX); +} + +static int +flock_unlock( + int fd, + G_GNUC_UNUSED char *resource) +{ + return flock(fd, LOCK_UN); +} + +amflock_impl_t amflock_flock_impl = { + flock_lock, + flock_lock, /* no read-only support */ + flock_unlock, + "flock" +}; diff --git a/common-src/amflock-lnlock.c b/common-src/amflock-lnlock.c new file mode 100644 index 0000000..142aea3 --- /dev/null +++ b/common-src/amflock-lnlock.c @@ -0,0 +1,262 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1998 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +/* moved from amflock.c by Dustin J. Mitchell */ + +#include "amanda.h" + +static int ln_lock(char *res, int op); +char *_lnlock_dir = AMANDA_TMPDIR; /* amflock-test changes this; it's a constant otherwise */ + +/* XXX - error checking in this section needs to be tightened up */ + +/* Delete a lock file. +*/ +static int +delete_lock( + char *fn) +{ + int rc; + + rc = unlink(fn); + if (rc != 0 && errno == ENOENT) rc = 0; + + return rc; +} + +/* Create a lock file. +*/ +static int +create_lock( + char *fn, + long pid) +{ + int fd; + FILE *f; + int mask; + + (void)delete_lock(fn); /* that's MY file! */ + + mask = umask(0027); + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0640); + umask(mask); + if (fd == -1) return -1; + + if((f = fdopen(fd, "w")) == NULL) { + aclose(fd); + return -1; + } + g_fprintf(f, "%ld\n", pid); + if (fclose(f) == EOF) + return -1; + return 0; +} + +/* Read the pid out of a lock file. +** -1=error, otherwise pid. +*/ +static long +read_lock( + char * fn) /* name of lock file */ +{ + int save_errno; + FILE *f; + long pid; + + if ((f = fopen(fn, "r")) == NULL) { + return -1; + } + if (fscanf(f, "%ld", &pid) != 1) { + save_errno = errno; + afclose(f); + errno = save_errno; + return -1; + } + if (fclose(f) != 0) { + return -1; + } + return pid; +} + +/* Link a lock if we can. +** 0=done, 1=already locked, -1=error. +*/ +static int +link_lock( + char * lk, /* real lock file */ + char * tlk) /* temp lock file */ +{ + int rc; + int serrno; /* saved errno */ + struct stat lkstat, tlkstat; + + /* an atomic check and set operation */ + rc = link(tlk, lk); + if (rc == 0) return 0; /* XXX do we trust it? */ + + /* link() says it failed - don't beleive it */ + serrno = errno; + + if (stat(lk, &lkstat) == 0 && + stat(tlk, &tlkstat) == 0 && + lkstat.st_ino == tlkstat.st_ino) + return 0; /* it did work! */ + + errno = serrno; + + if (errno == EEXIST) rc = 1; + + return rc; +} + +/* Steal a lock if we can. +** 0=done; 1=still in use; -1 = error. +*/ +static int +steal_lock( + char * fn, /* name of lock file to steal */ + long mypid, /* my process id */ + char * sres) /* name of steal-resource to lock */ +{ + long pid; + int rc; + + /* prevent a race with another stealer */ + rc = ln_lock(sres, 1); + if (rc != 0) goto error; + + pid = read_lock(fn); + if (pid == -1) { + if (errno == ENOENT) goto done; + goto error; + } + + if (pid == mypid) goto steal; /* i'm the locker! */ + + /* are they still there ? */ + rc = kill((pid_t)pid, 0); + if (rc != 0) { + if (errno == ESRCH) goto steal; /* locker has gone */ + goto error; + } + + rc = ln_lock(sres, 0); + if (rc != 0) goto error; + + return 1; + +steal: + rc = delete_lock(fn); + if (rc != 0) goto error; + +done: + rc = ln_lock(sres, 0); + if (rc != 0) goto error; + + return 0; + +error: + rc = ln_lock(sres, 0); + + return -1; +} + +static int +ln_lock( + char * res, /* name of resource to lock */ + int op) /* true to lock; false to unlock */ +{ + long mypid; + char *lockfile = NULL; + char *tlockfile = NULL; + char *mres = NULL; + int rc; + char pid_str[NUM_STR_SIZE]; + + mypid = (long)getpid(); + + lockfile = vstralloc(_lnlock_dir, "/am", res, ".lock", NULL); + + if (!op) { + /* unlock the resource */ + assert(read_lock(lockfile) == mypid); + + (void)delete_lock(lockfile); + amfree(lockfile); + return 0; + } + + /* lock the resource */ + + g_snprintf(pid_str, SIZEOF(pid_str), "%ld", mypid); + tlockfile = vstralloc(_lnlock_dir, "/am", res, ".", pid_str, NULL); + + (void)create_lock(tlockfile, mypid); + + mres = stralloc2(res, "."); + + while(1) { + rc = link_lock(lockfile, tlockfile); + if (rc == -1) break; + if (rc == 0) break; + + rc = steal_lock(lockfile, mypid, mres); + if (rc == -1) break; + if (rc == 0) continue; + sleep(1); + } + + (void) delete_lock(tlockfile); + + amfree(mres); + amfree(tlockfile); + amfree(lockfile); + + return rc; +} + +static int +lnlock_lock( + G_GNUC_UNUSED int fd, + char *resource) +{ + return ln_lock(resource, 1); +} + +static int +lnlock_unlock( + G_GNUC_UNUSED int fd, + char *resource) +{ + return ln_lock(resource, 0); +} + +amflock_impl_t amflock_lnlock_impl = { + lnlock_lock, + lnlock_lock, /* no read-only support */ + lnlock_unlock, + "lnlock" +}; diff --git a/common-src/amflock-lockf.c b/common-src/amflock-lockf.c new file mode 100644 index 0000000..90af1ff --- /dev/null +++ b/common-src/amflock-lockf.c @@ -0,0 +1,76 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1998 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +/* moved from amflock.c by Dustin J. Mitchell */ + +#include "amanda.h" + +/* XPG4-UNIX (eg, SGI IRIX, DEC DU) has F_ULOCK instead of F_UNLOCK */ +#if defined(F_ULOCK) && !defined(F_UNLOCK) +# define F_UNLOCK F_ULOCK +#endif + +static int +lockf_lock( + int fd, + G_GNUC_UNUSED char *resource) +{ + return lockf(fd, F_LOCK, (off_t)0); +} + +static int +lockf_unlock( + int fd, + G_GNUC_UNUSED char *resource) +{ + off_t pos; + + /* unlock from here on */ + if (lockf(fd, F_UNLOCK, (off_t)0) == -1) return -1; + + /* unlock from bof to here */ + pos = lseek(fd, (off_t)0, SEEK_CUR); + if (pos == (off_t)-1) { + if (errno == ESPIPE) + pos = (off_t)0; + else + return -1; + } + + if (pos > (off_t)0) { + if (lockf(fd, F_UNLOCK, -pos) == -1) + return -1; + } + + return 0; +} + +amflock_impl_t amflock_lockf_impl = { + lockf_lock, + lockf_lock, /* no read-only support */ + lockf_unlock, + "lockf" +}; diff --git a/common-src/amflock-posix.c b/common-src/amflock-posix.c new file mode 100644 index 0000000..4e2af7b --- /dev/null +++ b/common-src/amflock-posix.c @@ -0,0 +1,78 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1998 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +/* moved from amflock.c by Dustin J. Mitchell */ + +#include "amanda.h" + +static int +posix_lock( + int fd, + G_GNUC_UNUSED char *resource) +{ + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; /* to EOF */ + return fcntl(fd, F_SETLKW, &lock); +} + +static int +posix_rolock( + int fd, + G_GNUC_UNUSED char *resource) +{ + struct flock lock; + + lock.l_type = F_RDLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; /* to EOF */ + return fcntl(fd, F_SETLKW, &lock); +} + +static int +posix_unlock( + int fd, + G_GNUC_UNUSED char *resource) +{ + struct flock lock; + + lock.l_type = F_UNLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; /* to EOF */ + return fcntl(fd, F_SETLK, &lock); +} + +amflock_impl_t amflock_posix_impl = { + posix_lock, + posix_rolock, + posix_unlock, + "posix" +}; diff --git a/common-src/amflock-test.c b/common-src/amflock-test.c new file mode 100644 index 0000000..4becf5c --- /dev/null +++ b/common-src/amflock-test.c @@ -0,0 +1,85 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1998 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +#include "amanda.h" + +/* from amflock.c */ +extern amflock_impl_t *amflock_impls[]; + +int +main(void) +{ + amflock_impl_t **imp = amflock_impls; + char *filename = "./amflocktest.file"; + char *resource = "rez"; + int fd; + int lock_ro; + + /* set lnlock's lock directory to the current directory */ + extern char *_lnlock_dir; + _lnlock_dir = "."; + + while (*imp) { + g_fprintf(stderr, _("Testing amflock-%s\n"), (*imp)->impl_name); + alarm(5); /* time out after 5 seconds */ + + for (lock_ro = 0; lock_ro < 2; lock_ro++) { /* false (0) or true (1) */ + if (unlink(filename) == -1 && errno != ENOENT) { + perror("unlink"); + return 1; + } + + if ((fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600)) == -1) { + perror("open"); + return 1; + } + + if (lock_ro) { + if ((*imp)->amroflock_impl(fd, resource) != 0) { + perror("amroflock"); + return 1; + } + } else { + if ((*imp)->amflock_impl(fd, resource) != 0) { + perror("amflock"); + return 1; + } + } + + if ((*imp)->amfunlock_impl(fd, resource) != 0) { + perror("amfunlock"); + return 1; + } + + close(fd); /* ignore error */ + unlink(filename); /* ignore error */ + } + + imp++; + } + + return 0; +} diff --git a/common-src/amflock.h b/common-src/amflock.h new file mode 100644 index 0000000..f9d33e1 --- /dev/null +++ b/common-src/amflock.h @@ -0,0 +1,53 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1999 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +/* Moved from amanda.h and amflock.c by Dustin J. Mitchell */ + +/* Public interface */ + +/* + * Get a file lock (for read/write files). + */ +int amflock(int fd, char *resource); + +/* + * Get a file lock (for read-only files). + */ +int amroflock(int fd, char *resource); + +/* + * Release a file lock. + */ +int amfunlock(int fd, char *resource); + +/* Implementation interface */ +typedef int (*amflock_fn)(int, char *); +typedef struct amflock_impl_s { + amflock_fn amflock_impl; + amflock_fn amroflock_impl; + amflock_fn amfunlock_impl; + char *impl_name; +} amflock_impl_t; diff --git a/common-src/amgpgcrypt.pl b/common-src/amgpgcrypt.pl new file mode 100755 index 0000000..2852670 --- /dev/null +++ b/common-src/amgpgcrypt.pl @@ -0,0 +1,80 @@ +#!@PERL@ -w +# +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com +# + +# Amanda has problem with gpg mdc(modification detection code) in the binary mode. +# This program encrypt with mdc disabled. +# If mdc is required, use --armor option. + + + +# Run perl. +eval '(exit $?0)' && eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' + & eval 'exec /usr/bin/perl -S $0 $argv:q' + if 0; + +use Time::Local; + +my $AMANDA='@CLIENT_LOGIN@'; +my $saw_sigint = 0; + +$AMANDA_HOME = (getpwnam($AMANDA) )[7] || die "Cannot find $AMANDA home directory\n" ; + +#The following two ($AM_PASS, $AM_PRIV) are needed only for restore/recover +#They should be protected and stored away during other time. +$AM_PASS = "$AMANDA_HOME/.am_passphrase"; +$AM_PRIV = "$AMANDA_HOME/.gnupg/secring.gpg"; + +$ENV{'PATH'} = '/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/csw/bin'; + +$ENV{'GNUPGHOME'} = "$AMANDA_HOME/.gnupg"; + +sub encrypt() { +# system "gpg --armor --encrypt --recipient $AMANDA"; + system "gpg --batch --disable-mdc --encrypt --cipher-algo AES256 --recipient $AMANDA"; +} + +sub decrypt() { + system "gpg --batch --quiet --no-mdc-warning --secret-keyring $AM_PRIV --decrypt --passphrase-fd 3 3<$AM_PASS"; +} + +sub my_sig_catcher { + $saw_sigint = 1; +} + +#main + + + +$SIG{'INT'} = 'my_sig_catcher'; + + +if ( $#ARGV > 0 ) { + die "Usage: $0 [-d]\n"; +} + +if ( $#ARGV==0 && $ARGV[0] eq "-d" ) { + decrypt(); +} +else { + encrypt(); +} + +$SIG{'INT'} = 'DEFAULT'; diff --git a/common-src/columnar.c b/common-src/columnar.c new file mode 100644 index 0000000..6a11dd7 --- /dev/null +++ b/common-src/columnar.c @@ -0,0 +1,154 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-2000 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: James da Silva, Systems Design and Analysis Group + * Computer Science Department + * University of Maryland at College Park + */ +/* + * Originally living in conffile.c, this stuff supports columnar output in amreport. + */ + + +#include "amanda.h" +#include "columnar.h" + +ColumnInfo ColumnData[] = { + { "HostName", 0, 12, 12, 0, "%-*.*s", "HOSTNAME" }, + { "Disk", 1, 11, 11, 0, "%-*.*s", "DISK" }, + { "Level", 1, 1, 1, 0, "%*.*d", "L" }, + { "OrigKB", 1, 7, 0, 0, "%*.*lf", "ORIG-KB" }, + { "OutKB", 1, 7, 0, 0, "%*.*lf", "OUT-KB" }, + { "Compress", 1, 6, 1, 0, "%*.*lf", "COMP%" }, + { "DumpTime", 1, 7, 7, 0, "%*.*s", "MMM:SS" }, + { "DumpRate", 1, 6, 1, 0, "%*.*lf", "KB/s" }, + { "TapeTime", 1, 6, 6, 0, "%*.*s", "MMM:SS" }, + { "TapeRate", 1, 6, 1, 0, "%*.*lf", "KB/s" }, + { NULL, 0, 0, 0, 0, NULL, NULL } +}; + + +int +ColumnDataCount(void ) +{ + return (int)(SIZEOF(ColumnData) / SIZEOF(ColumnData[0])); +} + +/* conversion from string to table index + */ +int +StringToColumn( + char *s) +{ + int cn; + + for (cn=0; ColumnData[cn].Name != NULL; cn++) { + if (strcasecmp(s, ColumnData[cn].Name) == 0) { + break; + } + } + return cn; +} + +char +LastChar( + char *s) +{ + return s[strlen(s)-1]; +} + +int +SetColumnDataFromString( + ColumnInfo* ci, + char *s, + char **errstr) +{ + ci = ci; + + /* Convert from a Columnspec string to our internal format + * of columspec. The purpose is to provide this string + * as configuration paramter in the amanda.conf file or + * (maybe) as environment variable. + * + * This text should go as comment into the sample amanda.conf + * + * The format for such a ColumnSpec string s is a ',' seperated + * list of triples. Each triple consists of + * -the name of the column (as in ColumnData.Name) + * -prefix before the column + * -the width of the column + * if set to -1 it will be recalculated + * to the maximum length of a line to print. + * Example: + * "Disk=1:17,HostName=1:10,OutKB=1:7" + * or + * "Disk=1:-1,HostName=1:10,OutKB=1:7" + * + * You need only specify those colums that should be changed from + * the default. If nothing is specified in the configfile, the + * above compiled in values will be in effect, resulting in an + * output as it was all the time. + * ElB, 1999-02-24. + */ + + while (s && *s) { + int Space, Width; + int cn; + char *eon= strchr(s, '='); + + if (eon == NULL) { + *errstr = stralloc2(_("invalid columnspec: "), s); + return -1; + } + *eon= '\0'; + cn=StringToColumn(s); + if (ColumnData[cn].Name == NULL) { + *errstr = stralloc2(_("invalid column name: "), s); + return -1; + } + if (sscanf(eon+1, "%d:%d", &Space, &Width) != 2) { + *errstr = stralloc2(_("invalid format: "), eon + 1); + return -1; + } + ColumnData[cn].Width= Width; + ColumnData[cn].PrefixSpace = Space; + if (LastChar(ColumnData[cn].Format) == 's') { + if (Width < 0) + ColumnData[cn].MaxWidth= 1; + else + if (Width > ColumnData[cn].Precision) + ColumnData[cn].Precision= Width; + } + else { + if (Width < 0) { + ColumnData[cn].MaxWidth= 1; + } + else if (Width < ColumnData[cn].Precision) + ColumnData[cn].Precision = Width; + } + s= strchr(eon+1, ','); + if (s != NULL) + s++; + } + return 0; +} + diff --git a/common-src/columnar.h b/common-src/columnar.h new file mode 100644 index 0000000..a9f54b8 --- /dev/null +++ b/common-src/columnar.h @@ -0,0 +1,60 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-2000 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: James da Silva, Systems Design and Analysis Group + * Computer Science Department + * University of Maryland at College Park + */ +/* + * Originally living in conffile.h, this stuff supports columnar output in amreport. + */ + +#ifndef COLUMNAR_H +#define COLUMNAR_H + +/* for each column we define some values on how to + * format this column element + */ +typedef struct { + char *Name; /* column name */ + int PrefixSpace; /* the blank space to print before this + * column. It is used to get the space + * between the colums + */ + int Width; /* the width of the column itself */ + int Precision; /* the precision if its a float */ + int MaxWidth; /* if set, Width will be recalculated + * to the space needed */ + char *Format; /* the printf format string for this + * column element + */ + char *Title; /* the title to use for this column */ +} ColumnInfo; + +extern ColumnInfo ColumnData[]; + +int ColumnDataCount(void); +int StringToColumn(char *s); +char LastChar(char *s); +int SetColumnDataFromString(ColumnInfo* ci, char *s, char **errstr); /* (sic) */ + +#endif /* COLUMNAR_H */ diff --git a/common-src/debug.h b/common-src/debug.h new file mode 100644 index 0000000..b3d539e --- /dev/null +++ b/common-src/debug.h @@ -0,0 +1,227 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1999 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ +/* + * $Id: debug.h 6789 2007-06-18 20:18:52Z dustin $ + * + * Logging support + */ + +/* this file is included from amanda.h; there is no need to include + * it explicitly in source files. */ + +#ifndef AMANDA_DEBUG_H +#define AMANDA_DEBUG_H + +/* + * GENERAL LOGGING + */ + +/* Amanda uses glib's logging facilities. See + * http://developer.gnome.org/doc/API/2.2/glib/glib-Message-Logging.html + * + * Note that log output will go to stderr until debug_open is called. + * + * The error levels are assigned as follows: + * g_error -- errors that should dump core (will not return) + * g_critical -- fatal errors, exiting with exit status in + * error_exit_status() (will not return) + * g_warning -- non-fatal problems + * g_message -- normal status information + * g_info -- helpful extra details, but not verbose + * g_debug -- debug messages + * + * g_error and g_critical will respect erroutput_type, potentially + * sending the error to the Amanda logfile for this run (see logfile.c). + */ + +/* g_debug was introduced in glib 2.6, so define it here for systems where + * it is lacking. g_info doesn't exist even in glib 2.13, but maybe it will + * be invented soon.. + */ + +#ifndef g_debug +#define g_debug(...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, __VA_ARGS__) +#endif + +#ifndef g_info +#define g_info(...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__) +#endif + +/* + * FATAL ERROR HANDLING + */ + +/* for compatibility; these should eventually be substituted throughout + * the codebase. Extra calls to exit() and abort() should be optimized + * away, and are there only for stupid compilers. */ +#define errordump(...) do { g_error(__VA_ARGS__); abort(); } while (0) +#define error(...) do { g_critical(__VA_ARGS__); exit(error_exit_status); } while (0) + +/* Additional handling for error and critical messages. */ +typedef enum { + /* send message to stderr (for interactive programs) */ + ERR_INTERACTIVE = 1 << 0, /* (default) */ + + /* log to syslog */ + ERR_SYSLOG = 1 << 1, + + /* add an L_FATAL entry in the Amanda logfile for the + * current run */ + ERR_AMANDALOG = 1 << 2 +} erroutput_type_t; +extern erroutput_type_t erroutput_type; + +/* The process exit status that will be given when error() + * or errordump() is called. + */ +extern int error_exit_status; + +/* Supply a pointer to the logfile module's logerror(), if + * ERR_AMANDALOG is set. + * + * This function is required because libamanda, which contains + * debug.c, is not always linked with the logerror module + * (which only appears in server applications). + * + * @param logerror_fn: function pointer + */ +void set_logerror(void (*logerror_fn)(char *)); + +/* + * DEBUG LOGGING + */ + +/* short names */ +#define dbopen(a) debug_open(a) +#define dbreopen(a,b) debug_reopen(a,b) +#define dbrename(a,b) debug_rename(a,b) +#define dbclose() debug_close() +#define dbprintf debug_printf +#define dbfd() debug_fd() +#define dbfp() debug_fp() +#define dbfn() debug_fn() + +/* constants for db(re)open */ +#define DBG_SUBDIR_SERVER "server" +#define DBG_SUBDIR_CLIENT "client" +#define DBG_SUBDIR_AMANDAD "amandad" + +/* Open the debugging log in the given subdirectory. Once + * this function is called, debug logging is available. + * + * The debugging file is created in the given subdirectory of the + * amanda debugging directory, with a filename based on the current + * process name (from get_pname). + * + * @param subdir: subdirectory in which to create the debug file. + * This is usually one of the DBG_SUBDIR_* constants. + */ +void debug_open(char *subdir); + +/* Re-open a previously debug_close()d debug file, given by + * filename, optionally adding a notation as to why it was + * reopened. + * + * @param file: the filename of the debug file to reopen + * @param notation: reason for re-opening the file + */ +void debug_reopen(char *file, char *notation); + +/* Rename the debugging logfile into a configuration-specific subdirectory + * of SUBDIR. Any existing content of the file will be preserved. + * + * @param config: configuration name + * @param subdir: subdirectory in which to create the debug file. + */ +void debug_rename(char *config, char *subdir); + +/* Flush and close the debugging logfile. Call this function at application + * shutdown. + */ +void debug_close(void); + +/* Add a message to the debugging logfile. A newline is not automatically + * added. + * + * This function is deprecated in favor of glib's g_debug(). + */ +void debug_printf(const char *format, ...) G_GNUC_PRINTF(1,2); + +/* Get the file descriptor for the debug file + * + * @returns: the file descriptor + */ +int debug_fd(void); + +/* Get the stdio file handle for the debug file. + * + * @returns: the file handle + */ +FILE * debug_fp(void); + +/* Get the pathname of the debug file. + * + * The result should not be freed by the caller. + * + * @returns: the pathname + */ +char * debug_fn(void); + +/* Use 'dup2' to send stderr output to the debug file. This is useful + * when launching other applications, where the stderr of those applications + * may be necessary for debugging. It should be called in the child, after + * the fork(). + */ +void debug_dup_stderr_to_debug(void); + +/* + * PROCESS NAME + */ + +/* + * ASSERTIONS + */ + +#ifndef SWIG +#ifdef ASSERTIONS + +/* Like the standard assert(), but call g_error() to log the result properly */ +#define assert(exp) do { \ + if (!(exp)) { \ + g_error(_("assert: %s is false: file %s, line %d"), \ + stringize(exp), __FILE__, __LINE__); \ + g_assert_not_reached(); \ + } \ +} while (0) + +#else /* ASSERTIONS */ + +#define assert(exp) ((void)0) + +#endif /* ASSERTIONS */ +#endif /* SWIG */ + +#endif /* AMANDA_DEBUG_H */ diff --git a/common-src/file.h b/common-src/file.h new file mode 100644 index 0000000..98e6f2b --- /dev/null +++ b/common-src/file.h @@ -0,0 +1,122 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1997-1998 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: AMANDA core development group. + */ + +extern int mkpdir(char *file, mode_t mode, uid_t uid, gid_t gid); +extern int rmpdir(char *file, char *topdir); + +/* Given a pathname, convert it to "canonical form" for this system. Currently, + * this means nothing on POSIX, but means substituting /cygdrive, etc. on Cygwin. + * + * @param pathname: the pathname to canonicalize + * @param result_buf (output): the canonicalize pathname; this should be a buffer of + * at least PATH_MAX bytes. + */ +void canonicalize_pathname(char *pathname, char *result_buf); + +extern char *sanitise_filename(char *inp); +char *old_sanitise_filename(char *inp); +void safe_fd(int fd_start, int fd_count); +void safe_cd(void); +void save_core(void); + +/* Get the uid of CLIENT_LOGIN, or -1 if it doesn't exist. Note that, if + * only running a server, CLIENT_LOGIN may legitimately not exist. + * + * @returns: userid, or -1 if invalid + */ +uid_t get_client_uid(void); + +/* Get the gid of CLIENT_LOGIN, or -1 if it doesn't exist. Note that, if + * only running a server, CLIENT_LOGIN may legitimately not exist. + * + * @returns: groupid, or -1 if invalid + */ +gid_t get_client_gid(void); + +extern /*@only@*/ /*@null@*/ char *debug_agets(const char *c, int l, FILE *file); +extern /*@only@*/ /*@null@*/ char *debug_areads(const char *c, int l, int fd); +#define agets(f) debug_agets(__FILE__,__LINE__,(f)) +#define areads(f) debug_areads(__FILE__,__LINE__,(f)) + +ssize_t areads_dataready(int fd); +void areads_relbuf(int fd); + +/* + * "Safe" close macros. Close the object then set it to a value that + * will cause an error if referenced. + * + * aclose(fd) -- close a file descriptor and set it to -1. + * afclose(f) -- close a stdio file and set it to NULL. + * apclose(p) -- close a stdio pipe file and set it to NULL. + * + * Note: be careful not to do the following: + * + * for(fd = low; fd < high; fd++) { + * aclose(fd); + * } + * + * Since aclose() sets the argument to -1, this will loop forever. + * Just copy fd to a temp variable and use that with aclose(). + * + * Aclose() interacts with areads() to inform it to release any buffer + * it has outstanding on the file descriptor. + */ + +#define aclose(fd) do { \ + if((fd) >= 0) { \ + close(fd); \ + areads_relbuf(fd); \ + } \ + (fd) = -1; \ +} while(0) + +#define afclose(f) do { \ + if((f) != NULL) { \ + fclose(f); \ + } \ + (f) = NULL; \ +} while(0) + +#define apclose(p) do { \ + if((p) != NULL) { \ + pclose(p); \ + } \ + (p) = NULL; \ +} while(0) + + +/* Calls system open(), but takes care of interrupted system calls and + * clears the close-on-exec bit. In the failure case, errno is + * retained from the final call to open(). */ +extern int robust_open(const char * pathname, int flags, mode_t mode); + +/* Same idea but for close. */ +extern int robust_close(int fd); + +/* Get the original working directory, at application startup + * + * @returns: pointer to statically allocated string + */ +char *get_original_cwd(void); diff --git a/common-src/genversion.h b/common-src/genversion.h new file mode 100644 index 0000000..316c245 --- /dev/null +++ b/common-src/genversion.h @@ -0,0 +1,3 @@ +#define CC "gcc" +#define BUILT_DATE "Fri Aug 22 14:21:05 EDT 2008" +#define BUILT_MACH "x86_64-unknown-linux-gnu" diff --git a/common-src/glib-util.c b/common-src/glib-util.c new file mode 100644 index 0000000..ec9728a --- /dev/null +++ b/common-src/glib-util.c @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* + * Utilities that aren't quite included in glib + * + * Author: Dustin J. Mitchell , Ian Turner + */ + +#include "amanda.h" +#include "glib-util.h" +#include "conffile.h" /* For find_multiplier. */ + +typedef enum { + FLAG_STRING_NAME, + FLAG_STRING_SHORT_NAME, + FLAG_STRING_NICK +} FlagString; + +static char ** g_flags_to_strv(int value, GType type, FlagString source); + +void +_glib_util_foreach_glue(gpointer data, gpointer func) +{ + void (*one_arg_fn)(gpointer) = (void (*)(gpointer))func; + one_arg_fn(data); +} + +GValue* g_value_unset_init(GValue* value, GType type) { + g_return_val_if_fail(value != NULL, NULL); + + if (G_IS_VALUE(value)) { + g_value_unset(value); + } + g_value_init(value, type); + return value; +} + +GValue* g_value_unset_copy(const GValue * from, GValue * to) { + g_return_val_if_fail(from != NULL, NULL); + g_return_val_if_fail(to != NULL, NULL); + + g_value_unset_init(to, G_VALUE_TYPE(from)); + g_value_copy(from, to); + return to; +} + +void g_list_free_full(GList * list) { + GList * cur = list; + + while (cur != NULL) { + gpointer data = cur->data; + amfree(data); + cur = g_list_next(cur); + } + + g_list_free(list); +} + +void g_slist_free_full(GSList * list) { + GSList * cur = list; + + while (cur != NULL) { + gpointer data = cur->data; + amfree(data); + cur = g_slist_next(cur); + } + + g_slist_free(list); +} + +void g_queue_free_full(GQueue * queue) { + while (!g_queue_is_empty(queue)) { + gpointer data; + data = g_queue_pop_head(queue); + amfree(data); + } + g_queue_free(queue); +} + +void g_ptr_array_free_full(GPtrArray * array) { + size_t i; + + for (i = 0; i < array->len; i ++) { + amfree(g_ptr_array_index(array, i)); + } + g_ptr_array_free(array, TRUE); +} + +gboolean g_value_compare(GValue * a, GValue * b) { + if (a == NULL && b == NULL) + return TRUE; + if (a == NULL || b == NULL) + return FALSE; + if (G_VALUE_TYPE(a) != G_VALUE_TYPE(b)) + return FALSE; + if (g_value_fits_pointer(a) && g_value_fits_pointer(b)) { + return g_value_peek_pointer(a) == g_value_peek_pointer(b); + } else { + /* Since there is no builtin comparison function, we resort to + comparing serialized strings. Yuck. */ + char * a_str; + char * b_str; + gboolean rval; + a_str = g_strdup_value_contents(a); + b_str = g_strdup_value_contents(b); + rval = (0 == strcmp(a_str, b_str)); + amfree(a_str); + amfree(b_str); + return rval; + } + + g_assert_not_reached(); +} + +static gboolean g_value_set_boolean_from_string(GValue * val, char * string) { + if (strcasecmp(string, "true") == 0 || + strcasecmp(string, "yes") == 0 || + strcmp(string, "1") == 0) { + g_value_set_boolean(val, TRUE); + } else if (strcasecmp(string, "false") == 0 || + strcasecmp(string, "no") == 0 || + strcmp(string, "0") == 0) { + g_value_set_boolean(val, FALSE); + } else { + return FALSE; + } + + return TRUE; +} + +static gboolean g_value_set_int_from_string(GValue * val, char * string) { + long int strto_result; + char * strto_end; + gint64 multiplier; + strto_result = strtol(string, &strto_end, 0); + multiplier = find_multiplier(strto_end); + if (multiplier == G_MAXINT64) { + if (strto_result >= 0) { + g_value_set_int(val, G_MAXINT); + } else { + g_value_set_int(val, G_MININT); + } + return TRUE; + } else if (*string == '\0' || multiplier == 0 + || strto_result < G_MININT / multiplier + || strto_result > G_MAXINT / multiplier) { + return FALSE; + } else { + g_value_set_int(val, (int)(strto_result * multiplier)); + return TRUE; + } +} + +static gboolean g_value_set_uint_from_string(GValue * val, char * string) { + unsigned long int strto_result; + char * strto_end; + guint64 multiplier; + strto_result = strtoul(string, &strto_end, 0); + multiplier = find_multiplier(strto_end); /* casts */ + if (multiplier == G_MAXINT64) { + g_value_set_uint(val, G_MAXUINT); + return TRUE; + } else if (multiplier == 0 || *string == '\0' || + strto_result > G_MAXUINT / multiplier) { + return FALSE; + } else { + g_value_set_uint(val, (guint)(strto_result * multiplier)); + return TRUE; + } +} + +static gboolean g_value_set_uint64_from_string(GValue * val, char * string) { + unsigned long long int strto_result; + char * strto_end; + guint64 multiplier; + strto_result = strtoull(string, &strto_end, 0); + multiplier = find_multiplier(strto_end); /* casts */ + if (multiplier == G_MAXINT64) { + g_value_set_uint64(val, G_MAXUINT64); + return TRUE; + } else if (multiplier == 0 || *string == '\0' || + strto_result > G_MAXUINT64 / multiplier) { + return FALSE; + } else { + g_value_set_uint64(val, (guint64)(strto_result * multiplier)); + return TRUE; + } +} + +/* Flags can contain multiple values. We assume here that values are like + * C identifiers (that is, they match /[A-Za-z_][A-Za-z0-9_]+/), although + * that doesn't seem to be a requirement of GLib. With that assumption in + * mind, we look for the format "FLAG_1 | FLAG_2 | ... | FLAG_N". */ +static gboolean g_value_set_flags_from_string(GValue * val, char * string) { + guint value = 0; + char * strtok_saveptr; + char * string_copy; + char * strtok_first_arg; + const char delim[] = " \t,|"; + GFlagsClass * flags_class; + + flags_class = (GFlagsClass*) g_type_class_ref(G_VALUE_TYPE(val)); + g_return_val_if_fail(flags_class != NULL, FALSE); + g_return_val_if_fail(G_IS_FLAGS_CLASS(flags_class), FALSE); + + /* Don't let strtok stop on original. */ + strtok_first_arg = string_copy = strdup(string); + + for (;;) { + GFlagsValue * flag_value; + char * token = strtok_r(strtok_first_arg, delim, &strtok_saveptr); + strtok_first_arg = NULL; + + if (token == NULL) { + break; + } + + flag_value = g_flags_get_value_by_name(flags_class, token); + if (flag_value == NULL) { + flag_value = g_flags_get_value_by_nick(flags_class, token); + } + if (flag_value == NULL) { + g_fprintf(stderr, _("Invalid flag %s for type %s\n"), token, + g_type_name(G_VALUE_TYPE(val))); + continue; + } + + value |= flag_value->value; + } + + amfree(string_copy); + + if (value == 0) { + g_fprintf(stderr, _("No valid flags for type %s in string %s\n"), + g_type_name(G_VALUE_TYPE(val)), string); + return FALSE; + } + + g_value_set_flags(val, value); + return TRUE; + +} + +/* This function really ought not to be part of Amanda. In my (Ian's) opinion, + serialization and deserialization should be a part of the GValue + interface. But it's not, and here we are. */ +gboolean g_value_set_from_string(GValue * val, char * string) { + g_return_val_if_fail(val != NULL, FALSE); + g_return_val_if_fail(G_IS_VALUE(val), FALSE); + + if (G_VALUE_HOLDS_BOOLEAN(val)) { + return g_value_set_boolean_from_string(val, string); + } else if (G_VALUE_HOLDS_INT(val)) { + return g_value_set_int_from_string(val, string); + } else if (G_VALUE_HOLDS_UINT(val)) { + return g_value_set_uint_from_string(val, string); + } else if (G_VALUE_HOLDS_UINT64(val)) { + return g_value_set_uint64_from_string(val, string); + } else if (G_VALUE_HOLDS_STRING(val)) { + g_value_set_string(val, string); + return TRUE; + } else if (G_VALUE_HOLDS_FLAGS(val)) { + return g_value_set_flags_from_string(val, string); + } + + return TRUE; +} + +gint +g_compare_strings( + gconstpointer a, + gconstpointer b) +{ + return strcmp((char *)a, (char *)b); +} + +char * g_strjoinv_and_free(char ** strv, const char * seperator) { + char * rval = g_strjoinv(seperator, strv); + g_strfreev(strv); + return rval; +} + +char ** g_flags_name_to_strv(int value, GType type) { + return g_flags_to_strv(value, type, FLAG_STRING_NAME); +} + +char ** g_flags_short_name_to_strv(int value, GType type) { + return g_flags_to_strv(value, type, FLAG_STRING_SHORT_NAME); +} + +char ** g_flags_nick_to_strv(int value, GType type) { + return g_flags_to_strv(value, type, FLAG_STRING_NICK); +} + +static char * get_name_from_value(GFlagsValue * value, FlagString source) { + switch (source) { + case FLAG_STRING_NAME: + case FLAG_STRING_SHORT_NAME: + return strdup(value->value_name); + case FLAG_STRING_NICK: + return strdup(value->value_nick); + default: + return NULL; + } +} + +/* If freed and notfreed have a common prefix that is different from freed, + then return that and free freed. Otherwise, return freed. */ +static char * find_common_prefix(char * freed, const char * notfreed) { + char * freed_ptr = freed; + const char * notfreed_ptr = notfreed; + + if (freed == NULL) { + if (notfreed == NULL) { + return NULL; + } else { + return strdup(notfreed); + } + } else if (notfreed == NULL) { + amfree(freed); + return strdup(""); + } + + while (*freed_ptr == *notfreed_ptr) { + freed_ptr ++; + notfreed_ptr ++; + } + + *freed_ptr = '\0'; + return freed; +} + +static char ** g_flags_to_strv(int value, GType type, + FlagString source) { + GPtrArray * rval; + GFlagsValue * flagsvalue; + char * common_prefix = NULL; + int common_prefix_len; + GFlagsClass * class; + + g_return_val_if_fail(G_TYPE_IS_FLAGS(type), NULL); + g_return_val_if_fail((class = g_type_class_ref(type)) != NULL, NULL); + g_return_val_if_fail(G_IS_FLAGS_CLASS(class), NULL); + + rval = g_ptr_array_new(); + for (flagsvalue = class->values; + flagsvalue->value_name != NULL; + flagsvalue ++) { + if (source == FLAG_STRING_SHORT_NAME) { + common_prefix = find_common_prefix(common_prefix, + flagsvalue->value_name); + } + + if ((flagsvalue->value == 0 && value == 0) || + (flagsvalue->value != 0 && (value & flagsvalue->value))) { + g_ptr_array_add(rval, get_name_from_value(flagsvalue, source)); + } + } + + if (source == FLAG_STRING_SHORT_NAME && common_prefix != NULL && + ((common_prefix_len = strlen(common_prefix))) > 0) { + char * old; + char * new; + guint i; + for (i = 0; i < rval->len; i ++) { + old = g_ptr_array_index(rval, i); + new = strdup(old + common_prefix_len); + g_ptr_array_index(rval, i) = new; + g_free(old); + } + } + + g_ptr_array_add(rval, NULL); + + amfree(common_prefix); + return (char**)g_ptr_array_free(rval, FALSE); +} + +char * g_english_strjoinv(char ** strv, const char * conjunction) { + int length; + char * last; + char * joined; + char * rval; + strv = g_strdupv(strv); + + length = g_strv_length(strv); + last = strv[length - 1]; + strv[length - 1] = NULL; + + joined = g_strjoinv(", ", strv); + rval = g_strdup_printf("%s, %s %s", joined, conjunction, last); + + g_free(joined); + g_free(last); + g_strfreev(strv); + return rval; +} + +char * g_english_strjoinv_and_free(char ** strv, const char * conjunction) { + char * rval = g_english_strjoinv(strv, conjunction); + g_strfreev(strv); + return rval; +} + +#if !(GLIB_CHECK_VERSION(2,6,0)) +guint g_strv_length(gchar ** strv) { + int rval = 0; + + if (G_UNLIKELY(strv == NULL)) + return 0; + + while (*strv != NULL) { + rval ++; + strv ++; + } + return rval; +} + +#endif /* GLIB_CHECK_VERSION(2.6.0) */ diff --git a/common-src/glib-util.h b/common-src/glib-util.h new file mode 100644 index 0000000..3151d2b --- /dev/null +++ b/common-src/glib-util.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ +/* + * Utilities that aren't quite included in glib + * + * Author: Dustin J. Mitchell , Ian Turner + */ + +#ifndef GLIB_UTIL_H +#define GLIB_UTIL_H + +#include +#include + +/* like g_[s]list_foreach, but with a function taking only + * one argument. + */ +#define g_list_foreach_nodata(list, func) \ + g_list_foreach((list), _glib_util_foreach_glue, (gpointer)(func)); +#define g_slist_foreach_nodata(list, func) \ + g_slist_foreach((list), _glib_util_foreach_glue, (gpointer)(func)); +void _glib_util_foreach_glue(gpointer data, gpointer func); + +/* This function takes a GValue, which may be zero-filled or + * initialized. In either case, this function causes the GValue to be + * initialized with the given type. Note that this function lacks the + * safety of the standard g_value_ functions; it assumes that the + * passed value is zeroed or valid. + * + * Returns its first argument.*/ +GValue* g_value_unset_init(GValue* val, GType type); + +/* This does the same thing but also copies the contents of one value + * into another. Note that this function lacks the safety of the + * standard g_value_ functions; it assumes that the passed value is + * zeroed or valid. + * + * Returns its second (reset) argument.*/ +GValue* g_value_unset_copy(const GValue* from, GValue * to); + +/* These functions all take a GLib container, and call free() on all the + * pointers in the container before free()ing the container itself. */ +void g_list_free_full(GList * list); +void g_slist_free_full(GSList * list); +void g_queue_free_full(GQueue * queue); +void g_ptr_array_free_full(GPtrArray * array); + +/* g_value_compare() does what you expect. It returns TRUE if and + only if the two values have the same type and the same value. Note + that it will return FALSE if the same value is stored with two + different types: For example, a GValue with a UCHAR of 1 and a + GValue with a CHAR of 1 will be considered inequal. Also, this is a + 'shallow' comparison; pointers to distinct but equivalent objects + are considered inequal. */ +gboolean g_value_compare(GValue * a, GValue * b); + +/* Given a string and a GValue, parse the string and store it in the + GValue. The GValue should be pre-initalized to whatever type you want + parsed. */ +gboolean g_value_set_from_string(GValue * val, char * string); + +/* A GCompareFunc that will sort strings alphabetically (using strcmp) */ +gint g_compare_strings(gconstpointer a, gconstpointer b); + +/* These functions all take a Flags class and stringify it. They + * return a NULL-terminated array of strings that can be + * passed to g_strjoinv(), g_strfreev(), g_strdupv(), and + * g_strv_length(). Example output looks like: + * - g_flags_name_to_strv() -> "MEDIA_ACCESS_MODE_READ_ONLY" + * - g_flags_short_name_to_strv() -> "READ_ONLY" + * - g_flags_nick_to_strv() -> "read-only" + */ + +char ** g_flags_name_to_strv(int value, GType type); +char ** g_flags_short_name_to_strv(int value, GType type); +char ** g_flags_nick_to_strv(int value, GType type); + +/* Just like g_strjoinv, but frees the array as well. */ +char * g_strjoinv_and_free(char ** strv, const char * seperator); + +/* Just like g_strjoinv, but joins like an English list. The string would + * usually be "and" or "or". */ +char * g_english_strjoinv(char ** strv, const char * conjunction); + +/* Just like g_english_strjoinv, but also frees the array. */ +char * g_english_strjoinv_and_free(char ** strv, const char * conjunction); + +/* Replacement for built-in functions. */ +#if !(GLIB_CHECK_VERSION(2,6,0)) +guint g_strv_length(gchar ** strv); +#endif + +#endif + diff --git a/common-src/local-security.c b/common-src/local-security.c new file mode 100644 index 0000000..29a946d --- /dev/null +++ b/common-src/local-security.c @@ -0,0 +1,264 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1999 University of Maryland + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +/* + * $Id: local-security.c 6512 2007-05-24 17:00:24Z ian $ + * + * local-security.c - security and transport over local or a local-like command. + * + * XXX still need to check for initial keyword on connect so we can skip + * over shell garbage and other stuff that local might want to spew out. + */ + +#include "amanda.h" +#include "util.h" +#include "event.h" +#include "packet.h" +#include "queue.h" +#include "security.h" +#include "security-util.h" +#include "stream.h" +#include "version.h" + +/* + * Number of seconds amandad has to start up + */ +#define CONNECT_TIMEOUT 20 + +/* + * Interface functions + */ +static void local_connect(const char *, char *(*)(char *, void *), + void (*)(void *, security_handle_t *, security_status_t), + void *, void *); + +/* + * This is our interface to the outside world. + */ +const security_driver_t local_security_driver = { + "LOCAL", + local_connect, + sec_accept, + sec_close, + stream_sendpkt, + stream_recvpkt, + stream_recvpkt_cancel, + tcpma_stream_server, + tcpma_stream_accept, + tcpma_stream_client, + tcpma_stream_close, + sec_stream_auth, + sec_stream_id, + tcpm_stream_write, + tcpm_stream_read, + tcpm_stream_read_sync, + tcpm_stream_read_cancel, + tcpm_close_connection, + NULL, + NULL +}; + +static int newhandle = 1; + +/* + * Local functions + */ +static int runlocal(struct tcp_conn *, const char *, const char *); + + +/* + * local version of a security handle allocator. Logically sets + * up a network "connection". + */ +static void +local_connect( + const char * hostname, + char * (*conf_fn)(char *, void *), + void (*fn)(void *, security_handle_t *, security_status_t), + void * arg, + void * datap) +{ + struct sec_handle *rh; + char *amandad_path=NULL; + char *client_username=NULL; + char myhostname[MAX_HOSTNAME_LENGTH+1]; + + assert(fn != NULL); + assert(hostname != NULL); + + auth_debug(1, _("local: local_connect: %s\n"), hostname); + + rh = alloc(SIZEOF(*rh)); + security_handleinit(&rh->sech, &local_security_driver); + rh->hostname = NULL; + rh->rs = NULL; + rh->ev_timeout = NULL; + rh->rc = NULL; + + if (gethostname(myhostname, MAX_HOSTNAME_LENGTH) == -1) { + security_seterror(&rh->sech, _("gethostname failed")); + (*fn)(arg, &rh->sech, S_ERROR); + return; + } + myhostname[SIZEOF(myhostname)-1] = '\0'; + + if (strcmp(hostname, myhostname) != 0 && + match("^localhost(\\.localdomain)?$", hostname) == 0) { + security_seterror(&rh->sech, + _("%s: is not local"), hostname); + (*fn)(arg, &rh->sech, S_ERROR); + return; + } + rh->hostname = stralloc(hostname); + rh->rs = tcpma_stream_client(rh, newhandle++); + + if (rh->rs == NULL) + goto error; + + amfree(rh->hostname); + rh->hostname = stralloc(rh->rs->rc->hostname); + + /* + * We need to open a new connection. + * + * XXX need to eventually limit number of outgoing connections here. + */ + if(conf_fn) { + amandad_path = conf_fn("amandad_path", datap); + client_username = conf_fn("client_username", datap); + } + if(rh->rc->read == -1) { + if (runlocal(rh->rs->rc, amandad_path, client_username) < 0) { + security_seterror(&rh->sech, _("can't connect to %s: %s"), + hostname, rh->rs->rc->errmsg); + goto error; + } + rh->rc->refcnt++; + } + + /* + * The socket will be opened async so hosts that are down won't + * block everything. We need to register a write event + * so we will know when the socket comes alive. + * + * Overload rh->rs->ev_read to provide a write event handle. + * We also register a timeout. + */ + rh->fn.connect = fn; + rh->arg = arg; + rh->rs->ev_read = event_register((event_id_t)rh->rs->rc->write, EV_WRITEFD, + sec_connect_callback, rh); + rh->ev_timeout = event_register((event_id_t)CONNECT_TIMEOUT, EV_TIME, + sec_connect_timeout, rh); + + return; + +error: + (*fn)(arg, &rh->sech, S_ERROR); +} + +/* + * Forks a local to the host listed in rc->hostname + * Returns negative on error, with an errmsg in rc->errmsg. + */ +static int +runlocal( + struct tcp_conn * rc, + const char * amandad_path, + const char * client_username) +{ + int rpipe[2], wpipe[2]; + char *xamandad_path = (char *)amandad_path; + +#ifndef SINGLE_USERID + struct passwd *pwd = NULL; + uid_t uid = 0; + gid_t gid = 0; + + if (getuid() == 0) { + if (client_username && strlen(client_username) > 1) { + pwd = getpwnam(client_username); + if (!pwd) { + dbprintf("User '%s' doesn't exist\n", client_username); + } else { + uid = pwd->pw_uid; + gid = pwd->pw_gid; + } + } + if (!pwd) { + uid = get_client_uid(); + gid = get_client_gid(); + } + } +#endif + + memset(rpipe, -1, SIZEOF(rpipe)); + memset(wpipe, -1, SIZEOF(wpipe)); + if (pipe(rpipe) < 0 || pipe(wpipe) < 0) { + rc->errmsg = newvstrallocf(rc->errmsg, _("pipe: %s"), strerror(errno)); + return (-1); + } + + switch (rc->pid = fork()) { + case -1: + rc->errmsg = newvstrallocf(rc->errmsg, _("fork: %s"), strerror(errno)); + aclose(rpipe[0]); + aclose(rpipe[1]); + aclose(wpipe[0]); + aclose(wpipe[1]); + return (-1); + case 0: + dup2(wpipe[0], 0); + dup2(rpipe[1], 1); + break; + default: + rc->read = rpipe[0]; + aclose(rpipe[1]); + rc->write = wpipe[1]; + aclose(wpipe[0]); + return (0); + } + + safe_fd(-1, 0); + + if(!xamandad_path || strlen(xamandad_path) <= 1) + xamandad_path = vstralloc(amlibexecdir, "/", "amandad", + versionsuffix(), NULL); + +#ifndef SINGLE_USERID + if (uid != 0) + setreuid(uid, uid); + if (gid != 0) + setregid(gid, gid); +#endif + + execlp(xamandad_path, xamandad_path, + "-auth=local", "amdump", "amindexd", "amidxtaped", (char *)NULL); + error(_("error: couldn't exec %s: %s"), xamandad_path, strerror(errno)); + + /* should never go here, shut up compiler warning */ + return(-1); +} diff --git a/common-src/sockaddr-util.c b/common-src/sockaddr-util.c new file mode 100644 index 0000000..ffc6ca2 --- /dev/null +++ b/common-src/sockaddr-util.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2005 Zmanda Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + * + * Author: Dustin J. Mitchell + */ +/* + * Utility routines for handling sockaddrs + */ + +#include "sockaddr-util.h" + +void +dump_sockaddr( + sockaddr_union *sa) +{ +#ifdef WORKING_IPV6 + char ipstr[INET6_ADDRSTRLEN]; +#else + char ipstr[INET_ADDRSTRLEN]; +#endif + int port; + + port = SU_GET_PORT(sa); +#ifdef WORKING_IPV6 + if (SU_GET_FAMILY(sa) == AF_INET6) { + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr)); + dbprintf("(sockaddr_in6 *)%p = { %d, %d, %s }\n", + sa, + SU_GET_FAMILY(sa), + port, + ipstr); + } else +#endif + { + inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr)); + dbprintf("(sockaddr_in *)%p = { %d, %d, %s }\n", + sa, + SU_GET_FAMILY(sa), + port, + ipstr); + } +} + + +#ifdef WORKING_IPV6 +static char mystr_sockaddr[INET6_ADDRSTRLEN + 20]; +#else +static char mystr_sockaddr[INET_ADDRSTRLEN + 20]; +#endif + +char * +str_sockaddr( + sockaddr_union *sa) +{ +#ifdef WORKING_IPV6 + char ipstr[INET6_ADDRSTRLEN]; +#else + char ipstr[INET_ADDRSTRLEN]; +#endif + int port; + + port = SU_GET_PORT(sa); +#ifdef WORKING_IPV6 + if ( SU_GET_FAMILY(sa) == AF_INET6) { + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr)); + } else +#endif + { + inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr)); + } + g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s.%d", ipstr, port); + mystr_sockaddr[sizeof(mystr_sockaddr)-1] = '\0'; + + return mystr_sockaddr; +} + +/* Unmap a V4MAPPED IPv6 address into its equivalent IPv4 address. The location + * TMP is used to store the rewritten address, if necessary. Returns a pointer + * to the unmapped address. + */ +#if defined(WORKING_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) +static sockaddr_union * +unmap_v4mapped( + sockaddr_union *sa, + sockaddr_union *tmp) +{ + if (SU_GET_FAMILY(sa) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) { + SU_INIT(tmp, AF_INET); + SU_SET_PORT(tmp, SU_GET_PORT(sa)); + /* extract the v4 address from byte 12 of the v6 address */ + memcpy(&tmp->sin.sin_addr.s_addr, + &sa->sin6.sin6_addr.s6_addr[12], + sizeof(struct in_addr)); + return tmp; + } + + return sa; +} +#else +/* nothing to do if no IPv6 */ +#define unmap_v4mapped(sa, tmp) ((void)tmp, sa) +#endif + +int +cmp_sockaddr( + sockaddr_union *ss1, + sockaddr_union *ss2, + int addr_only) +{ + sockaddr_union tmp1, tmp2; + + /* if addresses are v4mapped, "unmap" them */ + ss1 = unmap_v4mapped(ss1, &tmp1); + ss2 = unmap_v4mapped(ss2, &tmp2); + + if (SU_GET_FAMILY(ss1) == SU_GET_FAMILY(ss2)) { + if (addr_only) { +#ifdef WORKING_IPV6 + if(SU_GET_FAMILY(ss1) == AF_INET6) + return memcmp( + &ss1->sin6.sin6_addr, + &ss2->sin6.sin6_addr, + sizeof(ss1->sin6.sin6_addr)); + else +#endif + return memcmp( + &ss1->sin.sin_addr, + &ss2->sin.sin_addr, + sizeof(ss1->sin.sin_addr)); + } else { + return memcmp(ss1, ss2, SS_LEN(ss1)); + } + } else { + /* compare families to give a total order */ + if (SU_GET_FAMILY(ss1) < SU_GET_FAMILY(ss2)) + return -1; + else + return 1; + } +} + diff --git a/common-src/sockaddr-util.h b/common-src/sockaddr-util.h new file mode 100644 index 0000000..977c4f9 --- /dev/null +++ b/common-src/sockaddr-util.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2005 Zmanda Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + * + * Author: Dustin J. Mitchell + */ +/* + * Utility routines for handling sockaddrs + */ + +#ifndef SOCKADDR_UTIL_H +#define SOCKADDR_UTIL_H + +#include "amanda.h" + +/* Dump a sockaddr_union using dbprintf + * + * @param sa: the sockaddr to dump + */ +void dump_sockaddr(sockaddr_union * sa); + +/* Convert a sockaddr_union to a string. + * + * NOTE: this function is not threadsafe! + * + * @param sa: the sockaddr_union to dump + * @returns: pointer to statically allocated string + */ +char * str_sockaddr(sockaddr_union *sa); + +/* Compare two sockaddr_union objects, optionally comparing + * only the address (and thus ignoring port, flow info, etc.). + * + * @param su1: one sockaddr_union to compare + * @param su2: the other sockaddr_union to compare + * @param addr_only: if true, ignore port, flow info, etc. + * @returns: -1, 0, or 1 for <, ==, >, respectively + */ +int cmp_sockaddr(sockaddr_union *su1, + sockaddr_union *su2, + int addr_only); + +/* Copy a sockaddr object. + * + * @param dest: destination + * @param src: source + */ +#define copy_sockaddr(dest, src) memcpy((dest), (src), SS_LEN((src))) + +/* The "best" address family we support. + */ +/* AF_NATIVE */ +#ifdef WORKING_IPV6 +#define AF_NATIVE AF_INET6 +#else +#define AF_NATIVE AF_INET +#endif + +/* Get the family for a sockaddr_union. + * + * @param su: the sockaddr_union to examine + */ +#define SU_GET_FAMILY(su) ((su)->sa.sa_family) +/* Calculate the length of the data in a sockaddr_union. + * + * @param su: the sockaddr_union to examine + * @returns: length of the data in the object + */ +/* SS_LEN(su) */ +#ifdef WORKING_IPV6 +# define SS_LEN(su) (SU_GET_FAMILY(su)==AF_INET6? sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) +#else +# define SS_LEN(su) (sizeof(struct sockaddr_in)) +#endif + +/* Initialize a sockaddr_union to all zeroes (as directed by RFC), + * and set its address family as specified + * + * @param su: sockaddr_union object to initialize + * @param family: an AF_* constant + */ +/* SU_INIT(su, family) */ +#define SU_INIT(su, family) do { \ + memset((su), 0, sizeof(*(su))); \ + (su)->sa.sa_family = (family); \ +} while (0); + +/* set a sockaddr_union to the family-appropriate equivalent of + * INADDR_ANY -- a wildcard address and port. Call SU_INIT(su) + * first to initialize the object and set the family. + * + * @param su: the sockaddr_union to set + */ +/* SU_SET_INADDR_ANY(su) */ +#ifdef WORKING_IPV6 +#define SU_SET_INADDR_ANY(su) do { \ + switch (SU_GET_FAMILY(su)) { \ + case AF_INET6: \ + (su)->sin6.sin6_flowinfo = 0; \ + (su)->sin6.sin6_addr = in6addr_any; \ + break; \ + case AF_INET: \ + (su)->sin.sin_addr.s_addr = INADDR_ANY; \ + break; \ + } \ +} while (0); +#else +#define SU_SET_INADDR_ANY(su) do { \ + (su)->sin.sin_addr.s_addr = INADDR_ANY; \ +} while (0); +#endif + +/* Set the port in a sockaddr_union that already has an family + * + * @param su: the sockaddr_union to manipulate + * @param port: the port to insert (in host byte order) + */ +/* SU_SET_PORT(su, port) */ +#ifdef WORKING_IPV6 +#define SU_SET_PORT(su, port) \ +switch (SU_GET_FAMILY(su)) { \ + case AF_INET: \ + (su)->sin.sin_port = (in_port_t)htons((port)); \ + break; \ + case AF_INET6: \ + (su)->sin6.sin6_port = (in_port_t)htons((port)); \ + break; \ + default: assert(0); \ +} +#else +#define SU_SET_PORT(su, port) \ + (su)->sin.sin_port = (in_port_t)htons((port)); +#endif + +/* Get the port in a sockaddr_union object + * + * @param su: the sockaddr_union to manipulate + * @return: the port, in host byte horder + */ +/* SU_GET_PORT(su) */ +#ifdef WORKING_IPV6 +#define SU_GET_PORT(su) (ntohs(SU_GET_FAMILY(su) == AF_INET6? (su)->sin6.sin6_port:(su)->sin.sin_port)) +#else +#define SU_GET_PORT(su) (ntohs((su)->sin.sin_port)) +#endif + +#endif /* SOCKADDR_UTIL_H */ diff --git a/common-src/svn-info.h b/common-src/svn-info.h new file mode 100644 index 0000000..5357aaf --- /dev/null +++ b/common-src/svn-info.h @@ -0,0 +1,2 @@ +#define BUILT_REV "1266" +#define BUILT_BRANCH "amanda-260" diff --git a/common-src/tapelist.h~HEAD b/common-src/tapelist.h~HEAD new file mode 100644 index 0000000..e6b58e2 --- /dev/null +++ b/common-src/tapelist.h~HEAD @@ -0,0 +1,61 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1998 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ +/* + * $Id: tapelist.h,v 1.2 2006/05/25 01:47:12 johnfranks Exp $ + * + */ + +#ifndef TAPELIST_H +#define TAPELIST_H + +#include "amanda.h" + +/* XXX This looks like a lot of other things, apart from the string + * marshalling and unmarshalling. Things like the EXTRACT_LIST in amrecover's + * innards are functionally similar, so there's probably a lot of opportunity + * to pare down extraneous code here by mushing things like that in. Rainy + * day project, perhaps. + */ + +typedef struct tapelist_s { + struct tapelist_s *next; + char *label; + int isafile; /* set to 1 and make *label the path to the file */ + off_t *files; + int numfiles; +} tapelist_t; + +int num_entries(tapelist_t *tapelist); +tapelist_t *append_to_tapelist(tapelist_t *tapelist, char *label, + off_t file, int isafile); +char *marshal_tapelist(tapelist_t *tapelist, int escape); +tapelist_t *unmarshal_tapelist_str(char *tapelist_str); +char *escape_label(char *label); +char *unescape_label(char *label); +void free_tapelist(tapelist_t *tapelist); +void dump_tapelist(tapelist_t *); + +#endif /* !TAPELIST_H */ diff --git a/common-src/timestamp.c b/common-src/timestamp.c new file mode 100644 index 0000000..dfeec75 --- /dev/null +++ b/common-src/timestamp.c @@ -0,0 +1,82 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1999 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ + +#include "timestamp.h" +#include "conffile.h" +#include + +/* + * Construct a datestamp (YYYYMMDD) from a time_t. + */ +char * get_datestamp_from_time(time_t when) { + struct tm *tm; + + if(when == (time_t)0) { + when = time((time_t *)NULL); + } + + tm = localtime(&when); + return g_strdup_printf("%04d%02d%02d", + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); +} + +/* + * Construct a timestamp (YYYYMMDDHHMMSS) from a time_t. + */ +char * get_timestamp_from_time(time_t when) { + struct tm *tm; + + if(when == (time_t)0) { + when = time((time_t *)NULL); + } + + tm = localtime(&when); + return g_strdup_printf("%04d%02d%02d%02d%02d%02d", + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +char * get_proper_stamp_from_time(time_t when) { + if (getconf_boolean(CNF_USETIMESTAMPS)) { + return get_timestamp_from_time(when); + } else { + return get_datestamp_from_time(when); + } +} + +time_state_t get_timestamp_state(char * timestamp) { + if (timestamp == NULL || *timestamp == '\0') { + return TIME_STATE_REPLACE; + } else if (strcmp(timestamp, "X") == 0) { + return TIME_STATE_UNDEF; + } else { + return TIME_STATE_SET; + } +} + +char * get_undef_timestamp(void) { + return strdup("X"); +} diff --git a/common-src/timestamp.h b/common-src/timestamp.h new file mode 100644 index 0000000..81a3b9e --- /dev/null +++ b/common-src/timestamp.h @@ -0,0 +1,58 @@ +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991-1999 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: the Amanda Development Team. Its members are listed in a + * file named AUTHORS, in the root directory of this distribution. + */ +/* + * $Id$ + * + * Date and time utility functions + */ + +#ifndef TIMESTAMP_H +#define TIMESTAMP_H + +#include "amanda.h" + +/* These functions do the opposite; they formats a time_t for + network or media storage. The return value is allocated with + malloc(). If time == 0, then these functions will use the current + time. */ +char * get_timestamp_from_time(time_t time); +char * get_datestamp_from_time(time_t time); +char * get_proper_stamp_from_time(time_t time); + +typedef enum { + TIME_STATE_REPLACE, + TIME_STATE_UNDEF, + TIME_STATE_SET +} time_state_t; + +/* Returns the state of a timestamp. */ +time_state_t get_timestamp_state(char * timestamp); + +/* Returns a "X" timestamp. */ +char * get_undef_timestamp(void); + +#endif /* TIMESTAMP_H */ + diff --git a/config/amanda/amplot.m4 b/config/amanda/amplot.m4 new file mode 100644 index 0000000..fba1884 --- /dev/null +++ b/config/amanda/amplot.m4 @@ -0,0 +1,56 @@ +# OVERVIEW +# +# 'amplot' is largely pieced together by the instantiation phase of +# configure; that is handled here. + +# SYNOPSIS +# +# AMANDA_SETUP_AMPLOT +# +# DESCRIPTION +# +# Check for the requirements for amplot, and set the Automake conditional +# WANT_AMPLOT appropriately. If amplot is to be built, then also set up +# the required substitutions to build it correctly. +# +AC_DEFUN([AMANDA_SETUP_AMPLOT], +[ + AC_REQUIRE([AMANDA_PROG_GNUPLOT]) + AC_REQUIRE([AMANDA_PROG_PCAT]) + AC_REQUIRE([AMANDA_PROG_COMPRESS]) + AC_REQUIRE([AMANDA_PROG_GZIP]) + AC_REQUIRE([AC_PROG_AWK]) + + if test "x$GNUPLOT" != "x"; then + WANT_AMPLOT=true + + # variable substitutions for amcat.awk + if test "$PCAT"; then + AMPLOT_CAT_PACK="if(o==\"z\")print \"$PCAT\"; else" + else + AMPLOT_CAT_PACK= + fi + if test "$COMPRESS"; then + AMPLOT_COMPRESS=$COMPRESS + AMPLOT_CAT_COMPRESS="if(o==\"Z\")print \"$COMPRESS -dc\"; else" + else + AMPLOT_CAT_COMPRESS= + fi + if test "$GZIP"; then + AMPLOT_COMPRESS=$GZIP + AMPLOT_CAT_GZIP="if(o==\"gz\")print \"$GZIP -dc\"; else" + else + AMPLOT_CAT_GZIP= + fi + + AC_SUBST(AMPLOT_COMPRESS) + AC_SUBST(AMPLOT_CAT_GZIP) + AC_SUBST(AMPLOT_CAT_COMPRESS) + AC_SUBST(AMPLOT_CAT_PACK) + else + WANT_AMPLOT=false + AMANDA_MSG_WARN([Not building 'amplot', because gnuplot was not found]) + fi + + AM_CONDITIONAL(WANT_AMPLOT, test x"$WANT_AMPLOT" = x"true") +]) diff --git a/config/amanda/bsd-security.m4 b/config/amanda/bsd-security.m4 new file mode 100644 index 0000000..a376707 --- /dev/null +++ b/config/amanda/bsd-security.m4 @@ -0,0 +1,58 @@ +# SYNOPSIS +# +# AMANDA_BSD_SECURITY +# +# OVERVIEW +# +# Handle configuration for BSD security, implementing the +# --without-bsd-security option. Also supplies the --without-amandahosts +# option to use .rhosts instead of .amandahosts +# +# Note that the defaults for *both* of these options are "yes", unlike +# the remainder of the security implementations. +# +# Defines BSD_SECURITY, and sets AM_CONDITIONAL WANT_BSD_SECURITY, +# if the user has selected this mechanism. Also defines USE_AMANDAHOSTS +# unless the user has specified --without-amandahosts. +# +AC_DEFUN([AMANDA_BSD_SECURITY], +[ + BSD_SECURITY="yes" + AC_ARG_WITH(bsd-security, + AS_HELP_STRING([--without-bsd-security], + [do not include BSD authentication]), + [ + case "$withval" in + n | no) BSD_SECURITY=no ;; + y | ye | yes) ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --without-bsd-security.]) + ;; + esac + ], + ) + + USE_AMANDAHOSTS=yes + AC_ARG_WITH(amandahosts, + AS_HELP_STRING([ --without-amandahosts], + [use ".rhosts" instead of ".amandahosts"]), + [ + case "$withval" in + n | no ) USE_AMANDAHOSTS="no" ;; + y | ye | yes) : ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --without-amandahosts option.]) + ;; + esac + ] + ) + + if test "x$BSD_SECURITY" = "xyes"; then + AC_DEFINE(BSD_SECURITY,1, + [Define to use BSD .rhosts/.amandahosts security. ]) + if test "x$USE_AMANDAHOSTS" = "xyes"; then + AC_DEFINE(USE_AMANDAHOSTS,1, + [Define if you want to use the ".amandahosts" for BSD security. ]) + fi + fi + + AM_CONDITIONAL(WANT_BSD_SECURITY, test x"$BSD_SECURITY" = x"yes") +]) diff --git a/config/amanda/bsdtcp-security.m4 b/config/amanda/bsdtcp-security.m4 new file mode 100644 index 0000000..044415b --- /dev/null +++ b/config/amanda/bsdtcp-security.m4 @@ -0,0 +1,34 @@ +# SYNOPSIS +# +# AMANDA_BSDTCP_SECURITY +# +# OVERVIEW +# +# Handle configuration for BSDTCP security, implementing the +# --with-bsdtcp-security option. +# +# Defines BSDTCP_SECURITY, and sets AM_CONDITIONAL WANT_BSDTCP_SECURITY, +# if the user has selected this mechanism. +# +AC_DEFUN([AMANDA_BSDTCP_SECURITY], +[ + BSDTCP_SECURITY="no" + AC_ARG_WITH(bsdtcp-security, + AS_HELP_STRING([--with-bsdtcp-security], + [include BSDTCP authentication]), + [ + case "$withval" in + n | no) : ;; + y | ye | yes) BSDTCP_SECURITY=yes ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --with-bsdtcp-security.]) + ;; + esac + ], + ) + + if test "x$BSDTCP_SECURITY" = "xyes"; then + AC_DEFINE(BSDTCP_SECURITY,1, + [Define if BSDTCP transport should be enabled.]) + fi + AM_CONDITIONAL(WANT_BSDTCP_SECURITY, test x"$BSDTCP_SECURITY" = x"yes") +]) diff --git a/config/amanda/bsdudp-security.m4 b/config/amanda/bsdudp-security.m4 new file mode 100644 index 0000000..1422bb7 --- /dev/null +++ b/config/amanda/bsdudp-security.m4 @@ -0,0 +1,34 @@ +# SYNOPSIS +# +# AMANDA_BSDUDP_SECURITY +# +# OVERVIEW +# +# Handle configuration for BSDUDP security, implementing the +# --with-bsdudp-security option. +# +# Defines BSDUDP_SECURITY, and sets AM_CONDITIONAL WANT_BSDUDP_SECURITY, +# if the user has selected this mechanism. +# +AC_DEFUN([AMANDA_BSDUDP_SECURITY], +[ + BSDUDP_SECURITY="no" + AC_ARG_WITH(bsdudp-security, + AS_HELP_STRING([--with-bsdudp-security], + [include BSDUDP authentication]), + [ + case "$withval" in + n | no) : ;; + y | ye | yes) BSDUDP_SECURITY=yes ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --with-bsdudp-security.]) + ;; + esac + ], + ) + + if test "x$BSDUDP_SECURITY" = "xyes"; then + AC_DEFINE(BSDUDP_SECURITY,1, + [Define if BSDUDP transport should be enabled.]) + fi + AM_CONDITIONAL(WANT_BSDUDP_SECURITY, test x"$BSDUDP_SECURITY" = x"yes") +]) diff --git a/config/amanda/changer.m4 b/config/amanda/changer.m4 new file mode 100644 index 0000000..23c3ae3 --- /dev/null +++ b/config/amanda/changer.m4 @@ -0,0 +1,274 @@ +# SYNOPSIS +# +# AMANDA_SETUP_CHANGER +# +# OVERVIEW +# +# Set up for changers. This first checks the availability of several +# changer-related headers, then, based on those results, tries to +# compile some test programs for each supported changer API. It finishes +# by defining a series of AM_CONDITIONALS which are all used in +# changer-src/Makefile.am. +# +# The macro also searches for chio, chs, mtx, and mcutil, which are used +# from various shell scripts in the changer-src/ directory. +# +AC_DEFUN([AMANDA_SETUP_CHANGER], [ + AC_REQUIRE([AMANDA_PROG_CHIO]) + AC_REQUIRE([AMANDA_PROG_CHS]) + AC_REQUIRE([AMANDA_PROG_MTX]) + AC_REQUIRE([AMANDA_PROG_MCUTIL]) + + AC_CHECK_HEADERS( \ + camlib.h \ + chio.h \ + linux/chio.h \ + scsi/sg.h \ + scsi/scsi_ioctl.h \ + sys/chio.h \ + sys/dsreq.h \ + sys/mtio.h \ + sys/scarray.h \ + sys/gscdds.h \ + sys/scsi.h \ + sys/scsiio.h \ + sys/scsi/impl/uscsi.h \ + sys/scsi/scsi/ioctl.h \ + ) + + # + # chio support + # + if test x"$ac_cv_header_sys_scsi_h" = x"yes"; then + AC_CACHE_CHECK([for HP/UX-like scsi changer support], + amanda_cv_hpux_scsi_chio, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include + ]], [[ + static struct element_addresses changer_info; + int i = SIOC_ELEMENT_ADDRESSES; + int j = SIOC_ELEMENT_STATUS; + int k = SIOC_MOVE_MEDIUM; + ]])],[amanda_cv_hpux_scsi_chio=yes],[amanda_cv_hpux_scsi_chio=no])]) + if test x"$amanda_cv_hpux_scsi_chio" = x"yes"; then + WANT_SCSI_HPUX=yes + WANT_CHG_SCSI=yes + fi + fi + + # + # Linux SCSI based on ioctl + # + if test x"$ac_cv_header_sys_mtio_h" = x"yes" && + test x"$ac_cv_header_scsi_scsi_ioctl_h" = x"yes"; then + AC_CACHE_CHECK([for Linux like scsi support (ioctl)], + amanda_cv_linux_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include + ]], [[ + int device; + char *Command; + ioctl(device, SCSI_IOCTL_SEND_COMMAND, Command); + ]])],[amanda_cv_linux_scsi=yes],[amanda_cv_linux_scsi=no])]) + fi + + # + # Linux SCSI based on sg + # + if test x"$ac_cv_header_sys_mtio_h" = x"yes" && + test x"$ac_cv_header_scsi_sg_h" = x"yes"; then + AC_CACHE_CHECK([for Linux like scsi support (sg)], + amanda_cv_linux_sg_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + int device; + struct sg_header *psg_header; + char *buffer; + write(device, buffer, 1); + ]])],[amanda_cv_linux_sg_scsi=yes],[amanda_cv_linux_sg_scsi=no])]) + fi + + if test x"$amanda_cv_linux_scsi" = x"yes" || + test x"$amanda_cv_linux_sg_scsi" = x"yes";then + WANT_SCSI_LINUX=yes + WANT_CHG_SCSI=yes + fi + + # + # HP-UX SCSI + # + if test x"$ac_cv_header_sys_mtio_h" = x"yes" && + test x"$ac_cv_header_sys_scsi_h" = x"yes"; then + AC_CACHE_CHECK([for HP-UX like scsi support], + amanda_cv_hpux_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include +#include + ]], [[ + int device; + char *Command; + ioctl(device, SIOC_IO, Command); + ]])],[amanda_cv_hpux_scsi=yes],[amanda_cv_hpux_scsi=no])]) + if test x"$amanda_cv_hpux_scsi" = x"yes";then + WANT_SCSI_HPUX_NEW=yes + WANT_CHG_SCSI=yes + WANT_CHG_SCSI_CHIO=yes + fi + fi + + # + # IRIX SCSI + # + if test x"$ac_cv_header_sys_mtio_h" = x"yes" && + test x"$ac_cv_header_sys_dsreq_h" = x"yes"; then + AC_CACHE_CHECK([for Irix like scsi support], + amanda_cv_irix_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + int device=1; + char Command; + ioctl(device, DS_ENTER, &Command); + ]])],[amanda_cv_irix_scsi=yes],[amanda_cv_irix_scsi=no])]) + if test x"$amanda_cv_irix_scsi" = x"yes";then + WANT_SCSI_IRIX=yes + WANT_CHG_SCSI=yes + fi + fi + + # + # Solaris SCSI + # + if test x"$ac_cv_header_sys_mtio_h" = x"yes" && + test x"$ac_cv_header_sys_scsi_impl_uscsi_h" = x"yes"; then + AC_CACHE_CHECK([for Solaris-like scsi support], + amanda_cv_solaris_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + int device; + char *Command; + ioctl(device, USCSICMD, Command); + ]])],[amanda_cv_solaris_scsi=yes],[amanda_cv_solaris_scsi=no])]) + if test x"$amanda_cv_solaris_scsi" = x"yes";then + WANT_SCSI_SOLARIS=yes + WANT_CHG_SCSI=yes + fi + fi + + # + # AIX SCSI + # + if test x"$ac_cv_header_sys_tape_h" = x"yes" && + test x"$ac_cv_header_sys_scarray_h" = x"yes" && + test x"$ac_cv_header_sys_gscdds_h" = x"yes"; then + AC_CACHE_CHECK([for AIX like scsi support], + amanda_cv_aix_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + int device; + char *Command; + ioctl(device, STIOCMD, Command); + ]])],[amanda_cv_aix_scsi=yes],[amanda_cv_aix_scsi=no])]) + if test x"$amanda_cv_aix_scsi" = x"yes";then + WANT_SCSI_AIX=yes + WANT_CHG_SCSI=yes + fi + fi + # + # BSD CAM SCSI + # + if test x"$ac_cv_header_cam_cam_h" = x"yes";then + AC_CACHE_CHECK([for CAM like scsi support], + amanda_cv_cam_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +# include +# include +# include +# include +# include +# include + ]], [[ + struct cam_device *curdev; + + curdev = cam_open_pass("", O_RDWR, NULL); + ]])],[amanda_cv_cam_scsi=yes],[amanda_cv_cam_scsi=no])]) + if test x"$amanda_cv_cam_scsi" = x"yes";then + WANT_SCSI_CAM=yes + WANT_CHG_SCSI=yes + AC_CHECK_LIB(cam,main) + fi + fi + + + # + # BSD SCSI + # + if test x"$ac_cv_header_sys_mtio_h" = x"yes" && + test x"$ac_cv_header_sys_scsiio_h" = x"yes"; then + AC_CACHE_CHECK([for BSD like scsi support], + amanda_cv_bsd_scsi, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + int device=1; + char Command; + ioctl(device, SCIOCCOMMAND, &Command); + ]])],[amanda_cv_bsd_scsi=yes],[amanda_cv_bsd_scsi=no])]) + if test x"$amanda_cv_bsd_scsi" = x"yes";then + WANT_SCSI_BSD=yes + WANT_CHG_SCSI=yes + fi + fi + + # Do not build chg-scsi-chio if we cannot find the needed support + # include files for the SCSI interfaces + # chio.h and sys/chio.h are chio based systems + if test x"$ac_cv_header_chio_h" = x"yes" || + test x"$ac_cv_header_linux_chio_h" = x"yes" || + test x"$ac_cv_header_sys_chio_h" = x"yes"; then + # chg-scsi does not support FreeBSD 3.0's chio.h; it became backward + # incompatible with the introduction of camlib.h + if test x"$ac_cv_header_camlib_h" != x"yes"; then + WANT_SCSI_CHIO=yes + # prefer to use chg-scsi, unless we already have a driver for that, + # in which case set it up as chg-scsi-chio. + if test x"$WANT_CHG_SCSI" = x"no"; then + WANT_CHG_SCSI=yes + else + WANT_CHG_SCSI_CHIO=yes + fi + fi + fi + + # scsi-based implementations + AM_CONDITIONAL(WANT_CHG_SCSI, test x"$WANT_CHG_SCSI" = x"yes") + AM_CONDITIONAL(WANT_SCSI_LINUX, test x"$WANT_SCSI_LINUX" = x"yes") + AM_CONDITIONAL(WANT_SCSI_HPUX_NEW, test x"$WANT_SCSI_HPUX_NEW" = x"yes") + AM_CONDITIONAL(WANT_SCSI_IRIX, test x"$WANT_SCSI_IRIX" = x"yes") + AM_CONDITIONAL(WANT_SCSI_SOLARIS, test x"$WANT_SCSI_SOLARIS" = x"yes") + AM_CONDITIONAL(WANT_SCSI_AIX, test x"$WANT_SCSI_AIX" = x"yes") + AM_CONDITIONAL(WANT_SCSI_CAM, test x"$WANT_SCSI_CAM" = x"yes") + AM_CONDITIONAL(WANT_SCSI_BSD, test x"$WANT_SCSI_BSD" = x"yes") + + # scsi-chio-based implementations + AM_CONDITIONAL(WANT_CHG_SCSI_CHIO, test x"$WANT_CHG_SCSI_CHIO" = x"yes") + AM_CONDITIONAL(WANT_SCSI_HPUX, test x"$WANT_SCSI_HPUX" = x"yes") + AM_CONDITIONAL(WANT_SCSI_CHIO, test x"$WANT_SCSI_CHIO" = x"yes") +]) diff --git a/config/amanda/components.m4 b/config/amanda/components.m4 new file mode 100644 index 0000000..8c7b902 --- /dev/null +++ b/config/amanda/components.m4 @@ -0,0 +1,177 @@ +# SYNOPSIS +# +# AMANDA_CHECK_COMPONENTS +# +# OVERVIEW +# +# Defines --without-client, --without-server, --without-restore, and +# --without-amrecover, and checks the results. +# +# Sets the AM_CONDITIONALs WANT_CLIENT, WANT_SERVER, WANT_RESTORE, +# and WANT_RECOVER. +# +# AM_CONDITIONAL WANT_TAPE is set if either server or restore support is +# being built. +# +AC_DEFUN([AMANDA_CHECK_COMPONENTS], [ + AC_REQUIRE([AMANDA_WITHOUT_SERVER]) + AC_REQUIRE([AMANDA_WITHOUT_CLIENT]) + AC_REQUIRE([AMANDA_WITHOUT_RESTORE]) + AC_REQUIRE([AMANDA_WITHOUT_AMRECOVER]) + AC_REQUIRE([AMANDA_WITH_CLIENT_ONLY]) dnl deprecated + AC_REQUIRE([AMANDA_WITH_SERVER_ONLY]) dnl deprecated + + # detect invalid combinations of components + if ! ${WANT_SERVER-true} && ${WANT_RESTORE-true}; then + AC_MSG_ERROR([--without-server requires --without-restore]) + fi + if ! ${WANT_CLIENT-true} && ${WANT_RECOVER-true}; then + AC_MSG_ERROR([--without-client requires --without-amrecover]) + fi + + AM_CONDITIONAL(WANT_CLIENT, $WANT_CLIENT) + AM_CONDITIONAL(WANT_RESTORE, $WANT_RESTORE) + AM_CONDITIONAL(WANT_SERVER, $WANT_SERVER) + AM_CONDITIONAL(WANT_RECOVER, $WANT_RECOVER) + + AM_CONDITIONAL(WANT_TAPE, $WANT_SERVER || $WANT_RESTORE) +]) + + +# SYNOPSIS +# +# AMANDA_WITHOUT_SERVER +# +# OVERVIEW +# +# Add option --without-server, and set WANT_SERVER to true or false, +# accordingly. +# +AC_DEFUN([AMANDA_WITHOUT_SERVER], [ + WANT_SERVER=true + AC_ARG_WITH(server, + AS_HELP_STRING([--without-server], [do not build server stuff (set --without-restore)]), [ + case "$withval" in + y | ye | yes) WANT_SERVER=true;; + n | no) WANT_SERVER=false;; + *) AC_MSG_ERROR([You must not supply an argument to the --without-server option.]) ;; + esac + ]) +]) + +# SYNOPSIS +# +# AMANDA_WITHOUT_CLIENT +# +# OVERVIEW +# +# Add option --without-client, and set WANT_CLIENT to true or false, +# accordingly. +# +AC_DEFUN([AMANDA_WITHOUT_CLIENT], [ + WANT_CLIENT=true + AC_ARG_WITH(client, + AS_HELP_STRING([--without-client], [do not build client stuff]), [ + case "$withval" in + y | ye | yes) WANT_CLIENT=true;; + n | no) WANT_CLIENT=false;; + *) AC_MSG_ERROR([You must not supply an argument to the --without-client option.]) ;; + esac + ]) +]) + +# SYNOPSIS +# +# AMANDA_WITHOUT_RESTORE +# +# OVERVIEW +# +# Add option --without-restore, and set WANT_RESTORE to true or false, +# accordingly. +# +AC_DEFUN([AMANDA_WITHOUT_RESTORE], [ + AC_REQUIRE([AMANDA_WITHOUT_SERVER]) + WANT_RESTORE=${WANT_SERVER-true} + AC_ARG_WITH(restore, + AS_HELP_STRING([--without-restore], [do not build amrestore nor amidxtaped]), [ + case "$withval" in + y | ye | yes) WANT_RESTORE=true;; + n | no) WANT_RESTORE=false;; + *) AC_MSG_ERROR([You must not supply an argument to --with-restore option.]) ;; + esac + ]) +]) + +# SYNOPSIS +# +# AMANDA_WITHOUT_AMRECOVER +# +# OVERVIEW +# +# Add option --without-amrecover, and set WANT_RECOVER (not WANT_AMRECOVER) to +# true or false, accordingly. +# +AC_DEFUN([AMANDA_WITHOUT_AMRECOVER], [ + AC_REQUIRE([AMANDA_WITHOUT_CLIENT]) + WANT_RECOVER=${WANT_CLIENT-true} + AC_ARG_WITH(amrecover, + AS_HELP_STRING([--without-amrecover], + [do not build amrecover]), [ + case "$withval" in + y | ye | yes) WANT_RECOVER=false;; + n | no) WANT_RECOVER=false;; + *) AC_MSG_ERROR([You must not supply an argument to --with-amrecover option.]) ;; + esac + ]) +]) + +## deprecated --with-* options + +AC_DEFUN([AMANDA_WITH_CLIENT_ONLY], [ + AC_ARG_WITH(client-only, + AS_HELP_STRING([--with-client-only], [deprecated: use --without-server]), + [ AC_MSG_ERROR([--with-client-only is deprecated, use --without-server instead.]) + ]) +],) + +AC_DEFUN([AMANDA_WITH_SERVER_ONLY], [ + AC_ARG_WITH(server-only, + AS_HELP_STRING([--with-server-only], [deprecated: use --without-client]), + [ AC_MSG_ERROR([--with-server-only is deprecated, use --without-client instead.]) + ],) +]) + +# SYNOPSIS +# +# AMANDA_SHOW_COMPONENTS_SUMMARY +# +# OVERVIEW +# +# Show a summary of the settings from this file. +# +AC_DEFUN([AMANDA_SHOW_COMPONENTS_SUMMARY], +[ + components='' + if $WANT_SERVER; then + components="$components server"; + else + components="$components (no server)"; + fi + if $WANT_RESTORE; then + components="$components restore"; + else + components="$components (no restore)"; + fi + if $WANT_CLIENT; then + components="$components client"; + else + components="$components (no client)"; + fi + if $WANT_RECOVER; then + components="$components amrecover"; + else + components="$components (no amrecover)"; + fi + + echo "Amanda Components: $components" +]) diff --git a/config/amanda/compress.m4 b/config/amanda/compress.m4 new file mode 100644 index 0000000..1fb47ec --- /dev/null +++ b/config/amanda/compress.m4 @@ -0,0 +1,71 @@ +# SYNOPSIS +# +# AMANDA_CHECK_COMPRESSION +# +# OVERVIEW +# +# Find a suitable compression program and define the following: +# +# - COMPRESS_PATH +# - COMPRESS_SUFFIX +# - COMPRESS_FAST_OPT +# - COMPRESS_BEST_OPT +# - UNCOMPRESS_PATH +# - UNCOMPRESS_OPT +# - HAVE_GZIP +# +AC_DEFUN([AMANDA_CHECK_COMPRESSION], +[ + AC_REQUIRE([AMANDA_PROG_CAT]) + AC_REQUIRE([AMANDA_PROG_COMPRESS]) + AC_REQUIRE([AMANDA_PROG_GZIP]) + + if test "$GZIP"; then + AC_DEFINE(HAVE_GZIP,1, + [Define if Amanda is using the gzip program. ]) + COMPRESS_PATH="$GZIP" + COMPRESS_SUFFIX=".gz" + COMPRESS_FAST_OPT="--fast" + COMPRESS_BEST_OPT="--best" + UNCOMPRESS_PATH="$GZIP" + UNCOMPRESS_OPT="-dc" + else + if test "$COMPRESS"; then + COMPRESS_PATH="$COMPRESS" + COMPRESS_SUFFIX=".Z" + COMPRESS_FAST_OPT="-f" + COMPRESS_BEST_OPT="-f" + UNCOMPRESS_PATH="$COMPRESS" + UNCOMPRESS_OPT="-dc" + else + # If we have to use cat, we don't define COMPRESS_FAST_OPT, + # COMPRESS_BEST_OPT, or UNCOMPRESS_OPT as "" since cat will look + # look for a file by the name of "". + # XXX is the above true? --dustin + + AMANDA_MSG_WARN([Cannot find either gzip or compress. Using cat.]) + COMPRESS_PATH="$CAT" + COMPRESS_SUFFIX="" + COMPRESS_FAST_OPT="" + COMPRESS_BEST_OPT="" + UNCOMPRESS_PATH="$CAT" + UNCOMPRESS_OPT="" + fi + fi + + AC_DEFINE_UNQUOTED(COMPRESS_PATH,"$COMPRESS_PATH", + [Define to the exact path to the gzip or the compress program. ]) + AC_DEFINE_UNQUOTED(COMPRESS_SUFFIX,"$COMPRESS_SUFFIX", + [Define to the suffix for the COMPRESS_PATH compression program. ]) + AC_DEFINE_UNQUOTED(COMPRESS_FAST_OPT,"$COMPRESS_FAST_OPT", + [Define as the command line option for fast compression. ]) + AC_DEFINE_UNQUOTED(COMPRESS_BEST_OPT,"$COMPRESS_BEST_OPT", + [Define as the command line option for best compression. ]) + AC_DEFINE_UNQUOTED(UNCOMPRESS_PATH,"$UNCOMPRESS_PATH", + [Define as the exact path to the gzip or compress command. ]) + AC_DEFINE_UNQUOTED(UNCOMPRESS_OPT,"$UNCOMPRESS_OPT", + [Define as any optional arguments to get UNCOMPRESS_PATH to uncompress. ]) + + # Empty GZIP so that make dist works. + GZIP= +]) diff --git a/config/amanda/config.m4 b/config/amanda/config.m4 new file mode 100644 index 0000000..fedf4bb --- /dev/null +++ b/config/amanda/config.m4 @@ -0,0 +1,58 @@ +# SYNOPSIS +# +# AMANDA_CONFIG_LCOAL +# +# OVERVIEW +# +# Invoke ./config.local, if it exists +# +AC_DEFUN([AMANDA_CONFIG_LOCAL], +[ + if test -f config.local; then + echo "running local script ./config.local" + . ./config.local + fi +]) + +# SYNOPSIS +# +# AMANDA_GET_SVN_INFO +# +# OVERVIEW +# +# If the build is in a Subversion working copy, and if an svn client +# is available, then update common-src/svn-info.h to reflect the current +# revision and branch. +# +# If these things are not available, then the file is not updated, and +# any previous contents are used. If the file does not exist, it is +# created. +# +AC_DEFUN([AMANDA_GET_SVN_INFO], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_REQUIRE([AMANDA_PROG_GREP]) + + AC_PATH_PROG(SVN, svn,, $LOCSYSPATH) + AC_MSG_CHECKING([Subversion revision information]) + if test -d $srcdir/.svn && test -n "$SVN" && (cd $srcdir > /dev/null ; $SVN info . ) > conftemp.svn; then + rev=`$GREP Revision: conftemp.svn|cut -d: -f 2|cut -c2-` + url=`$GREP URL: conftemp.svn|cut -d: -f 2-|cut -c2-` + ( echo '#define BUILT_REV "'$rev'"' + echo '#define BUILT_BRANCH "'`basename "$url"`'"' + ) > common-src/svn-info.h + + AC_MSG_RESULT([updated]) + else + # Makefiles will be upset if the file doesn't exist, so double-check + if test -f common-src/svn-info.h; then + : # all good + AC_MSG_RESULT([not changed]) + else + echo '/* no information available */' > common-src/svn-info.h + AC_MSG_RESULT([not available]) + fi + fi + + rm -f conftemp.svn +]) diff --git a/config/amanda/debugging.m4 b/config/amanda/debugging.m4 new file mode 100644 index 0000000..4a499dc --- /dev/null +++ b/config/amanda/debugging.m4 @@ -0,0 +1,148 @@ +# SYNOPSIS +# +# AMANDA_WITH_ASSERTIONS +# +# OVERVIEW +# +# Handles the --with-assertions flag. Defines ASSERTIONS if the flag is given. +# +AC_DEFUN([AMANDA_WITH_ASSERTIONS], +[ + AC_ARG_WITH(assertions, + AS_HELP_STRING([--with-assertions], + [compile assertions into code]), + [ + case "$withval" in + n | no) : ;; + y | ye | yes) + AC_DEFINE(ASSERTIONS,1, + [Define if you want assertion checking. ]) + ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --with-assertions option.]) + ;; + esac + ] + ) +]) + +# SYNOPSIS +# +# AMANDA_WITH_DEBUGGING +# +# OVERVIEW +# +# Handles the --with[out]-debugging flag. If debugging is not disabled, then define +# DEBUG_CODE, and define and substitute AMANDA_DBGDIR to either the location the +# user gave, or AMANDA_TMPDIR. +# +AC_DEFUN([AMANDA_WITH_DEBUGGING], +[ + AC_REQUIRE([AMANDA_WITH_TMPDIR]) + AC_ARG_WITH(debugging, + AS_HELP_STRING([--with-debugging=DIR] + [put debug logs in DIR (default same as --with-tmpdir)]), + [ debugging="$withval" ], + [ debugging="yes" ] + ) + + case "$debugging" in + n | no) AC_MSG_ERROR([Amanda no longer supports building with debugging disabled]);; + y | ye | yes) AMANDA_DBGDIR="$AMANDA_TMPDIR";; + *) AMANDA_DBGDIR="$debugging";; + esac + + # evaluate any extra variables in the directory + AC_DEFINE_DIR([AMANDA_DBGDIR], [AMANDA_DBGDIR], + [Location of Amanda directories and files. ]) +]) + +# SYNOPSIS +# +# AMANDA_GLIBC_BACKTRACE +# +# OVERVIEW +# +# Check for glibc's backtrace support, and define HAVE_GLIBC_BACKTRACE if it is present. +AC_DEFUN([AMANDA_GLIBC_BACKTRACE], +[ + AC_CHECK_HEADER([execinfo.h], [ + AC_CHECK_FUNC([backtrace_symbols_fd], [ + AC_DEFINE(HAVE_GLIBC_BACKTRACE, 1, + [Define this if glibc's backtrace functionality (execinfo.h) is present]) + ]) + ]) +]) + +# SYNOPSIS +# +# AMANDA_WITH_DEBUG_DAYS +# +# OVERVIEW +# +# Handles the --with-debug-days flag. Defines and substitutes AMANDA_DEBUG_DAYS. +# +AC_DEFUN([AMANDA_WITH_DEBUG_DAYS], +[ + AC_ARG_WITH(debug_days, + AS_HELP_STRING([--with-debug-days=NN], + [number of days to keep debugging files (default: 4)]), + [ + debug_days="$withval" + ], [ + debug_days="yes" + ] + ) + case "$debug_days" in + n | no) + AMANDA_DEBUG_DAYS=0 ;; + y | ye | yes) + AMANDA_DEBUG_DAYS=4 ;; + [[0-9]] | [[0-9]][[0-9]] | [[0-9]][[0-9]][[0-9]]) + AMANDA_DEBUG_DAYS="$debug_days" ;; + *) AC_MSG_ERROR([*** --with-debug-days value not numeric or out of range.]) + ;; + esac + AC_DEFINE_UNQUOTED(AMANDA_DEBUG_DAYS,$AMANDA_DEBUG_DAYS, + [Number of days to keep debugging files. ]) + AC_SUBST(AMANDA_DEBUG_DAYS) +]) + +# SYNOPSIS +# +# AMANDA_WITH_TESTING +# +# OVERVIEW +# +# Handles the --with-testing flag. Defines and substitutes SERVICE_SUFFIX, and +# defines AMANDA_SERVICE_NAME and KAMANDA_SERVICE_NAME. +# +AC_DEFUN([AMANDA_WITH_TESTING], +[ + AC_ARG_WITH(testing, + AS_HELP_STRING([--with-testing@<:@=SUFFIX@:>@], + [use alternate service names with suffix (default 'test')]), + [ + TESTING="$withval" + ], [ + TESTING="no" + ] + ) + case "$TESTING" in + n | no) SERVICE_SUFFIX="";; + y | ye | yes) SERVICE_SUFFIX="-test";; + *) SERVICE_SUFFIX="-$TESTING";; + esac + + AMANDA_SERVICE_NAME="amanda$SERVICE_SUFFIX" + KAMANDA_SERVICE_NAME="kamanda$SERVICE_SUFFIX" + + AC_SUBST(SERVICE_SUFFIX) + AC_DEFINE_UNQUOTED(SERVICE_SUFFIX, "$SERVICE_SUFFIX", + [A suffix that will be appended to service names. + * Useful for testing in parallel with a working version. ]) + AC_DEFINE_UNQUOTED(AMANDA_SERVICE_NAME, "$AMANDA_SERVICE_NAME", + [The name for the Amanda service. ]) + AC_DEFINE_UNQUOTED(KAMANDA_SERVICE_NAME, "$KAMANDA_SERVICE_NAME", + [The name for the Kerberized Amanda service. ]) +]) + diff --git a/config/amanda/defaults.m4 b/config/amanda/defaults.m4 new file mode 100644 index 0000000..a28931b --- /dev/null +++ b/config/amanda/defaults.m4 @@ -0,0 +1,138 @@ +# SYNOPSIS +# +# Get default settings for various configuration and command-line options: +# --with-index-server +# define and substitute DEFAULT_SERVER +# --with-config +# define and substitute DEFAULT_CONFIG +# --with-tape-server +# define and substitute DEFAULT_TAPE_SERVER +# --with-tape-device +# define and substitute DEFAULT_TAPE_DEVICE; substitue EXAMPLE_TAPEDEV +# --with-changer-device +# define and substitute DEFAULT_CHANGER_DEVICE +# --with-amandates +# define and substitute DEFAULT_AMANDATES_FILE +# +AC_DEFUN([AMANDA_SETUP_DEFAULTS], +[ + AC_ARG_WITH(index-server, + AS_HELP_STRING([--with-index-server=HOST], + [default amanda index server (default: `uname -n`)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-index-server option.]) + ;; + *) DEFAULT_SERVER="$withval" + ;; + esac + ], + : ${DEFAULT_SERVER=`uname -n`} + ) + AC_DEFINE_UNQUOTED(DEFAULT_SERVER,"$DEFAULT_SERVER", + [This is the default Amanda index server.]) + AC_SUBST(DEFAULT_SERVER) + + AC_ARG_WITH(config, + AS_HELP_STRING([--with-config=CONFIG], + [default amanda configuration (default: DailySet1)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-config option.]) + ;; + *) DEFAULT_CONFIG="$withval" + ;; + esac + ], + : ${DEFAULT_CONFIG=DailySet1} + ) + AC_DEFINE_UNQUOTED(DEFAULT_CONFIG,"$DEFAULT_CONFIG", + [This is the default Amanda configuration.]) + AC_SUBST(DEFAULT_CONFIG) + + AC_ARG_WITH(tape-server, + AS_HELP_STRING([--with-tape-server=HOST], + [default tape server for restore (default: same as index-server)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-tape-server option.]) + ;; + *) DEFAULT_TAPE_SERVER="$withval" + ;; + esac + ], + : ${DEFAULT_TAPE_SERVER=$DEFAULT_SERVER} + ) + AC_DEFINE_UNQUOTED(DEFAULT_TAPE_SERVER,"$DEFAULT_TAPE_SERVER", + [This is the default restoring Amanda tape server. ]) + AC_SUBST(DEFAULT_TAPE_SERVER) + + AC_ARG_WITH(tape-device, + AS_HELP_STRING([--with-tape-device=DEVICE], + [default device on restore tape server]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-tape-device option.]) + ;; + *) DEFAULT_TAPE_DEVICE="$withval" + ;; + esac + ] + ) + + AC_DEFINE_UNQUOTED(DEFAULT_TAPE_DEVICE,"$DEFAULT_TAPE_DEVICE", + [This is the default no-rewinding tape device. ]) + AC_SUBST(DEFAULT_TAPE_DEVICE) + + if test "${DEFAULT_TAPE_DEVICE+set}" = "set"; then + EXAMPLE_TAPEDEV="$DEFAULT_TAPE_DEVICE" + else + EXAMPLE_TAPEDEV="tape:/dev/YOUR-TAPE-DEVICE-HERE" + fi + AC_SUBST(EXAMPLE_TAPEDEV) + + AC_ARG_WITH(changer-device, + AS_HELP_STRING([--with-changer-device=DEV], + [default tape changer device (default: /dev/ch0)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-changer-device option.]) + ;; + *) DEFAULT_CHANGER_DEVICE="$withval" + ;; + esac + ] + ) + + if test -z "$DEFAULT_CHANGER_DEVICE"; then + DEFAULT_CHANGER_DEVICE=/dev/null + if test -f /dev/ch0; then + DEFAULT_CHANGER_DEVICE=/dev/ch0 + fi + fi + + AC_DEFINE_UNQUOTED(DEFAULT_CHANGER_DEVICE,"$DEFAULT_CHANGER_DEVICE", + [This is the default changer device. ]) + AC_SUBST(DEFAULT_CHANGER_DEVICE) + + AC_ARG_WITH(amandates, + AS_HELP_STRING([--with-amandates], + [default location for 'amandates' (default: $localstatedir/amanda/amandates)]), + [ + case "$withval" in + n | no) AC_MSG_ERROR([*** --without-amandates is not allowed.]);; + y | ye | yes) amandates='$localstatedir/amanda/amandates' ;; + *) amandates="$withval";; + esac + ], + [amandates='$localstatedir/amanda/amandates'] + ) + + AC_DEFINE_DIR([DEFAULT_AMANDATES_FILE], [amandates], + [Default location for 'amandates']) +]) diff --git a/config/amanda/devprefix.m4 b/config/amanda/devprefix.m4 new file mode 100644 index 0000000..6231dbf --- /dev/null +++ b/config/amanda/devprefix.m4 @@ -0,0 +1,115 @@ +# SYNOPSIS +# +# AMANDA_CHECK_DEVICE_PREFIXES +# +# DESCRIPTION +# +# Check for the prefixes used for particular devices. +# +# Defines DEV_PREFIX and RDEV_PREFIX to the appropriate prefixes. +# +AC_DEFUN([AMANDA_CHECK_DEVICE_PREFIXES], +[ + # disk device prefixes + AC_MSG_CHECKING(disk device prefixes) + + # Use df to find the mount point for the root filesystem. Use + # the positional parameters to find the particular line from df + # that contains the root paritition. We put it in a subshell so + # that the original positional parameters are not messed with. + dfline=`( + df / | while read line; do + set -- $line + dnl @S|@ means $ to m4 + while test @S|@# -gt 0; do + if test "x@S|@1" = "x/"; then + echo $line + break 2 + fi + shift + done + done + ) | sed 's/(//' | sed 's/)//' ` + + # Search for the mount point by using expr to find the parameter + # with dev in it. + mount=`( + set -- $dfline + dnl @S|@ means $ to m4 + while test @S|@# -gt 0; do + if expr "@S|@1" : '.*dev' >/dev/null 2>&1; then + echo @S|@1 + break + fi + shift + done + )` + + # get any system-specific configuration information + case "$target" in + *-hp-*) + CLIENT_SCRIPTS_OPT=amhpfixdevs + case $mount in + /dev/vg*) + AMANDA_MSG_WARN([Run amhpfixdevs on HP-UX systems using /dev/vg??.]) + ;; + esac + ;; + *-sni-sysv4) + DEV_PREFIX=/dev/dsk/ + RDEV_PREFIX=/dev/rdsk/ + CLIENT_SCRIPTS_OPT=amsinixfixdevs + if ! test -d /dev/dsk; then + AMANDA_MSG_WARN([Run amsinixfixdevs on Sinix systems using VxFS.]) + fi + ;; + *-sco3.2v4*) + DEV_PREFIX=/dev/ + RDEV_PREFIX=/dev/ + ;; + *) + CLIENT_SCRIPTS_OPT= + ;; + esac + + if test "$DEV_PREFIX" && test "$RDEV_PREFIX"; then + AC_MSG_RESULT((predefined) $DEV_PREFIX - $RDEV_PREFIX) + else + if test -d /dev/dsk; then + DEV_PREFIX=/dev/dsk/ + if test -d /dev/rdsk; then + RDEV_PREFIX=/dev/rdsk/ + else + RDEV_PREFIX=/dev/dsk/ + fi + elif test -d /dev; then + DEV_PREFIX=/dev/ + + # Some systems, notably Linux, do not have raw disk devices + # names. Check this by trying to see if a raw disk device name + # exists using the normal raw device path prepended to the + # mount point of the root filesystem. + if test "$mount"; then + dev_name="/dev/r`basename $mount`" + if test -b $dev_name -o -c $dev_name; then + RDEV_PREFIX=/dev/r + else + RDEV_PREFIX=/dev/ + fi + else + RDEV_PREFIX=/dev/r + fi + else + # just fake it.. + DEV_PREFIX=/ + RDEV_PREFIX=/ + fi + AC_MSG_RESULT($DEV_PREFIX - $RDEV_PREFIX) + fi + + AC_DEFINE_UNQUOTED(DEV_PREFIX,"${DEV_PREFIX}", + [Define as the prefix for disk devices, commonly /dev/ or /dev/dsk/ ]) + AC_DEFINE_UNQUOTED(RDEV_PREFIX,"${RDEV_PREFIX}", + [Define as the prefix for raw disk devices, commonly /dev/r or /dev/rdsk/ ]) + AC_SUBST(CLIENT_SCRIPTS_OPT) +]) diff --git a/config/amanda/dirs.m4 b/config/amanda/dirs.m4 new file mode 100644 index 0000000..ee9c58c --- /dev/null +++ b/config/amanda/dirs.m4 @@ -0,0 +1,266 @@ +# SYNOPSIS +# +# AMANDA_WITH_DUMPERDIR +# +# OVERVIEW +# +# Define and substitute DUMPER_DIR with the result. +# +AC_DEFUN([AMANDA_WITH_DUMPERDIR], +[ + AC_ARG_WITH(dumperdir, + AS_HELP_STRING([--with-dumperdir=DIR], + [where we install the dumpers (default: exec_prefix/dumper)]), + [ + AMANDA_MSG_WARN([--with-dumperdir is no longer used.]) + ] + ) +]) + +# SYNOPSIS +# +# AMANDA_WITH_CONFIGDIR +# +# OVERVIEW +# +# Allow user to specify the dumperdir, defaulting to ${exec_prefix}/dumper. +# Define and substitute DUMPER_DIR with the result. +# +AC_DEFUN([AMANDA_WITH_CONFIGDIR], +[ + AC_ARG_WITH(configdir, + AS_HELP_STRING([--with-configdir=DIR], + [runtime config files in DIR @<:@sysconfdir/amanda@:>@]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-configdir option.]) + ;; + *) CONFIG_DIR="$withval" + ;; + esac + ], [ + : ${CONFIG_DIR='${sysconfdir}/amanda'} # (variable will be evaluated below) + ] + ) + AC_DEFINE_DIR([CONFIG_DIR], [CONFIG_DIR], + [The directory in which configuration directories should be created. ]) +]) + +## deprecated --with-*dir options + +AC_DEFUN([AMANDA_WITH_INDEXDIR], +[ + AC_ARG_WITH(indexdir, + AS_HELP_STRING([--with-indexdir], [deprecated: use indexdir in amanda.conf]), + [ AC_MSG_ERROR([*** --with-indexdir is deprecated; use indexdir in amanda.conf instead.]) + ],) +]) + +AC_DEFUN([AMANDA_WITH_DBDIR], +[ + AC_ARG_WITH(dbdir, + AS_HELP_STRING([--with-dbdir], [deprecated: use infofile in amanda.conf]), + [ AC_MSG_ERROR([*** --with-dbdir is deprecated; use infofile in amanda.conf instead.]) + ],) +]) + +AC_DEFUN([AMANDA_WITH_LOGDIR], +[ + AC_ARG_WITH(logdir, + AS_HELP_STRING([--with-logdir], [deprecated: use logfile in amanda.conf]), + [ AC_MSG_ERROR([*** --with-logdir is deprecated; use logfile in amanda.conf instead.]) + ],) +]) + +# SYNOPSIS +# +# AMANDA_WITH_GNUTAR_LISTDIR +# +# OVERVIEW +# +# Implements --with-gnutar-listdir. Defines GNUTAR_LISTED_INCREMENTAL_DIR to the +# value given or $localstatedir/amanda/gnutar-lists by default. Any $xxxdir variables +# are fully evaluated in the value. +# +AC_DEFUN([AMANDA_WITH_GNUTAR_LISTDIR], +[ + AC_ARG_WITH(gnutar-listdir, + AS_HELP_STRING([--with-gnutar-listdir=DIR], + [put gnutar directory lists in DIR (default: localstatedir/amanda/gnutar-lists)]), + [ + case "$withval" in + n | no) GNUTAR_LISTDIR= ;; + y | ye | yes) GNUTAR_LISTDIR='${localstatedir}/amanda/gnutar-lists' ;; + *) GNUTAR_LISTDIR="$withval" ;; + esac + ], [ + GNUTAR_LISTDIR='${localstatedir}/amanda/gnutar-lists' + ] + ) + + # substitute $prefix, etc. if necessary + AC_DEFINE_DIR([GNUTAR_LISTED_INCREMENTAL_DIR], [GNUTAR_LISTDIR], + [The directory in which GNU tar should store directory lists for incrementals. ]) + + # handle deprecated option + AC_ARG_WITH(gnutar-listed-incremental, + AS_HELP_STRING([--with-gnutar-listed-incremental], + [deprecated; use --with-gnutar-listdir]), + [ + AC_MSG_ERROR([*** The gnutar-listed-incremental option is deprecated; use --with-gnutar-listdir instead]) + ] + ) +]) + +# SYNOPSIS +# +# AMANDA_WITH_TMPDIR +# +# OVERVIEW +# +# Implement --with-tmpdir. Defines and substitutes AMANDA_TMPDIR. +# +AC_DEFUN([AMANDA_WITH_TMPDIR], +[ + AC_ARG_WITH(tmpdir, + AS_HELP_STRING([--with-tmpdir], + [directory for temporary and debugging files (default: /tmp/amanda)]), + [ + tmpdir="$withval" + ], [ + tmpdir=yes + ] + ) + + case "$tmpdir" in + n | no) AC_MSG_ERROR([*** --without-tmpdir is not allowed.]);; + y | ye | yes) AMANDA_TMPDIR="/tmp/amanda";; + *) AMANDA_TMPDIR="$tmpdir";; + esac + + AC_DEFINE_DIR([AMANDA_TMPDIR], [AMANDA_TMPDIR], + [The directory in which Amanda should create temporary files. ]) +]) + +# SYNOPSIS +# +# AMANDA_EXPAND_DIRS +# +# OVERVIEW +# +# Expand any variable references in the following variables, then define them: +# - bindir +# - sbindir +# - libexecdir +# - mandir +# +# Also defines the following directories and expands any variable references: +# - amlibdir = --with-amlibdir or ${libdir}/amanda +# - amlibexecdir = --with-amlibexecdir or ${libexecdir}/amanda +# - amincludedir = ${includedir}/amanda +# - amperldir = --with-amperldir or `perl -V:installsitearch` +# - DUMPER_DIR = ${amlibexecdir}/application +# +AC_DEFUN([AMANDA_EXPAND_DIRS], +[ + AC_REQUIRE([AMANDA_PROG_PERL]) + + AC_DEFINE_DIR([bindir], [bindir], + [Directory in which user binaries should be installed. ]) + + AC_DEFINE_DIR([sbindir], [sbindir], + [Directory in which administrator binaries should be installed. ]) + + AC_DEFINE_DIR([libexecdir], [libexecdir], + [Directory in which internal binaries should be installed. ]) + + AC_DEFINE_DIR([mandir], [mandir], + [Directory in which man-pages should be installed]) + + + # amanda-specific directories + AMLIBDIR=$libdir/amanda + AC_ARG_WITH(amlibdir, + AS_HELP_STRING([--with-amlibdir[[[[[=PATH]]]]]], + [Where library are installed, default: $libdir/amanda]) + AS_HELP_STRING([--without-amlibdir], + [Library are installed in $libdir]), + [ + case "$withval" in + n | no) AMLIBDIR=$libdir ;; + y | ye | yes) AMLIBDIR=$libdir/amanda ;; + *) AMLIBDIR=$withval ;; + esac + ] + ) + AC_DEFINE_DIR([amlibdir], [AMLIBDIR], + [Directory in which Amanda libraries should be installed]) + + AMLIBEXECDIR=$libexecdir/amanda + AC_ARG_WITH(amlibexecdir, + AS_HELP_STRING([--with-amlibexecdir[[[[[=PATH]]]]]], + [Where amanda own programs are installed, default: $libexecdir/amanda]) + AS_HELP_STRING([--without-amlibexecdir], + [Amanda own programs are installed in $libexecdir]), + [ + case "$withval" in + n | no) AMLIBEXECDIR=$libexecdir ;; + y | ye | yes) AMLIBEXECDIR=$libexecdir/amanda ;; + *) AMLIBEXECDIR=$withval ;; + esac + ] + ) + AC_DEFINE_DIR([amlibexecdir], [AMLIBEXECDIR], + [Directory in which Amanda own programs should be installed]) + + amincludedir="${includedir}/amanda" + AC_DEFINE_DIR([amincludedir], [amincludedir], + [Directory in which Amanda header files should be installed]) + + AC_ARG_WITH(amperldir, + AS_HELP_STRING([--with-amperldir[[[[[=PATH]]]]]], + [Where amanda's perl modules are installed; default: installsitelib]) + AS_HELP_STRING([--without-amperldir], + [Install amanda's perl modules in $amlibdir/perl]), + [ + case "$withval" in + y | ye | yes) AMPERLLIB=DEFAULT ;; + n | no) AMPERLLIB=$amlibdir/perl ;; + *) AMPERLLIB=$withval ;; + esac + ], [ + AMPERLLIB=DEFAULT + ] + ) + # apply the default if no value was given. + if test x"$AMPERLLIB" = x"DEFAULT"; then + eval `$PERL -V:installsitelib` + AMPERLLIB=$installsitelib + fi + AC_DEFINE_DIR([amperldir], [AMPERLLIB], + [Directory in which perl modules should be installed]) + + DUMPER_DIR='${amlibexecdir}/application' + AC_DEFINE_DIR([DUMPER_DIR],[DUMPER_DIR], + [Directory in which dumper interfaces should be installed and searched. ]) + # TODO: rename to APPLICATION_DIR, add to Amanda::Paths and 'amgtconf build.APPLICATION_DIR' +]) + +# SYNOPSIS +# +# AMANDA_SHOW_DIRS_SUMMARY +# +# OVERVIEW +# +# Show a summary of the settings from this file. +# +AC_DEFUN([AMANDA_SHOW_DIRS_SUMMARY], +[ + echo "Directories:" + echo " Perl modules (amperldir): $amperldir" + echo " Dumper: $DUMPER_DIR" + echo " Configuration: $CONFIG_DIR" + echo " GNU Tar lists: $GNUTAR_LISTED_INCREMENTAL_DIR" + echo " Temporary: $AMANDA_TMPDIR" +]) diff --git a/config/amanda/documentation.m4 b/config/amanda/documentation.m4 new file mode 100644 index 0000000..af8a023 --- /dev/null +++ b/config/amanda/documentation.m4 @@ -0,0 +1,64 @@ +# OVERVIEW +# +# Configuration for the docbook-based manpages. +# +# We require XSLTPROC, as well as specific versions of Docbook and the +# Docbook DTD. + +AC_DEFUN([AMANDA_SETUP_DOCUMENTATION], +[ + AC_ARG_ENABLE(manpage-build, + AS_HELP_STRING([--enable-manpage-build], + [Build the manpages from their XML source (shipped manpages are usually sufficient)]), + [ ENABLE_MANPAGE_BUILD=$enableval ], + [ ENABLE_MANPAGE_BUILD=no ]) + + # and ensure that everything docbook-related is OK if we'll be using it + if test "x$ENABLE_MANPAGE_BUILD" = "xyes"; then + DOC_BUILD_DATE=`date '+%d-%m-%Y'` + + AC_PROG_XSLTPROC([--nonet]) + AC_CHECK_DOCBOOK_XSLT([1.72.0]) + AC_CHECK_DOCBOOK_XSLT_MIN([1.72.0]) + AC_CHECK_DOCBOOK_DTD([4.1.2]) + AC_CHECK_DOCBOOK_DTD([4.2]) + + if test -z "$XSLTPROC"; then + AC_MSG_ERROR([Cannot build manpages: 'xsltproc' was not found.]) + fi + + # if the 'current' Docbook revision is good enough, use that; otherwise, + # if 1.72.0 is available, use that. + XSLREL=current + if test "x$DOCBOOK_XSLT_CURRENT_VERSION" = "xno"; then + if test "x$HAVE_DOCBOOK_XSLT_1_72_0" = "xno"; then + AC_MSG_ERROR([Cannot build manpages: docbook version 1.72.0 or higher required.]) + else + XSLREL=1.72.0 + fi + fi + + # disable validation if the correct DTDs are not available + if test "x$HAVE_DOCBOOK_DTD_4_1_2" = "xno" || test "x$HAVE_DOCBOOK_DTD_4_2" = "xno"; then + AMANDA_MSG_WARN([Docbook DTD versions 4.1.2 and 4.2 are required for manpage validation; disabling validation]) + XSLTPROC_FLAGS="$XSLTPROC_FLAGS --novalid" + fi + fi + + AM_CONDITIONAL(ENABLE_MANPAGE_BUILD, test "x$ENABLE_MANPAGE_BUILD" = "xyes") + AC_SUBST(XSLREL) + AC_SUBST(DOC_BUILD_DATE) +]) + +# SYNOPSIS +# +# AMANDA_SHOW_DOCUMENTATION_SUMMARY +# +# OVERVIEW +# +# Show a summary of the settings from this file. +# +AC_DEFUN([AMANDA_SHOW_DOCUMENTATION_SUMMARY], +[ + echo "Build documentation:" $ENABLE_MANPAGE_BUILD +]) diff --git a/config/amanda/dumpers.m4 b/config/amanda/dumpers.m4 new file mode 100644 index 0000000..9c455c6 --- /dev/null +++ b/config/amanda/dumpers.m4 @@ -0,0 +1,398 @@ +# OVERVIEW +# + +# SYNOPSIS +# +# AMANDA_PROG_GNUTAR +# +# OVERVIEW +# +# Search for a GNU 'tar' binary, placing the result in the precious +# variable GNUTAR. The discovered binary is tested to ensure it's really +# GNU tar. +# +# Also handle --with-gnutar +# +AC_DEFUN([AMANDA_PROG_GNUTAR], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + # call with + AC_ARG_WITH(gnutar, + AS_HELP_STRING([--with-gnutar=PROG], + [use PROG as GNU 'tar']), + [ + # check withval + case "$withval" in + /*) GNUTAR="$withval";; + y|ye|yes) :;; + n|no) GNUTAR=no ;; + *) AC_MSG_ERROR([*** You must supply a full pathname to --with-gnutar]);; + esac + # done + ] + ) + + if test "x$GNUTAR" = "xno"; then + GNUTAR= + else + for gnutar_name in gtar gnutar tar; do + AC_PATH_PROGS(GNUTAR, $gnutar_name, , $LOCSYSPATH) + if test -n "$GNUTAR"; then + case "`\"$GNUTAR\" --version 2>&1`" in + *GNU*tar* | *Free*paxutils* ) + # OK, it is GNU tar + break + ;; + *) + # warning.. + AMANDA_MSG_WARN([$GNUTAR is not GNU tar, so it will not be used.]) + # reset the cache for GNUTAR so AC_PATH_PROGS will search again + GNUTAR='' + unset ac_cv_path_GNUTAR + ;; + esac + fi + done + fi + + if test "x$GNUTAR" != "x"; then + # define unquoted + AC_DEFINE_UNQUOTED(GNUTAR, "$GNUTAR", [Location of the GNU 'tar' binary]) + fi + AC_ARG_VAR(GNUTAR, [Location of the GNU 'tar' binary]) + AC_SUBST(GNUTAR) +]) + +# SYNOPSIS +# +# AMANDA_PROG_SAMBA_CLIENT +# +# OVERVIEW +# +# Search for a samba client (smbclient) binary, placing the result in +# the variable SAMBA_CLIENT. The discovered binary is tested to determine an +# internally significant version number, stored in SAMBA_VERSION. The version +# serves only to differentiate versions of Samba which Amanada must treat +# differently, and has no relation to the actual Samba version number. +# +# Automake conditional 'WANT_SAMBA' is set if a samba client is discovered. +# +# Also handles --with-smbclient and (deprecated) --with-samba-user +# +AC_DEFUN([AMANDA_PROG_SAMBA_CLIENT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + AC_ARG_WITH(smbclient, + AS_HELP_STRING([--with-smbclient=PROG], + [use PROG as 'smbclient']), + [ + case "$withval" in + /*) SAMBA_CLIENT="$withval";; + y|ye|yes) :;; + n|no) SAMBA_CLIENT=no ;; + *) AC_MSG_ERROR([*** You must supply a full pathname to --with-smbclient]);; + esac + ] + ) + + AC_ARG_WITH(samba-user, + AS_HELP_STRING([--with-samba-user], + [deprecated; place username in 'amandapass']), + [ AC_MSG_ERROR([--with-samba-user is no longer supported; place username in 'amandapass']) ] + ) + + if test "x$SAMBA_CLIENT" != "xno"; then + AC_PATH_PROG(SAMBA_CLIENT,smbclient,,$LOCSYSPATH) + smbversion=0 + if test ! -z "$SAMBA_CLIENT"; then + case "`\"$SAMBA_CLIENT\" '\\\\not.a.host.name\\notashare' -U nosuchuser -N -Tx /dev/null 2>&1`" in + *"Unknown host"*) + smbversion=1 + ;; + *"Connection to not.a.host.name failed"*) + smbversion=2 + ;; + *) + AMANDA_MSG_WARN([$SAMBA_CLIENT does not seem to be smbclient, so it will not be used.]) + SAMBA_CLIENT= + ;; + esac + if test -n "$SAMBA_CLIENT"; then + AC_DEFINE_UNQUOTED(SAMBA_CLIENT,"$SAMBA_CLIENT", + [Define the location of smbclient for backing up Samba PC clients. ]) + AC_DEFINE_UNQUOTED(SAMBA_VERSION, $smbversion, + [Not the actual samba version, just a number that should be increased whenever we start to rely on a new samba feature. ]) + fi + fi + fi + + AM_CONDITIONAL(WANT_SAMBA, test -n "$SAMBA_CLIENT") +]) + +# SYNOPSIS +# +# AMANDA_PROG_VDUMP_VRESTORE +# +# DESCRIPTION +# +# Search for 'vdump' and 'vrestore', setting and AC_DEFINE-ing VDUMP and +# VRESTORE if they are found. +# +AC_DEFUN([AMANDA_PROG_VDUMP_VRESTORE], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + AC_PATH_PROG(VDUMP,vdump,,$SYSLOCPATH) + AC_PATH_PROG(VRESTORE,vrestore,,$SYSLOCPATH) + if test "$VDUMP" -a "$VRESTORE"; then + AC_DEFINE_UNQUOTED(VDUMP,"$VDUMP",[Define the location of the vdump program. ]) + AC_DEFINE_UNQUOTED(VRESTORE,"$VRESTORE",[Define the location of the vrestore program. ]) + fi +]) + +# SYNOPSIS +# +# AMANDA_PROG_VXDUMP_VXRESTORE +# +# DESCRIPTION +# +# Search for 'vxdump' and 'vxrestore', setting and AC_DEFINE-ing VXDUMP +# and VXRESTORE if they are found. +# +# In addition to the standard paths, this macro will search in +# /usr/lib/fs/vxfs. +# +AC_DEFUN([AMANDA_PROG_VXDUMP_VXRESTORE], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + AC_PATH_PROG(VXDUMP,vxdump,,$SYSLOCPATH:/usr/lib/fs/vxfs) + AC_PATH_PROG(VXRESTORE,vxrestore,,$SYSLOCPATH:/usr/lib/fs/vxfs) + if test "$VXDUMP" -a "$VXRESTORE"; then + AC_DEFINE_UNQUOTED(VXDUMP,"$VXDUMP", +[Define the location of the vxdump program on HPUX and SINIX hosts or on + * other hosts where the Veritas filesystem (vxfs) has been installed. ]) + AC_DEFINE_UNQUOTED(VXRESTORE,"$VXRESTORE", +[Define the location of the vxrestore program on HPUX and SINIX hosts or on + * other hosts where the Veritas filesystem (vxfs) has been installed. ]) + fi +]) + +# SYNOPSIS +# +# AMANDA_PROG_XFSDUMP_XFSRESTORE +# +# DESCRIPTION +# +# Search for 'xfsdump' and 'xfsrestore', setting and AC_DEFINE-ing XFSDUMP +# and XFSRESTORE if they are found. +# +AC_DEFUN([AMANDA_PROG_XFSDUMP_XFSRESTORE], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + AC_PATH_PROGS(XFSDUMP,xfsdump,,$SYSLOCPATH) + AC_PATH_PROGS(XFSRESTORE,xfsrestore,,$SYSLOCPATH) + if test "$XFSDUMP" -a "$XFSRESTORE"; then + AC_DEFINE_UNQUOTED(XFSDUMP,"$XFSDUMP", + [Define the location of the xfsdump program on Irix hosts. ]) + AC_DEFINE_UNQUOTED(XFSRESTORE,"$XFSRESTORE", + [Define the location of the xfsrestore program on Irix hosts. ]) + AMANDA_MSG_WARN([[xfsdump causes the setuid-root rundump program to be enabled. To disable it, just #undef XFSDUMP in config/config.h]]) + fi +]) + +# SYNOPSIS +# +# AMANDA_PROG_DUMP_RESTORE +# +# DESCRIPTION +# +# Search for compatible dump and restore binaries. The exact name of +# the binaries we search for depends on the target system. If working +# binaries are found, DUMP and RESTORE are defined to their full paths. +# +# DUMP_RETURNS is defined if the system's 'dump' returns 1 on success. +# +# HAVE_DUMP_ESTIMATE is defined to the dump flag which enables estimates. +# +# The --with-honor-nodump flag is processed, and the result of the test is +# positive, then HAVE_HONOR_NODUMP is defined. +# +AC_DEFUN([AMANDA_PROG_DUMP_RESTORE], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_REQUIRE([AMANDA_PROG_GREP]) + + # Set the order of dump programs to look for. Finding the proper file + # system dumping program is problematic. Some systems, notably HP-UX + # and AIX, have both the backup and dump programs. HP-UX can't use the + # the backup program while AIX systems can't use the dump program. So + # a variable is set up here to specify the order of dump programs to + # search for on the system. + DUMP_PROGRAMS="ufsdump dump backup" + dump_returns_1= + case "$target" in + *-dg-*) + DUMP_PROGRAMS="dump "$DUMP_PROGRAMS + dump_returns_1=yes + ;; + *-ibm-aix*) + DUMP_PROGRAMS="backup "$DUMP_PROGRAMS + AC_DEFINE(AIX_BACKUP,1, + [Is DUMP the AIX program 'backup'?]) + ;; + *-ultrix*) + dump_returns_1=yes + ;; + esac + + if test -n "$dump_returns_1"; then + AC_DEFINE(DUMP_RETURNS_1,1, + [Define this if this system's dump exits with 1 as a success code. ]) + fi + + AC_PATH_PROGS(DUMP,$DUMP_PROGRAMS,,$SYSLOCPATH) + AC_PATH_PROGS(RESTORE,ufsrestore restore,,$SYSLOCPATH) + + # newer versions of GNU tar include a program named 'backup' which + # does *not* implement the expected 'dump' interface. Detect that here + # and pretend we never saw it. + if test -n "$DUMP"; then + if test "`basename $DUMP`" = "backup"; then + backup_gnutar=`$DUMP --version | $GREP "GNU tar"` + if test $? -eq 0; then + DUMP= + fi + fi + fi + + if test "$DUMP" -a "$RESTORE"; then + AC_DEFINE_UNQUOTED(DUMP,"$DUMP", + [Define the location of the ufsdump, backup, or dump program. ]) + AC_DEFINE_UNQUOTED(RESTORE,"$RESTORE", + [Define the location of the ufsrestore or restore program. ]) + + # check for an estimate flag + if test -x $DUMP; then + AC_CACHE_CHECK( + [whether $DUMP supports -E or -S for estimates], + amanda_cv_dump_estimate, + [ + case "$DUMP" in + *dump) + AC_TRY_COMMAND($DUMP 9Ef /dev/null /dev/null/invalid/fs 2>&1 + | $GREP -v Dumping + | $GREP -v Date + | $GREP -v Label >conftest.d-E 2>&1) + cat conftest.d-E >&AS_MESSAGE_LOG_FD() + AC_TRY_COMMAND($DUMP 9Sf /dev/null /dev/null/invalid/fs 2>&1 + | $GREP -v Dumping + | $GREP -v Date + | $GREP -v Label >conftest.d-S 2>&1) + cat conftest.d-S >&AS_MESSAGE_LOG_FD() + AC_TRY_COMMAND($DUMP 9f /dev/null /dev/null/invalid/fs 2>&1 + | $GREP -v Dumping + | $GREP -v Date + | $GREP -v Label >conftest.d 2>&1) + cat conftest.d >&AS_MESSAGE_LOG_FD() + if AC_TRY_COMMAND(cmp conftest.d-E conftest.d 1>&2); then + amanda_cv_dump_estimate=E + elif AC_TRY_COMMAND(cmp conftest.d-S conftest.d 1>&2); then + amanda_cv_dump_estimate=S + else + amanda_cv_dump_estimate=no + fi + rm -f conftest.d conftest.d-E conftest.d-S + ;; + *) amanda_cv_dump_estimate=no + ;; + esac + ]) + else + AMANDA_MSG_WARN([$DUMP is not executable, cannot run -E/-S test]) + amanda_cv_dump_estimate=no + fi + if test "x$amanda_cv_dump_estimate" != xno; then + AC_DEFINE_UNQUOTED(HAVE_DUMP_ESTIMATE, "$amanda_cv_dump_estimate", + [Define to the string that enables dump estimates. ]) + fi + + AC_ARG_WITH(dump-honor-nodump, + AS_HELP_STRING([--with-dump-honor-nodump], + [if dump supports -h, use it for level0s too]), + [ + if test -x $DUMP; then + AC_CACHE_CHECK( + [whether $DUMP supports -h (honor nodump flag)], + amanda_cv_honor_nodump, + [ + case "$DUMP" in + *dump) + AC_TRY_COMMAND($DUMP 9hf 0 /dev/null /dev/null/invalid/fs 2>&1 + | $GREP -v Dumping + | $GREP -v Date + | $GREP -v Label >conftest.d-h 2>&1) + cat conftest.d-h >&AS_MESSAGE_LOG_FD() + AC_TRY_COMMAND($DUMP 9f /dev/null /dev/null/invalid/fs 2>&1 + | $GREP -v Dumping + | $GREP -v Date + | $GREP -v Label >conftest.d 2>&1) + cat conftest.d >&AS_MESSAGE_LOG_FD() + if AC_TRY_COMMAND(diff conftest.d-h conftest.d 1>&2); then + amanda_cv_honor_nodump=yes + else + amanda_cv_honor_nodump=no + fi + rm -f conftest.d conftest.d-h + ;; + *) amanda_cv_honor_nodump=no + ;; + esac + ]) + else + AMANDA_MSG_WARN([$DUMP is not executable, cannot run -h test]) + amanda_cv_honor_nodump=no + fi + if test "x$amanda_cv_honor_nodump" = xyes; then + AC_DEFINE(HAVE_HONOR_NODUMP,1, + [Define this if dump accepts -h for honoring nodump. ]) + fi + ]) + fi +]) + +# SYNOPSIS +# +# AMANDA_CHECK_USE_RUNDUMP +# +# DESCRIPTION +# +# Decide if the 'rundump' setuid-root wrapper should be used to invoke +# dump. If so, USE_RUNDUMP is #defined. +# +AC_DEFUN([AMANDA_CHECK_USE_RUNDUMP], [ + USE_RUNDUMP=no + + # some systems require rundump unconditionally + case "$target" in + *-ultrix*) USE_RUNDUMP=yes ;; + *-dg-*) USE_RUNDUMP=yes ;; + esac + + AC_ARG_WITH(rundump, + AS_HELP_STRING([--with-rundump], [use rundump, a setuid-root wrapper, to invoke dump]), [ + case "$withval" in + n | no) USE_RUNDUMP=no ;; + y | ye | yes) USE_RUNDUMP=yes ;; + *) AC_MSG_ERROR([You must not supply an argument to --with-rundump option.]);; + esac + ]) + + if test x"$USE_RUNDUMP" = x"yes"; then + AC_DEFINE(USE_RUNDUMP,1, + [Define to invoke rundump (setuid-root) instead of DUMP program directly. ]) + fi +]) diff --git a/config/amanda/file-list b/config/amanda/file-list new file mode 100644 index 0000000..7e929ac --- /dev/null +++ b/config/amanda/file-list @@ -0,0 +1,41 @@ +## this file is automatically generated by autogen +EXTRA_DIST += amanda/amplot.m4 +EXTRA_DIST += amanda/bsd-security.m4 +EXTRA_DIST += amanda/bsdtcp-security.m4 +EXTRA_DIST += amanda/bsdudp-security.m4 +EXTRA_DIST += amanda/changer.m4 +EXTRA_DIST += amanda/components.m4 +EXTRA_DIST += amanda/compress.m4 +EXTRA_DIST += amanda/config.m4 +EXTRA_DIST += amanda/debugging.m4 +EXTRA_DIST += amanda/defaults.m4 +EXTRA_DIST += amanda/devprefix.m4 +EXTRA_DIST += amanda/dirs.m4 +EXTRA_DIST += amanda/documentation.m4 +EXTRA_DIST += amanda/dumpers.m4 +EXTRA_DIST += amanda/flags.m4 +EXTRA_DIST += amanda/flock.m4 +EXTRA_DIST += amanda/funcs.m4 +EXTRA_DIST += amanda/getfsent.m4 +EXTRA_DIST += amanda/i18n.m4 +EXTRA_DIST += amanda/ipv6.m4 +EXTRA_DIST += amanda/krb4-security.m4 +EXTRA_DIST += amanda/krb5-security.m4 +EXTRA_DIST += amanda/lfs.m4 +EXTRA_DIST += amanda/libs.m4 +EXTRA_DIST += amanda/net.m4 +EXTRA_DIST += amanda/progs.m4 +EXTRA_DIST += amanda/readdir.m4 +EXTRA_DIST += amanda/readline.m4 +EXTRA_DIST += amanda/rsh-security.m4 +EXTRA_DIST += amanda/s3-device.m4 +EXTRA_DIST += amanda/shmem.m4 +EXTRA_DIST += amanda/socklen_t_equiv.m4 +EXTRA_DIST += amanda/ssh-security.m4 +EXTRA_DIST += amanda/summary.m4 +EXTRA_DIST += amanda/swig.m4 +EXTRA_DIST += amanda/syshacks.m4 +EXTRA_DIST += amanda/tape.m4 +EXTRA_DIST += amanda/types.m4 +EXTRA_DIST += amanda/userid.m4 +EXTRA_DIST += amanda/version.m4 diff --git a/config/amanda/flags.m4 b/config/amanda/flags.m4 new file mode 100644 index 0000000..ba20da9 --- /dev/null +++ b/config/amanda/flags.m4 @@ -0,0 +1,301 @@ +# OVERVIEW/BACKGROUND +# +# This file manages flags in CFLAGS, CPPFLAGS, LDFLAGS, and LIBS. +# +# Flags can come from two several sources: +# - entry to ./configure or on the configure command line (they are +# `precious' variables) +# - added by autoconf tests during the execution of configure +# +# Although Automake supports overriding variables when invoking 'make', +# we don't support it (mostly because autoconf doesn't). Instead, users +# should specify such variables when invoking ./configure. +# +# CFLAGS are a little bit more complicated: Amanda has two categories, +# mandatory CFLAGS, which should be used everywhere, and warning CFLAGS, +# which are only used on Amanda code (not gnulib or yacc-generated code). +# To accomplish this, mandatory CFLAGS go directl into CFLAGS, while +# warwnings go in AMANDA_WARNING_CFLAGS; these are then added to +# AM_CFLAGS by the Makefiles. + +# SYNOPSIS +# +# AMANDA_INIT_FLAGS() +# +# DESCRIPTION +# +# Process variables given by the user on the command line, +# either as environment variables: +# CPPFLAGS=-Dfoo ./configure ... +# as assignments in the configure command line: +# ./configure LIBS=-lfoo ... +# or with the deprecated flags --with-cflags, --with-includes, and +# --with-libraries +# +AC_DEFUN([AMANDA_INIT_FLAGS], +[ + # support deprecated ./configure flags to set various compiler flags + + AC_ARG_WITH(cflags, + AS_HELP_STRING([--with-cflags=FLAGS], + [deprecated; use ./configure CFLAGS=... ]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-cflags option.]) + ;; + esac + + CFLAGS="$withval" + ]) + + AC_ARG_WITH(includes, + AS_HELP_STRING([--with-includes=INCLUDE-DIRS], + [deprecated; use ./configure CPPFLAGS='-I.. -I..']), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-includes option.]) + ;; + esac + + for dir in $withval; do + if test -d "$dir"; then + CPPFLAGS="$CPPFLAGS -I$dir" + else + AMANDA_MSG_WARN([Include directory $dir does not exist.]) + fi + done + ]) + + AC_ARG_WITH(libraries, + AS_HELP_STRING([--with-libraries=LIBRARY-DIRS], + [deprecated; use ./configure LDFLAGS='-L.. -L..' (add -R on Solaris, NetBSD)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-libraries option.]) + ;; + esac + + for dir in $withval; do + if test -d "$dir"; then + case "$target" in + *-solaris2*,*-netbsd*) + LDFLAGS="$LDFLAGS -R$dir" + ;; + esac + LDFLAGS="$LDFLAGS -L$dir" + else + AMANDA_MSG_WARN([Library directory $dir does not exist.]) + fi + done + ]) + + # Warn for just about everything + AMANDA_TEST_GCC_WARNING_FLAG(-Wall, [ + AMANDA_ADD_WARNING_CFLAG(-Wall) + ]) + + # And add any extra warnings too + AMANDA_TEST_GCC_WARNING_FLAG(-Wextra, [ + AMANDA_ADD_WARNING_CFLAG(-Wextra) + ], [ + AMANDA_TEST_GCC_WARNING_FLAG(-W, [ + AMANDA_ADD_WARNING_CFLAG(-W) + ]) + ]) + AC_SUBST([AMANDA_WARNING_CFLAGS]) +]) + +# SYNOPSIS +# +# AMANDA_STATIC_FLAGS(new_flags) +# +# DESCRIPTION +# +# Set AMANDA_STATIC_LDFLAGS to -static if --enable-static-binary +# +AC_DEFUN([AMANDA_STATIC_FLAGS], +[ + AC_ARG_ENABLE(static-binary, + AS_HELP_STRING([--enable-static-binary], + [To build statically linked binaries]), + [ + case "$withval" in + "" | y | ye | yes) + AMANDA_STATIC_LDFLAGS=-static + if test x"$enable_static" = x"no"; then + AC_MSG_ERROR([*** --enable-static-binary is incompatible with --disable-static]) + fi + ;; + *n | no) + AMANDA_STATIC_LDFLAGS= + ;; + esac + ]) + AC_SUBST([AMANDA_STATIC_LDFLAGS]) +]) + +# SYNOPSIS +# +# AMANDA_ADD_CFLAGS(new_flags) +# +# DESCRIPTION +# +# Add 'new_flags' to CFLAGS. +# +# 'new_flags' will be enclosed in double quotes in the resulting +# shell assignment. +# +AC_DEFUN([AMANDA_ADD_CFLAGS], + [CFLAGS="$CFLAGS $1"] +) + +# SYNOPSIS +# +# AMANDA_ADD_CPPFLAGS(new_flags) +# +# DESCRIPTION +# +# Add 'new_flags' to CPPFLAGS. +# +# 'new_flags' will be enclosed in double quotes in the resulting +# shell assignment. +# +AC_DEFUN([AMANDA_ADD_CPPFLAGS], + [CPPFLAGS="$CPPFLAGS $1"] +) + +# SYNOPSIS +# +# AMANDA_ADD_LDFLAGS(new_flags) +# +# DESCRIPTION +# +# Add 'new_flags' to LDFLAGS. +# +# 'new_flags' will be enclosed in double quotes in the resulting +# shell assignment. +# +AC_DEFUN([AMANDA_ADD_LDFLAGS], + [LDFLAGS="$LDFLAGS $1"] +) + +# SYNOPSIS +# +# AMANDA_ADD_LIBS(new_flags) +# +# DESCRIPTION +# +# Add 'new_flags' to LIBS. +# +# 'new_flags' will be enclosed in double quotes in the resulting +# shell assignment. +# +AC_DEFUN([AMANDA_ADD_LIBS], + [LIBS="$1 $LIBS"] +) + +# SYNOPSIS +# +# AMANDA_ADD_WARNING_CFLAG(flag) +# +# DESCRIPTION +# +# Add 'flag' to AMANDA_WARNING_CFLAGS +# +AC_DEFUN([AMANDA_ADD_WARNING_CFLAG], + [AMANDA_WARNING_CFLAGS="$AMANDA_WARNING_CFLAGS $1"] +) + +# SYNOPSIS +# +# AMANDA_ENABLE_GCC_WARNING(warning) +# +# OVERVIEW +# +# Enable warning 'warning' by adding flag -W'warning' to +# AMANDA_WARNING_CFLAGS. +# +AC_DEFUN([AMANDA_ENABLE_GCC_WARNING], +[ + AMANDA_TEST_GCC_WARNING_FLAG(-W$1, + [ + AMANDA_ADD_WARNING_CFLAG(-W$1) + ]) +]) + +# SYNOPSIS +# +# AMANDA_DISABLE_GCC_WARNING(warning) +# +# OVERVIEW +# +# Disable warning 'warning' by adding flag -Wno-'warning' to +# AMANDA_WARNING_CFLAGS. +# +AC_DEFUN([AMANDA_DISABLE_GCC_WARNING], +[ + # test for -W'warning', then add the 'no-' version. + AMANDA_TEST_GCC_WARNING_FLAG(-W$1, + [ + AMANDA_ADD_WARNING_CFLAG(-Wno-$1) + ]) +]) + +# SYNOPSIS +# +# AMANDA_TEST_GCC_WARNING_FLAG(flag, action-if-found, action-if-not-found) +# +# OVERVIEW +# +# See if CC is gcc, and if gcc -v --help contains the given flag. If so, +# run action-if-found; otherwise, run action-if-not-found. +# +# Intended for internal use in this file. +# +AC_DEFUN([AMANDA_TEST_GCC_WARNING_FLAG], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_EGREP]) + AC_MSG_CHECKING(for gcc flag $1) + if test "x$GCC" = "xyes"; then + changequote(,)dnl + $CC -v --help 2>&1 | $EGREP -- '[^[:alnum:]]$1[^[:alnum:]-]' 2>&1 > /dev/null + changequote([,])dnl + if test $? -eq 0; then + found_warning=yes + AC_MSG_RESULT(yes) + else + found_warning=no + AC_MSG_RESULT(no) + fi + else + found_warning=no + AC_MSG_RESULT(no (not using gcc)) + fi + + if test x"$found_warning" = x"yes"; then + ifelse($2, [], [:], $2) + else + ifelse($3, [], [:], $3) + fi +]) + +# SYNOPSIS +# +# AMANDA_SHOW_FLAGS_SUMMARY +# +# OVERVIEW +# +# Show a summary of the flags with which Amanda was configured +# +AC_DEFUN([AMANDA_SHOW_FLAGS_SUMMARY], +[ + echo "Compiler Flags:" + echo " CFLAGS: ${CFLAGS-(none)}" + echo " CPPFLAGS: ${CPPFLAGS-(none)}" + echo " LDFLAGS: ${LDFLAGS-(none)}" + echo " LIBS: ${LIBS-(none)}" +]) diff --git a/config/amanda/flock.m4 b/config/amanda/flock.m4 new file mode 100644 index 0000000..9850a5b --- /dev/null +++ b/config/amanda/flock.m4 @@ -0,0 +1,145 @@ +# SYNOPSIS +# +# AMANDA_SETUP_FILE_LOCKING +# +# OVERVIEW +# +# Set up file locking support. Four types of locking are available: +# USE_POSIX_FCNTL - use fcntl(). The full job. +# USE_FLOCK - use flock(). Does just as well. +# USE_LOCKF - use lockf(). Only handles advisory, exclusive, +# blocking file locks as used by Amanda. +# USE_LNLOCK - Home brew exclusive, blocking file lock. +# - No locking available. User beware! +# One of given symbols are defined if the method is discovered to +# be available; the methods are searched in the above order. +# +AC_DEFUN([AMANDA_SETUP_FILE_LOCKING], +[ + AC_CHECK_HEADERS( + fcntl.h \ + sys/fcntl.h \ + sys/types.h \ + sys/file.h \ + unistd.h \ + ) + + # find a working file-locking mechanism. + # Note: these all use AC_TRY_LINK to make sure that we can compile + # and link each variant. They do not try to test the variants -- + # that is left to runtime. + WORKING_FILE_LOCK="no" + + # check POSIX locking + AC_CACHE_CHECK( + [whether POSIX locking (with fcntl(2)) is available], + amanda_cv_posix_filelocking, + [ + AC_TRY_LINK([ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif +#if HAVE_FCNTL_H +# include +#endif + ], [ + struct flock lock; + + lock.l_type = F_RDLCK; + lock.l_start = 0; + lock.l_whence = SEEK_CUR; + lock.l_len = 0; + return fcntl(1, F_SETLK, &lock); + ], [ + amanda_cv_posix_filelocking="yes" + ],[ + amanda_cv_posix_filelocking="no" + ]) + ]) + if test "x$amanda_cv_posix_filelocking" = xyes; then + AC_DEFINE(WANT_AMFLOCK_POSIX,1,[Define to use POSIX (fcntl()) for file locking]) + WANT_AMFLOCK_POSIX="yes" + WORKING_FILE_LOCK="yes" + fi + AM_CONDITIONAL(WANT_AMFLOCK_POSIX, test x"$WANT_AMFLOCK_POSIX" = x"yes") + + # check flock-based (BSD) locking + AC_CACHE_CHECK( + [whether flock locking is available], + amanda_cv_flock_filelocking, + [ + AC_TRY_LINK([ +#if HAVE_SYS_FILE_H +# include +#endif + ], [ + return flock(1, LOCK_SH); + ], [ + amanda_cv_flock_filelocking="yes" + ],[ + amanda_cv_flock_filelocking="no" + ]) + ]) + if test "x$amanda_cv_flock_filelocking" = xyes; then + AC_DEFINE(WANT_AMFLOCK_FLOCK,1,[Define to use flock(2) for file locking]) + WANT_AMFLOCK_FLOCK="yes" + WORKING_FILE_LOCK="yes" + fi + AM_CONDITIONAL(WANT_AMFLOCK_FLOCK, test x"$WANT_AMFLOCK_FLOCK" = x"yes") + + # check lockf-based (SVR2, SVR3, SVR4) locking + AC_CACHE_CHECK( + [whether lockf(3) locking is available], + amanda_cv_lockf_filelocking, + [ + AC_TRY_LINK([ +#if HAVE_UNISTD_H +# include +#endif + ], [ + return lockf(1, F_LOCK, 0); + ], [ + amanda_cv_lockf_filelocking="yes" + ],[ + amanda_cv_lockf_filelocking="no" + ]) + ]) + if test "x$amanda_cv_lockf_filelocking" = xyes; then + AC_DEFINE(WANT_AMFLOCK_LOCKF,1,[Define to use lockf(3) for file locking.]) + WANT_AMFLOCK_LOCKF="yes" + WORKING_FILE_LOCK="yes" + fi + AM_CONDITIONAL(WANT_AMFLOCK_LOCKF, test x"$WANT_AMFLOCK_LOCKF" = x"yes") + + # check our homebrew hardlink-based locking (requires hardlinks) + AC_CACHE_CHECK( + [whether link(2) is available for locking], + amanda_cv_lnlock_filelocking, + [ + AC_TRY_LINK([ +#if HAVE_UNISTD_H +# include +#endif + ], [ + return link("/tmp/foo", "/tmp/bar"); + ], [ + amanda_cv_lnlock_filelocking="yes" + ],[ + amanda_cv_lnlock_filelocking="no" + ]) + ]) + if test "x$amanda_cv_lnlock_filelocking" = xyes; then + AC_DEFINE(WANT_AMFLOCK_LNLOCK,1,[Define to use link(2) to emulate file locking.]) + WANT_AMFLOCK_LNLOCK="yes" + WORKING_FILE_LOCK="yes" + fi + AM_CONDITIONAL(WANT_AMFLOCK_LNLOCK, test x"$WANT_AMFLOCK_LNLOCK" = x"yes") + + if test x"$WORKING_FILE_LOCK" = "no"; then + # this shouldn't happen, and is *bad* if it does + AC_MSG_ERROR([*** No working file locking capability found!]) + fi +]) diff --git a/config/amanda/funcs.m4 b/config/amanda/funcs.m4 new file mode 100644 index 0000000..862bac8 --- /dev/null +++ b/config/amanda/funcs.m4 @@ -0,0 +1,266 @@ +# SYNOPSIS +# +# AMANDA_FUNC_SELECT_ARG_TYPE +# +# OVERVIEW +# +# Figure out the select() argument type. DEFINEs SELECT_ARG_TYPE. +# +AC_DEFUN([AMANDA_FUNC_SELECT_ARG_TYPE], + [ + AC_REQUIRE([AC_HEADER_TIME]) + AC_CHECK_HEADERS( + sys/time.h \ + sys/types.h \ + sys/select.h \ + sys/socket.h \ + unistd.h \ + ) + + AC_CACHE_CHECK( + [for select() argument type], + amanda_cv_select_arg_type, + [ + rm -f conftest.c + cat <conftest.$ac_ext +#include "confdefs.h" +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +int main() +{ +#ifdef FD_SET_POINTER + (void)select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, 0); +#else + (void)select(0, (int *) 0, (int *) 0, (int *) 0, 0); +#endif + return 0; +} +EOF + + # Figure out the select argument type by first trying to + # compile with the fd_set argument. If the compile fails, + # then we know to use the int. If it suceeds, then try to + # use the int. If the int fails, then use fd_set. If + # both suceeed, then do a line count on the number of + # lines that the compiler spit out, assuming that the + # compile outputing more lines had more errors. + amanda_cv_select_arg_type=no + select_compile="${CC-cc} -c $CFLAGS $CPPFLAGS" + $select_compile -DFD_SET_POINTER conftest.$ac_ext 1>conftest.fd_set 2>&1 + if test $? -ne 0; then + amanda_cv_select_arg_type=int + fi + if test "$amanda_cv_select_arg_type" = no; then + $select_compile conftest.$ac_ext 1>conftest.int 2>&1 + if test $? -ne 0; then + amanda_cv_select_arg_type=fd_set + fi + fi + if test "$amanda_cv_select_arg_type" = no; then + wc_fdset=`wc -l +#include +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +main() { +#ifdef SO_SNDTIMEO + int sock = socket(AF_INET, SOCK_STREAM, 0); + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + return (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, + (void *)&timeout, sizeof(timeout))); +#else + return -1; +#endif +} + ], + amanda_cv_setsockopt_SO_SNDTIMEO=yes, + amanda_cv_setsockopt_SO_SNDTIMEO=no, + amanda_cv_setsockopt_SO_SNDTIMEO=no + ) + ] + ) + if test "$amanda_cv_setsockopt_SO_SNDTIMEO" = yes; then + AC_DEFINE(HAVE_SO_SNDTIMEO,1,[Define if SO_SNDTIMEO is available. ]) + fi + ] +) + +# SYNOPSIS +# +# AMANDA_FUNC_GETTIMEOFDAY_ARGS +# +# OVERVIEW +# +# Check for the one or two argument version of gettimeofday. DEFINEs +# HAVE_TWO_ARG_GETTIMEOFDAY if the two argument version is present. +# +AC_DEFUN([AMANDA_FUNC_GETTIMEOFDAY_ARGS], + [ + AC_REQUIRE([AC_HEADER_TIME]) + AC_CHECK_HEADERS( + time.h + sys/time.h + ) + + AC_CACHE_CHECK( + [for gettimeofday number of arguments], + amanda_cv_gettimeofday_args, + [ + AC_TRY_COMPILE( + [ +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + ], + [ + struct timeval val; + struct timezone zone; + gettimeofday(&val, &zone); + ], + amanda_cv_gettimeofday_args=2, + amanda_cv_gettimeofday_args=1 + ) + ] + ) + if test "$amanda_cv_gettimeofday_args" = 2; then + AC_DEFINE(HAVE_TWO_ARG_GETTIMEOFDAY,1,[Define if gettimeofday takes two arguments. ]) + fi + ] +) + +# SYNOPSIS +# +# ICE_CHECK_DECL (FUNCTION, HEADER-FILE...) +# +# OVERVIEW +# +# If FUNCTION is available, define `HAVE_FUNCTION'. If it is declared +# in one of the headers named in the whitespace-separated list +# HEADER_FILE, define `HAVE_FUNCTION_DECL` (in all capitals). +# +AC_DEFUN([ICE_CHECK_DECL], +[ +ice_have_$1=no +AC_CHECK_FUNCS($1, ice_have_$1=yes) +if test "${ice_have_$1}" = yes; then +AC_MSG_CHECKING(for $1 declaration in $2) +AC_CACHE_VAL(ice_cv_have_$1_decl, +[ +ice_cv_have_$1_decl=no +changequote(,)dnl +ice_re_params='[a-zA-Z_][a-zA-Z0-9_]*' +ice_re_word='(^|[^a-zA-Z0-9_])' +changequote([,])dnl +for header in $2; do +# Check for ordinary declaration +AC_EGREP_HEADER([${ice_re_word}$1[ ]*\(], $header, + ice_cv_have_$1_decl=yes) +if test "$ice_cv_have_$1_decl" = yes; then + break +fi +# Check for "fixed" declaration like "getpid _PARAMS((int))" +AC_EGREP_HEADER([${ice_re_word}$1[ ]*$ice_re_params\(\(], $header, + ice_cv_have_$1_decl=yes) +if test "$ice_cv_have_$1_decl" = yes; then + break +fi +done +]) +AC_MSG_RESULT($ice_cv_have_$1_decl) +if test "$ice_cv_have_$1_decl" = yes; then +AC_DEFINE_UNQUOTED([HAVE_]translit($1,[a-z],[A-Z])[_DECL],1,[Define if $1 is declared. ]) +fi +fi +])dnl + +# SYNOPSIS +# +# AMANDA_FUNC_SETPGID +# +# OVERVIEW +# +# Search for the function HAVE_SETPGID, and run an ICE_CHECK_DECL on it if so. +# +AC_DEFUN([AMANDA_FUNC_SETPGID], +[ + AC_CHECK_FUNC(setpgid, [ + AC_DEFINE(HAVE_SETPGID,1,[Define if setpgid() is available. ]) + ICE_CHECK_DECL(setpgid,sys/types.h unistd.h) + ]) +]) diff --git a/config/amanda/getfsent.m4 b/config/amanda/getfsent.m4 new file mode 100644 index 0000000..a45d75e --- /dev/null +++ b/config/amanda/getfsent.m4 @@ -0,0 +1,19 @@ +# SYNOPSIS +# +# AMANDA_SETUP_GETFSENT +# +# OVERVIEW +# +# Checks for support for client-src/getfsent.c +# +AC_DEFUN([AMANDA_SETUP_GETFSENT], [ + AC_CHECK_HEADERS( + fstab.h \ + mntent.h \ + mnttab.h \ + sys/vfstab.h \ + ) + + AC_CHECK_FUNCS(endmntent) + AC_CHECK_FUNCS(setmntent) +]) diff --git a/config/amanda/i18n.m4 b/config/amanda/i18n.m4 new file mode 100644 index 0000000..fc55d70 --- /dev/null +++ b/config/amanda/i18n.m4 @@ -0,0 +1,26 @@ +# SYNOPSIS +# +# AMANDA_SETUP_I18N +# +# OVERVIEW +# +# Set up Amanda's internationalization support. Note that configure.in +# itself must contain (not indented): +# +# AM_GNU_GETTEXT_VERSION([0.15]) +# AM_GNU_GETTEXT([external]) +# +AC_DEFUN([AMANDA_SETUP_I18N], [ + # FreeBSD needs to link libxpg4 + AC_CHECK_LIB(xpg4, setlocale) + + # ------------------------------------------------------------------ + # All list of languages for which a translation exist. Each + # language is separated by a space. + # ------------------------------------------------------------------ + ALL_LINGUAS="" + + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(MSGFMT, msgfmt,,$LOCSYSPATH) + AC_PATH_PROG(GETTEXT,gettext,,$LOCSYSPATH) +]) diff --git a/config/amanda/ipv6.m4 b/config/amanda/ipv6.m4 new file mode 100644 index 0000000..c3c1776 --- /dev/null +++ b/config/amanda/ipv6.m4 @@ -0,0 +1,151 @@ +# +# Checks to see if there's a sockaddr_storage structure +# +# usage: +# +# AMANDA_SOCKADDR_STORAGE +# +# results: +# +# HAVE_SOCKADDR_STORAGE (defined) +# +AC_DEFUN([AMANDA_SOCKADDR_STORAGE], +[ + AC_CACHE_CHECK([if sockaddr_storage struct exists], + ac_cv_has_sockaddr_storage, + [ + AC_TRY_COMPILE([ +# include +# include ], + [u_int i = sizeof (struct sockaddr_storage)], + ac_cv_has_sockaddr_storage=yes, + ac_cv_has_sockaddr_storage=no) + ]) + + if test $ac_cv_has_sockaddr_storage = yes ; then + AC_DEFINE(HAVE_SOCKADDR_STORAGE,1, + [struct sockaddr_storage exists]) + fi +]) + +# SYNOPSIS +# +# AMANDA_CHECK_IPV6 +# +# DESCRIPTION +# +# Determine if this system has basic IPv6 support. This +# addresse general availability (defining WORKING_IPV6 if +# there's some amount of compatibility there), as well as +# searching for specific functionality by requiring the other +# macros in this file. +# +AC_DEFUN([AMANDA_CHECK_IPV6], +[ + AC_REQUIRE([AMANDA_SOCKADDR_STORAGE]) + + WORKING_IPV6=no + AC_ARG_WITH(ipv6, + AS_HELP_STRING([--with-ipv6], + [enable IPv6 support (default if IPv6 is found)]) + AS_HELP_STRING([--without-ipv6], + [disable IPv6]), + [ + case "$withval" in + y | ye | yes) amanda_with_ipv6=yes;; + n | no) amanda_with_ipv6=no;; + *) + AC_MSG_ERROR([*** You must not supply an argument to --with-ipv6 option.]) + ;; + esac + ], [ + amanda_with_ipv6=maybe + ] + ) + + if test x"$amanda_with_ipv6" = x"yes" || + test x"$amanda_with_ipv6" = x"maybe" ; then + AC_CACHE_CHECK([for working IPv6], + amanda_cv_working_ipv6, + [ + case "$target" in + *-pc-cygwin) amanda_cv_working_ipv6=no;; + *) + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_WINSOCK2_H +#include +#endif +#include +#include + +main() +{ + int aa; + aa = socket(AF_INET6, SOCK_STREAM, 0); + if (aa > 0) return 0; + return aa; +}]])], + [ amanda_cv_working_ipv6=yes ], + [ amanda_cv_working_ipv6=no ], + [ amanda_cv_working_ipv6=yes ] + ) + esac + ]) + + if test "$amanda_cv_working_ipv6" = yes; then + WORKING_IPV6=yes + AC_DEFINE(WORKING_IPV6,1, + [Target system has functional IPv6 support]) + else + # error out only if the user specifically requested support + if test x"$amanda_with_ipv6" = x"yes"; then + AC_MSG_ERROR([IPv6 support was requested, but it is not working.]) + fi + fi + fi +]) + +# +# Checks to see if there's a sockaddr_storage structure +# +# usage: +# +# AC_SOCKADDR_STORAGE +# +# results: +# +# HAVE_SOCKADDR_STORAGE (defined) +# +AC_DEFUN([AC_SOCKADDR_STORAGE], + [AC_MSG_CHECKING(if sockaddr_storage struct exists) + AC_CACHE_VAL(ac_cv_has_sockaddr_storage, + AC_TRY_COMPILE([ +# include +# include ], + [u_int i = sizeof (struct sockaddr_storage)], + ac_cv_has_sockaddr_storage=yes, + ac_cv_has_sockaddr_storage=no)) + AC_MSG_RESULT($ac_cv_has_sockaddr_storage) + if test $ac_cv_has_sockaddr_storage = yes ; then + AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[if struct sockaddr_storage exists]) + fi]) + +# SYNOPSIS +# +# AMANDA_SHOW_IPV6_SUMMARY +# +# OVERVIEW +# +# Show a summary of the settings from this file. +# +AC_DEFUN([AMANDA_SHOW_IPV6_SUMMARY], +[ + echo "Working IPv6:" $WORKING_IPV6 +]) diff --git a/config/amanda/krb4-security.m4 b/config/amanda/krb4-security.m4 new file mode 100644 index 0000000..68f5416 --- /dev/null +++ b/config/amanda/krb4-security.m4 @@ -0,0 +1,234 @@ +# SYNOPSIS +# +# AMANDA_KRB4_SECURITY +# +# OVERVIEW +# +# Handle configuration for KRB4 security, implementing the --with-krb4-security +# option. If libraries are found, they are added to the relevant compiler flags. +# +# Defines KRB4_SECURITY, and sets AM_CONDITIONAL WANT_KRB4_SECURITY, +# if the user has selected this mechanism. Also, the following parameters +# are taken from options and defined: +# +# - SERVER_HOST_PRINCIPAL +# - SERVER_HOST_INSTANCE +# - SERVER_HOST_KEY_FILE +# - CLIENT_HOST_PRINCIPAL +# - CLIENT_HOST_INSTANCE +# - CLIENT_HOST_KEY_FILE +# - TICKET_LIFETIME +# +AC_DEFUN([AMANDA_KRB4_SECURITY], +[ + # Specify --with-krb4-security if Kerberos software is in somewhere + # other than the listed KRB4_SPOTS. We only compile kerberos support in + # if the right files are there. + + : ${KRB4_SPOTS="/usr/kerberos /usr/cygnus /usr /opt/kerberos"} + + KRB4_SECURITY="no" + AC_ARG_WITH(krb4-security, + AS_HELP_STRING([--with-krb4-security=DIR], + [Location of Kerberos software @<:@/usr/kerberos /usr/cygnus /usr /opt/kerberos@:>@]), + [ + case "$withval" in + n | no) ;; + y | ye | yes) KRB4_SECURITY="yes" ;; + *) KRB4_SPOTS="$KRB4_SECURITY" + KRB4_SECURITY="yes" + ;; + esac + ], + ) + + # check the remaining, subsidiary options + + AC_MSG_CHECKING([host principal]) + AC_ARG_WITH(server-principal, + AS_HELP_STRING([ --with-server-principal=ARG], + [server host principal ("amanda")]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-server-principal option.]) + ;; + *) SERVER_HOST_PRINCIPAL="$withval" ;; + esac + ], + [ : ${SERVER_HOST_PRINCIPAL="amanda"} ] + ) + AC_MSG_RESULT($SERVER_HOST_PRINCIPAL) + + AC_MSG_CHECKING([server host instance]) + AC_ARG_WITH(server-instance, + AS_HELP_STRING([ --with-server-instance=ARG], + [server host instance ("amanda")]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-server-instance option.]) + ;; + *) SERVER_HOST_INSTANCE="$withval" ;; + esac + ], + [ : ${SERVER_HOST_INSTANCE="amanda"} ] + ) + AC_MSG_RESULT($SERVER_HOST_INSTANCE) + + AC_MSG_CHECKING([server host key file]) + AC_ARG_WITH(server-keyfile, + AS_HELP_STRING([ --with-server-keyfile=ARG], + [server host key file ("/.amanda")]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-server-keyfile option.]) + ;; + *) SERVER_HOST_KEY_FILE="$withval" ;; + esac + ], + [ : ${SERVER_HOST_KEY_FILE="/.amanda"} ] + ) + AC_MSG_RESULT($SERVER_HOST_KEY_FILE) + + AC_MSG_CHECKING(client host principle) + AC_ARG_WITH(client-principal, + AS_HELP_STRING([ --with-client-principal=ARG], + [client host principle ("rcmd")]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-client-principal option.]) + ;; + *) CLIENT_HOST_PRINCIPAL="$withval" ;; + esac + ], + [ : ${CLIENT_HOST_PRINCIPAL="rcmd"} ] + ) + AC_MSG_RESULT($CLIENT_HOST_PRINCIPAL) + + AC_MSG_CHECKING([client host instance]) + AC_ARG_WITH(client-instance, + AS_HELP_STRING([ --with-client-instance=ARG], + [client host instance (HOSTNAME_INSTANCE)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-client-instance option.]) + ;; + *) CLIENT_HOST_INSTANCE="$withval" ;; + esac + ], + [ : ${CLIENT_HOST_INSTANCE=HOSTNAME_INSTANCE} ] + ) + AC_MSG_RESULT($CLIENT_HOST_INSTANCE) + + AC_MSG_CHECKING([client host key file]) + AC_ARG_WITH(client-keyfile, + AS_HELP_STRING([ --with-client-keyfile=ARG], + [client host key file (KEYFILE)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-client-keyfile option.]) + ;; + *) CLIENT_HOST_KEY_FILE="$withval" ;; + esac + ], + [ : ${CLIENT_HOST_KEY_FILE=KEYFILE} ] + ) + # Assume it's either KEYFILE (defined in krb.h), or a string filename... + if test "x$CLIENT_HOST_KEY_FILE" != "xKEYFILE"; then + # add quotes + CLIENT_HOST_KEY_FILE="\"$CLIENT_HOST_KEY_FILE\"" + fi + AC_MSG_RESULT($CLIENT_HOST_KEY_FILE) + + AC_MSG_CHECKING([ticket lifetime]) + AC_ARG_WITH(ticket-lifetime, + AS_HELP_STRING([ --ticket-lifetime], + [ticket lifetime (128)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-ticket-lifetime option.]) + ;; + *) TICKET_LIFETIME="$withval" ;; + esac + ], + [ : ${TICKET_LIFETIME=128} ] + ) + AC_MSG_RESULT($TICKET_LIFETIME) + + + if test "x${KRB4_SECURITY}" = "xyes"; then + AC_MSG_CHECKING(for Kerberos and Amanda kerberos4 bits) + found="no" + for dir in $KRB4_SPOTS; do + if test \( -f ${dir}/lib/libkrb.a -o -f ${dir}/lib/libkrb.so \) -a \( -f ${dir}/lib/libdes.a -o -f ${dir}/lib/libdes.so \) ; then + # + # This is the original Kerberos 4. + # + AC_MSG_RESULT(found in $dir) + found="yes" + + # + # This handles BSD/OS. + # + if test -d $dir/include/kerberosIV ; then + AMANDA_ADD_CPPFLAGS([-I$dir/include/kerberosIV]) + else + AMANDA_ADD_CPPFLAGS([-I$dir/include]) + fi + AMANDA_ADD_LDFLAGS([-L$dir/lib]) + AMANDA_ADD_LIBS([-lkrb -ldes]) + if test -f ${dir}/lib/libcom_err.a; then + AMANDA_ADD_LIBS([-lcom_err]) + fi + break + elif test \( -f ${dir}/lib/libkrb4.a -o -f ${dir}/lib/libkrb4.so \) && + test \( -f ${dir}/lib/libcrypto.a -o -f ${dir}/lib/libcrypto.so \) && + test \( -f ${dir}/lib/libdes425.a -o -f ${dir}/lib/libdes425.so \) ; then + # + # This is Kerberos 5 with Kerberos 4 back-support. + # + AC_MSG_RESULT(found in $dir) + found="yes" + AMANDA_ADD_CPPFLAGS([-I$dir/include -I$dir/include/kerberosIV]) + AMANDA_ADD_LDFLAGS([-L$dir/lib]) + if test \( -f ${dir}/lib/libkrb5.a -o -f ${dir}/lib/libkrb5.so \) && + test \( -f ${dir}/lib/libcom_err.a -o -f ${dir}/lib/libcom_err.so \) ; then + AMANDA_ADD_LIBS([-lkrb4 -lkrb5 -lcrypto -ldes425 -lcom_err]) + else + AMANDA_ADD_LIBS([-lkrb4 -lcrypto -ldes425]) + fi + break + fi + done + + if test "x$found" = "xno" ; then + AC_MSG_RESULT(no libraries found) + AMANDA_MSG_WARN([No Kerberos IV libraries were found on your system; disabling krb4-security]) + KRB4_SECURITY="no" + else + AC_DEFINE(KRB4_SECURITY, 1, + [Enable Kerberos IV security.]) + AC_DEFINE_UNQUOTED(SERVER_HOST_PRINCIPAL,"$SERVER_HOST_PRINCIPAL", + [The Kerberos server principal. ]) + AC_DEFINE_UNQUOTED(SERVER_HOST_INSTANCE,"$SERVER_HOST_INSTANCE", + [The Kerberos server instance. ]) + AC_DEFINE_UNQUOTED(SERVER_HOST_KEY_FILE,"$SERVER_HOST_KEY_FILE", + [The Kerberos server key file. ]) + AC_DEFINE_UNQUOTED(CLIENT_HOST_PRINCIPAL,"$CLIENT_HOST_PRINCIPAL", + [The Kerberos client host principal. ]) + AC_DEFINE_UNQUOTED(CLIENT_HOST_INSTANCE,$CLIENT_HOST_INSTANCE, + [The Kerberos client host instance. ]) + AC_DEFINE_UNQUOTED(CLIENT_HOST_KEY_FILE,$CLIENT_HOST_KEY_FILE, + [The Kerberos client host key file. ]) + AC_DEFINE_UNQUOTED(TICKET_LIFETIME,$TICKET_LIFETIME, + [The Kerberos ticket lifetime. ]) + fi + fi + AM_CONDITIONAL(WANT_KRB4_SECURITY, test x"$KRB4_SECURITY" = x"yes") +]) diff --git a/config/amanda/krb5-security.m4 b/config/amanda/krb5-security.m4 new file mode 100644 index 0000000..1cf0d7a --- /dev/null +++ b/config/amanda/krb5-security.m4 @@ -0,0 +1,105 @@ +# SYNOPSIS +# +# AMANDA_KRB5_SECURITY +# +# OVERVIEW +# +# Handle configuration for KRB5 security, implementing the --with-krb5-security +# option. If libraries are found, they are added to the relevant compiler flags. +# +# Defines KRB5_SECURITY, and sets AM_CONDITIONAL WANT_KRB5_SECURITY, +# if the user has selected this mechanism. Also, the following parameters +# are taken from options and defined: +# +# - SERVER_HOST_PRINCIPAL +# - SERVER_HOST_INSTANCE +# - SERVER_HOST_KEY_FILE +# - CLIENT_HOST_PRINCIPAL +# - CLIENT_HOST_INSTANCE +# - CLIENT_HOST_KEY_FILE +# - TICKET_LIFETIME +# +AC_DEFUN([AMANDA_KRB5_SECURITY], +[ + # Specify --with-krb5-security if Kerberos software is in somewhere + # other than the listed KRB5_SPOTS. We only compile kerberos support in + # if the right files are there. + + KRB5_SECURITY="no" + : ${KRB5_SPOTS="/usr/kerberos /usr/cygnus /usr /opt/kerberos"} + + AC_ARG_WITH(krb5-security, + AS_HELP_STRING([--with-krb5-security=DIR], + [Location of Kerberos V software @<:@/usr/kerberos /usr/cygnus /usr /opt/kerberos@:>@]), + [ + case "$withval" in + n | no) KRB5_SECURITY=no ;; + y | ye | yes) KRB5_SECURITY=yes ;; + *) KRB5_SPOTS="$KRB5_SECURITY" + KRB5_SECURITY=yes + ;; + esac + ] + ) + + if test "x$KRB5_SECURITY" = "xyes"; then + # if found, force the static versions of these libs (.a) by linking directly + # with the .a files. I don't know how to get -R dependancies checked + # in autoconf at this time. -kashmir + AC_MSG_CHECKING(for Kerberos V libraries) + KRB5_DIR_FOUND="" + for dir in $KRB5_SPOTS; do + for lib in lib lib64; do + k5libdir=${dir}/${lib} + if test \( -f ${k5libdir}/libkrb5.a -o -f ${k5libdir}/libkrb5.so \) -a \( -f ${k5libdir}/libgssapi_krb5.so -o -f ${k5libdir}/libgssapi_krb5.a \) -a \( -f ${k5libdir}/libcom_err.a -o -f ${k5libdir}/libcom_err.so \); then + if test -f ${k5libdir}/libk5crypto.a -o -f ${k5libdir}/libk5crypto.so; then + K5CRYPTO=-lk5crypto + elif test -f ${k5libdir}/libcrypto.a -o -f ${k5libdir}/libcrypto.so; then + K5CRYPTO=-lcrypto + else + K5CRYPTO="" + fi + if test -f ${k5libdir}/libkrb5support.a -o -f ${k5libdir}/libkrb5support.so; then + K5SUPPORT=-lkrb5support + else + K5SUPPORT="" + fi + KRB5_DIR_FOUND=$dir + KRB5_LIBDIR_FOUND=$k5libdir + AMANDA_ADD_LIBS([-lgssapi_krb5 -lkrb5 $K5CRYPTO $K5SUPPORT -lcom_err]) + break + elif test \( -f ${k5libdir}/libkrb5.a -o -f ${k5libdir}/libkrb5.so \) -a \( -f ${k5libdir}/libasn1.a -o -f ${k5libdir}/libasn1.so \) -a \( -f ${k5libdir}/libgssapi.a -o -f ${k5libdir}/libgssapi.so \); then + AMANDA_ADD_LIBS([-lgssapi -lkrb5 -lasn1]) + AMANDA_ADD_CPPFLAGS([-DKRB5_HEIMDAL_INCLUDES]) + break + fi + done + done + + if test "$KRB5_DIR_FOUND"; then + AC_MSG_RESULT(found in $KRB5_DIR_FOUND) + # + # some OS's, such as NetBSD, stick krb5 includes out of the way... + # should probably just use autoconf to look for various include + # options and set them, but don't quite want to do that until I've + # dug into it a bit more. + # + if test -d "$KRB5_DIR_FOUND/krb5" ; then + AMANDA_ADD_CPPFLAGS([-I$KRB5_DIR_FOUND/include/krb5]) + else + AMANDA_ADD_CPPFLAGS([-I$KRB5_DIR_FOUND/include]) + fi + AC_CHECK_LIB(krb5support,main) + AMANDA_ADD_LDFLAGS([-L$KRB5_LIBDIR_FOUND]) + + AC_DEFINE(KRB5_SECURITY,1, + [Define if Kerberos 5 security is to be enabled. ]) + else + AC_MSG_RESULT(no krb5 system libraries found) + AC_MSG_ERROR([No Kerberos V libraries were found on your system; krb5-security cannot be enabled]) + KRB5_SECURITY="no" + fi + fi + + AM_CONDITIONAL(WANT_KRB5_SECURITY, test x"$KRB5_SECURITY" = x"yes") +]) diff --git a/config/amanda/lfs.m4 b/config/amanda/lfs.m4 new file mode 100644 index 0000000..0de6a66 --- /dev/null +++ b/config/amanda/lfs.m4 @@ -0,0 +1,75 @@ +# SYNOPSIS +# +# AMANDA_SETUP_LFS +# +# OVERVIEW +# +# Set up for large file suport on this system. Besides adding compiler flags, +# defines NEED_RESETOFS if the tape device's offset must be reset before it reaches +# 2GB (a Linux kernel bug in systems without LFS support). +# +AC_DEFUN([AMANDA_SETUP_LFS], +[ + AC_REQUIRE([AMANDA_PROG_GETCONF]) + AC_REQUIRE([AC_SYS_LARGEFILE]) + + # we use 'getconf', if it exists, to get the relevant + # compiler flags. + GETCONF_LFS="LFS" + case "$target" in + *-hp-*) GETCONF_LFS="XBS5_ILP32_OFFBIG" ;; + *-ibm-aix*) GETCONF_LFS="XBS5_ILP32_OFFBIG" ;; + esac + + # Checks for compilers, typedefs, structures, and compiler characteristics. + # Check for large file compilation environment. + NEED_RESETOFS=yes + AC_CACHE_CHECK([for large file compilation CFLAGS], + amanda_cv_LFS_CFLAGS, + [ + amanda_cv_LFS_CFLAGS= + if test "$GETCONF"; then + if $GETCONF ${GETCONF_LFS}_CFLAGS >/dev/null 2>&1; then + amanda_cv_LFS_CFLAGS=`$GETCONF ${GETCONF_LFS}_CFLAGS 2>/dev/null` + NEED_RESETOFS=no + fi + fi + ] + ) + AMANDA_ADD_CFLAGS([$amanda_cv_LFS_CFLAGS]) + + AC_CACHE_CHECK( + [for large file compilation LDFLAGS], + amanda_cv_LFS_LDFLAGS, + [ + amanda_cv_LFS_LDFLAGS= + if test "$GETCONF"; then + if $GETCONF ${GETCONF_LFS}_LDFLAGS >/dev/null 2>&1; then + amanda_cv_LFS_LDFLAGS=`$GETCONF ${GETCONF_LFS}_LDFLAGS 2>/dev/null` + NEED_RESETOFS=no + fi + fi + ] + ) + AMANDA_ADD_LDFLAGS([$amanda_cv_LFS_LDFLAGS]) + + AC_CACHE_CHECK( + [for large file compilation LIBS], + amanda_cv_LFS_LIBS, + [ + amanda_cv_LFS_LIBS= + if test "$GETCONF"; then + if $GETCONF ${GETCONF_LFS}_LIBS >/dev/null 2>&1; then + amanda_cv_LFS_LIBS=`$GETCONF ${GETCONF_LFS}_LIBS 2>/dev/null` + NEED_RESETOFS=no + fi + fi + ] + ) + AMANDA_ADD_LIBS([$amanda_cv_LFS_LIBS]) + + if test x"$NEED_RESETOFS" = x"yes"; then + AC_DEFINE(NEED_RESETOFS,1, + [Define if we have to reset tape offsets when reaching 2GB. ]) + fi +]) diff --git a/config/amanda/libs.m4 b/config/amanda/libs.m4 new file mode 100644 index 0000000..4bf2bc2 --- /dev/null +++ b/config/amanda/libs.m4 @@ -0,0 +1,377 @@ +# OVERVIEW +# +# This file contains macros that search for specific libraries that are +# required or utilized by Amanda. + +# SYNOPSIS +# +# AMANDA_CHECK_LIBCURL +# +# OVERVIEW +# +# Check for LIBCURL support. Sets the shell variable HAVE_CURL to "yes" or +# "no" depending on the result of the test. If CURL is found, the necessary +# compiler flags are added, and a few other type checks are performed. +# +# Note that libcurl itself defines a number of useful symbols as well; see +# the libcurl distribution for details. +# +AC_DEFUN([AMANDA_CHECK_LIBCURL], [ + case "$target" in + sparc-sun-solaris2.10) # Solaris 10 + # curl is not in the LD_LIBRARY_PATH on Solaris 10, so we search + # for it in a few common paths; we then extract the -L flags and + # translate them to -R flags, as required by the runtime linker. + AC_PATH_PROG(CURL_CONFIG, curl-config, [], $LOCSYSPATH:/opt/csw/bin:/usr/local/bin:/opt/local/bin) + if test -n "$CURL_CONFIG"; then + curlflags=`$CURL_CONFIG --libs 2>/dev/null` + for flag in curlflags; do + case $flag in + -L*) LDFLAGS="$LDFLAGS "`echo "x$flag" | sed -e 's/^x-L/-R/'`;; + esac + done + fi + ;; + esac + + LIBCURL_CHECK_CONFIG(yes, 7.10.0, HAVE_CURL=yes, HAVE_CURL=no) + if test x"$HAVE_CURL" = x"yes"; then + AMANDA_ADD_LIBS($LIBCURL) + AMANDA_ADD_CPPFLAGS($LIBCURL_CPPFLAGS) + + AMANDA_CHECK_TYPE([curl_off_t], [off_t], [curl/curl.h]) + fi +]) + +# SYNOPSIS +# +# AMANDA_CHECK_HMAC +# +# OVERVIEW +# +# Check for HMAC support in -lcrypto. If found, the shell +# variable HAVE_HMAC will be set to 'yes'. The appropriate one of +# HAVE_OPENSSL_HMAC_H, HAVE_CRYPTO_HMAC_H, and HAVE_HMAC_H are also +# defined via AC_CHECK_HEADERS. +# +AC_DEFUN([AMANDA_CHECK_HMAC], [ + HAVE_HMAC=yes + AC_CHECK_LIB([crypto], [HMAC_CTX_init], [], [HAVE_HMAC=no]) + + found_hmac_h=no + AC_CHECK_HEADERS([openssl/hmac.h crypto/hmac.h hmac.h], + [found_hmac_h=yes; break]) + if test x"$found_hmac_h" != x"yes"; then + HAVE_HMAC=no + fi +]) + +# SYNOPSIS +# +# AMANDA_CHECK_NET_LIBS +# +# OVERIVEW +# +# Check for the libraries we'll need to use sockets, etc. +# +AC_DEFUN([AMANDA_CHECK_NET_LIBS], [ + # Make sure we don't use -lnsl and -lsun on Irix systems. + case "$target" in + *sgi-irix*) + AC_CHECK_LIB(socket,main) + ;; + *) + AC_CHECK_LIB(resolv,main) + AC_CHECK_LIB(nsl,main) + AC_CHECK_LIB(socket,main) + AC_CHECK_LIB(sun,main) + ;; + esac +]) + +# SYNOPSIS +# +# AMANDA_CHECK_GLIB +# +# OVERVIEW +# +# Search for glib. This is basically a wrapper for AM_PATH_GLIB_2_0, with +# the addition of system-specific configuration to convince Amanda to compile +# "out of the box" on more boxes. +# +AC_DEFUN([AMANDA_CHECK_GLIB], [ + # search for pkg-config, which the glib configuration uses, adding a few + # system-specific search paths. + AC_PATH_PROG(PKG_CONFIG, pkg-config, [], $LOCSYSPATH:/opt/csw/bin:/usr/local/bin:/opt/local/bin) + + case "$target" in + sparc-sun-solaris2.8) # Solaris 8 + # give the linker a runtime search path; pkg-config doesn't supply this. + # Users could also specify this with LD_LIBRARY_PATH to both ./configure + # and make. Adding this support here makes straight './configure; make' + # "just work" on Solaris 8 + if test -n "$PKG_CONFIG"; then + glib_R_flag=`$PKG_CONFIG glib-2.0 --libs-only-L 2>/dev/null | sed -e 's/-L/-R/g'` + LDFLAGS="$LDFLAGS $glib_R_flag" + fi + ;; + esac + + AM_PATH_GLIB_2_0(2.2.0,,[ + AC_MSG_ERROR(glib not found or too old; See http://wiki.zmanda.com/index.php/Installation for help) + ], gmodule gobject gthread) + AMANDA_ADD_CFLAGS($GLIB_CFLAGS) + AMANDA_ADD_CPPFLAGS($GLIB_CPPFLAGS) + AMANDA_ADD_LIBS($GLIB_LIBS) +]) + +# LIBCURL_CHECK_CONFIG is from the libcurl +# distribution and licensed under the BSD license: +# Copyright (c) 1996 - 2007, Daniel Stenberg, . +# +# All rights reserved. +# +# Permission to use, copy, modify, and distribute this software for any purpose +# with or without fee is hereby granted, provided that the above copyright +# notice and this permission notice appear in all copies. +# +# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], +# [ACTION-IF-YES], [ACTION-IF-NO]) +# ---------------------------------------------------------- +# David Shaw May-09-2006 +# +# Checks for libcurl. DEFAULT-ACTION is the string yes or no to +# specify whether to default to --with-libcurl or --without-libcurl. +# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the +# minimum version of libcurl to accept. Pass the version as a regular +# version number like 7.10.1. If not supplied, any version is +# accepted. ACTION-IF-YES is a list of shell commands to run if +# libcurl was successfully found and passed the various tests. +# ACTION-IF-NO is a list of shell commands that are run otherwise. +# Note that using --without-libcurl does run ACTION-IF-NO. +# +# This macro #defines HAVE_LIBCURL if a working libcurl setup is +# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary +# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are +# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy +# where yyy are the various protocols supported by libcurl. Both xxx +# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of +# the macro for the complete list of possible defines. Shell +# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also +# defined to 'yes' for those features and protocols that were found. +# Note that xxx and yyy keep the same capitalization as in the +# curl-config list (e.g. it's "HTTP" and not "http"). +# +# Users may override the detected values by doing something like: +# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure +# +# For the sake of sanity, this macro assumes that any libcurl that is +# found is after version 7.7.2, the first version that included the +# curl-config script. Note that it is very important for people +# packaging binary versions of libcurl to include this script! +# Without curl-config, we can only guess what protocols are available, +# or use curl_version_info to figure it out at runtime. + +AC_DEFUN([LIBCURL_CHECK_CONFIG], +[ + AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL]) + AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4]) + AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6]) + AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz]) + AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS]) + AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN]) + AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI]) + AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM]) + + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET]) + AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP]) + + AC_ARG_WITH(libcurl, + AC_HELP_STRING([--with-libcurl=DIR],[look for the curl library in DIR]), + [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) + + if test "$_libcurl_with" != "no" ; then + + AC_PROG_AWK + + _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" + + _libcurl_try_link=yes + + if test -d "$_libcurl_with" ; then + LIBCURL_CPPFLAGS="-I$withval/include" + _libcurl_ldflags="-L$withval/lib" + AC_PATH_PROG([_libcurl_config],[curl-config],["$withval/bin"],["$withval/bin"]) + else + AC_PATH_PROG([_libcurl_config],[curl-config]) + fi + + if test x$_libcurl_config != "x" ; then + AC_CACHE_CHECK([for the version of libcurl], + [libcurl_cv_lib_curl_version], + [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) + + _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` + _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` + + if test $_libcurl_wanted -gt 0 ; then + AC_CACHE_CHECK([for libcurl >= version $2], + [libcurl_cv_lib_version_ok], + [ + if test $_libcurl_version -ge $_libcurl_wanted ; then + libcurl_cv_lib_version_ok=yes + else + libcurl_cv_lib_version_ok=no + fi + ]) + fi + + if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then + if test x"$LIBCURL_CPPFLAGS" = "x" ; then + LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` + fi + if test x"$LIBCURL" = "x" ; then + LIBCURL=`$_libcurl_config --libs` + + # This is so silly, but Apple actually has a bug in their + # curl-config script. Fixed in Tiger, but there are still + # lots of Panther installs around. + case "${host}" in + powerpc-apple-darwin7*) + LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` + ;; + esac + fi + + # All curl-config scripts support --feature + _libcurl_features=`$_libcurl_config --feature` + + # Is it modern enough to have --protocols? (7.12.4) + if test $_libcurl_version -ge 461828 ; then + _libcurl_protocols=`$_libcurl_config --protocols` + fi + else + _libcurl_try_link=no + fi + + unset _libcurl_wanted + fi + + if test $_libcurl_try_link = yes ; then + + # we didn't find curl-config, so let's see if the user-supplied + # link line (or failing that, "-lcurl") is enough. + LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} + + AC_CACHE_CHECK([whether libcurl is usable], + [libcurl_cv_lib_curl_usable], + [ + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBCURL $LIBS" + + AC_LINK_IFELSE(AC_LANG_PROGRAM([#include ],[ +/* Try and use a few common options to force a failure if we are + missing symbols or can't link. */ +int x; +curl_easy_setopt(NULL,CURLOPT_URL,NULL); +x=CURL_ERROR_SIZE; +x=CURLOPT_WRITEFUNCTION; +x=CURLOPT_FILE; +x=CURLOPT_ERRORBUFFER; +x=CURLOPT_STDERR; +x=CURLOPT_VERBOSE; +]),libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + ]) + + if test $libcurl_cv_lib_curl_usable = yes ; then + + # Does curl_free() exist in this version of libcurl? + # If not, fake it with free() + + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBS $LIBCURL" + + AC_CHECK_FUNC(curl_free,, + AC_DEFINE(curl_free,free, + [Define curl_free() as free() if our version of curl lacks curl_free.])) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + + AC_DEFINE(HAVE_LIBCURL,1, + [Define to 1 if you have a functional curl library.]) + AC_SUBST(LIBCURL_CPPFLAGS) + AC_SUBST(LIBCURL) + + for _libcurl_feature in $_libcurl_features ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1]) + eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes + done + + if test "x$_libcurl_protocols" = "x" ; then + + # We don't have --protocols, so just assume that all + # protocols are available + _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT" + + if test x$libcurl_feature_SSL = xyes ; then + _libcurl_protocols="$_libcurl_protocols HTTPS" + + # FTPS wasn't standards-compliant until version + # 7.11.0 + if test $_libcurl_version -ge 461568; then + _libcurl_protocols="$_libcurl_protocols FTPS" + fi + fi + fi + + for _libcurl_protocol in $_libcurl_protocols ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1]) + eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes + done + else + unset LIBCURL + unset LIBCURL_CPPFLAGS + fi + fi + + unset _libcurl_try_link + unset _libcurl_version_parse + unset _libcurl_config + unset _libcurl_feature + unset _libcurl_features + unset _libcurl_protocol + unset _libcurl_protocols + unset _libcurl_version + unset _libcurl_ldflags + fi + + if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then + # This is the IF-NO path + ifelse([$4],,:,[$4]) + else + # This is the IF-YES path + ifelse([$3],,:,[$3]) + fi + + unset _libcurl_with +])dnl + diff --git a/config/amanda/net.m4 b/config/amanda/net.m4 new file mode 100644 index 0000000..f2c1805 --- /dev/null +++ b/config/amanda/net.m4 @@ -0,0 +1,167 @@ +# OVERVIEW +# +# Networking-related macros + +# SYNOPSIS +# +# AMANDA_WITH_FQDN +# +# OVERVIEW +# +# Check for --with-fqdn, and DEFINE USE_FQDN if given. +# +AC_DEFUN([AMANDA_WITH_FQDN], [ + AC_ARG_WITH(fqdn, + AS_HELP_STRING([--with-fqdn], + [use FQDN's to backup multiple networks]), + [ USE_FQDN=$withval ], [ USE_FQDN=no ]) + + case "$USE_FQDN" in + n | no) : ;; + y | ye | yes) + AC_DEFINE(USE_FQDN,1, + [Define for backups being done on a multiple networks and FQDNs are used. ]) + ;; + *) AC_MSG_ERROR([You must not supply an argument to --with-fqdn option.]) + ;; + esac +]) + +# SYNOPSIS +# +# AMANDA_WITH_REUSEPORTS +# +# OVERVIEW +# +# Check for --with-reuseports, and DEFINE USE_REUSEADDR if given. +# +AC_DEFUN([AMANDA_WITH_REUSEPORTS], [ + AC_ARG_WITH(reuseports, + AS_HELP_STRING([--without-reuseaddr], + [Don't reuse network connections until full timeout period]), + [ case "$withval" in + y | ye | yes) USE_REUSEADDR=no;; + n | no) USE_REUSEADDR=yes;; + *) AC_MSG_ERROR([You must not supply an argument to --without-reuseports]);; + esac + ], + [ USE_REUSEADDR=yes; ]) + if test x"$USE_REUSEADDR" = x"yes"; then + AC_DEFINE(USE_REUSEADDR,1, + [Define to set SO_REUSEADDR on network connections.]) + fi +]) + +# SYNOPSIS +# +# AMANDA_WITH_PORTRANGES +# +# OVERVIEW +# +# Implement --with-low-tcpportrange, --with-tcpportrange, and --with-udpportrange. +# Results are DEFINED in LOW_TCPPORTRANGE, TCPPORTRANGE, and UDPPORTRANGE, +# respectively. +# +AC_DEFUN([AMANDA_WITH_PORTRANGES], [ + AC_ARG_WITH(low-tcpportrange, + AS_HELP_STRING([--with-low-tcpportrange=low/high], + [bind reserved TCP server sockets to ports within this range (default: unlimited)]), + [ LOW_TCPPORTRANGE="$withval" ], + [ LOW_TCPPORTRANGE=unlimited ]) + + if test x"$LOW_TCPPORTRANGE" != x"unlimited"; then + if test x`echo "$LOW_TCPPORTRANGE" | sed 's/[[0-9]][[0-9]]*,[[0-9]][[0-9]]*//'` != x""; then + AC_MSG_ERROR([--with-low-tcpportrange requires two comma-separated positive numbers]) + fi + min_low_tcp_port=`echo "$LOW_TCPPORTRANGE" | sed 's/,.*//'` + max_low_tcp_port=`echo "$LOW_TCPPORTRANGE" | sed 's/.*,//'` + if test $min_low_tcp_port -gt $max_low_tcp_port; then + AC_MSG_ERROR([the second TCP port number must be greater than the first in --with-low-tcpportrange]) + fi + if test $min_low_tcp_port -lt 512; then + AMANDA_MSG_WARN([the low TCP port range should be 512 or greater in --with-low-tcpportrange]) + fi + if test $max_low_tcp_port -ge 1024; then + AMANDA_MSG_WARN([the low TCP port range should be less than 1024 in --with-low-tcpportrange]) + fi + AC_DEFINE_UNQUOTED(LOW_TCPPORTRANGE,$LOW_TCPPORTRANGE, + [A comma-separated list of two integers, determining the minimum and maximum + * reserved TCP port numbers sockets should be bound to. (mainly for amrecover) ]) + fi + + AC_ARG_WITH(tcpportrange, + AS_HELP_STRING([--with-tcpportrange=low/high], + [bind unreserved TCP server sockets to ports within this range (default: unlimited)]), + [ TCPPORTRANGE="$withval" ], + [ TCPPORTRANGE="unlimited" ]) + + if test x"$TCPPORTRANGE" != x"unlimited"; then + if test x`echo "$TCPPORTRANGE" | sed 's/[[0-9]][[0-9]]*,[[0-9]][[0-9]]*//'` != x""; then + AC_MSG_ERROR([--with-tcpportrange requires two comma-separated positive numbers]) + fi + min_tcp_port=`echo "$TCPPORTRANGE" | sed 's/,.*//'` + max_tcp_port=`echo "$TCPPORTRANGE" | sed 's/.*,//'` + if test $min_tcp_port -gt $max_tcp_port; then + AC_MSG_ERROR([the second TCP port number must be greater than the first in --with-tcpportrange]) + fi + if test $min_tcp_port -lt 1024; then + AMANDA_MSG_WARN([the TCP port range should be 1024 or greater in --with-tcpportrange]) + fi + if test $max_tcp_port -ge 65536; then + AMANDA_MSG_WARN([the TCP port range should be less than 65536 in --with-tcpportrange]) + fi + AC_DEFINE_UNQUOTED(TCPPORTRANGE,$TCPPORTRANGE, + [A comma-separated list of two integers, determining the minimum and + * maximum unreserved TCP port numbers sockets should be bound to. ]) + fi + + AC_ARG_WITH(udpportrange, + AS_HELP_STRING([--with-udpportrange=low/high], + [bind reserved UDP server sockets to ports within this range (default: unlimited)]), + [ UDPPORTRANGE="$withval" ], + [ UDPPORTRANGE="unlimited" ]) + if test x"$UDPPORTRANGE" != x"unlimited"; then + if test x`echo "$UDPPORTRANGE" | sed 's/[[0-9]][[0-9]]*,[[0-9]][[0-9]]*//'` != x""; then + AC_MSG_ERROR([--with-udpportrange requires two comma-separated positive numbers]) + fi + min_udp_port=`echo "$UDPPORTRANGE" | sed 's/,.*//'` + max_udp_port=`echo "$UDPPORTRANGE" | sed 's/.*,//'` + if test $min_udp_port -gt $max_udp_port; then + AC_MSG_ERROR([the second UDP port number must be greater than the first in --with-udpportrange]) + fi + if test $max_udp_port -ge 1024; then + AMANDA_MSG_WARN([the UDP port range should be less than 1025 in --with-udpportrange]) + fi + if test $min_udp_port -le 0; then + AMANDA_MSG_WARN([the UDP port range should be greater than 0 in --with-udpportrange]) + fi + AC_DEFINE_UNQUOTED(UDPPORTRANGE,$UDPPORTRANGE, + [A comma-separated list of two integers, determining the minimum and + * maximum reserved UDP port numbers sockets should be bound to. ]) + fi +]) + +# SYNOPSIS +# +# AMANDA_WITH_BUFFERED_DUMP +# +# OVERVIEW +# +# Implement --with-buffered-dump, and DEFINEs DUMPER_SOCKET_BUFFERING if the option +# is given. +# +AC_DEFUN([AMANDA_WITH_BUFFERED_DUMP], [ + AC_ARG_WITH(buffered-dump, + AS_HELP_STRING([--with-buffered-dump], + [buffer the dumping sockets on the server for speed]), + [ DUMPER_SOCKET_BUFFERING=$withval ], + [ DUMPER_SOCKET_BUFFERING=no ]) + case "$DUMPER_SOCKET_BUFFERING" in + n | no) ;; + y | ye | yes) + AC_DEFINE(DUMPER_SOCKET_BUFFERING,1, + [Define if dumper should buffer the sockets for faster throughput. ]) + ;; + *) AC_MSG_ERROR([You must not supply an argument to --with-buffered-dump.]) ;; + esac +]) diff --git a/config/amanda/progs.m4 b/config/amanda/progs.m4 new file mode 100644 index 0000000..79babba --- /dev/null +++ b/config/amanda/progs.m4 @@ -0,0 +1,392 @@ +# OVERVIEW +# +# Code to handle searches for programs Amanda needs. +# +# Because Amanda uses a customized search path, many macros which are standard +# in autoconf have been wrapped here. Where this is the only change, the description +# of those macros has been omitted. +# +# All of these macros indicate their requirements using AC_REQUIRE, so the order in +# which they are called in configure.in is inconsequential. + +# SYNOPSIS +# +# AMANDA_INIT_PROGS +# +# OVERVIEW +# +# Set up some amanda-specific path directories. This should be AC_REQUIRE()d by +# any macros which need to search for a program. +# +# SYSPATH is a list of likely system locations for a file, while +# LOCPATH is a list of likely local locations. The two are combined +# in different orders in SYSLOCPATH and LOCSYSPATH. +# +AC_DEFUN([AMANDA_INIT_PROGS], +[ + SYSPATH="/bin:/usr/bin:/sbin:/usr/sbin:/opt/SUNWspro/bin:/usr/ucb:/usr/sfw/bin:/usr/bsd:/etc:/usr/etc" + # expand prefix or exec_prefix in LOCPATH + LOCPATH=`( + test "x$prefix" = xNONE && prefix=$ac_default_prefix + test "x$exec_prefix" = xNONE && exec_prefix=${prefix} + eval echo "$libexecdir:$PATH:/usr/local/sbin:/usr/local/bin:/usr/ccs/bin" + )` + SYSLOCPATH="$SYSPATH:$LOCPATH" + LOCSYSPATH="$LOCPATH:$SYSPATH" +]) + +# SYNOPSIS +# +# AMANDA_PROG_LINT +# +# OVERVIEW +# +# Find a lint binary (either lint or splint) and record its name in AMLINT. +# Set up appropriate flags for the discovered binary in AMLINTFLAGS +# +AC_DEFUN([AMANDA_PROG_LINT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_REQUIRE([AMANDA_PROG_GREP]) + + AC_PATH_PROG(AMLINT,lint,,/opt/SUNWspro/bin:$SYSLOCPATH) + if test ! -z "$AMLINT"; then + $AMLINT -flags 2>&1 | $GREP -- '-errfmt=' > /dev/null + if test $? -eq 0; then + AMLINTFLAGS="-n -s -u -m -x" + AMLINTFLAGS="$AMLINTFLAGS -errchk=%all" + AMLINTFLAGS="$AMLINTFLAGS -errfmt=macro" + AMLINTFLAGS="$AMLINTFLAGS -errhdr=no%/usr/include" + AMLINTFLAGS="$AMLINTFLAGS -errhdr=%user" + AMLINTFLAGS="$AMLINTFLAGS -errsecurity=extended" + AMLINTFLAGS="$AMLINTFLAGS -errtags=yes" + AMLINTFLAGS="$AMLINTFLAGS -Ncheck=%all" + AMLINTFLAGS="$AMLINTFLAGS -Nlevel=2" + AMLINTFLAGS="$AMLINTFLAGS -erroff=E_ASGN_NEVER_USED" + AMLINTFLAGS="$AMLINTFLAGS,E_ASGN_RESET" + AMLINTFLAGS="$AMLINTFLAGS,E_CAST_INT_CONST_TO_SMALL_INT" + AMLINTFLAGS="$AMLINTFLAGS,E_CAST_INT_TO_SMALL_INT" + AMLINTFLAGS="$AMLINTFLAGS,E_CAST_UINT_TO_SIGNED_INT" + AMLINTFLAGS="$AMLINTFLAGS,E_CONSTANT_CONDITION" + AMLINTFLAGS="$AMLINTFLAGS,E_ENUM_UNUSE" + AMLINTFLAGS="$AMLINTFLAGS,E_EXPR_NULL_EFFECT" + AMLINTFLAGS="$AMLINTFLAGS,E_FUNC_RET_ALWAYS_IGNOR" + AMLINTFLAGS="$AMLINTFLAGS,E_FUNC_RET_MAYBE_IGNORED" + AMLINTFLAGS="$AMLINTFLAGS,E_H_C_CHECK0" + AMLINTFLAGS="$AMLINTFLAGS,E_H_C_CHECK1" + AMLINTFLAGS="$AMLINTFLAGS,E_H_C_CHECK2" + AMLINTFLAGS="$AMLINTFLAGS,E_INCL_MNUSD" + AMLINTFLAGS="$AMLINTFLAGS,E_INCL_NUSD" + AMLINTFLAGS="$AMLINTFLAGS,E_MCR_NODIFF" + AMLINTFLAGS="$AMLINTFLAGS,E_NAME_MULTIPLY_DEF" + AMLINTFLAGS="$AMLINTFLAGS,E_P_REF_NULL_PSBL" + AMLINTFLAGS="$AMLINTFLAGS,E_P_REF_SUSP" + AMLINTFLAGS="$AMLINTFLAGS,E_PTRDIFF_OVERFLOW" + AMLINTFLAGS="$AMLINTFLAGS,E_P_USE_NULL_PSBL" + AMLINTFLAGS="$AMLINTFLAGS,E_P_USE_SUSP" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_ACCESS_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_CHDIR_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_CHMOD_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_CREAT_WITHOUT_EXCL" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_EXEC_PATH" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_EXEC_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_FOPEN_MODE" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_GETENV_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_MKDIR_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_PRINTF_VAR_FMT" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_RAND_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_SCANF_VAR_FMT" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_SELECT_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_SHELL_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_STRNCPY_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_UMASK_WARN" + AMLINTFLAGS="$AMLINTFLAGS,E_SEC_USE_AFTER_STAT" + AMLINTFLAGS="$AMLINTFLAGS,E_SIGN_EXTENSION_PSBL" + AMLINTFLAGS="$AMLINTFLAGS,E_TYPEDEF_UNUSE" + AMLINTFLAGS="$AMLINTFLAGS,E_UNCAL_F" + else + AMLINTFLAGS="" + fi + else + AC_PATH_PROG(AMLINT,splint,,$SYSLOCPATH) + if test ! -z "$AMLINT"; then + AMLINT="splint" + else + AMLINT='echo "Error: LINT is not installed" ; false' + fi + AMLINTFLAGS='+show-scan +unixlib -weak -globs +usedef +usereleased +impouts -paramimptemp -varuse -warnposix -redef -preproc -fixedformalarray -retval -unrecog -usevarargs -formatcode' + fi + AC_SUBST(AMLINTFLAGS) +]) + +# SYNOPSIS +# +# AMANDA_PROG_GNUPLOT +# +# OVERVIEW +# +# Search for a 'gnuplot' binary, placing the result in the precious +# variable GNUPLOT. Also accepts --with-gnuplot to indicate the location +# of the binary. +# +AC_DEFUN([AMANDA_PROG_GNUPLOT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + AC_ARG_WITH(gnuplot, + AS_HELP_STRING([--with-gnuplot=PATH], + [use gnuplot executable at PATH in amplot]), + [ + case "$withval" in + y | ye | yes) : ;; + n | no) GNUPLOT= ;; + *) GNUPLOT="$withval" ;; + esac + ]) + AC_PATH_PROG(GNUPLOT,gnuplot,,$LOCSYSPATH) + + AC_ARG_VAR(GNUPLOT, [Location of the 'gnuplot' binary]) + AC_SUBST(GNUPLOT) +]) + +# SYNOPSIS +# +# AMANDA_PROG_PRINT +# +# OVERVIEW +# +# Search for a binary for printing, usually either 'lp' or 'lpr', and put its +# path in PRINT, as well as defining it in LPRCMD in config.h. +# +# LPRFLAG is defined in config.h as the appropriate command-line flag to use +# to select a printer; either -P or -d. +# +AC_DEFUN([AMANDA_PROG_PRINT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + AC_PATH_PROGS(PRINT, lpr lp) + if test ! -z "$PRINT"; then + AC_DEFINE_UNQUOTED(LPRCMD, "$PRINT", + [Command for starting printing jobs. ]) + + AC_CACHE_CHECK([which flag to use to select a printer], + amanda_cv_printer_flag, [ + amanda_cv_printer_flag=$PRINTER_FLAG + case "$PRINT" in + lpr|*/lpr) amanda_cv_printer_flag="-P";; + lp|*/lp) amanda_cv_printer_flag="-d";; + esac + ]) + if test ! -z "$amanda_cv_printer_flag"; then + AC_DEFINE_UNQUOTED(LPRFLAG, "$amanda_cv_printer_flag", + [LPRCMD switch for specifying a printer name. ]) + else + AMANDA_MSG_WARN([WARNING: amanda will always print to the default printer]) + fi + fi +]) + +# SYNOPSIS +# +# AMANDA_PROG_GNUPLOT +# +# OVERVIEW +# +# Search for a 'gnuplot' binary, placing the result in the precious +# variable GNUPLOT. Also accepts --with-gnuplot to indicate the location +# of the binary. +# +AC_DEFUN([AMANDA_PROG_GNUPLOT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + + AC_ARG_WITH(gnuplot, + AS_HELP_STRING([--with-gnuplot=PATH], + [use gnuplot executable at PATH in amplot]), + [ + case "$withval" in + y | ye | yes) : ;; + n | no) GNUPLOT=no ;; + *) GNUPLOT="$withval" ;; + esac + ]) + if test "x$GNUPLOT" = "xno"; then + GNUPLOT= + else + AC_PATH_PROG(GNUPLOT,gnuplot,,$LOCSYSPATH) + fi + + AC_ARG_VAR(GNUPLOT, [Location of the 'gnuplot' binary]) + AC_SUBST(GNUPLOT) +]) + +## simple macros needing no description; some add AC_DEFINE_UNQUOTED + +AC_DEFUN([AMANDA_PROG_GREP], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(GREP,grep,grep,$LOCSYSPATH) + AC_DEFINE_UNQUOTED(GREP,"$GREP", + [Define the location of the grep program. ]) +]) + +AC_DEFUN([AMANDA_PROG_CAT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(CAT,cat,cat,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_COMPRESS], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(COMPRESS,compress,,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_DD], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(DD,dd,,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_GETCONF], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(GETCONF,getconf,,$SYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_GZIP], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(GZIP,gzip,,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_SORT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_REQUIRE([AMANDA_CHECK_COMPONENTS]) + + AC_PATH_PROG(SORT,sort,NONE,$LOCSYSPATH) + + # sort is only needed in the server build + if test x"$SORT" = x"NONE" && $WANT_SERVER; then + AC_MSG_ERROR([Set SORT to the path of the sort program.]) + fi + + AC_DEFINE_UNQUOTED(SORT_PATH,"$SORT", + [Define to the exact path to the sort program. ]) +]) + +AC_DEFUN([AMANDA_PROG_MAILER], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROGS(MAILER,Mail mailx mail,NONE) + if test x"$MAILER" = x"NONE"; then + AMANDA_MSG_WARN([WARNING: Amanda cannot send mail reports without a mailer.]) + else + AC_DEFINE_UNQUOTED(MAILER,"$MAILER", + [A program that understands -s "subject" user < message_file]) + fi +]) + +# SYNOPSIS +# +# AMANDA_PROG_MT +# +# OVERVIEW +# +# Find and SUBST 'mt', and additionally calculate the proper flag to use +# to identify the tape device (usually -f) and DEFINE and SUBST that value +# as MT_FILE_FLAG. +# +AC_DEFUN([AMANDA_PROG_MT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(MT,mt,mt,$LOCSYSPATH) + + case "$target" in + *-hp-*) MT_FILE_FLAG="-t" ;; + *) MT_FILE_FLAG="-f" ;; + esac + + AC_SUBST(MT_FILE_FLAG) + AC_DEFINE_UNQUOTED(MT_FILE_FLAG, "$MT_FILE_FLAG", + [The switch to be used when invoking mt to specify the + * tape device. ]) +]) + + +AC_DEFUN([AMANDA_PROG_CHIO], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(CHIO,chio,chio,$LOCSYSPATH) +]) + + +AC_DEFUN([AMANDA_PROG_CHS], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(CHS,chs,chs,$LOCSYSPATH) +]) + + +AC_DEFUN([AMANDA_PROG_MTX], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(MTX,mtx,mtx,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_MCUTIL], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(MCUTIL,mcutil,mcutil,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_PCAT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(PCAT,pcat,,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_PERL], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROGS(PERL,perl5 perl,,$LOCSYSPATH) + AC_ARG_VAR([PERL], [Path to the 'perl' binary]) + AC_PROG_PERL_VERSION([5.6.0], [], [ + AC_MSG_ERROR([Amanda requires at least perl 5.6.0]) + ]) +]) + +AC_DEFUN([AMANDA_PROG_SWIG], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROGS(SWIG,swig,,$LOCSYSPATH) + AC_ARG_VAR([SWIG], [Path to the 'swig' binary (developers only)]) + AC_PROG_SWIG([1.3.28]) +]) + +AC_DEFUN([AMANDA_PROG_AR], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(AR,ar,,$LOCSYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_BASH], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(BASH,bash,,$SYSPATH) +]) + +AC_DEFUN([AMANDA_PROG_SSH], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROGS(SSH, ssh, , $LOCSYSPATH) + AC_DEFINE_UNQUOTED(SSH, "$SSH", [Path to the SSH binary]) +]) + +AC_DEFUN([AMANDA_PROG_GETTEXT], +[ + AC_REQUIRE([AMANDA_INIT_PROGS]) + AC_PATH_PROG(GETTEXT,gettext,,$LOCSYSPATH) +]) diff --git a/config/amanda/readdir.m4 b/config/amanda/readdir.m4 new file mode 100644 index 0000000..4db19c7 --- /dev/null +++ b/config/amanda/readdir.m4 @@ -0,0 +1,32 @@ +# SYNOPSIS +# +# AMANDA_CHECK_READDIR +# +# OVERVIEW +# +# Check for one of the readdir variants, as well as the dirent headers. +# See common-src/util.c and amanda.h for the use of these symbols. +# +AC_DEFUN([AMANDA_CHECK_READDIR], [ + AC_HEADER_DIRENT + + # include the dirent headers as described in the autoconf documentation. + AC_CHECK_DECLS([readdir, readdir_r, readdir64, readdir64_r],,,[ +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + ]) +]) diff --git a/config/amanda/readline.m4 b/config/amanda/readline.m4 new file mode 100644 index 0000000..dbf8be5 --- /dev/null +++ b/config/amanda/readline.m4 @@ -0,0 +1,75 @@ +# SYNOPSIS +# +# AMANDA_CHECK_READLINE +# +# OVERVIEW +# +# Check for readline support. Defines HAVE_READLINE if readline +# is available, and also checks for a number of readline headers and +# adds readline libraries to READLINE_LIBS. +# +# See common-src/util.{c,h}. +# +AC_DEFUN([AMANDA_CHECK_READLINE], [ + AC_ARG_WITH(readline, + dnl no initial space here, so the results line up properly +AS_HELP_STRING([--with-readline], [require readline support (for amrecover)]) +AS_HELP_STRING([--without-readline], [don't search for readline]), + [ + case "$withval" in + y | ye | yes | n | no) : ;; + *) AC_MSG_ERROR([*** --with-readline does not take a value]) + esac + want_readline="$withval" + ], [ + want_readline="maybe" # meaning "only if we can find it" + ]) + + # unless the user said "no", look for readline. + if test x"$want_readline" != x"no"; then + # we need a tgetent() somewhere.. + proceed="false" + AC_CHECK_LIB(termcap, tgetent, [ + READLINE_LIBS="-ltermcap" + proceed="true" + ], [ + AC_CHECK_LIB(curses, tgetent, [ + READLINE_LIBS="-lcurses" + proceed="true" + ], [ + AC_CHECK_LIB(ncurses, tgetent, [ + READLINE_LIBS="-lncurses" + proceed="true" + ]) + ]) + ]) + + if $proceed; then + proceed="false" + AC_CHECK_HEADERS( history.h readline.h readline/history.h readline/readline.h, [ + # found at least one of the headers, so we can proceed. + proceed="true" + ]) + fi + + if $proceed; then + proceed="false" + AC_CHECK_LIB(readline,readline, [ + READLINE_LIBS="-lreadline $READLINE_LIBS" + proceed="true" + ],,$READLINE_LIBS) + fi + + if $proceed; then + # we have readline! + AC_DEFINE(HAVE_READLINE, 1, [System has readline support (headers and libraries)]) + else + # no readline. if the user *really* wanted it, bail out. + if test x"$want_readline" = x"yes"; then + AC_MSG_ERROR([*** No readline implementation found. Try using --with-libraries and --with-includes]) + fi + READLINE_LIBS="" + fi + fi + AC_SUBST(READLINE_LIBS) +]) diff --git a/config/amanda/rsh-security.m4 b/config/amanda/rsh-security.m4 new file mode 100644 index 0000000..891d50f --- /dev/null +++ b/config/amanda/rsh-security.m4 @@ -0,0 +1,32 @@ +# SYNOPSIS +# +# AMANDA_RSH_SECURITY +# +# OVERVIEW +# +# Handle configuration for RSH security, implementing the --with-rsh-security +# option and checking for the relevant programs and options. +# +AC_DEFUN([AMANDA_RSH_SECURITY], +[ + RSH_SECURITY=no + AC_ARG_WITH(rsh-security, + AS_HELP_STRING([--with-rsh-security], + [include RSH authentication]), + [ + case "$withval" in + n | no) : ;; + y | ye | yes) RSH_SECURITY=yes ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --with-rsh-security.]) + ;; + esac + ], + ) + + if test "x$RSH_SECURITY" = "xyes"; then + AC_DEFINE(RSH_SECURITY,1, + [Define if RSH transport should be enabled. ]) + fi + AM_CONDITIONAL(WANT_RSH_SECURITY, test x"$RSH_SECURITY" = x"yes") +]) + diff --git a/config/amanda/s3-device.m4 b/config/amanda/s3-device.m4 new file mode 100644 index 0000000..1aa37cb --- /dev/null +++ b/config/amanda/s3-device.m4 @@ -0,0 +1,65 @@ +# SYNOPSIS +# +# AMANDA_S3_DEVICE +# +# OVERVIEW +# +# Perform the necessary checks for the S3 Device. If the S3 device should be built, +# WANT_S3_DEVICE is DEFINEd and set up as an AM_CONDITIONAL. +# +# The subsidiary DevPay support, if enabled, defines and AM_CONDITIONALizes +# WANT_DEVPAY. +# +AC_DEFUN([AMANDA_S3_DEVICE], [ + AC_REQUIRE([AMANDA_CHECK_LIBCURL]) + AC_REQUIRE([AMANDA_CHECK_HMAC]) + + AC_ARG_ENABLE([s3-device], + AS_HELP_STRING([--disable-s3-device], + [disable the S3 device]), + [ WANT_S3_DEVICE=$enableval ], [ WANT_S3_DEVICE=maybe ]) + + AC_MSG_CHECKING([whether to include the Amazon S3 device]) + # if the user didn't specify 'no', then check for support + if test x"$WANT_S3_DEVICE" != x"no"; then + if test x"$HAVE_CURL" = x"yes" -a x"$HAVE_HMAC" = x"yes"; then + WANT_S3_DEVICE=yes + else + # no support -- if the user explicitly enabled the device, + # then this is an error + if test x"$WANT_S3_DEVICE" = x"yes"; then + AC_MSG_RESULT(no) + AC_MSG_ERROR([Cannot build the Amazon S3 device: one or more prerequisites are missing.]) + else + WANT_S3_DEVICE=no + fi + fi + fi + AC_MSG_RESULT($WANT_S3_DEVICE) + + AM_CONDITIONAL([WANT_S3_DEVICE], [test x"$WANT_S3_DEVICE" = x"yes"]) + + # Now handle any setup for S3, if we want it. + if test x"$WANT_S3_DEVICE" = x"yes"; then + AC_DEFINE(WANT_S3_DEVICE, [], [Compile Amazon S3 driver]) + fi + + + AC_ARG_ENABLE([devpay], + AS_HELP_STRING([--enable-devpay], + [Use devpay authentication for Amazon S3 driver]), + [WANT_DEVPAY=$enableval], [WANT_DEVPAY=no]) + + AC_MSG_CHECKING([whether to include the Amazon S3 device's DevPay support]) + if test x"$WANT_DEVPAY" = x"yes"; then + if test x"$WANT_S3_DEVICE" != x"yes"; then + AC_MSG_RESULT(no) + AC_MSG_ERROR([DevPay support requires the S3 device (--enable-s3-device)]) + fi + + AC_DEFINE([WANT_DEVPAY], [], [Compile Amazon DevPay support]) + fi + AC_MSG_RESULT($WANT_DEVPAY) + + AM_CONDITIONAL([WANT_DEVPAY], [test "$WANT_DEVPAY" = "yes"]) +]) diff --git a/config/amanda/shmem.m4 b/config/amanda/shmem.m4 new file mode 100644 index 0000000..d620e5d --- /dev/null +++ b/config/amanda/shmem.m4 @@ -0,0 +1,130 @@ +# SYNOPSIS +# +# AMANDA_FUNC_SHM_ARG_TYPE +# +# OVERVIEW +# +# Determine the type of the second argument to shmdt/shmat, defining +# that type (without the *) in SHM_ARG_TYPE. +# +AC_DEFUN([AMANDA_FUNC_SHM_ARG_TYPE], [ + AC_CHECK_HEADERS( + sys/types.h \ + sys/ipc.h \ + sys/shm.h \ + ) + + AC_CACHE_CHECK( + [for shmdt() argument type], + amanda_cv_shmdt_arg_type, + [ + if test "$ac_cv_func_shmget" = yes; then + cat <conftest.$ac_ext +#include "confdefs.h" +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_IPC_H +# include +#endif +#ifdef HAVE_SYS_SHM_H +# include +#endif + +#ifdef __cplusplus +extern "C" void *shmat(int, void *, int); +#else +void *shmat(); +#endif + +int main() +{ + int i; + return 0; +} +EOF + ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext >/dev/null 2>/dev/null + if test $? = 0; then + amanda_cv_shmdt_arg_type=void + else + amanda_cv_shmdt_arg_type=char + fi + rm -f conftest* + else + amanda_cv_shmdt_arg_type=nothing + fi + ] + ) + AC_DEFINE_UNQUOTED(SHM_ARG_TYPE,$amanda_cv_shmdt_arg_type, + [Define to type of shmget() function argument. ]) + ] +) + +# SYNOPSIS +# +# AMANDA_CHECK_SHMEM +# +# OVERVIEW +# +# Check for shared memory support; checks for the --with-mmap option, +# and then ensures that the proper compilation infrastructure is in place +# for either mmap or shared memory support. +# +# Defines several HAVE_*_DECL symbols via ICE_CHECK_DECL, as well as +# HAVE_SYSVSHM if shared memory support is discovered. +# +AC_DEFUN([AMANDA_CHECK_SHMEM], +[ + AC_REQUIRE([AC_HEADER_STDC]) + AC_ARG_WITH(mmap, + AS_HELP_STRING([--with-mmap], + [force use of mmap instead of shared memory support]), + [ + case "$FORCE_MMAP" in + y | ye | yes | n | no) : ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --with-mmap.]) ;; + esac + FORCE_MMAP=$withval + ], + [ : ${FORCE_MMAP=no} ] + ) + + + AC_CHECK_HEADERS(\ + sys/shm.h \ + sys/mman.h \ + ) + + AC_FUNC_MMAP + + AC_CHECK_FUNCS(shmget, + [ + AMANDA_FUNC_SHM_ARG_TYPE + case "$FORCE_MMAP" in + n | no) + AC_DEFINE(HAVE_SYSVSHM,1, + [Define if SysV shared-memory functions are available. ]) + ;; + esac + ] + ) + ICE_CHECK_DECL(shmat,sys/types.h sys/ipc.h sys/shm.h) + ICE_CHECK_DECL(shmctl,sys/types.h sys/ipc.h sys/shm.h) + ICE_CHECK_DECL(shmdt,sys/types.h sys/ipc.h sys/shm.h) + ICE_CHECK_DECL(shmget,sys/types.h sys/ipc.h sys/shm.h) + + if test "x$ac_cv_func_mmap_fixed_mapped" != xyes; then + case "$FORCE_MMAP" in + n | no) + if test "x$ac_cv_func_shmget" != xyes; then + AMANDA_MSG_WARN([Neither shmget() nor mmap() found. This system will not support the Amanda server.]) + NO_SERVER_MODE=true + fi + ;; + y | ye | yes) + AMANDA_MSG_WARN([--with-mmap used on a system with no mmap() support. This system will not support the Amanda server.]) + NO_SERVER_MODE=true + ;; + esac + fi +]) diff --git a/config/amanda/socklen_t_equiv.m4 b/config/amanda/socklen_t_equiv.m4 new file mode 100644 index 0000000..1d95d3b --- /dev/null +++ b/config/amanda/socklen_t_equiv.m4 @@ -0,0 +1,48 @@ +# SYNOPSIS +# +# AMANDA_SOCKLEN_T_EQUIV +# +# OVERVIEW +# +# Find a type which will work like socklen_t should. Unfortunately, +# HP/UX systems define socklen_t, but use int * as the result parameter +# for socket functions returning a socket length. +# +# This check defines a type socklen_t_equiv which is of the appropriate +# size to be used with socket functions. +# +AC_DEFUN([AMANDA_SOCKLEN_T_EQUIV], +[ + ## lifted from config/gnulib/socklen.m4 + AC_REQUIRE([gl_HEADER_SYS_SOCKET])dnl + AC_MSG_CHECKING([for socklen_t equivalent]) + AC_CACHE_VAL([gl_cv_socklen_t_equiv], + [# Systems have either "struct sockaddr *" or + # "void *" as the second argument to getpeername + gl_cv_socklen_t_equiv= + for arg2 in "struct sockaddr" void; do + for t in socklen_t int size_t "unsigned int" "long int" "unsigned long int"; do + AC_TRY_COMPILE( + [#include + #include + + int getpeername (int, $arg2 *, $t *);], + [$t len; + getpeername (0, 0, &len);], + [gl_cv_socklen_t_equiv="$t"]) + test "$gl_cv_socklen_t_equiv" != "" && break + done + test "$gl_cv_socklen_t_equiv" != "" && break + done + ]) + ## end lifting from config/gnulib/socklen.m4 + # fallback if the check fails + if test "$gl_cv_socklen_t_equiv" = ""; then + gl_cv_socklen_t_equiv=socklen_t + fi + AC_MSG_RESULT([$gl_cv_socklen_t_equiv]) + + AC_DEFINE_UNQUOTED([socklen_t_equiv], [$gl_cv_socklen_t_equiv], + [type to use for socket length parameters; use instead of socklen_t]) +]) + diff --git a/config/amanda/ssh-security.m4 b/config/amanda/ssh-security.m4 new file mode 100644 index 0000000..9fd8d97 --- /dev/null +++ b/config/amanda/ssh-security.m4 @@ -0,0 +1,71 @@ +# SYNOPSIS +# +# AMANDA_SSH_SECURITY +# +# OVERVIEW +# +# Handle configuration for SSH security, implementing the --with-ssh-security +# option and checking for the relevant programs and options. +# +AC_DEFUN([AMANDA_SSH_SECURITY], +[ + SSH_SECURITY=no + AC_ARG_WITH(ssh-security, + AS_HELP_STRING([--with-ssh-security], + [include SSH authentication]), + [ + case "$withval" in + n | no) : ;; + y | ye | yes) SSH_SECURITY=yes ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --with-ssh-security.]) + ;; + esac + ], + ) + + if test "x$SSH_SECURITY" = "xyes"; then + # find the SSH binary + AC_PATH_PROGS(SSH, ssh, , $LOCSYSPATH) + + # see what options we should use + AC_ARG_WITH(ssh-options, + AS_HELP_STRING([ --with-ssh-options=@<:@OPTIONS@:>@], + [Use these ssh options for ssh security; the default should work]), + [ SSH_OPTIONS="$withval" ], + [ SSH_OPTIONS='' ] + ) + + case "$SSH_OPTIONS" in + y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to --with-ssh-options.]);; + *) : ;; + esac + + AC_MSG_CHECKING([SSH options]) + # if we didn't get SSH options from the user, figure them out for ourselves + if test -z "$SSH_OPTIONS"; then + case `$SSH -V 2>&1` in + OpenSSH*) SSH_OPTIONS='-x -o BatchMode=yes -o PreferredAuthentications=publickey';; + *) SSH_OPTIONS='-x -o BatchMode=yes' ;; + esac + fi + + # now convert that to a comma-separated list of C strings + eval "set dummy ${SSH_OPTIONS}"; shift + SSH_OPTIONS='' + for i in "${@}"; do + quoted="\"`echo "$i" | sed -e 's/\"/\\\"/'`\"" + SSH_OPTIONS="${SSH_OPTIONS}${SSH_OPTIONS:+, }$quoted"; + done + AC_MSG_RESULT($SSH_OPTIONS) + + # finally, make the various outputs for all of this + AC_DEFINE(SSH_SECURITY,1, + [Define if SSH transport should be enabled. ]) + AC_DEFINE_UNQUOTED(SSH, "$SSH", + [Path to the SSH binary]) + AC_DEFINE_UNQUOTED(SSH_OPTIONS, $SSH_OPTIONS, + [Arguments to ssh]) + fi + AM_CONDITIONAL(WANT_SSH_SECURITY, test x"$SSH_SECURITY" = x"yes") +]) diff --git a/config/amanda/summary.m4 b/config/amanda/summary.m4 new file mode 100644 index 0000000..105373c --- /dev/null +++ b/config/amanda/summary.m4 @@ -0,0 +1,71 @@ +# OVERVIEW/BACKGROUND +# +# This file creates an end-of-run summary of the Amanda configuration. +# + +# SYNOPSIS +# +# AMANDA_INIT_SUMMARY() +# +# DESCRIPTION +# +# Set up for producing a summary. This should be called early in the configure +# process +# +AC_DEFUN([AMANDA_INIT_SUMMARY], +[ + # initialize warnings file + rm -f config.warnings +]) + +# SYNOPSIS +# +# AMANDA_MSG_WARN() +# +# DESCRIPTION +# +# Like AC_MSG_WARN, but also adds the message to the summary +# +AC_DEFUN([AMANDA_MSG_WARN], [ + AC_MSG_WARN([$1]) + AMANDA_ADD_WARNING([$1]) +]) + +# SYNOPSIS +# +# AMANDA_ADD_WARNING_QUOTED(warning-text) #if text already quoted +# AMANDA_ADD_WARNING(warning-text) #if text not quoted +# +# DESCRIPTION +# +# Add the given text to the warnings summary +# +AC_DEFUN([AMANDA_ADD_WARNING_QUOTED], [ + cat <>config.warnings +$1 +AAW_EOF]) + +AC_DEFUN([AMANDA_ADD_WARNING], [ +AMANDA_ADD_WARNING_QUOTED([_AS_QUOTE([$1])]) +]) + +# SYNOPSIS +# +# AMANDA_SHOW_SUMMARY() +# +# DESCRIPTION +# +# Output the configuration summary. +# +AC_DEFUN([AMANDA_SHOW_SUMMARY], [ + AMANDA_SHOW_FLAGS_SUMMARY + AMANDA_SHOW_COMPONENTS_SUMMARY + AMANDA_SHOW_IPV6_SUMMARY + AMANDA_SHOW_DOCUMENTATION_SUMMARY + AMANDA_SHOW_DIRS_SUMMARY + if test -f config.warnings; then + echo "WARNINGS:" + cat config.warnings | sed -e 's/^/ /g' + rm config.warnings + fi +]) diff --git a/config/amanda/swig.m4 b/config/amanda/swig.m4 new file mode 100644 index 0000000..dadfc89 --- /dev/null +++ b/config/amanda/swig.m4 @@ -0,0 +1,76 @@ +# OVERVIEW +# +# Set up for building SWIG bindings. Note that shipped tarballs contain pre-built +# SWIG bindings, so there should be no need for SWIG on non-developer machines. +# SYNOPSIS +# +# Find perl and SWIG, and substitute PERL_INC, the -I command that will lead the compiler +# to perl.h and friends. +# +# Supports --with-perlextlibs, for adding extra LIBS declarations to perl extensions. +# +AC_DEFUN([AMANDA_SETUP_SWIG], +[ + AC_REQUIRE([AMANDA_PROG_SWIG]) + AC_REQUIRE([AMANDA_PROG_PERL]) + + # If we want cygwin to copy ddl to modules directory. + WANT_CYGWIN_COPY_PERL_DLL="false" + + # get the include path for building perl extensions + PERL_INC=`$PERL -MExtUtils::Embed -e perl_inc` + AC_SUBST(PERL_INC) + + if test x"$enable_shared" = x"no"; then + AC_MSG_ERROR([*** Amanda cannot be compiled without shared-library support (do not use --disable-shared)]) + fi + + case "$target" in + *freebsd@<:@123456@:>@*) # up to and including FreeBSD 6.* + # Before 7.0, FreeBSD systems don't include a DT_NEEDS segment in + # libgthread to automatically pull in the desired threading library. + # Instead, they assume that any application linking against + # libgthread will pull in the threading library. This is fine for + # Amanda C applications, but for Perl applications this assumption + # means that the perl binary would pull in the threading library. + # But perl is compiled without threading by default. + # + # Specifically, this occurs on any FreeBSD using gcc-3.*: the linking + # decision is made in gcc's spec files, which were changed in + # gcc-4.0. For a more in-depth discussion, see + # http://wiki.zmanda.com/index.php/Installation/OS_Specific_Notes/Installing_Amanda_on_FreeBSD + # + # The easiest solution for the "default" case is to link all perl + # extension libraries against the threading library, so it is loaded + # when perl loads the extension library. The default threading + # library in FreeBSD is libpthread. The below default will work on + # such a FreeBSD system, but ports maintainers and those with + # different configurations may need to override this value with + # --with-perlextlibs. + # + # We can't use -pthread because gcc on FreeBSD ignores -pthread in + # combination with -shared. See + # http://lists.freebsd.org/pipermail/freebsd-stable/2006-June/026229.html + + PERLEXTLIBS="-lpthread" + ;; + *-pc-cygwin) + # When need -lperl and the '-L' where it is located, + # we don't want the DynaLoader.a + PERLEXTLIBS=`perl -MExtUtils::Embed -e ldopts | sed -e 's/^.*-L/-L/'` + WANT_CYGWIN_COPY_PERL_DLL="true"; + ;; + esac + AM_CONDITIONAL(WANT_CYGWIN_COPY_PERL_DLL,$WANT_CYGWIN_COPY_PERL_DLL) + + AC_ARG_WITH(perlextlibs, + AC_HELP_STRING([--with-perlextlibs=libs],[extra LIBS for Perl extensions]), + [ + case "$withval" in + y|ye|yes) AC_MSG_ERROR([*** You must specify a value for --with-perlextlibs]);; + n|no) PERLEXTLIBS='';; + *) PERLEXTLIBS="$withval" ;; + esac + ]) + AC_SUBST(PERLEXTLIBS) +]) diff --git a/config/amanda/syshacks.m4 b/config/amanda/syshacks.m4 new file mode 100644 index 0000000..c3e9935 --- /dev/null +++ b/config/amanda/syshacks.m4 @@ -0,0 +1,108 @@ +# SYNOPSIS +# +# AMANDA_SYSHACKS +# +# OVERVIEW +# +# This macro encapsulates any system-specific hacks required to make Amanda +# compile that don't fit neatly into any other macro. It is implemented as a +# big 'case' statement based on the canonical target architecture. +# +# It also serves as a list of the "supported" architectures, represented by +# case statements with empty bodies. If no architecture matches, the user +# is presented with a warning. +# +AC_DEFUN([AMANDA_SYSHACKS], [ + AC_REQUIRE([AC_CANONICAL_TARGET]) + case "$target" in + *-dec-osf*) + ;; + *-dg-*) + ;; + *-netbsd*) + ;; + *-freebsd*) + ;; + *-openbsd*) + ;; + *-hp-*) + case "$CC" in + *gcc*) + AMANDA_ADD_CPPFLAGS([-D__STDC_EXT__]) + ;; + *cc*) + AMANDA_ADD_CFLAGS([-Ae]) + ;; + esac + ;; + *-ibm-aix*) + ;; + m88k-motorola-sysv4) + ;; + *-nextstep3) + ;; + *-pc-bsdi*) + ;; + *-pc-linux-*) + ;; + *-redhat-linux-*) + ;; + *-suse-linux-*) + ;; + x86_64-*-linux-*) + ;; + alpha*-*-linux-*) + ;; + sparc*-*-linux-*) + ;; + powerpc-*-linux-*) + ;; + *-sgi-irix3*) + # The old cc won't work! + if test "x$GCC" != "xyes"; then + AC_MSG_ERROR([The old SGI IRIX compiler ($CC) will not compile Amanda; use CC=gcc]) + fi + ;; + *-sgi-irix4*) + ;; + *-sgi-irix5*) + ;; + *-sgi-irix6*) + ;; + *-solaris2*) + ;; + *-sun-sunos4.1*) + ;; + *-ultrix*) + ;; + *-sysv4.2uw2*) + ;; + *-sco3.2v5*) + ;; + i386-pc-isc4*) + ;; + *-sni-sysv4) + ;; + *-pc-cygwin) + AC_DEFINE(IGNORE_TAR_ERRORS,1,[Define on Cygwin. ]) + # Cygwin needs PATH to find cygwin1.dll + AC_DEFINE(NEED_PATH_ENV,1,[Define on Cygwin. ]) + AC_DEFINE(IGNORE_FSTAB,1,[Define on Cygwin. ]) + AMANDA_ADD_LDFLAGS([-Wl,-enable-runtime-pseudo-reloc -no-undefined]) + ;; + *-apple-darwin7*) # MacOS X 10.3.* (Panther) + ;; + *-apple-darwin8*) # MacOS X 10.4.* (Tiger) + ;; + *) + AMANDA_ADD_WARNING( +[***** +This machine, target type $target, is not known to be fully supported +by this configure script. If the installation of Amanda on this system +succeeds or needed any patches, please email amanda-hackers@amanda.org +with the patches or an indication of the sucess or failure of the +Amanda installation on your system. +*****]) + ;; + esac +]) diff --git a/config/amanda/tape.m4 b/config/amanda/tape.m4 new file mode 100644 index 0000000..d08f27a --- /dev/null +++ b/config/amanda/tape.m4 @@ -0,0 +1,198 @@ +# SYNOPSIS +# +# AMANDA_WITH_MAXTAPEBLOCKSIZE +# +# OVERVIEW +# +# Implement the --with-maxtapeblocksize option, and DEFINE and SUBST the +# result in MAX_TAPE_BLOCk_KB and MAXTAPEBLOCKSIZE, respectively. +# +AC_DEFUN([AMANDA_WITH_MAXTAPEBLOCKSIZE], [ + AC_ARG_WITH(maxtapeblocksize, + AS_HELP_STRING([--with-maxtapeblocksize=kb], + [Maximum size of a tape block (default: 32)]), + [ MAXTAPEBLOCKSIZE="$withval" ], + [ MAXTAPEBLOCKSIZE=32 ] + ) + + AC_DEFINE_UNQUOTED(MAX_TAPE_BLOCK_KB,($MAXTAPEBLOCKSIZE), + [Maximum size of a tape block in KBytes.]) + AC_SUBST(MAXTAPEBLOCKSIZE) +]) + +# SYNOPSIS +# +# AMANDA_TAPE_DEVICE +# +# OVERVIEW +# +# Set up for the 'tape' device. One of the conditionals WANT_TAPE_XENIX, +# WANT_TAPE_AIX, WANT_TAPE_UWARE, and WANT_TAPE_POSIX will be true; the +# corresponding symbols are also DEFINEd. Finally, WANT_TAPE_DEVICE is +# defined nad AM_CONDITIONAL'd if the tape device should be supported (if +# at least one of the backends is available). +# +# If 'struct mtget' fields mt_flags, mt_fileno, mt_blkno, mt_dsreg, and +# mt_erreg, the corresponding HAVE_MT_* is DEFINEd. +# +# Not that most of the checks in this section correspond to the older +# tapeio (in tape-src/), rather than the new tape device. +# +AC_DEFUN([AMANDA_TAPE_DEVICE], [ + AC_CHECK_HEADERS( \ + linux/zftape.h \ + sys/tape.h \ + sys/mtio.h \ + ) + + # check for MTIOCTOP, an indicator of POSIX tape support + AC_CACHE_CHECK([for MTIOCTOP], amanda_cv_HAVE_MTIOCTOP,[ + AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TAPE_H +# include +#endif +#ifdef HAVE_SYS_MTIO_H +# include +#endif +#ifndef MTIOCTOP +#error MTIOCTOP not defined +#endif + ], + [ int dummy = 0; ], + amanda_cv_HAVE_MTIOCTOP=yes, + amanda_cv_HAVE_MTIOCTOP=no, + amanda_cv_HAVE_MTIOCTOP=no)] + + HAVE_MTIOCTOP=$amanda_cv_HAVE_MTIOCTOP + ) + + # decide which tape device to compile (arranged in such a way that + # only one actually gets compiled) + case "$target" in + *-ibm-aix*) aix_tapeio=yes ;; + *-sysv4.2uw2*) uware_tapeio=yes ;; + *-sco3.2v5*) xenix_tapeio=yes ;; + i386-pc-isc4*) xenix_tapeio=yes ;; + esac + + # maybe we have no tape device at all (e.g., Mac OS X)? + if test -n "$xenix_tapeio" || + test -n "$aix_tapeio" || + test -n "$uware_tapeio" || + test -n "$HAVE_MTIOCTOP"; then + want_tape_device=yes + AC_DEFINE(WANT_TAPE_DEVICE, 1, [Define if the tape-device will be built]) + fi + + AM_CONDITIONAL(WANT_TAPE_XENIX, test -n "$xenix_tapeio") + AM_CONDITIONAL(WANT_TAPE_AIX, test -n "$aix_tapeio") + AM_CONDITIONAL(WANT_TAPE_UWARE, test -n "$uware_tapeio") + AM_CONDITIONAL(WANT_TAPE_POSIX, test -n "$HAVE_MTIOCTOP") + AM_CONDITIONAL(WANT_TAPE_DEVICE, test -n "$want_tape_device") + + if test -n "$xenix_tapeio"; then + AC_DEFINE(WANT_TAPE_XENIX,1,[Define on XENIX/ISC. ]) + fi + + if test -n "$aix_tapeio"; then + AC_DEFINE(WANT_TAPE_AIX,1,[Define on AIX. ]) + fi + + if test -n "$uware_tapeio"; then + AC_DEFINE(WANT_TAPE_UWARE,1,[Define on UnixWare. ]) + fi + + # + # Check for various "mt status" related structure elements. + # + AC_MSG_CHECKING([for mt_flags mtget structure element]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + struct mtget buf; + long ds; + + ds = buf.mt_flags; + ]])],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MT_FLAGS,1, + [Define if the mtget structure has an mt_flags field]) + ],[ + AC_MSG_RESULT(no) + ]) + + AC_MSG_CHECKING([for mt_fileno mtget structure element]) + mt_fileno_result="found" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + struct mtget buf; + long ds; + + ds = buf.mt_fileno; + ]])],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MT_FILENO,1, + [Define if the mtget structure has an mt_fileno field]) + ],[ + AC_MSG_RESULT(no) + ]) + + AC_MSG_CHECKING(for mt_blkno mtget structure element) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + struct mtget buf; + long ds; + + ds = buf.mt_blkno; + ]])],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MT_BLKNO,1, + [Define if the mtget structure has an mt_blkno field]) + ],[ + AC_MSG_RESULT(no) + ]) + + AC_MSG_CHECKING(for mt_dsreg mtget structure element) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + struct mtget buf; + long ds; + + ds = buf.mt_dsreg; + ]])],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MT_DSREG,1, + [Define if the mtget structure has an mt_dsreg field]) + ],[ + AC_MSG_RESULT(no) + ]) + + AC_MSG_CHECKING(for mt_erreg mtget structure element) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + struct mtget buf; + long ds; + + ds = buf.mt_erreg; + ]])],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MT_ERREG,1, + [Define if the mtget structure has an mt_erreg field]) + ],[ + AC_MSG_RESULT(no) + ]) +]) diff --git a/config/amanda/types.m4 b/config/amanda/types.m4 new file mode 100644 index 0000000..ff9e852 --- /dev/null +++ b/config/amanda/types.m4 @@ -0,0 +1,188 @@ +# SYNOPSIS +# +# AMANDA_CHECK_TYPE(type, replacement-type, header) +# +# OVERVIEW +# +# Like AC_CHECK_TYPE, where action-if-not-found DEFINEs $1 to $2. +# +# 'header' must be a single header name, or blank to use the default +# headers. +# +AC_DEFUN([AMANDA_CHECK_TYPE], [ + AC_REQUIRE([AC_HEADER_STDC]) + AC_CHECK_TYPE($1, [], [ + AC_DEFINE($1, $2, [Type for $1, if it is not defined by the system]) + ], ifelse($3, [], [], [ +#ifdef STDC_HEADERS +#include +#include +#endif +#include <$3> + ]) + ) +]) +# +# SYNOPSIS +# +# AMANDA_TYPE_PID_T +# +# OVERVIEW +# +# Check whether pid_t is a long, int, or short. DEFINE PRINTF_PID_T to the +# corresponding printf format. +# +AC_DEFUN([AMANDA_TYPE_PID_T], [ + AC_REQUIRE([AC_HEADER_STDC]) + AC_REQUIRE([AC_TYPE_PID_T]) + AC_CACHE_CHECK([for pid_t type], amanda_cv_pid_type, + [ + amanda_cv_pid_type=unknown + if test "$ac_cv_type_pid_t" = no; then + amanda_cv_pid_type=int + fi + for TEST_amanda_cv_pid_type in long short int; do + if test $amanda_cv_pid_type = unknown; then + AC_EGREP_CPP(typedef.*${TEST_amanda_cv_pid_type}.*pid_t, + [ +#include +#if STDC_HEADERS +#include +#include +#endif + ], + amanda_cv_pid_type=$TEST_amanda_cv_pid_type) + fi + if test $amanda_cv_pid_type = unknown; then + AC_EGREP_CPP(ZZZZ.*${TEST_amanda_cv_pid_type}, + [ +#include +#if STDC_HEADERS +#include +#include +#endif + ZZZZ pid_t + ], + amanda_cv_pid_type=$TEST_amanda_cv_pid_type) + fi + done + if test $amanda_cv_pid_type = unknown; then + amanda_cv_pid_type=int + fi + ] + ) + case $amanda_cv_pid_type in + int) AC_DEFINE_UNQUOTED(PRINTF_PID_T,"%d",[Define to printf formatting string to print a PID. ]) ;; + long) AC_DEFINE_UNQUOTED(PRINTF_PID_T,"%ld") ;; + short) AC_DEFINE_UNQUOTED(PRINTF_PID_T,"%d") ;; + esac + ] +) + +# SYNOPSIS +# +# CF_WAIT +# +# OVERVIEW +# +# Test for the presence of , 'union wait', arg-type of 'wait()'. +# by T.E.Dickey" , Jim Spath +# +# DEFINEs WAIT_USES_UNION if 'union wait' is found. Note that many systems +# support *both* 'union wait' and 'int' using a transparent union. +# +# Original comments: +# +# FIXME: These tests should have been in autoconf 1.11! +# +# Note that we cannot simply grep for 'union wait' in the wait.h file, +# because some Posix systems turn this on only when a BSD variable is +# defined. Since I'm trying to do without special defines, I'll live +# with the default behavior of the include-file. +# +# I do _2_ compile checks, because we may have union-wait, but the +# prototype for 'wait()' may want an int. +# +# Don't use HAVE_UNION_WAIT, because the autoconf documentation implies +# that if we've got union-wait, we'll automatically use it. +# +# Garrett Wollman adds: +# The tests described above don't quite do the right thing, +# since some systems have hacks which allow `union wait' to +# still work even though `int' is preferred (and generates +# fewer warnings). Since all of these systems use prototypes, +# we can use the prototype of wait(2) to disambiguate them. +# +# Alexandre Oliva adds: +# A single compile check is enough. If we don't have union wait, +# it's obvious that the test will fail, and that we must use int. +# If we do, the prototype (on STDC systems) and WIFEXITED will tell +# whether we're supposed to be using union wait instead of int. +# +AC_DEFUN([CF_WAIT], [ + AC_REQUIRE([AC_TYPE_PID_T]) + AC_HAVE_HEADERS(sys/wait.h wait.h) + AC_CACHE_CHECK([whether wait uses union wait], [cf_cv_arg_union_wait], [ + AC_TRY_COMPILE([ +#include + +#if HAVE_SYS_WAIT_H +# include +#else +# if HAVE_WAIT_H +# include +# endif +#endif + +#ifdef __STDC__ +pid_t wait(union wait *); +#endif +], [ + union wait x; int i; + wait(&x); i = WIFEXITED(x) +], [cf_cv_arg_union_wait=yes], [cf_cv_arg_union_wait=no])]) + if test $cf_cv_arg_union_wait = yes; then + AC_DEFINE(WAIT_USES_UNION,1, + [Defined if wait() puts the status in a union wait instead of int. ]) + fi +]) + +# SYNOPSIS +# +# CF_WAIT_INT +# +# OVERVIEW +# +# Test for the presence of , 'union wait', arg-type of 'wait()'. +# by T.E.Dickey" , Jim Spath +# +# DEFINEs WAIT_USES_INT if an int result type is found. +# +AC_DEFUN([CF_WAIT_INT], [ + AC_REQUIRE([AC_TYPE_PID_T]) + AC_HAVE_HEADERS(sys/wait.h wait.h) + AC_CACHE_CHECK([whether wait uses int], [cf_cv_arg_int], [ + AC_TRY_COMPILE([ +#include + +#if HAVE_SYS_WAIT_H +# include +#else +# if HAVE_WAIT_H +# include +# endif +#endif + +#ifdef __STDC__ +pid_t wait(int *); +#endif +], [ + int x; int i; + wait(&x); i = WIFEXITED(x) +], [cf_cv_arg_int=yes], [cf_cv_arg_int=no])]) +if test $cf_cv_arg_int = yes; then + AC_DEFINE(WAIT_USES_INT,1, + [Defined if wait() puts the status in a int instead of a union wait. ]) +fi +]) + diff --git a/config/amanda/userid.m4 b/config/amanda/userid.m4 new file mode 100644 index 0000000..8ef15c8 --- /dev/null +++ b/config/amanda/userid.m4 @@ -0,0 +1,187 @@ +# SYNOPSIS +# +# AMANDA_DISABLE_INSTALLPERMS +# +# OVERVIEW +# +# Handle the --disable-installperms option, which disables all post-install +# chown/chmod operations. This is useful when packaging, as most packaging +# systems build as non-root, and apply permissions in the post-install step of +# the package itself. +# +AC_DEFUN([AMANDA_DISABLE_INSTALLPERMS], +[ + WANT_INSTALLPERMS=yes + AC_ARG_ENABLE(installperms, + AS_HELP_STRING([--disable-installperms], + [do not modify ownership and permissions on installed files]), + [ WANT_INSTALLPERMS="$enableval" ], + [ WANT_INSTALLPERMS="yes" ] + ) + AM_CONDITIONAL(WANT_INSTALLPERMS, test x"$WANT_INSTALLPERMS" = x"yes") +]) + +# SYNOPSIS +# +# AMANDA_WITH_FORCE_UID +# +# OVERVIEW +# +# Handle the --without-force-id option, which disables userid checks for +# all Amanda applications. Defines CHECK_USERID *unless* this option is +# given. +# +AC_DEFUN([AMANDA_WITH_FORCE_UID], +[ + AC_ARG_WITH(force-uid, + AS_HELP_STRING([--without-force-uid], + [do not check userids when running programs]), + CHECK_USERID="$withval", + : ${CHECK_USERID=yes} + ) + case "$CHECK_USERID" in + y | ye | yes) + AC_DEFINE(CHECK_USERID, 1, + [Define to force to another user on client machines. ]) + ;; + n | no) : + ;; + *) + AC_MSG_ERROR([*** You must not supply an argument to --with-force-uid option.]) + esac +]) + +# SYNOPSIS +# +# AMANDA_WITH_USER +# +# OVERVIEW +# +# Handle the --with-user option, which sets the userid Amanda expects to run +# under. Defines and substitutes CLIENT_LOGIN. +# +AC_DEFUN([AMANDA_WITH_USER], +[ + AC_ARG_WITH(user, + AS_HELP_STRING([--with-user=USER], + [force execution to USER on client systems (REQUIRED)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-user option.]) + ;; + *) + CLIENT_LOGIN="$withval" + ;; + esac + ], [ + AMANDA_MSG_WARN([[no user specified (--with-user) -- using 'amanda']]) + CLIENT_LOGIN=amanda + ] + ) + + AC_DEFINE_UNQUOTED(CLIENT_LOGIN,"$CLIENT_LOGIN", + [Define as a the user to force to on client machines. ]) + AC_SUBST(CLIENT_LOGIN) +]) + +# SYNOPSIS +# +# AMANDA_WITH_GROUP +# +# OVERVIEW +# +# Handle the --with-group option, which sets the groupid Amanda expects to run +# under. Substitutes (but does not define) SETUID_GROUP. +# +AC_DEFUN([AMANDA_WITH_GROUP], +[ + AC_ARG_WITH(group, + AS_HELP_STRING([--with-group=GROUP], + [group allowed to execute setuid-root programs (REQUIRED)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-group option.]) + ;; + *) SETUID_GROUP="$withval" + ;; + esac + ], [ + AMANDA_MSG_WARN([[no group specified (--with-group) -- using 'backup']]) + CLIENT_LOGIN=backup + ] + ) + AC_SUBST(SETUID_GROUP) +]) + +# SYNOPSIS +# +# AMANDA_WITH_OWNER +# +# OVERVIEW +# +# Handle the --with-owner option, which sets the userid the 'make install' process +# will use. Substitutes and defines BINARY_OWNER. +# +AC_DEFUN([AMANDA_WITH_OWNER], +[ + AC_REQUIRE([AMANDA_WITH_USER]) + AC_ARG_WITH(owner, + AS_HELP_STRING([--with-owner=USER] + [force ownership of installed files to USER (default same as --with-user)]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([*** You must supply an argument to the --with-owner option.]) + ;; + *) BINARY_OWNER="$withval" + ;; + esac + ], [ + BINARY_OWNER="$CLIENT_LOGIN" + ] + ) + AC_DEFINE_UNQUOTED(BINARY_OWNER,"$BINARY_OWNER", + [Define as the user who owns installed binaries. ]) + AC_SUBST(BINARY_OWNER) +]) + +# SYNOPSIS +# +# AMANDA_WITH_SINGLE_USERID +# +# OVERVIEW +# +# Check if this system is one on which clients should be built setuid, +# Sets up AM_CONDITIONAL/define WANT_SETUID_CLIENT and defines +# SINGLE_USERID if either the system requires it or the user specified it. +# +AC_DEFUN([AMANDA_WITH_SINGLE_USERID], +[ + SINGLE_USERID=${SINGLE_USERID:-no} + WANT_SETUID_CLIENT=${WANT_SETUID_CLIENT:-true} + + AC_ARG_WITH(single-userid, + AS_HELP_STRING([--with-single-userid] + [force amanda to run as a single userid (for testing)]), + [ SINGLE_USERID=$withval ]) + + case "$target" in + *-pc-cygwin) + WANT_SETUID_CLIENT=false + SINGLE_USERID=yes + ;; + esac + + if test x"$WANT_SETUID_CLIENT" = x"true"; then + AC_DEFINE(WANT_SETUID_CLIENT,1, + [Define if clients should be built setuid-root]) + fi + AM_CONDITIONAL(WANT_SETUID_CLIENT, test x"$WANT_SETUID_CLIENT" = x"true") + + if test x"$SINGLE_USERID" = x"yes"; then + AC_DEFINE(SINGLE_USERID, 1, + [Define if all of Amanda will run as a single userid (e.g., on Cygwin or for installchecks)]) + fi +]) diff --git a/config/amanda/version.m4 b/config/amanda/version.m4 new file mode 100644 index 0000000..f1ecb8a --- /dev/null +++ b/config/amanda/version.m4 @@ -0,0 +1,115 @@ +# Amanda version handling macros + +# SYNOPSIS +# +# AMANDA_SNAPSHOT_STAMP +# +# DESCRIPTION +# +# If srcdir contains a file named SNAPSHOT, with a line matching +# Snapshot Date: [0-9]* +# then set add the date to VERSION and set +# SNAPSHOT_STAMP=SNAPSHOT. +# +AC_DEFUN([AMANDA_SNAPSHOT_STAMP], +[ + if test -f "$srcdir/SNAPSHOT"; then + cat < "$srcdir/SNAPSHOT" + changequote(,) + snapdate=`sed -n '/^Snapshot Date: \([0-9]*\)/ s//\1/p' < $srcdir/SNAPSHOT` + changequote([,]) + test -z "$snapdate" || VERSION="$VERSION-$snapdate" + SNAPSHOT_STAMP=SNAPSHOT + else + SNAPSHOT_STAMP= + fi + AC_SUBST(SNAPSHOT_STAMP) +]) + +# SYNOPSIS +# +# AMANDA_SPLIT_VERSION +# +# DESCRIPTION +# +# Set the version number of this release of Amanda from the VERSION +# string, which is set in AM_INIT_AUTOMAKE. Sets VERSION_MAJOR, +# VERSION_MINOR, VERSION_PATCH, and VERSION_COMMENT to the +# corresponding components of VERSION, and VERSION_SUFFIX to a +# version-specific filename suffix. +# +AC_DEFUN([AMANDA_SPLIT_VERSION], +[ + changequote(,) + VERSION_MAJOR=`expr "$VERSION" : '\([0-9]*\)'` + VERSION_MINOR=`expr "$VERSION" : '[0-9]*\.\([0-9]*\)'` + VERSION_PATCH=`expr "$VERSION" : '[0-9]*\.[0-9]*\.\([0-9]*\)'` + VERSION_COMMENT=\"`expr "$VERSION" : '[0-9]*\.[0-9]*\.[0-9]*\(.*\)'`\" + changequote([,]) + + VERSION_SUFFIX="$VERSION" + AC_SUBST(VERSION_MAJOR) + AC_SUBST(VERSION_MINOR) + AC_SUBST(VERSION_PATCH) + AC_SUBST(VERSION_COMMENT) + AC_SUBST(VERSION_SUFFIX) +]) + +# SYNOPSIS +# +# AMANDA_WITH_SUFFIXES +# +# DESCRIPTION +# +# Implement the --with-suffixes option. If it is given, then set +# program_transform_name appropriately and AC_DEFINE USE_VERSION_SUFFIXES to 1. +# USE_VERSION_SUFFIXES is substituted with the value 'no' or 'yes'. +# +AC_DEFUN([AMANDA_WITH_SUFFIXES], +[ + AC_ARG_WITH(suffixes, + [ --with-suffixes install binaries with version string appended to name], + USE_VERSION_SUFFIXES=$withval, + : ${USE_VERSION_SUFFIXES=no} + ) + + case "$USE_VERSION_SUFFIXES" in + y | ye | yes) USE_VERSION_SUFFIXES=yes + AC_DEFINE(USE_VERSION_SUFFIXES, 1, + [Define to have programs use version suffixes when calling other programs.]) + + program_suffix="-$VERSION_SUFFIX" + # This is from the output of configure.in. + if test "x$program_transform_name" = xs,x,x,; then + program_transform_name= + else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed + fi + test "x$program_prefix" != xNONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" + # Use a double $ so make ignores it. + test "x$program_suffix" != xNONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + + # sed with no file args requires a program. + test "x$program_transform_name" = "" && program_transform_name="xs,x,x," + # Remove empty command + cat <<\EOF_SED > conftestsed +s,\;\;,\;,g; s,\; \$,,g; s,\;$,,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed + ;; + n | no) USE_VERSION_SUFFIXES=no + ;; + *) AC_MSG_ERROR([*** You must not supply an argument to --with-suffixes option.]) + ;; + esac + + AC_SUBST(USE_VERSION_SUFFIXES) +]) diff --git a/config/automake/file-list b/config/automake/file-list new file mode 100644 index 0000000..7038942 --- /dev/null +++ b/config/automake/file-list @@ -0,0 +1,5 @@ +## this file is automatically generated by autogen +EXTRA_DIST += automake/installperms.am +EXTRA_DIST += automake/precompile.am +EXTRA_DIST += automake/scripts.am +EXTRA_DIST += automake/vars.am diff --git a/config/automake/installperms.am b/config/automake/installperms.am new file mode 100644 index 0000000..245345b --- /dev/null +++ b/config/automake/installperms.am @@ -0,0 +1,91 @@ +# vim:ft=automake +# +# Adjust post-install permissions settings. This rule works off two +# specially-formatted variables, INSTALLPERMS_exec and INSTALLPERMS_data. +# Each is a whitespace-separated list of commands, all of which are either +# a variable assignment or a filename. Three variables are available: +# +# - dest= sets the destination directory to e.g., $(sbindir) +# - chown= controls changes in ownership; value is first argument to chown +# - chmod= controls changes in permissions; value is first argument to chmod +# +# As a special case, chown=amanda is taken as equivalent to +# chown=$(BINARY_OWNER):$(SETUID_GROUP), which may otherwise have problems with +# whitespace in the user/group names. +# +# when a filename is seen, the currently active variables are applied. +# +# Note that scripts are data, not executables! +# +# EXAMPLE +# +# sbin_PROGRAMS = foo bar bing +# libexec_PROGRAMS = pro gram +# sbin_SCRIPTS = sk ript +# INSTALLPERMS_exec = \ +# dest=$(sbindir) chown=amanda chmod= \ +# foo bar \ +# chmod=u+s,o-rwx \ +# bing +# dest=$(libexecdir) chmod= \ +# $(libexec_PROGRAMS) +# INSTALLPERMS_data = \ +# dest=$(sbindir) chown=amanda chmod= \ +# $(sbin_SCRIPTS) +# +# This whole operation is not required when making builds for packaging, +# and can be disabled with --disable-installperms, via the WANT_INSTALLPERMS +# AM_CONDITIONAL. + +# sed expression to strip leading directories from a filename; this converts e.g., +# src/foo/bar.so to bar.so. +strip_leading_dirs=s|^.*/|| + +if WANT_INSTALLPERMS +installperms-exec: + @installperms="$(INSTALLPERMS_exec)"; \ + test -n "$$installperms" && echo "Setting installation permissions on executables"; \ + dest=; chown=; chmod=; \ + for cmd in $$installperms; do \ + case "$$cmd" in \ + chown=amanda) \ + echo " ($$cmd)"; chown="$(BINARY_OWNER):$(SETUID_GROUP)";; \ + dest=*|chown=*|chmod=*) \ + echo " ($$cmd)"; eval $$cmd;; \ + *) pa="$(DESTDIR)$$dest"/`echo "$$cmd"|sed '$(strip_leading_dirs)'|sed '$(transform)'`; \ + if test -n "$$chown"; then \ + echo chown "$$chown" "$$pa"; \ + chown "$$chown" "$$pa" || exit 1; \ + fi; \ + if test -n "$$chmod"; then \ + echo chmod "$$chmod" "$$pa"; \ + chmod "$$chmod" "$$pa" || exit 1; \ + fi; \ + esac; \ + done + +installperms-data: + @installperms="$(INSTALLPERMS_data)"; \ + test -n "$$installperms" && echo "Setting installation permissions on data"; \ + dest=; chown=; chmod=; \ + for cmd in $$installperms; do \ + case "$$cmd" in \ + chown=amanda) \ + echo " ($$cmd)"; chown="$(BINARY_OWNER):$(SETUID_GROUP)";; \ + dest=*|chown=*|chmod=*) \ + echo " ($$cmd)"; eval $$cmd;; \ + *) pa="$(DESTDIR)$$dest"/`echo "$$cmd"|sed '$(strip_leading_dirs)'|sed '$(transform)'`; \ + if test -n "$$chown"; then \ + echo chown "$$chown" "$$pa"; \ + chown "$$chown" "$$pa" || exit 1; \ + fi; \ + if test -n "$$chmod"; then \ + echo chmod "$$chmod" "$$pa"; \ + chmod "$$chmod" "$$pa" || exit 1; \ + fi; \ + esac; \ + done + +install-exec-hook: installperms-exec +install-data-hook: installperms-data +endif diff --git a/config/automake/precompile.am b/config/automake/precompile.am new file mode 100644 index 0000000..36444d9 --- /dev/null +++ b/config/automake/precompile.am @@ -0,0 +1,11 @@ +# vim:ft=automake + +# A rule to make precompiler output from C files. This is not used during +# ordinary builds, but but can very useful in debugging problems on strange +# architectures. With this rule, we can ask users to 'make foo.i' and send +# the result to us. +# +# It touches some automake internals ($COMPILE), but since it's not +# build-critical, that's OK. +%.i : %.c + $(COMPILE) -E -o $@ $< diff --git a/config/automake/scripts.am b/config/automake/scripts.am new file mode 100644 index 0000000..129df49 --- /dev/null +++ b/config/automake/scripts.am @@ -0,0 +1,141 @@ +# vim:ft=automake +# Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License version 2.1 as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +# SYNOPSIS: +# +# Automake magic to handle the various tasks of building scripts. Scripts can +# be built down to extensionless executables (e.g., foo.pl -> foo), or to +# files with the usual extension (foo-lib.sh.in -> foo.sh). +# +# Files which support it are syntax-checked when the user invokes 'make check'. +# +# All *target* filenames must be listed in SCRIPTS_SHELL, SCRIPTS_PERL, and +# SCRIPTS_AWK to support 'make check', 'make dist', and 'make distclean'. +# +# USAGE: +# +# include $(top_srcdir)/config/automake/vars.am +# include $(top_srcdir)/config/automake/scripts.am +# ... +# SCRIPTS_PERL = fooscript barscript perl-lib.pl perlmod.pm +# SCRIPTS_SHELL = shell1 shell2 sh-lib.sh +# SCRIPTS_AWK = talk balk chalk awk-lib.awk +# +# with the corresponding files in the repository: +# +# fooscript.pl barscript.pl perl-lib.pl.in perlmod.pm.in +# shell1.sh shell2.sh sh-lib.sh.in +# talk.awk balk.awk chalk.awk awk-lib.awk.in +# +# by default, all shell and perl scripts are syntax checked. If this is +# a problem (for example, perl scripts depending on Amanda extension +# modules), then assign to CHECK_{PERL,SHELL} the list of files you wish +# to be checked (which can be empty). +# +# To add extra flags to the perl checks (e.g., to add new -I flags), set +# CHECK_PERL_FLAGS. + +# Implementation note: +# +# This file uses config.status to substitute @foo@ in those scripts while +# converting them. It also adds the executable bits (a+x) to extensionless +# files. The substitution works even though the files are not listed in +# configure.in + +# Perl +%: %.pl $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + chmod a+x $@ + +%.pl: %.pl.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +%.pm: %.pm.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +# Shell +%: %.sh $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + chmod a+x $@ + +%.sh: %.sh.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +# Awk +%: %.awk $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + chmod a+x $@ + +%.awk: %.awk.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +# config.status leaves config.log files around +CLEANFILES += config.log + +# and we'll need to clean up our generated files for distclean +DISTCLEANFILES += $(SCRIPTS_SHELL) $(SCRIPTS_PERL) $(SCRIPTS_AWK) + +# syntax-check perl scripts on 'make check' +check-perl: $(CHECK_PERL) + @CHECK_PERL="$(CHECK_PERL)"; \ + if test -n "$(PERL)"; then \ + for perlobj in $$CHECK_PERL; do \ + $(PERL) $(CHECK_PERL_FLAGS) -c -w -T $$perlobj || exit 1; \ + done; \ + fi +check-local: check-perl + +# syntax-check shell scripts on 'make check' +CHECK_SHELL = $(SCRIPTS_SHELL) +check-shell: $(CHECK_SHELL) + @CHECK_SHELL="$(CHECK_SHELL)"; \ + if test -n "$$CHECK_SHELL"; then \ + if test -n "$(BASH)"; then \ + for shobj in $$CHECK_SHELL; do \ + if $(BASH) -n $$shobj; then \ + echo "$$shobj syntax OK"; \ + else \ + echo "$$shobj syntax error"; \ + exit 1; \ + fi; \ + done; \ + else \ + echo "No 'bash' available -- cannot syntax-check shell scripts"; \ + fi; \ + fi +check-local: check-shell + +# make sure that the sources for all shell and perl scripts get included +# in the distribution +dist-scripts: + SCRIPTS_PERL="$(SCRIPTS_PERL)"; SCRIPTS_SHELL="$(SCRIPTS_SHELL)"; SCRIPTS_AWK="$(SCRIPTS_AWK)"; \ + for script in $$SCRIPTS_PERL; do \ + test -f $(srcdir)/$${script}.pl && { cp -p $(srcdir)/$${script}.pl $(distdir)/ || exit 1; } \ + done; \ + for script in $$SCRIPTS_SHELL; do \ + test -f $(srcdir)/$${script}.sh && { cp -p $(srcdir)/$${script}.sh $(distdir)/ || exit 1; } \ + done; \ + for script in $$SCRIPTS_AWK; do \ + test -f $(srcdir)/$${script}.awk && { cp -p $(srcdir)/$${script}.awk $(distdir)/ || exit 1; } \ + done; \ + for script in $$SCRIPTS_SHELL $$SCRIPTS_PERL $$SCRIPTS_AWK; do \ + test -f $(srcdir)/$${script}.in && { cp -p $(srcdir)/$${script}.in $(distdir)/ || exit 1; } \ + done; \ + true +dist-hook: dist-scripts diff --git a/config/automake/vars.am b/config/automake/vars.am new file mode 100644 index 0000000..88aa8a8 --- /dev/null +++ b/config/automake/vars.am @@ -0,0 +1,32 @@ +# vim:ft=automake +# Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License version 2.1 as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +# simple include file to pre-define variables which are then +='d by other +# scripts in this directory. + +SUFFIXES = + +EXTRA_DIST = + +BUILT_SOURCES = + +MOSTLYCLEANFILES = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = diff --git a/config/compile b/config/compile new file mode 100644 index 0000000..80b645b --- /dev/null +++ b/config/compile @@ -0,0 +1,140 @@ +#! /bin/sh +# Wrapper for compilers which do not understand `-c -o'. + +scriptversion=2004-09-10.20 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand `-c -o'. +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file `INSTALL'. + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "compile $scriptversion" + exit 0 + ;; +esac + +ofile= +cfile= +eat= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we strip `-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no `-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # `.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` + +# Create the lock directory. +# Note: use `[/.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + mv "$cofile" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/config/gettext-macros/codeset.m4 b/config/gettext-macros/codeset.m4 new file mode 100644 index 0000000..a6e67ec --- /dev/null +++ b/config/gettext-macros/codeset.m4 @@ -0,0 +1,21 @@ +# codeset.m4 serial AM1 (gettext-0.10.40) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, + [AC_TRY_LINK([#include ], + [char* cs = nl_langinfo(CODESET);], + am_cv_langinfo_codeset=yes, + am_cv_langinfo_codeset=no) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE(HAVE_LANGINFO_CODESET, 1, + [Define if you have and nl_langinfo(CODESET).]) + fi +]) diff --git a/config/gettext-macros/file-list b/config/gettext-macros/file-list new file mode 100644 index 0000000..60ef11b --- /dev/null +++ b/config/gettext-macros/file-list @@ -0,0 +1,30 @@ +## this file is automatically generated by autogen +EXTRA_DIST += gettext-macros/codeset.m4 +EXTRA_DIST += gettext-macros/gettext.m4 +EXTRA_DIST += gettext-macros/glibc21.m4 +EXTRA_DIST += gettext-macros/glibc2.m4 +EXTRA_DIST += gettext-macros/iconv.m4 +EXTRA_DIST += gettext-macros/intdiv0.m4 +EXTRA_DIST += gettext-macros/intmax.m4 +EXTRA_DIST += gettext-macros/inttypes_h.m4 +EXTRA_DIST += gettext-macros/inttypes.m4 +EXTRA_DIST += gettext-macros/inttypes-pri.m4 +EXTRA_DIST += gettext-macros/isc-posix.m4 +EXTRA_DIST += gettext-macros/lcmessage.m4 +EXTRA_DIST += gettext-macros/lib-ld.m4 +EXTRA_DIST += gettext-macros/lib-link.m4 +EXTRA_DIST += gettext-macros/lib-prefix.m4 +EXTRA_DIST += gettext-macros/longdouble.m4 +EXTRA_DIST += gettext-macros/longlong.m4 +EXTRA_DIST += gettext-macros/nls.m4 +EXTRA_DIST += gettext-macros/po.m4 +EXTRA_DIST += gettext-macros/printf-posix.m4 +EXTRA_DIST += gettext-macros/progtest.m4 +EXTRA_DIST += gettext-macros/signed.m4 +EXTRA_DIST += gettext-macros/size_max.m4 +EXTRA_DIST += gettext-macros/stdint_h.m4 +EXTRA_DIST += gettext-macros/uintmax_t.m4 +EXTRA_DIST += gettext-macros/ulonglong.m4 +EXTRA_DIST += gettext-macros/wchar_t.m4 +EXTRA_DIST += gettext-macros/wint_t.m4 +EXTRA_DIST += gettext-macros/xsize.m4 diff --git a/config/gettext-macros/gettext.m4 b/config/gettext-macros/gettext.m4 new file mode 100644 index 0000000..fdcaecc --- /dev/null +++ b/config/gettext-macros/gettext.m4 @@ -0,0 +1,631 @@ +# gettext.m4 serial 53 (gettext-0.15) +dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2005. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value `$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], ifelse([$1], [external], [no], [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if test "$gt_cv_func_gnugettext_libc" != "yes"; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + dnl Add a version number to the cache macros. + define([gt_api_version], ifelse([$2], [need-formatstring-macros], 3, ifelse([$2], [need-ngettext], 2, 1))) + define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc]) + define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl]) + + AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, + [AC_TRY_LINK([#include +]ifelse([$2], [need-formatstring-macros], +[[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +]], [])[extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings;], + [bindtextdomain ("", ""); +return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_domain_bindings], + gt_cv_func_gnugettext_libc=yes, + gt_cv_func_gnugettext_libc=no)]) + + if test "$gt_cv_func_gnugettext_libc" != "yes"; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + gt_cv_func_gnugettext_libintl, + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_TRY_LINK([#include +]ifelse([$2], [need-formatstring-macros], +[[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +]], [])[extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *);], + [bindtextdomain ("", ""); +return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], + gt_cv_func_gnugettext_libintl=yes, + gt_cv_func_gnugettext_libintl=no) + dnl Now see whether libintl exists and depends on libiconv. + if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include +]ifelse([$2], [need-formatstring-macros], +[[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +]], [])[extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *);], + [bindtextdomain ("", ""); +return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + gt_cv_func_gnugettext_libintl=yes + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if test "$gt_cv_func_gnugettext_libc" = "yes" \ + || { test "$gt_cv_func_gnugettext_libintl" = "yes" \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE(ENABLE_NLS, 1, + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if test "$gt_cv_func_gnugettext_libintl" = "yes"; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if test "$gt_cv_func_gnugettext_libintl" = "yes"; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE(HAVE_GETTEXT, 1, + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE(HAVE_DCGETTEXT, 1, + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST(BUILD_INCLUDED_LIBINTL) + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATOBJEXT) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST(DATADIRNAME) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST(INSTOBJEXT) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST(GENCAT) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST(INTLOBJS) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST(INTLLIBS) + + dnl Make all documented variables known to autoconf. + AC_SUBST(LIBINTL) + AC_SUBST(LTLIBINTL) + AC_SUBST(POSUB) +]) + + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([gt_GLIBC2])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([gl_VISIBILITY])dnl + AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl + AC_REQUIRE([bh_C_SIGNED])dnl + AC_REQUIRE([gl_AC_TYPE_LONG_LONG])dnl + AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([gl_GLIBC21])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gt_INTL_MACOSX])dnl + + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) + AC_CHECK_FUNCS([asprintf fwprintf putenv setenv setlocale snprintf wcslen]) + + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + gt_CHECK_DECL(_snprintf, [#include ]) + gt_CHECK_DECL(_snwprintf, [#include ]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(getc_unlocked, [#include ]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + + AM_LANGINFO_CODESET + gt_LC_MESSAGES + + dnl Compilation on mingw and Cygwin needs special Makefile rules, because + dnl 1. when we install a shared library, we must arrange to export + dnl auxiliary pointer variables for every exported variable, + dnl 2. when we install a shared library and a static library simultaneously, + dnl the include file specifies __declspec(dllimport) and therefore we + dnl must arrange to define the auxiliary pointer variables for the + dnl exported variables _also_ in the static library. + if test "$enable_shared" = yes; then + case "$host_os" in + cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + AC_SUBST([WOE32DLL]) + + dnl Rename some macros and functions used for locking. + AH_BOTTOM([ +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init libintl_lock_init +#define glthread_lock_lock libintl_lock_lock +#define glthread_lock_unlock libintl_lock_unlock +#define glthread_lock_destroy libintl_lock_destroy +#define glthread_rwlock_init libintl_rwlock_init +#define glthread_rwlock_rdlock libintl_rwlock_rdlock +#define glthread_rwlock_wrlock libintl_rwlock_wrlock +#define glthread_rwlock_unlock libintl_rwlock_unlock +#define glthread_rwlock_destroy libintl_rwlock_destroy +#define glthread_recursive_lock_init libintl_recursive_lock_init +#define glthread_recursive_lock_lock libintl_recursive_lock_lock +#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock +#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy +#define glthread_once libintl_once +#define glthread_once_call libintl_once_call +#define glthread_once_singlethreaded libintl_once_singlethreaded +]) +]) + + +dnl Checks for the core files of the intl subdirectory: +dnl dcigettext.c +dnl eval-plural.h +dnl explodename.c +dnl finddomain.c +dnl gettextP.h +dnl gmo.h +dnl hash-string.h hash-string.c +dnl l10nflist.c +dnl libgnuintl.h.in (except the *printf stuff) +dnl loadinfo.h +dnl loadmsgcat.c +dnl localealias.c +dnl log.c +dnl plural-exp.h plural-exp.c +dnl plural.y +dnl Used by libglocale. +AC_DEFUN([gt_INTL_SUBDIR_CORE], +[ + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_LOCK])dnl + + AC_TRY_LINK( + [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], + [], + [AC_DEFINE([HAVE_BUILTIN_EXPECT], 1, + [Define to 1 if the compiler understands __builtin_expect.])]) + + AC_CHECK_HEADERS([argz.h limits.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \ + argz_next __fsetlocking]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(feof_unlocked, [#include ]) + gt_CHECK_DECL(fgets_unlocked, [#include ]) + + AM_ICONV + + dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined, + dnl and a _NL_LOCALE_NAME macro always. + AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name, + [AC_TRY_LINK([#include +#include ], + [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES));], + gt_cv_nl_locale_name=yes, + gt_cv_nl_locale_name=no) + ]) + if test $gt_cv_nl_locale_name = yes; then + AC_DEFINE(HAVE_NL_LOCALE_NAME, 1, + [Define if you have and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.]) + fi + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + + +dnl Checks for special options needed on MacOS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in MacOS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + gt_cv_func_CFPreferencesCopyAppValue, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], + [CFPreferencesCopyAppValue(NULL, NULL)], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, + [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in MacOS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, + [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) + + +dnl gt_CHECK_DECL(FUNC, INCLUDES) +dnl Check whether a function is declared. +AC_DEFUN([gt_CHECK_DECL], +[ + AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, + [AC_TRY_COMPILE([$2], [ +#ifndef $1 + char *p = (char *) $1; +#endif +], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) + if test $ac_cv_have_decl_$1 = yes; then + gt_value=1 + else + gt_value=0 + fi + AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) diff --git a/config/gettext-macros/glibc2.m4 b/config/gettext-macros/glibc2.m4 new file mode 100644 index 0000000..e8f5bfe --- /dev/null +++ b/config/gettext-macros/glibc2.m4 @@ -0,0 +1,30 @@ +# glibc2.m4 serial 1 +dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.0 or newer. +# From Bruno Haible. + +AC_DEFUN([gt_GLIBC2], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer, + ac_cv_gnu_library_2, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2=yes, + ac_cv_gnu_library_2=no) + ] + ) + AC_SUBST(GLIBC2) + GLIBC2="$ac_cv_gnu_library_2" + ] +) diff --git a/config/gettext-macros/glibc21.m4 b/config/gettext-macros/glibc21.m4 new file mode 100644 index 0000000..d95fd98 --- /dev/null +++ b/config/gettext-macros/glibc21.m4 @@ -0,0 +1,30 @@ +# glibc21.m4 serial 3 +dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([gl_GLIBC21], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, + ac_cv_gnu_library_2_1, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2_1=yes, + ac_cv_gnu_library_2_1=no) + ] + ) + AC_SUBST(GLIBC21) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/config/gettext-macros/iconv.m4 b/config/gettext-macros/iconv.m4 new file mode 100644 index 0000000..654c415 --- /dev/null +++ b/config/gettext-macros/iconv.m4 @@ -0,0 +1,101 @@ +# iconv.m4 serial AM4 (gettext-0.11.3) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_func_iconv=yes) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_lib_iconv=yes + am_cv_func_iconv=yes) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST(LIBICONV) + AC_SUBST(LTLIBICONV) +]) + +AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL(am_cv_proto_iconv, [ + AC_TRY_COMPILE([ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif +], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([$]{ac_t:- + }[$]am_cv_proto_iconv) + AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, + [Define as const if the declaration of iconv() needs const.]) + fi +]) diff --git a/config/gettext-macros/intdiv0.m4 b/config/gettext-macros/intdiv0.m4 new file mode 100644 index 0000000..b8d7817 --- /dev/null +++ b/config/gettext-macros/intdiv0.m4 @@ -0,0 +1,70 @@ +# intdiv0.m4 serial 1 (gettext-0.11.3) +dnl Copyright (C) 2002 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + AC_TRY_RUN([ +#include +#include + +static void +#ifdef __cplusplus +sigfpe_handler (int sig) +#else +sigfpe_handler (sig) int sig; +#endif +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} +], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no, + [ + # Guess based on the CPU. + case "$host_cpu" in + alpha* | i[34567]86 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac + ]) + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value, + [Define if integer division by zero raises signal SIGFPE.]) +]) diff --git a/config/gettext-macros/intmax.m4 b/config/gettext-macros/intmax.m4 new file mode 100644 index 0000000..d99c999 --- /dev/null +++ b/config/gettext-macros/intmax.m4 @@ -0,0 +1,30 @@ +# intmax.m4 serial 2 (gettext-0.14.2) +dnl Copyright (C) 2002-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, + [AC_TRY_COMPILE([ +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif +], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE(HAVE_INTMAX_T, 1, + [Define if you have the 'intmax_t' type in or .]) + fi +]) diff --git a/config/gettext-macros/inttypes-pri.m4 b/config/gettext-macros/inttypes-pri.m4 new file mode 100644 index 0000000..a3df331 --- /dev/null +++ b/config/gettext-macros/inttypes-pri.m4 @@ -0,0 +1,30 @@ +# inttypes-pri.m4 serial 2 (gettext-0.15) +dnl Copyright (C) 1997-2002, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +# Define PRI_MACROS_BROKEN if exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + if test $gl_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + gt_cv_inttypes_pri_broken, + [ + AC_TRY_COMPILE([#include +#ifdef PRId32 +char *p = PRId32; +#endif +], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1, + [Define if exists and defines unusable PRI* macros.]) + fi +]) diff --git a/config/gettext-macros/inttypes.m4 b/config/gettext-macros/inttypes.m4 new file mode 100644 index 0000000..779bcea --- /dev/null +++ b/config/gettext-macros/inttypes.m4 @@ -0,0 +1,25 @@ +# inttypes.m4 serial 1 (gettext-0.11.4) +dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H if exists and doesn't clash with +# . + +AC_DEFUN([gt_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h, + [ + AC_TRY_COMPILE( + [#include +#include ], + [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no) + ]) + if test $gt_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, + [Define if exists and doesn't clash with .]) + fi +]) diff --git a/config/gettext-macros/inttypes_h.m4 b/config/gettext-macros/inttypes_h.m4 new file mode 100644 index 0000000..a5d075d --- /dev/null +++ b/config/gettext-macros/inttypes_h.m4 @@ -0,0 +1,26 @@ +# inttypes_h.m4 serial 6 +dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1;], + gl_cv_header_inttypes_h=yes, + gl_cv_header_inttypes_h=no)]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/config/gettext-macros/isc-posix.m4 b/config/gettext-macros/isc-posix.m4 new file mode 100644 index 0000000..74dc8f2 --- /dev/null +++ b/config/gettext-macros/isc-posix.m4 @@ -0,0 +1,24 @@ +# isc-posix.m4 serial 2 (gettext-0.11.2) +dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# This file is not needed with autoconf-2.53 and newer. Remove it in 2005. + +# This test replaces the one in autoconf. +# Currently this macro should have the same name as the autoconf macro +# because gettext's gettext.m4 (distributed in the automake package) +# still uses it. Otherwise, the use in gettext.m4 makes autoheader +# give these diagnostics: +# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX +# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX + +undefine([AC_ISC_POSIX]) + +AC_DEFUN([AC_ISC_POSIX], + [ + dnl This test replaces the obsolescent AC_ISC_POSIX kludge. + AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) + ] +) diff --git a/config/gettext-macros/lcmessage.m4 b/config/gettext-macros/lcmessage.m4 new file mode 100644 index 0000000..19aa77e --- /dev/null +++ b/config/gettext-macros/lcmessage.m4 @@ -0,0 +1,30 @@ +# lcmessage.m4 serial 4 (gettext-0.14.2) +dnl Copyright (C) 1995-2002, 2004-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995. + +# Check whether LC_MESSAGES is available in . + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], gt_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + gt_cv_val_LC_MESSAGES=yes, gt_cv_val_LC_MESSAGES=no)]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi +]) diff --git a/config/gettext-macros/lib-ld.m4 b/config/gettext-macros/lib-ld.m4 new file mode 100644 index 0000000..96c4e2c --- /dev/null +++ b/config/gettext-macros/lib-ld.m4 @@ -0,0 +1,110 @@ +# lib-ld.m4 serial 3 (gettext-0.13) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision +dnl with libtool.m4. + +dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]* | [A-Za-z]:[\\/]*)] + [re_direlt='/[^/][^/]*/\.\./'] + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(acl_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) diff --git a/config/gettext-macros/lib-link.m4 b/config/gettext-macros/lib-link.m4 new file mode 100644 index 0000000..9292919 --- /dev/null +++ b/config/gettext-macros/lib-link.m4 @@ -0,0 +1,630 @@ +# lib-link.m4 serial 8 (gettext-0.15) +dnl Copyright (C) 2001-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ(2.50) + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + undefine([Name]) + undefine([NAME]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. If found, it +dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and +dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIB[]NAME" + AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + undefine([Name]) + undefine([NAME]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, +dnl hardcode_direct, hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + dnl Tell automake >= 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + libext="$acl_cv_libext" + shlibext="$acl_cv_shlibext" + hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + hardcode_direct="$acl_cv_hardcode_direct" + hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE(rpath, + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib$1-prefix], +[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib + --without-lib$1-prefix don't search for lib$1 in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + done + dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/config/gettext-macros/lib-prefix.m4 b/config/gettext-macros/lib-prefix.m4 new file mode 100644 index 0000000..a8684e1 --- /dev/null +++ b/config/gettext-macros/lib-prefix.m4 @@ -0,0 +1,185 @@ +# lib-prefix.m4 serial 5 (gettext-0.15) +dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing +dnl the basename of the libdir, either "lib" or "lib64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. The current + dnl practice is that on a system supporting 32-bit and 64-bit instruction + dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit + dnl libraries go under $prefix/lib. We determine the compiler's default + dnl mode by looking at the compiler's library search path. If at least + dnl of its elements ends in /lib64 or points to a directory whose absolute + dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the + dnl default, namely "lib". + acl_libdirstem=lib + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi +]) diff --git a/config/gettext-macros/longdouble.m4 b/config/gettext-macros/longdouble.m4 new file mode 100644 index 0000000..25590f4 --- /dev/null +++ b/config/gettext-macros/longdouble.m4 @@ -0,0 +1,31 @@ +# longdouble.m4 serial 2 (gettext-0.15) +dnl Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the compiler supports the 'long double' type. +dnl Prerequisite: AC_PROG_CC + +dnl This file is only needed in autoconf <= 2.59. Newer versions of autoconf +dnl have a macro AC_TYPE_LONG_DOUBLE with identical semantics. + +AC_DEFUN([gt_TYPE_LONGDOUBLE], +[ + AC_CACHE_CHECK([for long double], gt_cv_c_long_double, + [if test "$GCC" = yes; then + gt_cv_c_long_double=yes + else + AC_TRY_COMPILE([ + /* The Stardent Vistra knows sizeof(long double), but does not support it. */ + long double foo = 0.0; + /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ + int array [2*(sizeof(long double) >= sizeof(double)) - 1]; + ], , + gt_cv_c_long_double=yes, gt_cv_c_long_double=no) + fi]) + if test $gt_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.]) + fi +]) diff --git a/config/gettext-macros/longlong.m4 b/config/gettext-macros/longlong.m4 new file mode 100644 index 0000000..7b399e0 --- /dev/null +++ b/config/gettext-macros/longlong.m4 @@ -0,0 +1,23 @@ +# longlong.m4 serial 5 +dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG if 'long long' works. + +AC_DEFUN([gl_AC_TYPE_LONG_LONG], +[ + AC_CACHE_CHECK([for long long], ac_cv_type_long_long, + [AC_TRY_LINK([long long ll = 1LL; int i = 63;], + [long long llmax = (long long) -1; + return ll << i | ll >> i | llmax / ll | llmax % ll;], + ac_cv_type_long_long=yes, + ac_cv_type_long_long=no)]) + if test $ac_cv_type_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, + [Define if you have the 'long long' type.]) + fi +]) diff --git a/config/gettext-macros/nls.m4 b/config/gettext-macros/nls.m4 new file mode 100644 index 0000000..7967cc2 --- /dev/null +++ b/config/gettext-macros/nls.m4 @@ -0,0 +1,31 @@ +# nls.m4 serial 3 (gettext-0.15) +dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ(2.50) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) +]) diff --git a/config/gettext-macros/po.m4 b/config/gettext-macros/po.m4 new file mode 100644 index 0000000..00133ef --- /dev/null +++ b/config/gettext-macros/po.m4 @@ -0,0 +1,428 @@ +# po.m4 serial 13 (gettext-0.15) +dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ(2.50) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AM_NLS])dnl + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" < +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, + [ + AC_EGREP_CPP(notposix, [ +#if defined __NetBSD__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], gt_cv_func_printf_posix="guessing no", + gt_cv_func_printf_posix="guessing yes") + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE(HAVE_POSIX_PRINTF, 1, + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) diff --git a/config/gettext-macros/progtest.m4 b/config/gettext-macros/progtest.m4 new file mode 100644 index 0000000..a56365c --- /dev/null +++ b/config/gettext-macros/progtest.m4 @@ -0,0 +1,92 @@ +# progtest.m4 serial 4 (gettext-0.14.2) +dnl Copyright (C) 1996-2003, 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1996. + +AC_PREREQ(2.50) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) diff --git a/config/gettext-macros/signed.m4 b/config/gettext-macros/signed.m4 new file mode 100644 index 0000000..048f593 --- /dev/null +++ b/config/gettext-macros/signed.m4 @@ -0,0 +1,17 @@ +# signed.m4 serial 1 (gettext-0.10.40) +dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([bh_C_SIGNED], +[ + AC_CACHE_CHECK([for signed], bh_cv_c_signed, + [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)]) + if test $bh_cv_c_signed = no; then + AC_DEFINE(signed, , + [Define to empty if the C compiler doesn't support this keyword.]) + fi +]) diff --git a/config/gettext-macros/size_max.m4 b/config/gettext-macros/size_max.m4 new file mode 100644 index 0000000..029e471 --- /dev/null +++ b/config/gettext-macros/size_max.m4 @@ -0,0 +1,60 @@ +# size_max.m4 serial 4 +dnl Copyright (C) 2003, 2005-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS(stdint.h) + dnl First test whether the system already has SIZE_MAX. + AC_MSG_CHECKING([for SIZE_MAX]) + result= + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], result=yes) + if test -z "$result"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + _AC_COMPUTE_INT([sizeof (size_t) * CHAR_BIT - 1], size_t_bits_minus_1, + [#include +#include ], size_t_bits_minus_1=) + _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, + [#include ], fits_in_uint=) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_TRY_COMPILE([#include + extern size_t foo; + extern unsigned long foo; + ], [], fits_in_uint=0) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + result="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + result="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + result='((size_t)~(size_t)0)' + fi + fi + AC_MSG_RESULT([$result]) + if test "$result" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$result], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi +]) diff --git a/config/gettext-macros/stdint_h.m4 b/config/gettext-macros/stdint_h.m4 new file mode 100644 index 0000000..3355f35 --- /dev/null +++ b/config/gettext-macros/stdint_h.m4 @@ -0,0 +1,26 @@ +# stdint_h.m4 serial 5 +dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1;], + gl_cv_header_stdint_h=yes, + gl_cv_header_stdint_h=no)]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/config/gettext-macros/uintmax_t.m4 b/config/gettext-macros/uintmax_t.m4 new file mode 100644 index 0000000..bf83ed7 --- /dev/null +++ b/config/gettext-macros/uintmax_t.m4 @@ -0,0 +1,30 @@ +# uintmax_t.m4 serial 9 +dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ(2.13) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in or . + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([gl_AC_TYPE_UNSIGNED_LONG_LONG]) + test $ac_cv_type_unsigned_long_long = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, + [Define to unsigned long or unsigned long long + if and don't define.]) + else + AC_DEFINE(HAVE_UINTMAX_T, 1, + [Define if you have the 'uintmax_t' type in or .]) + fi +]) diff --git a/config/gettext-macros/ulonglong.m4 b/config/gettext-macros/ulonglong.m4 new file mode 100644 index 0000000..dee10cc --- /dev/null +++ b/config/gettext-macros/ulonglong.m4 @@ -0,0 +1,23 @@ +# ulonglong.m4 serial 4 +dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_UNSIGNED_LONG_LONG if 'unsigned long long' works. + +AC_DEFUN([gl_AC_TYPE_UNSIGNED_LONG_LONG], +[ + AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long, + [AC_TRY_LINK([unsigned long long ull = 1ULL; int i = 63;], + [unsigned long long ullmax = (unsigned long long) -1; + return ull << i | ull >> i | ullmax / ull | ullmax % ull;], + ac_cv_type_unsigned_long_long=yes, + ac_cv_type_unsigned_long_long=no)]) + if test $ac_cv_type_unsigned_long_long = yes; then + AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, + [Define if you have the 'unsigned long long' type.]) + fi +]) diff --git a/config/gettext-macros/wchar_t.m4 b/config/gettext-macros/wchar_t.m4 new file mode 100644 index 0000000..cde2129 --- /dev/null +++ b/config/gettext-macros/wchar_t.m4 @@ -0,0 +1,20 @@ +# wchar_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, + [AC_TRY_COMPILE([#include + wchar_t foo = (wchar_t)'\0';], , + gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/config/gettext-macros/wint_t.m4 b/config/gettext-macros/wint_t.m4 new file mode 100644 index 0000000..b8fff9c --- /dev/null +++ b/config/gettext-macros/wint_t.m4 @@ -0,0 +1,20 @@ +# wint_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, + [AC_TRY_COMPILE([#include + wint_t foo = (wchar_t)'\0';], , + gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/config/gettext-macros/xsize.m4 b/config/gettext-macros/xsize.m4 new file mode 100644 index 0000000..85bb721 --- /dev/null +++ b/config/gettext-macros/xsize.m4 @@ -0,0 +1,13 @@ +# xsize.m4 serial 3 +dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_REQUIRE([AC_C_INLINE]) + AC_CHECK_HEADERS(stdint.h) +]) diff --git a/config/gnulib/base64.m4 b/config/gnulib/base64.m4 new file mode 100644 index 0000000..24801ef --- /dev/null +++ b/config/gnulib/base64.m4 @@ -0,0 +1,16 @@ +# base64.m4 serial 3 +dnl Copyright (C) 2004, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_BASE64], +[ + gl_PREREQ_BASE64 +]) + +# Prerequisites of lib/base64.c. +AC_DEFUN([gl_PREREQ_BASE64], [ + AC_REQUIRE([AC_C_INLINE]) + AC_REQUIRE([AC_C_RESTRICT]) +]) diff --git a/config/gnulib/file-list b/config/gnulib/file-list new file mode 100644 index 0000000..f2c14fc --- /dev/null +++ b/config/gnulib/file-list @@ -0,0 +1,55 @@ +## this file is automatically generated by autogen +EXTRA_DIST += gnulib/absolute-header.m4 +EXTRA_DIST += gnulib/alloca.m4 +EXTRA_DIST += gnulib/arpa_inet_h.m4 +EXTRA_DIST += gnulib/base64.m4 +EXTRA_DIST += gnulib/eoverflow.m4 +EXTRA_DIST += gnulib/extensions.m4 +EXTRA_DIST += gnulib/float_h.m4 +EXTRA_DIST += gnulib/fsusage.m4 +EXTRA_DIST += gnulib/getaddrinfo.m4 +EXTRA_DIST += gnulib/gettimeofday.m4 +EXTRA_DIST += gnulib/gnulib-cache.m4 +EXTRA_DIST += gnulib/gnulib-common.m4 +EXTRA_DIST += gnulib/gnulib-comp.m4 +EXTRA_DIST += gnulib/gnulib-tool.m4 +EXTRA_DIST += gnulib/include_next.m4 +EXTRA_DIST += gnulib/inet_ntop.m4 +EXTRA_DIST += gnulib/intmax_t.m4 +EXTRA_DIST += gnulib/inttypes_h.m4 +EXTRA_DIST += gnulib/lib-ld.m4 +EXTRA_DIST += gnulib/lib-link.m4 +EXTRA_DIST += gnulib/lib-prefix.m4 +EXTRA_DIST += gnulib/lock.m4 +EXTRA_DIST += gnulib/longlong.m4 +EXTRA_DIST += gnulib/malloc.m4 +EXTRA_DIST += gnulib/mkdtemp.m4 +EXTRA_DIST += gnulib/netinet_in_h.m4 +EXTRA_DIST += gnulib/onceonly_2_57.m4 +EXTRA_DIST += gnulib/physmem.m4 +EXTRA_DIST += gnulib/safe-read.m4 +EXTRA_DIST += gnulib/safe-write.m4 +EXTRA_DIST += gnulib/size_max.m4 +EXTRA_DIST += gnulib/snprintf.m4 +EXTRA_DIST += gnulib/socklen.m4 +EXTRA_DIST += gnulib/sockpfaf.m4 +EXTRA_DIST += gnulib/ssize_t.m4 +EXTRA_DIST += gnulib/stdbool.m4 +EXTRA_DIST += gnulib/stdint_h.m4 +EXTRA_DIST += gnulib/stdint.m4 +EXTRA_DIST += gnulib/stdio_h.m4 +EXTRA_DIST += gnulib/stdlib_h.m4 +EXTRA_DIST += gnulib/strdup.m4 +EXTRA_DIST += gnulib/string_h.m4 +EXTRA_DIST += gnulib/sys_socket_h.m4 +EXTRA_DIST += gnulib/sys_stat_h.m4 +EXTRA_DIST += gnulib/sys_time_h.m4 +EXTRA_DIST += gnulib/tempname.m4 +EXTRA_DIST += gnulib/ulonglong.m4 +EXTRA_DIST += gnulib/unistd_h.m4 +EXTRA_DIST += gnulib/vasnprintf.m4 +EXTRA_DIST += gnulib/visibility.m4 +EXTRA_DIST += gnulib/wchar.m4 +EXTRA_DIST += gnulib/wchar_t.m4 +EXTRA_DIST += gnulib/wint_t.m4 +EXTRA_DIST += gnulib/xsize.m4 diff --git a/config/gnulib/float_h.m4 b/config/gnulib/float_h.m4 new file mode 100644 index 0000000..1b1ad10 --- /dev/null +++ b/config/gnulib/float_h.m4 @@ -0,0 +1,19 @@ +# float_h.m4 serial 2 +dnl Copyright (C) 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FLOAT_H], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + FLOAT_H= + case "$host_os" in + beos*) + FLOAT_H=float.h + gl_CHECK_NEXT_HEADERS([float.h]) + ;; + esac + AC_SUBST([FLOAT_H]) +]) diff --git a/config/gnulib/fsusage.m4 b/config/gnulib/fsusage.m4 new file mode 100644 index 0000000..18eedbc --- /dev/null +++ b/config/gnulib/fsusage.m4 @@ -0,0 +1,269 @@ +#serial 23 +# Obtaining file system usage information. + +# Copyright (C) 1997, 1998, 2000, 2001, 2003-2007 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Written by Jim Meyering. + +AC_DEFUN([gl_FSUSAGE], +[ + AC_CHECK_HEADERS_ONCE(sys/param.h) + AC_CHECK_HEADERS_ONCE(sys/vfs.h sys/fs_types.h) + AC_CHECK_HEADERS(sys/mount.h, [], [], + [AC_INCLUDES_DEFAULT + [#if HAVE_SYS_PARAM_H + #include + #endif]]) + gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=yes], [gl_cv_fs_space=no]) + if test $gl_cv_fs_space = yes; then + AC_LIBOBJ(fsusage) + gl_PREREQ_FSUSAGE_EXTRA + fi +]) + +# Try to determine how a program can obtain file system usage information. +# If successful, define the appropriate symbol (see fsusage.c) and +# execute ACTION-IF-FOUND. Otherwise, execute ACTION-IF-NOT-FOUND. +# +# gl_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([gl_FILE_SYSTEM_USAGE], +[ + +AC_MSG_NOTICE([checking how to get file system space usage]) +ac_fsusage_space=no + +# Perform only the link test since it seems there are no variants of the +# statvfs function. This check is more than just AC_CHECK_FUNCS(statvfs) +# because that got a false positive on SCO OSR5. Adding the declaration +# of a `struct statvfs' causes this test to fail (as it should) on such +# systems. That system is reported to work fine with STAT_STATFS4 which +# is what it gets when this test fails. +if test $ac_fsusage_space = no; then + # SVR4 + AC_CACHE_CHECK([for statvfs function (SVR4)], fu_cv_sys_stat_statvfs, + [AC_TRY_LINK([#include +#if defined __GLIBC__ && !defined __BEOS__ +Do not use statvfs on systems with GNU libc, because that function stats +all preceding entries in /proc/mounts, and that makes df hang if even +one of the corresponding file systems is hard-mounted, but not available. +statvfs in GNU libc on BeOS operates differently: it only makes a system +call. +#endif + +#ifdef __osf__ +"Do not use Tru64's statvfs implementation" +#endif + +#include ], + [struct statvfs fsd; statvfs (0, &fsd);], + fu_cv_sys_stat_statvfs=yes, + fu_cv_sys_stat_statvfs=no)]) + if test $fu_cv_sys_stat_statvfs = yes; then + ac_fsusage_space=yes + AC_DEFINE(STAT_STATVFS, 1, + [ Define if there is a function named statvfs. (SVR4)]) + fi +fi + +if test $ac_fsusage_space = no; then + # DEC Alpha running OSF/1 + AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs3_osf1, + [AC_TRY_RUN([ +#include +#include +#include + int + main () + { + struct statfs fsd; + fsd.f_fsize = 0; + return statfs (".", &fsd, sizeof (struct statfs)) != 0; + }], + fu_cv_sys_stat_statfs3_osf1=yes, + fu_cv_sys_stat_statfs3_osf1=no, + fu_cv_sys_stat_statfs3_osf1=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1) + if test $fu_cv_sys_stat_statfs3_osf1 = yes; then + ac_fsusage_space=yes + AC_DEFINE(STAT_STATFS3_OSF1, 1, + [ Define if statfs takes 3 args. (DEC Alpha running OSF/1)]) + fi +fi + +if test $ac_fsusage_space = no; then +# AIX + AC_MSG_CHECKING([for two-argument statfs with statfs.bsize dnl +member (AIX, 4.3BSD)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs2_bsize, + [AC_TRY_RUN([ +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_VFS_H +#include +#endif + int + main () + { + struct statfs fsd; + fsd.f_bsize = 0; + return statfs (".", &fsd) != 0; + }], + fu_cv_sys_stat_statfs2_bsize=yes, + fu_cv_sys_stat_statfs2_bsize=no, + fu_cv_sys_stat_statfs2_bsize=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs2_bsize) + if test $fu_cv_sys_stat_statfs2_bsize = yes; then + ac_fsusage_space=yes + AC_DEFINE(STAT_STATFS2_BSIZE, 1, +[ Define if statfs takes 2 args and struct statfs has a field named f_bsize. + (4.3BSD, SunOS 4, HP-UX, AIX PS/2)]) + fi +fi + +if test $ac_fsusage_space = no; then +# SVR3 + AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs4, + [AC_TRY_RUN([#include +#include + int + main () + { + struct statfs fsd; + return statfs (".", &fsd, sizeof fsd, 0) != 0; + }], + fu_cv_sys_stat_statfs4=yes, + fu_cv_sys_stat_statfs4=no, + fu_cv_sys_stat_statfs4=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs4) + if test $fu_cv_sys_stat_statfs4 = yes; then + ac_fsusage_space=yes + AC_DEFINE(STAT_STATFS4, 1, + [ Define if statfs takes 4 args. (SVR3, Dynix, Irix, Dolphin)]) + fi +fi + +if test $ac_fsusage_space = no; then +# 4.4BSD and NetBSD + AC_MSG_CHECKING([for two-argument statfs with statfs.fsize dnl +member (4.4BSD and NetBSD)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs2_fsize, + [AC_TRY_RUN([#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + int + main () + { + struct statfs fsd; + fsd.f_fsize = 0; + return statfs (".", &fsd) != 0; + }], + fu_cv_sys_stat_statfs2_fsize=yes, + fu_cv_sys_stat_statfs2_fsize=no, + fu_cv_sys_stat_statfs2_fsize=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs2_fsize) + if test $fu_cv_sys_stat_statfs2_fsize = yes; then + ac_fsusage_space=yes + AC_DEFINE(STAT_STATFS2_FSIZE, 1, +[ Define if statfs takes 2 args and struct statfs has a field named f_fsize. + (4.4BSD, NetBSD)]) + fi +fi + +if test $ac_fsusage_space = no; then + # Ultrix + AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)]) + AC_CACHE_VAL(fu_cv_sys_stat_fs_data, + [AC_TRY_RUN([#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_FS_TYPES_H +#include +#endif + int + main () + { + struct fs_data fsd; + /* Ultrix's statfs returns 1 for success, + 0 for not mounted, -1 for failure. */ + return statfs (".", &fsd) != 1; + }], + fu_cv_sys_stat_fs_data=yes, + fu_cv_sys_stat_fs_data=no, + fu_cv_sys_stat_fs_data=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_fs_data) + if test $fu_cv_sys_stat_fs_data = yes; then + ac_fsusage_space=yes + AC_DEFINE(STAT_STATFS2_FS_DATA, 1, +[ Define if statfs takes 2 args and the second argument has + type struct fs_data. (Ultrix)]) + fi +fi + +if test $ac_fsusage_space = no; then + # SVR2 + AC_TRY_CPP([#include + ], + AC_DEFINE(STAT_READ_FILSYS, 1, + [Define if there is no specific function for reading file systems usage + information and you have the header file. (SVR2)]) + ac_fsusage_space=yes) +fi + +AS_IF([test $ac_fsusage_space = yes], [$1], [$2]) + +]) + + +# Check for SunOS statfs brokenness wrt partitions 2GB and larger. +# If exists and struct statfs has a member named f_spare, +# enable the work-around code in fsusage.c. +AC_DEFUN([gl_STATFS_TRUNCATES], +[ + AC_MSG_CHECKING([for statfs that truncates block counts]) + AC_CACHE_VAL(fu_cv_sys_truncating_statfs, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if !defined(sun) && !defined(__sun) +choke -- this is a workaround for a Sun-specific problem +#endif +#include +#include ]], + [[struct statfs t; long c = *(t.f_spare); + if (c) return 0;]])], + [fu_cv_sys_truncating_statfs=yes], + [fu_cv_sys_truncating_statfs=no])]) + if test $fu_cv_sys_truncating_statfs = yes; then + AC_DEFINE(STATFS_TRUNCATES_BLOCK_COUNTS, 1, + [Define if the block counts reported by statfs may be truncated to 2GB + and the correct values may be stored in the f_spare array. + (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem. + SunOS 4.1.1 seems not to be affected.)]) + fi + AC_MSG_RESULT($fu_cv_sys_truncating_statfs) +]) + + +# Prerequisites of lib/fsusage.c not done by gl_FILE_SYSTEM_USAGE. +AC_DEFUN([gl_PREREQ_FSUSAGE_EXTRA], +[ + AC_CHECK_HEADERS(dustat.h sys/fs/s5param.h sys/filsys.h sys/statfs.h) + gl_STATFS_TRUNCATES +]) diff --git a/config/gnulib/gettimeofday.m4 b/config/gnulib/gettimeofday.m4 new file mode 100644 index 0000000..b9bbb10 --- /dev/null +++ b/config/gnulib/gettimeofday.m4 @@ -0,0 +1,101 @@ +#serial 11 + +# Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +dnl From Jim Meyering. + +AC_DEFUN([gl_FUNC_GETTIMEOFDAY], +[ + AC_REQUIRE([AC_C_RESTRICT]) + AC_REQUIRE([gl_HEADER_SYS_TIME_H]) + AC_CHECK_FUNCS_ONCE([gettimeofday]) + + AC_CACHE_CHECK([for gettimeofday with POSIX signature], + [gl_cv_func_gettimeofday_posix_signature], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + struct timeval c; + ]], + [[ + int (*f) (struct timeval *restrict, void *restrict) = gettimeofday; + int x = f (&c, 0); + return !(x | c.tv_sec | c.tv_usec); + ]])], + [gl_cv_func_gettimeofday_posix_signature=yes], + [gl_cv_func_gettimeofday_posix_signature=no])]) + + gl_FUNC_GETTIMEOFDAY_CLOBBER + + if test $gl_cv_func_gettimeofday_posix_signature != yes; then + REPLACE_GETTIMEOFDAY=1 + SYS_TIME_H=sys/time.h + if test $gl_cv_func_gettimeofday_clobber != yes; then + AC_LIBOBJ(gettimeofday) + gl_PREREQ_GETTIMEOFDAY + fi + fi +]) + + +dnl See if gettimeofday clobbers the static buffer that localtime uses +dnl for its return value. The gettimeofday function from Mac OS X 10.0.4 +dnl (i.e., Darwin 1.3.7) has this problem. +dnl +dnl If it does, then arrange to use gettimeofday and localtime only via +dnl the wrapper functions that work around the problem. + +AC_DEFUN([gl_FUNC_GETTIMEOFDAY_CLOBBER], +[ + AC_REQUIRE([gl_HEADER_SYS_TIME_H]) + + AC_CACHE_CHECK([whether gettimeofday clobbers localtime buffer], + [gl_cv_func_gettimeofday_clobber], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + ]], + [[ + time_t t = 0; + struct tm *lt; + struct tm saved_lt; + struct timeval tv; + lt = localtime (&t); + saved_lt = *lt; + gettimeofday (&tv, NULL); + return memcmp (lt, &saved_lt, sizeof (struct tm)) != 0; + ]])], + [gl_cv_func_gettimeofday_clobber=no], + [gl_cv_func_gettimeofday_clobber=yes], + dnl When crosscompiling, assume it is broken. + [gl_cv_func_gettimeofday_clobber=yes])]) + + if test $gl_cv_func_gettimeofday_clobber = yes; then + REPLACE_GETTIMEOFDAY=1 + SYS_TIME_H=sys/time.h + gl_GETTIMEOFDAY_REPLACE_LOCALTIME + AC_DEFINE([GETTIMEOFDAY_CLOBBERS_LOCALTIME], 1, + [Define if gettimeofday clobbers the localtime buffer.]) + fi +]) + +AC_DEFUN([gl_GETTIMEOFDAY_REPLACE_LOCALTIME], [ + AC_LIBOBJ(gettimeofday) + gl_PREREQ_GETTIMEOFDAY + AC_DEFINE([gmtime], [rpl_gmtime], + [Define to rpl_gmtime if the replacement function should be used.]) + AC_DEFINE([localtime], [rpl_localtime], + [Define to rpl_localtime if the replacement function should be used.]) +]) + +# Prerequisites of lib/gettimeofday.c. +AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [ + AC_CHECK_HEADERS([sys/timeb.h]) + AC_CHECK_FUNCS([_ftime]) +]) diff --git a/config/gnulib/include_next.m4 b/config/gnulib/include_next.m4 new file mode 100644 index 0000000..7ce472b --- /dev/null +++ b/config/gnulib/include_next.m4 @@ -0,0 +1,107 @@ +# include_next.m4 serial 4 +dnl Copyright (C) 2006, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert and Derek Price. + +AC_DEFUN([gl_INCLUDE_NEXT], +[ + AC_LANG_PREPROC_REQUIRE() + AC_CACHE_CHECK([whether the preprocessor supports include_next], + [gl_cv_have_include_next], + [rm -rf conftestd1 conftestd2 + mkdir conftestd1 conftestd2 + cat < conftestd1/conftest.h +#define DEFINED_IN_CONFTESTD1 +#include_next +#ifdef DEFINED_IN_CONFTESTD2 +int foo; +#else +#error "include_next doesn't work" +#endif +EOF + cat < conftestd2/conftest.h +#ifndef DEFINED_IN_CONFTESTD1 +#error "include_next test doesn't work" +#endif +#define DEFINED_IN_CONFTESTD2 +EOF + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -Iconftestd1 -Iconftestd2" + AC_COMPILE_IFELSE([#include ], + [gl_cv_have_include_next=yes], + [gl_cv_have_include_next=no]) + CPPFLAGS="$save_CPPFLAGS" + rm -rf conftestd1 conftestd2 + ]) + if test $gl_cv_have_include_next = yes; then + + dnl FIXME: Remove HAVE_INCLUDE_NEXT and update everything that uses it + dnl to use @INCLUDE_NEXT@ instead. + AC_DEFINE([HAVE_INCLUDE_NEXT], 1, + [Define if your compiler supports the #include_next directive.]) + + INCLUDE_NEXT=include_next + else + INCLUDE_NEXT=include + fi + AC_SUBST([INCLUDE_NEXT]) +]) + +# gl_CHECK_NEXT_HEADERS(HEADER1 HEADER2 ...) +# ------------------------------------------ +# For each arg foo.h, if #include_next works, define NEXT_FOO_H to be +# ''; otherwise define it to be +# '"///usr/include/foo.h"', or whatever other absolute file name is suitable. +# That way, a header file with the following line: +# #@INCLUDE_NEXT@ @NEXT_FOO_H@ +# behaves (after sed substitution) as if it contained +# #include_next +# even if the compiler does not support include_next. +# The three "///" are to pacify Sun C 5.8, which otherwise would say +# "warning: #include of /usr/include/... may be non-portable". +# Use `""', not `<>', so that the /// cannot be confused with a C99 comment. +AC_DEFUN([gl_CHECK_NEXT_HEADERS], +[ + AC_REQUIRE([gl_INCLUDE_NEXT]) + AC_CHECK_HEADERS_ONCE([$1]) + + AC_FOREACH([gl_HEADER_NAME], [$1], + [AS_VAR_PUSHDEF([gl_next_header], + [gl_cv_next_]m4_quote(m4_defn([gl_HEADER_NAME]))) + if test $gl_cv_have_include_next = yes; then + AS_VAR_SET([gl_next_header], ['<'gl_HEADER_NAME'>']) + else + AC_CACHE_CHECK( + [absolute name of <]m4_quote(m4_defn([gl_HEADER_NAME]))[>], + m4_quote(m4_defn([gl_next_header])), + [AS_VAR_PUSHDEF([gl_header_exists], + [ac_cv_header_]m4_quote(m4_defn([gl_HEADER_NAME]))) + if test AS_VAR_GET(gl_header_exists) = yes; then + AC_LANG_CONFTEST( + [AC_LANG_SOURCE( + [[#include <]]m4_dquote(m4_defn([gl_HEADER_NAME]))[[>]] + )]) + dnl eval is necessary to expand ac_cpp. + dnl Ultrix and Pyramid sh refuse to redirect output of eval, + dnl so use subshell. + AS_VAR_SET([gl_next_header], + ['"'`(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + sed -n '\#/]m4_quote(m4_defn([gl_HEADER_NAME]))[#{ + s#.*"\(.*/]m4_quote(m4_defn([gl_HEADER_NAME]))[\)".*#\1# + s#^/[^/]#//&# + p + q + }'`'"']) + else + AS_VAR_SET([gl_next_header], ['<'gl_HEADER_NAME'>']) + fi + AS_VAR_POPDEF([gl_header_exists])]) + fi + AC_SUBST( + AS_TR_CPP([NEXT_]m4_quote(m4_defn([gl_HEADER_NAME]))), + [AS_VAR_GET([gl_next_header])]) + AS_VAR_POPDEF([gl_next_header])]) +]) diff --git a/config/gnulib/malloc.m4 b/config/gnulib/malloc.m4 new file mode 100644 index 0000000..764f2a9 --- /dev/null +++ b/config/gnulib/malloc.m4 @@ -0,0 +1,41 @@ +# malloc.m4 serial 8 +dnl Copyright (C) 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# gl_FUNC_MALLOC_POSIX +# -------------------- +# Test whether 'malloc' is POSIX compliant (sets errno to ENOMEM when it +# fails), and replace malloc if it is not. +AC_DEFUN([gl_FUNC_MALLOC_POSIX], +[ + AC_REQUIRE([gl_CHECK_MALLOC_POSIX]) + if test $gl_cv_func_malloc_posix = yes; then + HAVE_MALLOC_POSIX=1 + AC_DEFINE([HAVE_MALLOC_POSIX], 1, + [Define if the 'malloc' function is POSIX compliant.]) + else + AC_LIBOBJ([malloc]) + HAVE_MALLOC_POSIX=0 + fi + AC_SUBST([HAVE_MALLOC_POSIX]) +]) + +# Test whether malloc, realloc, calloc are POSIX compliant, +# Set gl_cv_func_malloc_posix to yes or no accordingly. +AC_DEFUN([gl_CHECK_MALLOC_POSIX], +[ + AC_CACHE_CHECK([whether malloc, realloc, calloc are POSIX compliant], + [gl_cv_func_malloc_posix], + [ + dnl It is too dangerous to try to allocate a large amount of memory: + dnl some systems go to their knees when you do that. So assume that + dnl all Unix implementations of the function are POSIX compliant. + AC_TRY_COMPILE([], + [#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + choke me + #endif + ], [gl_cv_func_malloc_posix=yes], [gl_cv_func_malloc_posix=no]) + ]) +]) diff --git a/config/gnulib/mkdtemp.m4 b/config/gnulib/mkdtemp.m4 new file mode 100644 index 0000000..0eeafbc --- /dev/null +++ b/config/gnulib/mkdtemp.m4 @@ -0,0 +1,20 @@ +# mkdtemp.m4 serial 5 +dnl Copyright (C) 2001-2003, 2006-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gt_FUNC_MKDTEMP], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + AC_REPLACE_FUNCS(mkdtemp) + if test $ac_cv_func_mkdtemp = no; then + HAVE_MKDTEMP=0 + gl_PREREQ_MKDTEMP + fi +]) + +# Prerequisites of lib/mkdtemp.c +AC_DEFUN([gl_PREREQ_MKDTEMP], +[: +]) diff --git a/config/gnulib/physmem.m4 b/config/gnulib/physmem.m4 new file mode 100644 index 0000000..456bb37 --- /dev/null +++ b/config/gnulib/physmem.m4 @@ -0,0 +1,39 @@ +# physmem.m4 serial 7 +dnl Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Check for the external symbol, _system_configuration, +# a struct with member `physmem'. +AC_DEFUN([gl_SYS__SYSTEM_CONFIGURATION], + [AC_CACHE_CHECK(for external symbol _system_configuration, + gl_cv_var__system_configuration, + [AC_LINK_IFELSE([AC_LANG_PROGRAM( + [[#include + ]], + [double x = _system_configuration.physmem; + if (x > 0.0) return 0;])], + [gl_cv_var__system_configuration=yes], + [gl_cv_var__system_configuration=no])]) + + if test $gl_cv_var__system_configuration = yes; then + AC_DEFINE(HAVE__SYSTEM_CONFIGURATION, 1, + [Define to 1 if you have the external variable, + _system_configuration with a member named physmem.]) + fi + ] +) + +AC_DEFUN([gl_PHYSMEM], +[ + AC_LIBOBJ([physmem]) + + # Prerequisites of lib/physmem.c. + AC_CHECK_HEADERS([sys/pstat.h sys/sysmp.h sys/sysinfo.h \ + machine/hal_sysinfo.h sys/table.h sys/param.h sys/sysctl.h \ + sys/systemcfg.h],,, [AC_INCLUDES_DEFAULT]) + + AC_CHECK_FUNCS(pstat_getstatic pstat_getdynamic sysmp getsysinfo sysctl table) + AC_REQUIRE([gl_SYS__SYSTEM_CONFIGURATION]) +]) diff --git a/config/gnulib/safe-read.m4 b/config/gnulib/safe-read.m4 new file mode 100644 index 0000000..7a89d0a --- /dev/null +++ b/config/gnulib/safe-read.m4 @@ -0,0 +1,18 @@ +# safe-read.m4 serial 5 +dnl Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_SAFE_READ], +[ + AC_LIBOBJ([safe-read]) + + gl_PREREQ_SAFE_READ +]) + +# Prerequisites of lib/safe-read.c. +AC_DEFUN([gl_PREREQ_SAFE_READ], +[ + AC_REQUIRE([gt_TYPE_SSIZE_T]) +]) diff --git a/config/gnulib/safe-write.m4 b/config/gnulib/safe-write.m4 new file mode 100644 index 0000000..db119ff --- /dev/null +++ b/config/gnulib/safe-write.m4 @@ -0,0 +1,18 @@ +# safe-write.m4 serial 3 +dnl Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_SAFE_WRITE], +[ + AC_LIBOBJ([safe-write]) + + gl_PREREQ_SAFE_WRITE +]) + +# Prerequisites of lib/safe-write.c. +AC_DEFUN([gl_PREREQ_SAFE_WRITE], +[ + gl_PREREQ_SAFE_READ +]) diff --git a/config/gnulib/ssize_t.m4 b/config/gnulib/ssize_t.m4 new file mode 100644 index 0000000..4eaef93 --- /dev/null +++ b/config/gnulib/ssize_t.m4 @@ -0,0 +1,21 @@ +# ssize_t.m4 serial 4 (gettext-0.15) +dnl Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether ssize_t is defined. + +AC_DEFUN([gt_TYPE_SSIZE_T], +[ + AC_CACHE_CHECK([for ssize_t], [gt_cv_ssize_t], + [AC_TRY_COMPILE([#include ], + [int x = sizeof (ssize_t *) + sizeof (ssize_t); + return !x;], + [gt_cv_ssize_t=yes], [gt_cv_ssize_t=no])]) + if test $gt_cv_ssize_t = no; then + AC_DEFINE([ssize_t], [int], + [Define as a signed type of the same size as size_t.]) + fi +]) diff --git a/config/gnulib/stdint.m4 b/config/gnulib/stdint.m4 new file mode 100644 index 0000000..03bb093 --- /dev/null +++ b/config/gnulib/stdint.m4 @@ -0,0 +1,395 @@ +# stdint.m4 serial 28 +dnl Copyright (C) 2001-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert and Bruno Haible. +dnl Test whether is supported or must be substituted. + +AC_DEFUN([gl_STDINT_H], +[ + AC_PREREQ(2.59)dnl + + dnl Check for long long int and unsigned long long int. + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + if test $ac_cv_type_long_long_int = yes; then + HAVE_LONG_LONG_INT=1 + else + HAVE_LONG_LONG_INT=0 + fi + AC_SUBST([HAVE_LONG_LONG_INT]) + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + HAVE_UNSIGNED_LONG_LONG_INT=1 + else + HAVE_UNSIGNED_LONG_LONG_INT=0 + fi + AC_SUBST([HAVE_UNSIGNED_LONG_LONG_INT]) + + dnl Check for . + dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_inttypes_h. + if test $ac_cv_header_inttypes_h = yes; then + HAVE_INTTYPES_H=1 + else + HAVE_INTTYPES_H=0 + fi + AC_SUBST([HAVE_INTTYPES_H]) + + dnl Check for . + dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_sys_types_h. + if test $ac_cv_header_sys_types_h = yes; then + HAVE_SYS_TYPES_H=1 + else + HAVE_SYS_TYPES_H=0 + fi + AC_SUBST([HAVE_SYS_TYPES_H]) + + gl_CHECK_NEXT_HEADERS([stdint.h]) + if test $ac_cv_header_stdint_h = yes; then + HAVE_STDINT_H=1 + else + HAVE_STDINT_H=0 + fi + AC_SUBST([HAVE_STDINT_H]) + + dnl Now see whether we need a substitute . + if test $ac_cv_header_stdint_h = yes; then + AC_CACHE_CHECK([whether stdint.h conforms to C99], + [gl_cv_header_working_stdint_h], + [gl_cv_header_working_stdint_h=no + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */ +#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */ +#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */ +#include +/* Dragonfly defines WCHAR_MIN, WCHAR_MAX only in . */ +#if !(defined WCHAR_MIN && defined WCHAR_MAX) +#error "WCHAR_MIN, WCHAR_MAX not defined in " +#endif +] +gl_STDINT_INCLUDES +[ +#ifdef INT8_MAX +int8_t a1 = INT8_MAX; +int8_t a1min = INT8_MIN; +#endif +#ifdef INT16_MAX +int16_t a2 = INT16_MAX; +int16_t a2min = INT16_MIN; +#endif +#ifdef INT32_MAX +int32_t a3 = INT32_MAX; +int32_t a3min = INT32_MIN; +#endif +#ifdef INT64_MAX +int64_t a4 = INT64_MAX; +int64_t a4min = INT64_MIN; +#endif +#ifdef UINT8_MAX +uint8_t b1 = UINT8_MAX; +#else +typedef int b1[(unsigned char) -1 != 255 ? 1 : -1]; +#endif +#ifdef UINT16_MAX +uint16_t b2 = UINT16_MAX; +#endif +#ifdef UINT32_MAX +uint32_t b3 = UINT32_MAX; +#endif +#ifdef UINT64_MAX +uint64_t b4 = UINT64_MAX; +#endif +int_least8_t c1 = INT8_C (0x7f); +int_least8_t c1max = INT_LEAST8_MAX; +int_least8_t c1min = INT_LEAST8_MIN; +int_least16_t c2 = INT16_C (0x7fff); +int_least16_t c2max = INT_LEAST16_MAX; +int_least16_t c2min = INT_LEAST16_MIN; +int_least32_t c3 = INT32_C (0x7fffffff); +int_least32_t c3max = INT_LEAST32_MAX; +int_least32_t c3min = INT_LEAST32_MIN; +int_least64_t c4 = INT64_C (0x7fffffffffffffff); +int_least64_t c4max = INT_LEAST64_MAX; +int_least64_t c4min = INT_LEAST64_MIN; +uint_least8_t d1 = UINT8_C (0xff); +uint_least8_t d1max = UINT_LEAST8_MAX; +uint_least16_t d2 = UINT16_C (0xffff); +uint_least16_t d2max = UINT_LEAST16_MAX; +uint_least32_t d3 = UINT32_C (0xffffffff); +uint_least32_t d3max = UINT_LEAST32_MAX; +uint_least64_t d4 = UINT64_C (0xffffffffffffffff); +uint_least64_t d4max = UINT_LEAST64_MAX; +int_fast8_t e1 = INT_FAST8_MAX; +int_fast8_t e1min = INT_FAST8_MIN; +int_fast16_t e2 = INT_FAST16_MAX; +int_fast16_t e2min = INT_FAST16_MIN; +int_fast32_t e3 = INT_FAST32_MAX; +int_fast32_t e3min = INT_FAST32_MIN; +int_fast64_t e4 = INT_FAST64_MAX; +int_fast64_t e4min = INT_FAST64_MIN; +uint_fast8_t f1 = UINT_FAST8_MAX; +uint_fast16_t f2 = UINT_FAST16_MAX; +uint_fast32_t f3 = UINT_FAST32_MAX; +uint_fast64_t f4 = UINT_FAST64_MAX; +#ifdef INTPTR_MAX +intptr_t g = INTPTR_MAX; +intptr_t gmin = INTPTR_MIN; +#endif +#ifdef UINTPTR_MAX +uintptr_t h = UINTPTR_MAX; +#endif +intmax_t i = INTMAX_MAX; +uintmax_t j = UINTMAX_MAX; + +#include /* for CHAR_BIT */ +#define TYPE_MINIMUM(t) \ + ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) +#define TYPE_MAXIMUM(t) \ + ((t) ((t) 0 < (t) -1 ? (t) -1 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) +struct s { + int check_PTRDIFF: + PTRDIFF_MIN == TYPE_MINIMUM (ptrdiff_t) + && PTRDIFF_MAX == TYPE_MAXIMUM (ptrdiff_t) + ? 1 : -1; + /* Detect bug in FreeBSD 6.0 / ia64. */ + int check_SIG_ATOMIC: + SIG_ATOMIC_MIN == TYPE_MINIMUM (sig_atomic_t) + && SIG_ATOMIC_MAX == TYPE_MAXIMUM (sig_atomic_t) + ? 1 : -1; + int check_SIZE: SIZE_MAX == TYPE_MAXIMUM (size_t) ? 1 : -1; + int check_WCHAR: + WCHAR_MIN == TYPE_MINIMUM (wchar_t) + && WCHAR_MAX == TYPE_MAXIMUM (wchar_t) + ? 1 : -1; + /* Detect bug in mingw. */ + int check_WINT: + WINT_MIN == TYPE_MINIMUM (wint_t) + && WINT_MAX == TYPE_MAXIMUM (wint_t) + ? 1 : -1; + + /* Detect bugs in glibc 2.4 and Solaris 10 stdint.h, among others. */ + int check_UINT8_C: + (-1 < UINT8_C (0)) == (-1 < (uint_least8_t) 0) ? 1 : -1; + int check_UINT16_C: + (-1 < UINT16_C (0)) == (-1 < (uint_least16_t) 0) ? 1 : -1; + + /* Detect bugs in OpenBSD 3.9 stdint.h. */ +#ifdef UINT8_MAX + int check_uint8: (uint8_t) -1 == UINT8_MAX ? 1 : -1; +#endif +#ifdef UINT16_MAX + int check_uint16: (uint16_t) -1 == UINT16_MAX ? 1 : -1; +#endif +#ifdef UINT32_MAX + int check_uint32: (uint32_t) -1 == UINT32_MAX ? 1 : -1; +#endif +#ifdef UINT64_MAX + int check_uint64: (uint64_t) -1 == UINT64_MAX ? 1 : -1; +#endif + int check_uint_least8: (uint_least8_t) -1 == UINT_LEAST8_MAX ? 1 : -1; + int check_uint_least16: (uint_least16_t) -1 == UINT_LEAST16_MAX ? 1 : -1; + int check_uint_least32: (uint_least32_t) -1 == UINT_LEAST32_MAX ? 1 : -1; + int check_uint_least64: (uint_least64_t) -1 == UINT_LEAST64_MAX ? 1 : -1; + int check_uint_fast8: (uint_fast8_t) -1 == UINT_FAST8_MAX ? 1 : -1; + int check_uint_fast16: (uint_fast16_t) -1 == UINT_FAST16_MAX ? 1 : -1; + int check_uint_fast32: (uint_fast32_t) -1 == UINT_FAST32_MAX ? 1 : -1; + int check_uint_fast64: (uint_fast64_t) -1 == UINT_FAST64_MAX ? 1 : -1; + int check_uintptr: (uintptr_t) -1 == UINTPTR_MAX ? 1 : -1; + int check_uintmax: (uintmax_t) -1 == UINTMAX_MAX ? 1 : -1; + int check_size: (size_t) -1 == SIZE_MAX ? 1 : -1; +}; + ]])], + [gl_cv_header_working_stdint_h=yes])]) + fi + if test "$gl_cv_header_working_stdint_h" = yes; then + STDINT_H= + else + dnl Check for , and for + dnl (used in Linux libc4 >= 4.6.7 and libc5). + AC_CHECK_HEADERS([sys/inttypes.h sys/bitypes.h]) + if test $ac_cv_header_sys_inttypes_h = yes; then + HAVE_SYS_INTTYPES_H=1 + else + HAVE_SYS_INTTYPES_H=0 + fi + AC_SUBST([HAVE_SYS_INTTYPES_H]) + if test $ac_cv_header_sys_bitypes_h = yes; then + HAVE_SYS_BITYPES_H=1 + else + HAVE_SYS_BITYPES_H=0 + fi + AC_SUBST([HAVE_SYS_BITYPES_H]) + + dnl Check for (missing in Linux uClibc when built without wide + dnl character support). + AC_CHECK_HEADERS_ONCE([wchar.h]) + + gl_STDINT_TYPE_PROPERTIES + STDINT_H=stdint.h + fi + AC_SUBST(STDINT_H) +]) + +dnl gl_STDINT_BITSIZEOF(TYPES, INCLUDES) +dnl Determine the size of each of the given types in bits. +AC_DEFUN([gl_STDINT_BITSIZEOF], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + AC_FOREACH([gltype], [$1], + [AH_TEMPLATE([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [Define to the number of bits in type ']gltype['.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([for bit size of $gltype], [gl_cv_bitsizeof_${gltype}], + [AC_COMPUTE_INT([result], [sizeof ($gltype) * CHAR_BIT], + [$2 +#include ], [result=unknown]) + eval gl_cv_bitsizeof_${gltype}=\$result + ]) + eval result=\$gl_cv_bitsizeof_${gltype} + if test $result = unknown; then + dnl Use a nonempty default, because some compilers, such as IRIX 5 cc, + dnl do a syntax check even on unused #if conditions and give an error + dnl on valid C code like this: + dnl #if 0 + dnl # if > 32 + dnl # endif + dnl #endif + result=0 + fi + GLTYPE=`echo "$gltype" | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + AC_DEFINE_UNQUOTED([BITSIZEOF_${GLTYPE}], [$result]) + eval BITSIZEOF_${GLTYPE}=\$result + done + AC_FOREACH([gltype], [$1], + [AC_SUBST([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) +]) + +dnl gl_CHECK_TYPES_SIGNED(TYPES, INCLUDES) +dnl Determine the signedness of each of the given types. +dnl Define HAVE_SIGNED_TYPE if type is signed. +AC_DEFUN([gl_CHECK_TYPES_SIGNED], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + AC_FOREACH([gltype], [$1], + [AH_TEMPLATE([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [Define to 1 if ']gltype[' is a signed integer type.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([whether $gltype is signed], [gl_cv_type_${gltype}_signed], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([$2[ + int verify[2 * (($gltype) -1 < ($gltype) 0) - 1];]])], + result=yes, result=no) + eval gl_cv_type_${gltype}_signed=\$result + ]) + eval result=\$gl_cv_type_${gltype}_signed + GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + if test "$result" = yes; then + AC_DEFINE_UNQUOTED([HAVE_SIGNED_${GLTYPE}], 1) + eval HAVE_SIGNED_${GLTYPE}=1 + else + eval HAVE_SIGNED_${GLTYPE}=0 + fi + done + AC_FOREACH([gltype], [$1], + [AC_SUBST([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) +]) + +dnl gl_INTEGER_TYPE_SUFFIX(TYPES, INCLUDES) +dnl Determine the suffix to use for integer constants of the given types. +dnl Define t_SUFFIX for each such type. +AC_DEFUN([gl_INTEGER_TYPE_SUFFIX], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + AC_FOREACH([gltype], [$1], + [AH_TEMPLATE(translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX], + [Define to l, ll, u, ul, ull, etc., as suitable for + constants of type ']gltype['.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([for $gltype integer literal suffix], + [gl_cv_type_${gltype}_suffix], + [eval gl_cv_type_${gltype}_suffix=no + eval result=\$gl_cv_type_${gltype}_signed + if test "$result" = yes; then + glsufu= + else + glsufu=u + fi + for glsuf in "$glsufu" ${glsufu}l ${glsufu}ll ${glsufu}i64; do + case $glsuf in + '') gltype1='int';; + l) gltype1='long int';; + ll) gltype1='long long int';; + i64) gltype1='__int64';; + u) gltype1='unsigned int';; + ul) gltype1='unsigned long int';; + ull) gltype1='unsigned long long int';; + ui64)gltype1='unsigned __int64';; + esac + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([$2 + extern $gltype foo; + extern $gltype1 foo;])], + [eval gl_cv_type_${gltype}_suffix=\$glsuf]) + eval result=\$gl_cv_type_${gltype}_suffix + test "$result" != no && break + done]) + GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + eval result=\$gl_cv_type_${gltype}_suffix + test "$result" = no && result= + eval ${GLTYPE}_SUFFIX=\$result + AC_DEFINE_UNQUOTED([${GLTYPE}_SUFFIX], $result) + done + AC_FOREACH([gltype], [$1], + [AC_SUBST(translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX])]) +]) + +dnl gl_STDINT_INCLUDES +AC_DEFUN([gl_STDINT_INCLUDES], +[[ + /* BSD/OS 4.0.1 has a bug: , and must be + included before . */ + #include + #include + #if HAVE_WCHAR_H + # include + # include + # include + #endif +]]) + +dnl gl_STDINT_TYPE_PROPERTIES +dnl Compute HAVE_SIGNED_t, BITSIZEOF_t and t_SUFFIX, for all the types t +dnl of interest to stdint_.h. +AC_DEFUN([gl_STDINT_TYPE_PROPERTIES], +[ + gl_STDINT_BITSIZEOF([ptrdiff_t sig_atomic_t size_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) + gl_CHECK_TYPES_SIGNED([sig_atomic_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) + gl_cv_type_ptrdiff_t_signed=yes + gl_cv_type_size_t_signed=no + gl_INTEGER_TYPE_SUFFIX([ptrdiff_t sig_atomic_t size_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) + +# Hey Emacs! +# Local Variables: +# indent-tabs-mode: nil +# End: diff --git a/config/gnulib/stdio_h.m4 b/config/gnulib/stdio_h.m4 new file mode 100644 index 0000000..b9a6998 --- /dev/null +++ b/config/gnulib/stdio_h.m4 @@ -0,0 +1,82 @@ +# stdio_h.m4 serial 7 +dnl Copyright (C) 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_STDIO_H], +[ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + gl_CHECK_NEXT_HEADERS([stdio.h]) +]) + +AC_DEFUN([gl_STDIO_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1 +]) + +AC_DEFUN([gl_STDIO_H_DEFAULTS], +[ + GNULIB_FPRINTF_POSIX=0; AC_SUBST([GNULIB_FPRINTF_POSIX]) + GNULIB_PRINTF_POSIX=0; AC_SUBST([GNULIB_PRINTF_POSIX]) + GNULIB_SNPRINTF=0; AC_SUBST([GNULIB_SNPRINTF]) + GNULIB_SPRINTF_POSIX=0; AC_SUBST([GNULIB_SPRINTF_POSIX]) + GNULIB_VFPRINTF_POSIX=0; AC_SUBST([GNULIB_VFPRINTF_POSIX]) + GNULIB_VPRINTF_POSIX=0; AC_SUBST([GNULIB_VPRINTF_POSIX]) + GNULIB_VSNPRINTF=0; AC_SUBST([GNULIB_VSNPRINTF]) + GNULIB_VSPRINTF_POSIX=0; AC_SUBST([GNULIB_VSPRINTF_POSIX]) + GNULIB_VASPRINTF=0; AC_SUBST([GNULIB_VASPRINTF]) + GNULIB_FSEEK=0; AC_SUBST([GNULIB_FSEEK]) + GNULIB_FSEEKO=0; AC_SUBST([GNULIB_FSEEKO]) + GNULIB_FTELL=0; AC_SUBST([GNULIB_FTELL]) + GNULIB_FTELLO=0; AC_SUBST([GNULIB_FTELLO]) + GNULIB_FFLUSH=0; AC_SUBST([GNULIB_FFLUSH]) + GNULIB_GETDELIM=0; AC_SUBST([GNULIB_GETDELIM]) + GNULIB_GETLINE=0; AC_SUBST([GNULIB_GETLINE]) + dnl Assume proper GNU behavior unless another module says otherwise. + REPLACE_FPRINTF=0; AC_SUBST([REPLACE_FPRINTF]) + REPLACE_VFPRINTF=0; AC_SUBST([REPLACE_VFPRINTF]) + REPLACE_PRINTF=0; AC_SUBST([REPLACE_PRINTF]) + REPLACE_VPRINTF=0; AC_SUBST([REPLACE_VPRINTF]) + REPLACE_SNPRINTF=0; AC_SUBST([REPLACE_SNPRINTF]) + HAVE_DECL_SNPRINTF=1; AC_SUBST([HAVE_DECL_SNPRINTF]) + REPLACE_VSNPRINTF=0; AC_SUBST([REPLACE_VSNPRINTF]) + HAVE_DECL_VSNPRINTF=1; AC_SUBST([HAVE_DECL_VSNPRINTF]) + REPLACE_SPRINTF=0; AC_SUBST([REPLACE_SPRINTF]) + REPLACE_VSPRINTF=0; AC_SUBST([REPLACE_VSPRINTF]) + HAVE_VASPRINTF=1; AC_SUBST([HAVE_VASPRINTF]) + REPLACE_VASPRINTF=0; AC_SUBST([REPLACE_VASPRINTF]) + HAVE_FSEEKO=1; AC_SUBST([HAVE_FSEEKO]) + REPLACE_FSEEKO=0; AC_SUBST([REPLACE_FSEEKO]) + REPLACE_FSEEK=0; AC_SUBST([REPLACE_FSEEK]) + HAVE_FTELLO=1; AC_SUBST([HAVE_FTELLO]) + REPLACE_FTELLO=0; AC_SUBST([REPLACE_FTELLO]) + REPLACE_FTELL=0; AC_SUBST([REPLACE_FTELL]) + REPLACE_FFLUSH=0; AC_SUBST([REPLACE_FFLUSH]) + HAVE_DECL_GETDELIM=1; AC_SUBST([HAVE_DECL_GETDELIM]) + HAVE_DECL_GETLINE=1; AC_SUBST([HAVE_DECL_GETLINE]) + REPLACE_GETLINE=0; AC_SUBST([REPLACE_GETLINE]) +]) + +dnl Code shared by fseeko and ftello. Determine if large files are supported, +dnl but stdin does not start as a large file by default. +AC_DEFUN([gl_STDIN_LARGE_OFFSET], + [ + AC_CACHE_CHECK([whether stdin defaults to large file offsets], + [gl_cv_var_stdin_large_offset], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], +[#if defined __SL64 && defined __SCLE /* cygwin */ + /* Cygwin 1.5.24 and earlier fail to put stdin in 64-bit mode, making + fseeko/ftello needlessly fail. This bug was fixed at the same time + that cygwin started exporting asnprintf (cygwin 1.7.0), so we use + that as a link-time test for cross-compiles rather than building + a runtime test. */ + size_t s; + if (asnprintf (NULL, &s, "")) + return 0; +#endif])], + [gl_cv_var_stdin_large_offset=yes], + [gl_cv_var_stdin_large_offset=no])]) +]) diff --git a/config/gnulib/stdlib_h.m4 b/config/gnulib/stdlib_h.m4 new file mode 100644 index 0000000..ea9286e --- /dev/null +++ b/config/gnulib/stdlib_h.m4 @@ -0,0 +1,35 @@ +# stdlib_h.m4 serial 3 +dnl Copyright (C) 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_STDLIB_H], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + gl_CHECK_NEXT_HEADERS([stdlib.h]) +]) + +AC_DEFUN([gl_STDLIB_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1 +]) + +AC_DEFUN([gl_STDLIB_H_DEFAULTS], +[ + GNULIB_MALLOC_POSIX=0; AC_SUBST([GNULIB_MALLOC_POSIX]) + GNULIB_REALLOC_POSIX=0; AC_SUBST([GNULIB_REALLOC_POSIX]) + GNULIB_CALLOC_POSIX=0; AC_SUBST([GNULIB_CALLOC_POSIX]) + GNULIB_GETSUBOPT=0; AC_SUBST([GNULIB_GETSUBOPT]) + GNULIB_MKDTEMP=0; AC_SUBST([GNULIB_MKDTEMP]) + GNULIB_MKSTEMP=0; AC_SUBST([GNULIB_MKSTEMP]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_CALLOC_POSIX=1; AC_SUBST([HAVE_CALLOC_POSIX]) + HAVE_GETSUBOPT=1; AC_SUBST([HAVE_GETSUBOPT]) + HAVE_MALLOC_POSIX=1; AC_SUBST([HAVE_MALLOC_POSIX]) + HAVE_MKDTEMP=1; AC_SUBST([HAVE_MKDTEMP]) + HAVE_REALLOC_POSIX=1; AC_SUBST([HAVE_REALLOC_POSIX]) + REPLACE_MKSTEMP=0; AC_SUBST([REPLACE_MKSTEMP]) +]) diff --git a/config/gnulib/sys_stat_h.m4 b/config/gnulib/sys_stat_h.m4 new file mode 100644 index 0000000..1bc08a1 --- /dev/null +++ b/config/gnulib/sys_stat_h.m4 @@ -0,0 +1,48 @@ +# sys_stat_h.m4 serial 6 -*- Autoconf -*- +dnl Copyright (C) 2006-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Eric Blake. +dnl Test whether contains lstat and mkdir or must be substituted. + +AC_DEFUN([gl_HEADER_SYS_STAT_H], +[ + dnl Check for lstat. Systems that lack it (mingw) also lack symlinks, so + dnl stat is a good replacement. + AC_CHECK_FUNCS_ONCE([lstat]) + if test $ac_cv_func_lstat = yes; then + HAVE_LSTAT=1 + else + HAVE_LSTAT=0 + fi + AC_SUBST([HAVE_LSTAT]) + + dnl Check for mkdir. Mingw has _mkdir(name) in the nonstandard + dnl instead. + AC_CHECK_DECLS([mkdir], + [], + [AC_CHECK_HEADERS([io.h])], + [#include ]) + if test $ac_cv_have_decl_mkdir = yes; then + HAVE_DECL_MKDIR=1 + else + HAVE_DECL_MKDIR=0 + fi + AC_SUBST([HAVE_DECL_MKDIR]) + if test "$ac_cv_header_io_h" = yes; then + HAVE_IO_H=1 + else + HAVE_IO_H=0 + fi + AC_SUBST([HAVE_IO_H]) + AC_REQUIRE([AC_C_INLINE]) + + dnl Check for broken stat macros. + AC_REQUIRE([AC_HEADER_STAT]) + + gl_CHECK_NEXT_HEADERS([sys/stat.h]) + SYS_STAT_H='sys/stat.h' + AC_SUBST([SYS_STAT_H]) +]) # gl_HEADER_SYS_STAT_H diff --git a/config/gnulib/sys_time_h.m4 b/config/gnulib/sys_time_h.m4 new file mode 100644 index 0000000..13ac576 --- /dev/null +++ b/config/gnulib/sys_time_h.m4 @@ -0,0 +1,57 @@ +# Configure a replacement for . + +# Copyright (C) 2007 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Written by Paul Eggert and Martin Lambers. + +AC_DEFUN([gl_HEADER_SYS_TIME_H], +[ + dnl Use AC_REQUIRE here, so that the REPLACE_GETTIMEOFDAY=0 statement + dnl below is expanded once only, before all REPLACE_GETTIMEOFDAY=1 + dnl statements that occur in other macros. + AC_REQUIRE([gl_HEADER_SYS_TIME_H_BODY]) +]) + +AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY], +[ + AC_REQUIRE([AC_C_RESTRICT]) + gl_CHECK_NEXT_HEADERS([sys/time.h]) + + if test $ac_cv_header_sys_time_h = yes; then + HAVE_SYS_TIME_H=1 + else + HAVE_SYS_TIME_H=0 + fi + AC_SUBST([HAVE_SYS_TIME_H]) + + AC_CACHE_CHECK([for struct timeval], [gl_cv_sys_struct_timeval], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#if HAVE_SYS_TIME_H + #include + #endif + #include + ]], + [[static struct timeval x; x.tv_sec = x.tv_usec;]])], + [gl_cv_sys_struct_timeval=yes], + [gl_cv_sys_struct_timeval=no])]) + if test $gl_cv_sys_struct_timeval = yes; then + HAVE_STRUCT_TIMEVAL=1 + else + HAVE_STRUCT_TIMEVAL=0 + fi + AC_SUBST([HAVE_STRUCT_TIMEVAL]) + + dnl Assume POSIX behavior unless another module says otherwise. + REPLACE_GETTIMEOFDAY=0 + AC_SUBST([REPLACE_GETTIMEOFDAY]) + if test $HAVE_SYS_TIME_H = 0 || test $HAVE_STRUCT_TIMEVAL = 0; then + SYS_TIME_H=sys/time.h + else + SYS_TIME_H= + fi + AC_SUBST([SYS_TIME_H]) +]) diff --git a/config/gnulib/tempname.m4 b/config/gnulib/tempname.m4 new file mode 100644 index 0000000..4c44d37 --- /dev/null +++ b/config/gnulib/tempname.m4 @@ -0,0 +1,22 @@ +#serial 3 + +# Copyright (C) 2006-2007 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# glibc provides __gen_tempname as a wrapper for mk[ds]temp. Expose +# it as a public API, and provide it on systems that are lacking. +AC_DEFUN([gl_FUNC_GEN_TEMPNAME], +[ + AC_REQUIRE([AC_SYS_LARGEFILE]) + + AC_LIBOBJ([tempname]) + gl_PREREQ_TEMPNAME +]) + +# Prerequisites of lib/tempname.c. +AC_DEFUN([gl_PREREQ_TEMPNAME], +[ + : +]) diff --git a/config/gnulib/ulonglong.m4 b/config/gnulib/ulonglong.m4 new file mode 100644 index 0000000..9fae98e --- /dev/null +++ b/config/gnulib/ulonglong.m4 @@ -0,0 +1,48 @@ +# ulonglong.m4 serial 6 +dnl Copyright (C) 1999-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.60, but can be removed once we +# assume 2.61 everywhere. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[unsigned long long int ull = 18446744073709551615ULL; + typedef int a[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[unsigned long long int ullmax = 18446744073709551615ull; + return (ull << 63 | ull >> 63 | ull << i | ull >> i + | ullmax / ull | ullmax % ull);]])], + [ac_cv_type_unsigned_long_long_int=yes], + [ac_cv_type_unsigned_long_long_int=no])]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1, + [Define to 1 if the system has the type `unsigned long long int'.]) + fi +]) + +# This macro is obsolescent and should go away soon. +AC_DEFUN([gl_AC_TYPE_UNSIGNED_LONG_LONG], +[ + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + ac_cv_type_unsigned_long_long=$ac_cv_type_unsigned_long_long_int + if test $ac_cv_type_unsigned_long_long = yes; then + AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, + [Define if you have the 'unsigned long long' type.]) + fi +]) diff --git a/config/gnulib/unistd_h.m4 b/config/gnulib/unistd_h.m4 new file mode 100644 index 0000000..b12f84e --- /dev/null +++ b/config/gnulib/unistd_h.m4 @@ -0,0 +1,56 @@ +# unistd_h.m4 serial 9 +dnl Copyright (C) 2006-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Simon Josefsson, Bruno Haible. + +AC_DEFUN([gl_UNISTD_H], +[ + dnl Use AC_REQUIRE here, so that the default behavior below is expanded + dnl once only, before all statements that occur in other macros. + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + + gl_CHECK_NEXT_HEADERS([unistd.h]) + + AC_CHECK_HEADERS_ONCE([unistd.h]) + if test $ac_cv_header_unistd_h = yes; then + HAVE_UNISTD_H=1 + else + HAVE_UNISTD_H=0 + fi + AC_SUBST([HAVE_UNISTD_H]) +]) + +AC_DEFUN([gl_UNISTD_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1 +]) + +AC_DEFUN([gl_UNISTD_H_DEFAULTS], +[ + GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN]) + GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2]) + GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR]) + GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE]) + GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD]) + GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R]) + GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN]) + GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK]) + GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK]) + GNULIB_SLEEP=0; AC_SUBST([GNULIB_SLEEP]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_DUP2=1; AC_SUBST([HAVE_DUP2]) + HAVE_FTRUNCATE=1; AC_SUBST([HAVE_FTRUNCATE]) + HAVE_READLINK=1; AC_SUBST([HAVE_READLINK]) + HAVE_SLEEP=1; AC_SUBST([HAVE_SLEEP]) + HAVE_DECL_GETLOGIN_R=1; AC_SUBST([HAVE_DECL_GETLOGIN_R]) + REPLACE_CHOWN=0; AC_SUBST([REPLACE_CHOWN]) + REPLACE_FCHDIR=0; AC_SUBST([REPLACE_FCHDIR]) + REPLACE_GETCWD=0; AC_SUBST([REPLACE_GETCWD]) + REPLACE_LCHOWN=0; AC_SUBST([REPLACE_LCHOWN]) + REPLACE_LSEEK=0; AC_SUBST([REPLACE_LSEEK]) +]) diff --git a/config/gnulib/wchar.m4 b/config/gnulib/wchar.m4 new file mode 100644 index 0000000..70b1248 --- /dev/null +++ b/config/gnulib/wchar.m4 @@ -0,0 +1,54 @@ +dnl A placeholder for ISO C99 , for platforms that have issues. + +dnl Copyright (C) 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Eric Blake. + +# wchar.m4 serial 4 + +AC_DEFUN([gl_WCHAR_H], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + AC_CACHE_CHECK([whether is standalone], + [gl_cv_header_wchar_h_standalone], + [AC_COMPILE_IFELSE([[#include +wchar_t w;]], + [gl_cv_header_wchar_h_standalone=yes], + [gl_cv_header_wchar_h_standalone=no])]) + if test $gl_cv_header_wchar_h_standalone != yes; then + WCHAR_H=wchar.h + fi + + dnl Prepare for creating substitute . + dnl Do it always: WCHAR_H may be empty here but can be set later. + dnl Check for (missing in Linux uClibc when built without wide + dnl character support). + AC_CHECK_HEADERS_ONCE([wchar.h]) + if test $ac_cv_header_wchar_h = yes; then + HAVE_WCHAR_H=1 + else + HAVE_WCHAR_H=0 + fi + AC_SUBST([HAVE_WCHAR_H]) + gl_CHECK_NEXT_HEADERS([wchar.h]) +]) + +AC_DEFUN([gl_WCHAR_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1 +]) + +AC_DEFUN([gl_WCHAR_H_DEFAULTS], +[ + GNULIB_WCWIDTH=0; AC_SUBST([GNULIB_WCWIDTH]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_DECL_WCWIDTH=1; AC_SUBST([HAVE_DECL_WCWIDTH]) + REPLACE_WCWIDTH=0; AC_SUBST([REPLACE_WCWIDTH]) + WCHAR_H= + AC_SUBST([WCHAR_H]) +]) diff --git a/config/libtool.m4 b/config/libtool.m4 new file mode 100644 index 0000000..285a567 --- /dev/null +++ b/config/libtool.m4 @@ -0,0 +1,6214 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 47 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed >conftest.exp + $SED '/^$/d' conftest.err >conftest.er2 + if test ! -s conftest.err || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed > conftest.exp + $SED '/^$/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# -------------------- +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ------------------------------------------------------------------ +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_unknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed > out/conftest.exp + $SED '/^$/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.err || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AMANDA_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AMANDA_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AMANDA_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AMANDA_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +#- set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/${ac_tool_prefix}nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + esac + fi + done + IFS="$lt_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AMANDA_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# --------------- +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# -------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# +# Check for any special shared library compilation flags. +# +_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= +if test "$GCC" = no; then + case $host_os in + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' + ;; + esac +fi +if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then + AMANDA_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) + if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then : + else + AMANDA_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) + _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no + fi +fi + + +# +# Check to make sure the static flag actually works. +# +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +# Report which librarie types wil actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + ia64*|hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sco*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + if $CC -v --help 2>/dev/null | grep -- -shared > /dev/null 2> /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC ${wl}-G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC ${wl}-G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC ${wl}-G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-Bstatic' + fi + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris* | sysv5*) + symcode='[[BDRT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + sco*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + *) + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + if $CC -v --help 2>/dev/null | grep -- -static > /dev/null 2> /dev/null; then + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + else + # GCC with Sun linker + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-Bstatic' + fi + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + unixware*) + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "x$archive_cmds" = "x"; then + if test "$GCC" = yes; then + wlarc='${wl}' + if $CC -v --help 2>/dev/null | grep -- -shared > /dev/null 2> /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC ${wl}-G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC ${wl}-G ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + fi + else + wlarc='' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + fi + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4.2uw2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv5*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) diff --git a/config/link-warning.h b/config/link-warning.h new file mode 100644 index 0000000..fda0194 --- /dev/null +++ b/config/link-warning.h @@ -0,0 +1,28 @@ +/* GL_LINK_WARNING("literal string") arranges to emit the literal string as + a linker warning on most glibc systems. + We use a linker warning rather than a preprocessor warning, because + #warning cannot be used inside macros. */ +#ifndef GL_LINK_WARNING + /* This works on platforms with GNU ld and ELF object format. + Testing __GLIBC__ is sufficient for asserting that GNU ld is in use. + Testing __ELF__ guarantees the ELF object format. + Testing __GNUC__ is necessary for the compound expression syntax. */ +# if defined __GLIBC__ && defined __ELF__ && defined __GNUC__ +# define GL_LINK_WARNING(message) \ + GL_LINK_WARNING1 (__FILE__, __LINE__, message) +# define GL_LINK_WARNING1(file, line, message) \ + GL_LINK_WARNING2 (file, line, message) /* macroexpand file and line */ +# define GL_LINK_WARNING2(file, line, message) \ + GL_LINK_WARNING3 (file ":" #line ": warning: " message) +# define GL_LINK_WARNING3(message) \ + ({ static const char warning[sizeof (message)] \ + __attribute__ ((__unused__, \ + __section__ (".gnu.warning"), \ + __aligned__ (1))) \ + = message "\n"; \ + (void)0; \ + }) +# else +# define GL_LINK_WARNING(message) ((void) 0) +# endif +#endif diff --git a/config/macro-archive/ac_define_dir.m4 b/config/macro-archive/ac_define_dir.m4 new file mode 100644 index 0000000..f3d8734 --- /dev/null +++ b/config/macro-archive/ac_define_dir.m4 @@ -0,0 +1,47 @@ +##### http://autoconf-archive.cryp.to/ac_define_dir.html +# +# SYNOPSIS +# +# AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION]) +# +# DESCRIPTION +# +# This macro sets VARNAME to the expansion of the DIR variable, +# taking care of fixing up ${prefix} and such. +# +# VARNAME is then offered as both an output variable and a C +# preprocessor symbol. +# +# Example: +# +# AC_DEFINE_DIR([DATADIR], [datadir], [Where data are placed to.]) +# +# LAST MODIFICATION +# +# 2006-10-13 +# +# COPYLEFT +# +# Copyright (c) 2006 Stepan Kasal +# Copyright (c) 2006 Andreas Schwab +# Copyright (c) 2006 Guido U. Draheim +# Copyright (c) 2006 Alexandre Oliva +# +# Copying and distribution of this file, with or without +# modification, are permitted in any medium without royalty provided +# the copyright notice and this notice are preserved. + +AC_DEFUN([AC_DEFINE_DIR], [ + prefix_NONE= + exec_prefix_NONE= + test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix + test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix +dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn +dnl refers to ${prefix}. Thus we have to use `eval' twice. + eval ac_define_dir="\"[$]$2\"" + eval ac_define_dir="\"$ac_define_dir\"" + AC_SUBST($1, "$ac_define_dir") + AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3]) + test "$prefix_NONE" && prefix=NONE + test "$exec_prefix_NONE" && exec_prefix=NONE +]) diff --git a/config/macro-archive/ac_prog_perl_version.m4 b/config/macro-archive/ac_prog_perl_version.m4 new file mode 100644 index 0000000..886765d --- /dev/null +++ b/config/macro-archive/ac_prog_perl_version.m4 @@ -0,0 +1,59 @@ +##### http://autoconf-archive.cryp.to/ac_prog_perl_version.html +# +# SYNOPSIS +# +# AC_PROG_PERL_VERSION(VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# +# DESCRIPTION +# +# Makes sure that perl supports the version indicated. If true the +# shell commands in ACTION-IF-TRUE are executed. If not the shell +# commands in ACTION-IF-FALSE are run. Note if $PERL is not set (for +# example by running AC_CHECK_PROG or AC_PATH_PROG), +# AC_CHECK_PROG(PERL, perl, perl) will be run. +# +# Example: +# +# AC_PROG_PERL_VERSION(5.6.0) +# +# This will check to make sure that the perl you have supports at +# least version 5.6.0. +# +# LAST MODIFICATION +# +# 2002-09-25 +# +# COPYLEFT +# +# Copyright (c) 2002 Dean Povey +# +# Copying and distribution of this file, with or without +# modification, are permitted in any medium without royalty provided +# the copyright notice and this notice are preserved. + +AC_DEFUN([AC_PROG_PERL_VERSION],[dnl +# Make sure we have perl +if test -z "$PERL"; then +AC_CHECK_PROG(PERL,perl,perl) +fi + +# Check if version of Perl is sufficient +ac_perl_version="$1" + +if test "x$PERL" != "x"; then + AC_MSG_CHECKING(for perl version greater than or equal to $ac_perl_version) + # NB: It would be nice to log the error if there is one, but we cannot rely + # on autoconf internals + $PERL -e "use $ac_perl_version;" > /dev/null 2>&1 + if test $? -ne 0; then + AC_MSG_RESULT(no); + $3 + else + AC_MSG_RESULT(ok); + $2 + fi +else + AC_MSG_WARN(could not find perl) +fi +])dnl + diff --git a/config/macro-archive/ac_prog_swig.m4 b/config/macro-archive/ac_prog_swig.m4 new file mode 100644 index 0000000..20520b2 --- /dev/null +++ b/config/macro-archive/ac_prog_swig.m4 @@ -0,0 +1,124 @@ +# Modified by Dustin J. Mitchell, Zmanda, Inc. as follows: +# - remove warnings -- Amanda tarballs ship pre-swigged, so users +# need not be alarmed if they don't have SWIG. +# +##### http://autoconf-archive.cryp.to/ac_pkg_swig.html +# +# SYNOPSIS +# +# AC_PROG_SWIG([major.minor.micro]) +# +# DESCRIPTION +# +# This macro searches for a SWIG installation on your system. If +# found you should call SWIG via $(SWIG). You can use the optional +# first argument to check if the version of the available SWIG is +# greater than or equal to the value of the argument. It should have +# the format: N[.N[.N]] (N is a number between 0 and 999. Only the +# first N is mandatory.) +# +# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks +# that the swig package is this version number or higher. +# +# In configure.in, use as: +# +# AC_PROG_SWIG(1.3.17) +# SWIG_ENABLE_CXX +# SWIG_MULTI_MODULE_SUPPORT +# SWIG_PYTHON +# +# LAST MODIFICATION +# +# 2006-10-22 +# +# COPYLEFT +# +# Copyright (c) 2006 Sebastian Huber +# Copyright (c) 2006 Alan W. Irwin +# Copyright (c) 2006 Rafael Laboissiere +# Copyright (c) 2006 Andrew Collier +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. + +AC_DEFUN([AC_PROG_SWIG],[ + AC_PATH_PROG([SWIG],[swig]) + if test -z "$SWIG" ; then + SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false' + elif test -n "$1" ; then + AC_MSG_CHECKING([for SWIG version]) + [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + # Calculate the required version number components + [required=$1] + [required_major=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_major" ; then + [required_major=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_minor=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_minor" ; then + [required_minor=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_patch=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_patch" ; then + [required_patch=0] + fi + # Calculate the available version number components + [available=$swig_version] + [available_major=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_major" ; then + [available_major=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_minor=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_minor" ; then + [available_minor=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_patch=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_patch" ; then + [available_patch=0] + fi + if test $available_major -ne $required_major \ + -o $available_minor -ne $required_minor \ + -o $available_patch -lt $required_patch ; then + SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false' + else + SWIG_LIB=`$SWIG -swiglib` + fi + else + SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false' + fi + fi + AC_SUBST([SWIG_LIB]) +]) diff --git a/config/macro-archive/ax_compare_version.m4 b/config/macro-archive/ax_compare_version.m4 new file mode 100644 index 0000000..a7581b4 --- /dev/null +++ b/config/macro-archive/ax_compare_version.m4 @@ -0,0 +1,201 @@ +##### http://autoconf-archive.cryp.to/ax_compare_version.html +# +# SYNOPSIS +# +# AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# +# DESCRIPTION +# +# This macro compares two version strings. It is used heavily in the +# macro _AX_PATH_BDB for library checking. Due to the various number +# of minor-version numbers that can exist, and the fact that string +# comparisons are not compatible with numeric comparisons, this is +# not necessarily trivial to do in a autoconf script. This macro +# makes doing these comparisons easy. +# +# The six basic comparisons are available, as well as checking +# equality limited to a certain number of minor-version levels. +# +# The operator OP determines what type of comparison to do, and can +# be one of: +# +# eq - equal (test A == B) +# ne - not equal (test A != B) +# le - less than or equal (test A <= B) +# ge - greater than or equal (test A >= B) +# lt - less than (test A < B) +# gt - greater than (test A > B) +# +# Additionally, the eq and ne operator can have a number after it to +# limit the test to that number of minor versions. +# +# eq0 - equal up to the length of the shorter version +# ne0 - not equal up to the length of the shorter version +# eqN - equal up to N sub-version levels +# neN - not equal up to N sub-version levels +# +# When the condition is true, shell commands ACTION-IF-TRUE are run, +# otherwise shell commands ACTION-IF-FALSE are run. The environment +# variable 'ax_compare_version' is always set to either 'true' or +# 'false' as well. +# +# Examples: +# +# AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8]) +# AX_COMPARE_VERSION([3.15],[lt],[3.15.8]) +# +# would both be true. +# +# AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8]) +# AX_COMPARE_VERSION([3.15],[gt],[3.15.8]) +# +# would both be false. +# +# AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8]) +# +# would be true because it is only comparing two minor versions. +# +# AX_COMPARE_VERSION([3.15.7],[eq0],[3.15]) +# +# would be true because it is only comparing the lesser number of +# minor versions of the two values. +# +# Note: The characters that separate the version numbers do not +# matter. An empty string is the same as version 0. OP is evaluated +# by autoconf, not configure, so must be a string, not a variable. +# +# The author would like to acknowledge Guido Draheim whose advice +# about the m4_case and m4_ifvaln functions make this macro only +# include the portions necessary to perform the specific comparison +# specified by the OP argument in the final configure script. +# +# LAST MODIFICATION +# +# 2004-03-01 +# +# COPYLEFT +# +# Copyright (c) 2004 Tim Toolan +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. + +dnl ######################################################################### +AC_DEFUN([AX_COMPARE_VERSION], [ + # Used to indicate true or false condition + ax_compare_version=false + + # Convert the two version strings to be compared into a format that + # allows a simple string comparison. The end result is that a version + # string of the form 1.12.5-r617 will be converted to the form + # 0001001200050617. In other words, each number is zero padded to four + # digits, and non digits are removed. + AS_VAR_PUSHDEF([A],[ax_compare_version_A]) + A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ + -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/[[^0-9]]//g'` + + AS_VAR_PUSHDEF([B],[ax_compare_version_B]) + B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ + -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/[[^0-9]]//g'` + + dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary + dnl # then the first line is used to determine if the condition is true. + dnl # The sed right after the echo is to remove any indented white space. + m4_case(m4_tolower($2), + [lt],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` + ], + [gt],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` + ], + [le],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` + ], + [ge],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` + ],[ + dnl Split the operator from the subversion count if present. + m4_bmatch(m4_substr($2,2), + [0],[ + # A count of zero means use the length of the shorter version. + # Determine the number of characters in A and B. + ax_compare_version_len_A=`echo "$A" | awk '{print(length)}'` + ax_compare_version_len_B=`echo "$B" | awk '{print(length)}'` + + # Set A to no more than B's length and B to no more than A's length. + A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` + B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` + ], + [[0-9]+],[ + # A count greater than zero means use only that many subversions + A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` + B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` + ], + [.+],[ + AC_WARNING( + [illegal OP numeric parameter: $2]) + ],[]) + + # Pad zeros at end of numbers to make same length. + ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" + B="$B`echo $A | sed 's/./0/g'`" + A="$ax_compare_version_tmp_A" + + # Check for equality or inequality as necessary. + m4_case(m4_tolower(m4_substr($2,0,2)), + [eq],[ + test "x$A" = "x$B" && ax_compare_version=true + ], + [ne],[ + test "x$A" != "x$B" && ax_compare_version=true + ],[ + AC_WARNING([illegal OP parameter: $2]) + ]) + ]) + + AS_VAR_POPDEF([A])dnl + AS_VAR_POPDEF([B])dnl + + dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. + if test "$ax_compare_version" = "true" ; then + m4_ifvaln([$4],[$4],[:])dnl + m4_ifvaln([$5],[else $5])dnl + fi +]) dnl AX_COMPARE_VERSION diff --git a/config/macro-archive/docbook-dtd.m4 b/config/macro-archive/docbook-dtd.m4 new file mode 100644 index 0000000..935b169 --- /dev/null +++ b/config/macro-archive/docbook-dtd.m4 @@ -0,0 +1,112 @@ +##### http://autoconf-archive.cryp.to/ac_check_docbook_dtd.html +# +# SYNOPSIS +# +# AC_CHECK_DOCBOOK_DTD([dtd-version]) +# +# DESCRIPTION +# +# Check for access to a docbook DTD of a particular revision. +# +# This macro can be used for multiple versions within the same script. +# +# Input: +# $1 is the version of docbook to search for; default 'current' +# Output: +# $HAVE_DOCBOOK_DTD_VERS will be set to 'yes' or 'no' depending +# on the results of the test, where VERS is $1, with '_' substituted +# for '.' $HAVE_DOCBOOK_DTD will also be set to the same value. +# +# Example: +# AC_CHECK_DOCBOOK_DTD(4.3) +# if test "x$HAVE_DOCBOOK_DTD_4_3" = "xyes"; then +# .. +# +# LAST MODIFICATION +# +# 2007-06-28 +# +# AUTHOR +# +# Dustin J. Mitchell +# +# COPYRIGHT +# +# Copyright (c) 2007 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +AC_DEFUN([AC_CHECK_DOCBOOK_DTD], +[ + AC_REQUIRE([AC_PROG_XSLTPROC]) + + dnl define a temporary variable for the version, so this macro can be + dnl used with multiple versions + define([_VERS], $1) + ifelse(_VERS, [], [define([_VERS], [current])]) + + dnl define variable names ending in _VERS which will actually have the + dnl version number as a suffix + define([ac_cv_docbook_dtd_VERS], patsubst([ac_cv_docbook_dtd_]_VERS, [\.], [_])) + define([HAVE_DOCBOOK_DTD_VERS], patsubst([HAVE_DOCBOOK_DTD_]_VERS, [\.], [_])) + + AC_CACHE_CHECK([for Docbook DTD version ]_VERS, [ac_cv_docbook_dtd_VERS], + [ + ac_cv_docbook_dtd_VERS=no + if test -n "$XSLTPROC"; then + MY_XSLTPROC_FLAGS=`echo "" $XSLTPROC_FLAGS|sed -e s/--novalid//g` + cat <conftest.xml + + + + +EOF + echo "Trying '$XSLTPROC $MY_XSLTPROC_FLAGS conftest.xml'" >&AS_MESSAGE_LOG_FD + echo "conftest.xml:" >&AS_MESSAGE_LOG_FD + echo "====" >&AS_MESSAGE_LOG_FD + cat conftest.xml >&AS_MESSAGE_LOG_FD + echo "====" >&AS_MESSAGE_LOG_FD + + $XSLTPROC $MY_XSLTPROC_FLAGS conftest.xml >conftest.out 2>&1 + if test "$?" = 0 -o "$?" = 5; then + # failing to load the DTD is just a warning, so check for it in the output. + if grep 'warning: failed to load external entity' conftest.out >/dev/null 2>&1; then + : # no good.. + else + ac_cv_docbook_dtd_VERS=yes + fi + fi + cat conftest.out >&AS_MESSAGE_LOG_FD + + rm -f conftest.xml conftest.out + fi + ]) + + HAVE_DOCBOOK_DTD_VERS="$ac_cv_docbook_dtd_VERS" + HAVE_DOCBOOK_DTD="$HAVE_DOCBOOK_DTD_VERS" + + dnl clean up m4 namespace + undefine([_VERS]) + undefine([ac_cv_docbook_dtd_VERS]) + undefine([HAVE_DOCBOOK_DTD_VERS]) +]) diff --git a/config/macro-archive/docbook-xslt-min.m4 b/config/macro-archive/docbook-xslt-min.m4 new file mode 100644 index 0000000..e92c848 --- /dev/null +++ b/config/macro-archive/docbook-xslt-min.m4 @@ -0,0 +1,108 @@ +##### http://autoconf-archive.cryp.to/ac_check_docbook_xslt_min.html +# +# SYNOPSIS +# +# AC_CHECK_DOCBOOK_XSLT_MIN(min-xslt-version) +# +# DESCRIPTION +# +# Check that the 'current' version of docbook is at least version +# min-xslt-version. +# +# If the test is successful, $DOCBOOK_XSLT_CURRENT_VERSION will be set to the +# current docbook version; if not, it will be set to 'no'. +# +# Example: +# AC_CHECK_DOCBOOK_XSLT_MIN(1.72.0) +# if test "x$DOCBOOK_XSLT_CURRENT_VERSION" = "xno"; then +# .. +# +# LAST MODIFICATION +# +# 2007-06-28 +# +# AUTHOR +# +# Dustin J. Mitchell +# +# COPYRIGHT +# +# Copyright (c) 2007 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +AC_DEFUN([AC_CHECK_DOCBOOK_XSLT_MIN], +[ + AC_REQUIRE([AC_PROG_XSLTPROC]) + + AC_CACHE_CHECK([for current Docbook XSLT version], [ac_cv_docbook_xslt_current_version], + [ + ac_cv_docbook_xslt_current_version=no + + if test -n "$XSLTPROC"; then + cat >conftest.xsl < + + + + + + + +EOF + echo "Trying '$XSLTPROC $XSLTPROC_FLAGS http://docbook.sourceforge.net/release/xsl/current/VERSION' with input:" >&AS_MESSAGE_LOG_FD + echo "====" >&AS_MESSAGE_LOG_FD + cat conftest.xsl >&AS_MESSAGE_LOG_FD + echo "====" >&AS_MESSAGE_LOG_FD + + ac_cv_docbook_xslt_current_version=`$XSLTPROC $XSLTPROC_FLAGS conftest.xsl http://docbook.sourceforge.net/release/xsl/current/VERSION 2>&AS_MESSAGE_LOG_FD` + + if test "$?" != 0; then + ac_cv_docbook_xslt_current_version='no' + fi + + rm conftest.xsl + fi + ]) + + DOCBOOK_XSLT_CURRENT_VERSION="$ac_cv_docbook_xslt_current_version" + AC_MSG_CHECKING([whether Docbook XSLT version is $1 or newer]) + + if test x"$DOCBOOK_XSLT_CURRENT_VERSION" = x"no"; then + AC_MSG_RESULT([no]) + else + AX_COMPARE_VERSION([$DOCBOOK_XSLT_CURRENT_VERSION], [lt], [$1], [ + # version is less than required, so mark it as "no" + DOCBOOK_XSLT_CURRENT_VERSION=no + ]) + + if test x"$DOCBOOK_XSLT_CURRENT_VERSION" = x"no"; then + AC_MSG_RESULT([no]) + else + AC_MSG_RESULT([yes ($DOCBOOK_XSLT_CURRENT_VERSION)]) + fi + fi +]) diff --git a/config/macro-archive/docbook-xslt.m4 b/config/macro-archive/docbook-xslt.m4 new file mode 100644 index 0000000..ab4b6ce --- /dev/null +++ b/config/macro-archive/docbook-xslt.m4 @@ -0,0 +1,93 @@ +##### http://autoconf-archive.cryp.to/ac_check_docbook_xslt.html +# +# SYNOPSIS +# +# AC_CHECK_DOCBOOK_XSLT([xslt-version]) +# +# DESCRIPTION +# +# Check for access to docbook stylesheets of a particular revision. +# +# This macro can be used for multiple versions within the same script. +# +# Input: +# $1 is the version of docbook to search for; default 'current' +# Output: +# $HAVE_DOCBOOK_XSLT_VERS will be set to 'yes' or 'no' depending +# on the results of the test, where VERS is $1, with '_' substituted +# for '.' $HAVE_DOCBOOK_XSLT will also be set to the same value. +# +# Example: +# AC_CHECK_DOCBOOK_XSLT(1.72.0) +# if test "x$HAVE_DOCBOOK_XSLT_1_72_0" = "xyes"; then +# .. +# +# LAST MODIFICATION +# +# 2007-06-28 +# +# AUTHOR +# +# Dustin J. Mitchell +# +# COPYRIGHT +# +# Copyright (c) 2007 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +AC_DEFUN([AC_CHECK_DOCBOOK_XSLT], +[ + AC_REQUIRE([AC_PROG_XSLTPROC]) + + dnl define a temporary variable for the version, so this macro can be + dnl used with multiple versions + define([_VERS], $1) + ifelse(_VERS, [], [define([_VERS], [current])]) + + dnl define variable names ending in _VERS which will actually have the + dnl version number as a suffix + define([ac_cv_docbook_xslt_VERS], patsubst([ac_cv_docbook_xslt_]_VERS, [\.], [_])) + define([HAVE_DOCBOOK_XSLT_VERS], patsubst([HAVE_DOCBOOK_XSLT_]_VERS, [\.], [_])) + + AC_CACHE_CHECK([for Docbook XSLT version ]_VERS, [ac_cv_docbook_xslt_VERS], + [ + ac_cv_docbook_xslt_VERS=no + if test -n "$XSLTPROC"; then + echo "Trying '$XSLTPROC $XSLTPROC_FLAGS http://docbook.sourceforge.net/release/xsl/_VERS/xhtml/docbook.xsl'" >&AS_MESSAGE_LOG_FD + $XSLTPROC $XSLTPROC_FLAGS http://docbook.sourceforge.net/release/xsl/_VERS/xhtml/docbook.xsl >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + + if test "$?" = 0; then + ac_cv_docbook_xslt_VERS=yes + fi + fi + ]) + + HAVE_DOCBOOK_XSLT_VERS="$ac_cv_docbook_xslt_VERS" + HAVE_DOCBOOK_XSLT="$HAVE_DOCBOOK_XSLT_VERS" + + dnl clean up m4 namespace + undefine([_VERS]) + undefine([ac_cv_docbook_xslt_VERS]) + undefine([HAVE_DOCBOOK_XSLT_VERS]) +]) diff --git a/config/macro-archive/file-list b/config/macro-archive/file-list new file mode 100644 index 0000000..7773a1d --- /dev/null +++ b/config/macro-archive/file-list @@ -0,0 +1,9 @@ +## this file is automatically generated by autogen +EXTRA_DIST += macro-archive/ac_define_dir.m4 +EXTRA_DIST += macro-archive/ac_prog_perl_version.m4 +EXTRA_DIST += macro-archive/ac_prog_swig.m4 +EXTRA_DIST += macro-archive/ax_compare_version.m4 +EXTRA_DIST += macro-archive/docbook-dtd.m4 +EXTRA_DIST += macro-archive/docbook-xslt.m4 +EXTRA_DIST += macro-archive/docbook-xslt-min.m4 +EXTRA_DIST += macro-archive/xsltproc.m4 diff --git a/config/macro-archive/xsltproc.m4 b/config/macro-archive/xsltproc.m4 new file mode 100644 index 0000000..b782967 --- /dev/null +++ b/config/macro-archive/xsltproc.m4 @@ -0,0 +1,92 @@ +##### http://autoconf-archive.cryp.to/ac_prog_xsltproc.html +# +# SYNOPSIS +# +# AC_PROG_XSLTPROC([default-flags]) +# +# DESCRIPTION +# +# Finds an xsltproc executable. +# +# Input: +# default-flags is the default $XSLTPROC_FLAGS, which will be +# overridden if the user specifies --with-xsltproc-flags. +# +# Output: +# $XSLTPROC contains the path to xsltproc, or is empty if none was +# found or the user specified --without-xsltproc. $XSLTPROC_FLAGS +# contains the flags to use with xsltproc. +# +# LAST MODIFICATION +# +# 2007-04-17 +# +# AUTHOR +# +# Dustin J. Mitchell +# +# COPYRIGHT +# +# Copyright (c) 2007 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +AC_DEFUN([AC_PROG_XSLTPROC], +[ +XSLTPROC_FLAGS="$1" +AC_SUBST(XSLTPROC_FLAGS) + +# The (lack of) whitespace and overquoting here are all necessary for +# proper formatting. +AC_ARG_WITH(xsltproc, +AS_HELP_STRING([--with-xsltproc[[[[[=PATH]]]]]], + [Use the xsltproc binary in in PATH.]), + [ ac_with_xsltproc=$withval; ], + [ ac_with_xsltproc=maybe; ]) + +AC_ARG_WITH(xsltproc-flags, +AS_HELP_STRING([ --with-xsltproc-flags=FLAGS], + [Flags to pass to xsltproc (default $1)]), + [ if test "x$withval" == "xno"; then + XSLTPROC_FLAGS='' + else + if test "x$withval" != "xyes"; then + XSLTPROC_FLAGS="$withval" + fi + fi + ]) + +# search for xsltproc if it wasn't specified +if test "$ac_with_xsltproc" = "yes" -o "$ac_with_xsltproc" = "maybe"; then + AC_PATH_PROGS(XSLTPROC,xsltproc,,$LOCSYSPATH) +else + if test "$ac_with_xsltproc" != "no"; then + if test -x "$ac_with_xsltproc"; then + XSLTPROC="$ac_with_xsltproc"; + else + AMANDA_MSG_WARN([Specified xsltproc of $ac_with_xsltproc isn't executable; searching for an alternative.]) + AC_PATH_PROGS(XSLTPROC,xsltproc,,$LOCSYSPATH) + fi + fi +fi +]) diff --git a/config/ylwrap b/config/ylwrap new file mode 100755 index 0000000..102bd89 --- /dev/null +++ b/config/ylwrap @@ -0,0 +1,223 @@ +#! /bin/sh +# ylwrap - wrapper for lex/yacc invocations. + +scriptversion=2005-05-14.22 + +# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case "$1" in + '') + echo "$0: No files given. Try \`$0 --help' for more information." 1>&2 + exit 1 + ;; + --basedir) + basedir=$2 + shift 2 + ;; + -h|--h*) + cat <<\EOF +Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... + +Wrapper for lex/yacc invocations, renaming files as desired. + + INPUT is the input file + OUTPUT is one file PROG generates + DESIRED is the file we actually want instead of OUTPUT + PROGRAM is program to run + ARGS are passed to PROG + +Any number of OUTPUT,DESIRED pairs may be used. + +Report bugs to . +EOF + exit $? + ;; + -v|--v*) + echo "ylwrap $scriptversion" + exit $? + ;; +esac + + +# The input. +input="$1" +shift +case "$input" in + [\\/]* | ?:[\\/]*) + # Absolute path; do nothing. + ;; + *) + # Relative path. Make it absolute. + input="`pwd`/$input" + ;; +esac + +pairlist= +while test "$#" -ne 0; do + if test "$1" = "--"; then + shift + break + fi + pairlist="$pairlist $1" + shift +done + +# The program to run. +prog="$1" +shift +# Make any relative path in $prog absolute. +case "$prog" in + [\\/]* | ?:[\\/]*) ;; + *[\\/]*) prog="`pwd`/$prog" ;; +esac + +# FIXME: add hostname here for parallel makes that run commands on +# other machines. But that might take us over the 14-char limit. +dirname=ylwrap$$ +trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15 +mkdir $dirname || exit 1 + +cd $dirname + +case $# in + 0) $prog "$input" ;; + *) $prog "$@" "$input" ;; +esac +ret=$? + +if test $ret -eq 0; then + set X $pairlist + shift + first=yes + # Since DOS filename conventions don't allow two dots, + # the DOS version of Bison writes out y_tab.c instead of y.tab.c + # and y_tab.h instead of y.tab.h. Test to see if this is the case. + y_tab_nodot="no" + if test -f y_tab.c || test -f y_tab.h; then + y_tab_nodot="yes" + fi + + # The directory holding the input. + input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'` + # Quote $INPUT_DIR so we can use it in a regexp. + # FIXME: really we should care about more than `.' and `\'. + input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'` + + while test "$#" -ne 0; do + from="$1" + # Handle y_tab.c and y_tab.h output by DOS + if test $y_tab_nodot = "yes"; then + if test $from = "y.tab.c"; then + from="y_tab.c" + else + if test $from = "y.tab.h"; then + from="y_tab.h" + fi + fi + fi + if test -f "$from"; then + # If $2 is an absolute path name, then just use that, + # otherwise prepend `../'. + case "$2" in + [\\/]* | ?:[\\/]*) target="$2";; + *) target="../$2";; + esac + + # We do not want to overwrite a header file if it hasn't + # changed. This avoid useless recompilations. However the + # parser itself (the first file) should always be updated, + # because it is the destination of the .y.c rule in the + # Makefile. Divert the output of all other files to a temporary + # file so we can compare them to existing versions. + if test $first = no; then + realtarget="$target" + target="tmp-`echo $target | sed s/.*[\\/]//g`" + fi + # Edit out `#line' or `#' directives. + # + # We don't want the resulting debug information to point at + # an absolute srcdir; it is better for it to just mention the + # .y file with no path. + # + # We want to use the real output file name, not yy.lex.c for + # instance. + # + # We want the include guards to be adjusted too. + FROM=`echo "$from" | sed \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ + -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` + TARGET=`echo "$2" | sed \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ + -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` + + sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \ + -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$? + + # Check whether header files must be updated. + if test $first = no; then + if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then + echo "$2" is unchanged + rm -f "$target" + else + echo updating "$2" + mv -f "$target" "$realtarget" + fi + fi + else + # A missing file is only an error for the first file. This + # is a blatant hack to let us support using "yacc -d". If -d + # is not specified, we don't want an error when the header + # file is "missing". + if test $first = yes; then + ret=1 + fi + fi + shift + shift + first=no + done +else + ret=$? +fi + +# Remove the directory. +cd .. +rm -rf $dirname + +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/device-src/Makefile.am b/device-src/Makefile.am new file mode 100644 index 0000000..75177d7 --- /dev/null +++ b/device-src/Makefile.am @@ -0,0 +1,64 @@ +# Makefile for Amanda tape library. + +SUBDIRS = . tests + +include $(top_srcdir)/config/automake/precompile.am + +INCLUDES = -I$(top_builddir)/common-src \ + -I$(top_srcdir)/common-src \ + -I$(top_srcdir)/gnulib + +AM_CFLAGS = $(AMANDA_WARNING_CFLAGS) +AM_LDFLAGS = $(AMANDA_STATIC_LDFLAGS) + +sbin_PROGRAMS = + +## libamdevice.la + +amlib_LTLIBRARIES = libamdevice.la +libamdevice_la_LDFLAGS = -release $(VERSION) +libamdevice_la_SOURCES = property.c device.c queueing.c semaphore.c \ + null-device.c rait-device.c vfs-device.c +libamdevice_la_LIBADD = ../common-src/libamanda.la + +# tape-device has *lots* of conditionals; the first is whether to support +# the device at all, and the remainder select a particular kind of OS-specific +# backend. + +if WANT_TAPE_DEVICE +libamdevice_la_SOURCES += tape-device.c + +if WANT_TAPE_XENIX +libamdevice_la_SOURCES += tape-xenix.c +endif +if WANT_TAPE_AIX +libamdevice_la_SOURCES += tape-aix.c +endif +if WANT_TAPE_UWARE +libamdevice_la_SOURCES += tape-uware.c +endif +if WANT_TAPE_POSIX +libamdevice_la_SOURCES += tape-posix.c +endif + +endif + +if WANT_S3_DEVICE +libamdevice_la_SOURCES += s3-device.c s3.c +endif + +## activate-devpay + +if WANT_DEVPAY +sbin_PROGRAMS += activate-devpay +activate_devpay_SOURCES = activate-devpay.c +endif + +## headers + +noinst_HEADERS = null-device.h semaphore.h \ + tape-ops.h property.h rait-device.h s3.h \ + s3-device.h tape-device.h vfs-device.h \ + device.h queueing.h + +aminclude_HEADERS = diff --git a/device-src/Makefile.in b/device-src/Makefile.in new file mode 100644 index 0000000..70898dd --- /dev/null +++ b/device-src/Makefile.in @@ -0,0 +1,1122 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for Amanda tape library. + +# vim:ft=automake + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(aminclude_HEADERS) $(noinst_HEADERS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/automake/precompile.am +sbin_PROGRAMS = $(am__EXEEXT_1) + +# tape-device has *lots* of conditionals; the first is whether to support +# the device at all, and the remainder select a particular kind of OS-specific +# backend. +@WANT_TAPE_DEVICE_TRUE@am__append_1 = tape-device.c +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_XENIX_TRUE@am__append_2 = tape-xenix.c +@WANT_TAPE_AIX_TRUE@@WANT_TAPE_DEVICE_TRUE@am__append_3 = tape-aix.c +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_UWARE_TRUE@am__append_4 = tape-uware.c +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_POSIX_TRUE@am__append_5 = tape-posix.c +@WANT_S3_DEVICE_TRUE@am__append_6 = s3-device.c s3.c +@WANT_DEVPAY_TRUE@am__append_7 = activate-devpay +subdir = device-src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/config/macro-archive/ac_define_dir.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_perl_version.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_swig.m4 \ + $(top_srcdir)/config/macro-archive/ax_compare_version.m4 \ + $(top_srcdir)/config/macro-archive/docbook-dtd.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt-min.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt.m4 \ + $(top_srcdir)/config/macro-archive/xsltproc.m4 \ + $(top_srcdir)/config/amanda/amplot.m4 \ + $(top_srcdir)/config/amanda/bsd-security.m4 \ + $(top_srcdir)/config/amanda/bsdtcp-security.m4 \ + $(top_srcdir)/config/amanda/bsdudp-security.m4 \ + $(top_srcdir)/config/amanda/changer.m4 \ + $(top_srcdir)/config/amanda/components.m4 \ + $(top_srcdir)/config/amanda/compress.m4 \ + $(top_srcdir)/config/amanda/config.m4 \ + $(top_srcdir)/config/amanda/debugging.m4 \ + $(top_srcdir)/config/amanda/defaults.m4 \ + $(top_srcdir)/config/amanda/devprefix.m4 \ + $(top_srcdir)/config/amanda/dirs.m4 \ + $(top_srcdir)/config/amanda/documentation.m4 \ + $(top_srcdir)/config/amanda/dumpers.m4 \ + $(top_srcdir)/config/amanda/flags.m4 \ + $(top_srcdir)/config/amanda/flock.m4 \ + $(top_srcdir)/config/amanda/funcs.m4 \ + $(top_srcdir)/config/amanda/getfsent.m4 \ + $(top_srcdir)/config/amanda/i18n.m4 \ + $(top_srcdir)/config/amanda/ipv6.m4 \ + $(top_srcdir)/config/amanda/krb4-security.m4 \ + $(top_srcdir)/config/amanda/krb5-security.m4 \ + $(top_srcdir)/config/amanda/lfs.m4 \ + $(top_srcdir)/config/amanda/libs.m4 \ + $(top_srcdir)/config/amanda/net.m4 \ + $(top_srcdir)/config/amanda/progs.m4 \ + $(top_srcdir)/config/amanda/readdir.m4 \ + $(top_srcdir)/config/amanda/readline.m4 \ + $(top_srcdir)/config/amanda/rsh-security.m4 \ + $(top_srcdir)/config/amanda/s3-device.m4 \ + $(top_srcdir)/config/amanda/shmem.m4 \ + $(top_srcdir)/config/amanda/socklen_t_equiv.m4 \ + $(top_srcdir)/config/amanda/ssh-security.m4 \ + $(top_srcdir)/config/amanda/summary.m4 \ + $(top_srcdir)/config/amanda/swig.m4 \ + $(top_srcdir)/config/amanda/syshacks.m4 \ + $(top_srcdir)/config/amanda/tape.m4 \ + $(top_srcdir)/config/amanda/types.m4 \ + $(top_srcdir)/config/amanda/userid.m4 \ + $(top_srcdir)/config/amanda/version.m4 \ + $(top_srcdir)/config/gnulib/alloca.m4 \ + $(top_srcdir)/config/gnulib/arpa_inet_h.m4 \ + $(top_srcdir)/config/gnulib/base64.m4 \ + $(top_srcdir)/config/gnulib/eoverflow.m4 \ + $(top_srcdir)/config/gnulib/extensions.m4 \ + $(top_srcdir)/config/gnulib/float_h.m4 \ + $(top_srcdir)/config/gnulib/fsusage.m4 \ + $(top_srcdir)/config/gnulib/getaddrinfo.m4 \ + $(top_srcdir)/config/gnulib/gettimeofday.m4 \ + $(top_srcdir)/config/gnulib/gnulib-comp.m4 \ + $(top_srcdir)/config/gnulib/include_next.m4 \ + $(top_srcdir)/config/gnulib/inet_ntop.m4 \ + $(top_srcdir)/config/gnulib/intmax_t.m4 \ + $(top_srcdir)/config/gnulib/lock.m4 \ + $(top_srcdir)/config/gnulib/longlong.m4 \ + $(top_srcdir)/config/gnulib/malloc.m4 \ + $(top_srcdir)/config/gnulib/mkdtemp.m4 \ + $(top_srcdir)/config/gnulib/netinet_in_h.m4 \ + $(top_srcdir)/config/gnulib/onceonly_2_57.m4 \ + $(top_srcdir)/config/gnulib/physmem.m4 \ + $(top_srcdir)/config/gnulib/safe-read.m4 \ + $(top_srcdir)/config/gnulib/safe-write.m4 \ + $(top_srcdir)/config/gnulib/snprintf.m4 \ + $(top_srcdir)/config/gnulib/socklen.m4 \ + $(top_srcdir)/config/gnulib/sockpfaf.m4 \ + $(top_srcdir)/config/gnulib/ssize_t.m4 \ + $(top_srcdir)/config/gnulib/stdbool.m4 \ + $(top_srcdir)/config/gnulib/stdint.m4 \ + $(top_srcdir)/config/gnulib/stdio_h.m4 \ + $(top_srcdir)/config/gnulib/stdlib_h.m4 \ + $(top_srcdir)/config/gnulib/strdup.m4 \ + $(top_srcdir)/config/gnulib/string_h.m4 \ + $(top_srcdir)/config/gnulib/sys_socket_h.m4 \ + $(top_srcdir)/config/gnulib/sys_stat_h.m4 \ + $(top_srcdir)/config/gnulib/sys_time_h.m4 \ + $(top_srcdir)/config/gnulib/tempname.m4 \ + $(top_srcdir)/config/gnulib/ulonglong.m4 \ + $(top_srcdir)/config/gnulib/unistd_h.m4 \ + $(top_srcdir)/config/gnulib/vasnprintf.m4 \ + $(top_srcdir)/config/gnulib/visibility.m4 \ + $(top_srcdir)/config/gnulib/wchar.m4 \ + $(top_srcdir)/config/gettext-macros/gettext.m4 \ + $(top_srcdir)/config/gettext-macros/iconv.m4 \ + $(top_srcdir)/config/gettext-macros/inttypes_h.m4 \ + $(top_srcdir)/config/gettext-macros/lib-ld.m4 \ + $(top_srcdir)/config/gettext-macros/lib-link.m4 \ + $(top_srcdir)/config/gettext-macros/lib-prefix.m4 \ + $(top_srcdir)/config/gettext-macros/longlong.m4 \ + $(top_srcdir)/config/gettext-macros/nls.m4 \ + $(top_srcdir)/config/gettext-macros/po.m4 \ + $(top_srcdir)/config/gettext-macros/progtest.m4 \ + $(top_srcdir)/config/gettext-macros/size_max.m4 \ + $(top_srcdir)/config/gettext-macros/stdint_h.m4 \ + $(top_srcdir)/config/gettext-macros/wchar_t.m4 \ + $(top_srcdir)/config/gettext-macros/wint_t.m4 \ + $(top_srcdir)/config/gettext-macros/xsize.m4 \ + $(top_srcdir)/config/libtool.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(amlibdir)" "$(DESTDIR)$(sbindir)" \ + "$(DESTDIR)$(amincludedir)" +amlibLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(amlib_LTLIBRARIES) +libamdevice_la_DEPENDENCIES = ../common-src/libamanda.la +am__libamdevice_la_SOURCES_DIST = property.c device.c queueing.c \ + semaphore.c null-device.c rait-device.c vfs-device.c \ + tape-device.c tape-xenix.c tape-aix.c tape-uware.c \ + tape-posix.c s3-device.c s3.c +@WANT_TAPE_DEVICE_TRUE@am__objects_1 = tape-device.lo +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_XENIX_TRUE@am__objects_2 = \ +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_XENIX_TRUE@ tape-xenix.lo +@WANT_TAPE_AIX_TRUE@@WANT_TAPE_DEVICE_TRUE@am__objects_3 = \ +@WANT_TAPE_AIX_TRUE@@WANT_TAPE_DEVICE_TRUE@ tape-aix.lo +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_UWARE_TRUE@am__objects_4 = \ +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_UWARE_TRUE@ tape-uware.lo +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_POSIX_TRUE@am__objects_5 = \ +@WANT_TAPE_DEVICE_TRUE@@WANT_TAPE_POSIX_TRUE@ tape-posix.lo +@WANT_S3_DEVICE_TRUE@am__objects_6 = s3-device.lo s3.lo +am_libamdevice_la_OBJECTS = property.lo device.lo queueing.lo \ + semaphore.lo null-device.lo rait-device.lo vfs-device.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) +libamdevice_la_OBJECTS = $(am_libamdevice_la_OBJECTS) +libamdevice_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libamdevice_la_LDFLAGS) $(LDFLAGS) -o $@ +@WANT_DEVPAY_TRUE@am__EXEEXT_1 = activate-devpay$(EXEEXT) +sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(sbin_PROGRAMS) +am__activate_devpay_SOURCES_DIST = activate-devpay.c +@WANT_DEVPAY_TRUE@am_activate_devpay_OBJECTS = \ +@WANT_DEVPAY_TRUE@ activate-devpay.$(OBJEXT) +activate_devpay_OBJECTS = $(am_activate_devpay_OBJECTS) +activate_devpay_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(top_builddir)/config@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libamdevice_la_SOURCES) $(activate_devpay_SOURCES) +DIST_SOURCES = $(am__libamdevice_la_SOURCES_DIST) \ + $(am__activate_devpay_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +amincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(aminclude_HEADERS) $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMANDA_DBGDIR = @AMANDA_DBGDIR@ +AMANDA_DEBUG_DAYS = @AMANDA_DEBUG_DAYS@ +AMANDA_STATIC_LDFLAGS = @AMANDA_STATIC_LDFLAGS@ +AMANDA_TMPDIR = @AMANDA_TMPDIR@ +AMANDA_WARNING_CFLAGS = @AMANDA_WARNING_CFLAGS@ +AMLINT = @AMLINT@ +AMLINTFLAGS = @AMLINTFLAGS@ +AMPLOT_CAT_COMPRESS = @AMPLOT_CAT_COMPRESS@ +AMPLOT_CAT_GZIP = @AMPLOT_CAT_GZIP@ +AMPLOT_CAT_PACK = @AMPLOT_CAT_PACK@ +AMPLOT_COMPRESS = @AMPLOT_COMPRESS@ +AMTAR = @AMTAR@ +AR = @AR@ +ARPA_INET_H = @ARPA_INET_H@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH = @BASH@ +BINARY_OWNER = @BINARY_OWNER@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +CAT = @CAT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CHIO = @CHIO@ +CHS = @CHS@ +CLIENT_LOGIN = @CLIENT_LOGIN@ +CLIENT_SCRIPTS_OPT = @CLIENT_SCRIPTS_OPT@ +COMPRESS = @COMPRESS@ +CONFIG_DIR = @CONFIG_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL_CONFIG = @CURL_CONFIG@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DD = @DD@ +DEFAULT_AMANDATES_FILE = @DEFAULT_AMANDATES_FILE@ +DEFAULT_CHANGER_DEVICE = @DEFAULT_CHANGER_DEVICE@ +DEFAULT_CONFIG = @DEFAULT_CONFIG@ +DEFAULT_SERVER = @DEFAULT_SERVER@ +DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@ +DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOC_BUILD_DATE = @DOC_BUILD_DATE@ +DUMP = @DUMP@ +DUMPER_DIR = @DUMPER_DIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EOVERFLOW = @EOVERFLOW@ +EXAMPLE_TAPEDEV = @EXAMPLE_TAPEDEV@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FLOAT_H = @FLOAT_H@ +GETCONF = @GETCONF@ +GETTEXT = @GETTEXT@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNUPLOT = @GNUPLOT@ +GNUTAR = @GNUTAR@ +GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GZIP = @GZIP@ +HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_MKDIR = @HAVE_DECL_MKDIR@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_IO_H = @HAVE_IO_H@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRNDUP = @HAVE_STRNDUP@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE__BOOL = @HAVE__BOOL@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBS = @LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAILER = @MAILER@ +MAKEINFO = @MAKEINFO@ +MAXTAPEBLOCKSIZE = @MAXTAPEBLOCKSIZE@ +MCUTIL = @MCUTIL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MT = @MT@ +MTX = @MTX@ +MT_FILE_FLAG = @MT_FILE_FLAG@ +NETINET_IN_H = @NETINET_IN_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCAT = @PCAT@ +PERL = @PERL@ +PERLEXTLIBS = @PERLEXTLIBS@ +PERL_INC = @PERL_INC@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +PRINT = @PRINT@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_FCHDIR = @REPLACE_FCHDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +RESTORE = @RESTORE@ +SAMBA_CLIENT = @SAMBA_CLIENT@ +SERVICE_SUFFIX = @SERVICE_SUFFIX@ +SETUID_GROUP = @SETUID_GROUP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SNAPSHOT_STAMP = @SNAPSHOT_STAMP@ +SORT = @SORT@ +SSH = @SSH@ +STDBOOL_H = @STDBOOL_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SVN = @SVN@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYS_SOCKET_H = @SYS_SOCKET_H@ +SYS_STAT_H = @SYS_STAT_H@ +SYS_TIME_H = @SYS_TIME_H@ +USE_NLS = @USE_NLS@ +USE_VERSION_SUFFIXES = @USE_VERSION_SUFFIXES@ +VDUMP = @VDUMP@ +VERSION = @VERSION@ +VERSION_COMMENT = @VERSION_COMMENT@ +VERSION_MAJOR = @VERSION_MAJOR@ +VERSION_MINOR = @VERSION_MINOR@ +VERSION_PATCH = @VERSION_PATCH@ +VERSION_SUFFIX = @VERSION_SUFFIX@ +VRESTORE = @VRESTORE@ +VXDUMP = @VXDUMP@ +VXRESTORE = @VXRESTORE@ +WCHAR_H = @WCHAR_H@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XFSDUMP = @XFSDUMP@ +XFSRESTORE = @XFSRESTORE@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XSLREL = @XSLREL@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +amincludedir = @amincludedir@ +amlibdir = @amlibdir@ +amlibexecdir = @amlibexecdir@ +amperldir = @amperldir@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = . tests +INCLUDES = -I$(top_builddir)/common-src \ + -I$(top_srcdir)/common-src \ + -I$(top_srcdir)/gnulib + +AM_CFLAGS = $(AMANDA_WARNING_CFLAGS) +AM_LDFLAGS = $(AMANDA_STATIC_LDFLAGS) +amlib_LTLIBRARIES = libamdevice.la +libamdevice_la_LDFLAGS = -release $(VERSION) +libamdevice_la_SOURCES = property.c device.c queueing.c semaphore.c \ + null-device.c rait-device.c vfs-device.c $(am__append_1) \ + $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) $(am__append_6) +libamdevice_la_LIBADD = ../common-src/libamanda.la +@WANT_DEVPAY_TRUE@activate_devpay_SOURCES = activate-devpay.c +noinst_HEADERS = null-device.h semaphore.h \ + tape-ops.h property.h rait-device.h s3.h \ + s3-device.h tape-device.h vfs-device.h \ + device.h queueing.h + +aminclude_HEADERS = +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/config/automake/precompile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu device-src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu device-src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-amlibLTLIBRARIES: $(amlib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(amlibdir)" || $(MKDIR_P) "$(DESTDIR)$(amlibdir)" + @list='$(amlib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(amlibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(amlibdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(amlibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(amlibdir)/$$f"; \ + else :; fi; \ + done + +uninstall-amlibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(amlib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(amlibdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(amlibdir)/$$p"; \ + done + +clean-amlibLTLIBRARIES: + -test -z "$(amlib_LTLIBRARIES)" || rm -f $(amlib_LTLIBRARIES) + @list='$(amlib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libamdevice.la: $(libamdevice_la_OBJECTS) $(libamdevice_la_DEPENDENCIES) + $(libamdevice_la_LINK) -rpath $(amlibdir) $(libamdevice_la_OBJECTS) $(libamdevice_la_LIBADD) $(LIBS) +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \ + rm -f "$(DESTDIR)$(sbindir)/$$f"; \ + done + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +activate-devpay$(EXEEXT): $(activate_devpay_OBJECTS) $(activate_devpay_DEPENDENCIES) + @rm -f activate-devpay$(EXEEXT) + $(LINK) $(activate_devpay_OBJECTS) $(activate_devpay_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/activate-devpay.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/null-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/property.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queueing.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rait-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/semaphore.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tape-aix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tape-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tape-posix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tape-uware.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tape-xenix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfs-device.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-amincludeHEADERS: $(aminclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(amincludedir)" || $(MKDIR_P) "$(DESTDIR)$(amincludedir)" + @list='$(aminclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(amincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(amincludedir)/$$f'"; \ + $(amincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(amincludedir)/$$f"; \ + done + +uninstall-amincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(aminclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(amincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(amincludedir)/$$f"; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(amlibdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(amincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-amlibLTLIBRARIES clean-generic clean-libtool \ + clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: install-amincludeHEADERS install-amlibLTLIBRARIES + +install-dvi: install-dvi-recursive + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-recursive + +install-info: install-info-recursive + +install-man: + +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-amincludeHEADERS uninstall-amlibLTLIBRARIES \ + uninstall-sbinPROGRAMS + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-amlibLTLIBRARIES \ + clean-generic clean-libtool clean-sbinPROGRAMS ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am \ + install-amincludeHEADERS install-amlibLTLIBRARIES install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-amincludeHEADERS uninstall-amlibLTLIBRARIES \ + uninstall-sbinPROGRAMS + + +# A rule to make precompiler output from C files. This is not used during +# ordinary builds, but but can very useful in debugging problems on strange +# architectures. With this rule, we can ask users to 'make foo.i' and send +# the result to us. +# +# It touches some automake internals ($COMPILE), but since it's not +# build-critical, that's OK. +%.i : %.c + $(COMPILE) -E -o $@ $< +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/device-src/activate-devpay.c b/device-src/activate-devpay.c new file mode 100644 index 0000000..196834d --- /dev/null +++ b/device-src/activate-devpay.c @@ -0,0 +1,226 @@ +/* This program creates the token and certificate files for Amazon Devpay's + * Simple Token Service (STS). Right now you can then use those files with + * the S3 device. */ + +#include "amanda.h" + +#include +#include + +#include +#include + +#include "base64.h" +#include "s3.h" + +#ifndef WANT_DEVPAY +# error activate_devpay only works if devpay is enabled. +#endif + +#define MAX_RESPONSE_SIZE (1024*1024) + +typedef struct { + GString * user_token; + GString * access_key; + GString * secret_key; +} Credentials; + +static void usage(void) { + g_fprintf(stderr, +"USAGE: activate-devpay KEY [ >> amanda.conf ]\n" +" This tool uses an Amazon Devpay activation key to retrieve an\n" +" user token, access key, and secret key for use with Amazon S3. Output\n" +" is in a form suitable for placement in an Amanda configuration file\n"); + + exit(EXIT_FAILURE); +} + +/* This function is **not** thread-safe. Sorry. */ +static const char * parse_commandline(int argc, char ** argv) { + if (argc != 2) { + usage(); + return NULL; + } else { + return argv[1]; + } +} + +static char * activation_url(const char *key) { + char * url; + char * encoded_key; + + encoded_key = curl_escape(key, 0); + url = g_strdup_printf(STS_BASE_URL "?Action=ActivateDesktopProduct&ActivationKey=%s&ProductToken=" STS_PRODUCT_TOKEN "&Version=2007-06-05", encoded_key); + curl_free(encoded_key); + + return url; +} + +/* This function is a CURLOPT_WRITEFUNCTION and a wrapper for + g_markup_parse_context_parse(). It's not very smart about errors. */ +static size_t libcurl_gmarkup_glue(void *ptr, size_t size1, size_t size2, + void *stream) { + GMarkupParseContext *context = stream; + /* If this overflows, we have real problems, because we are expected to + * return the result of this multiplication in a size_t. */ + size_t read_size = size1 * size2; + GError * error = NULL; + + read_size = size1 * size2; + + if (g_markup_parse_context_parse(context, ptr, read_size, &error)) { + return read_size; + } else { + if (error == NULL) { + g_fprintf(stderr, "Internal error parsing XML.\n"); + } else { + g_fprintf(stderr, "Error parsing XML: %s\n", + error->message); + g_error_free(error); + } + exit(EXIT_FAILURE); + } +} + +static void do_server_stuff(const char * key, GMarkupParseContext * parser) { + char * url; + CURL* handle; + char curl_error_buffer[CURL_ERROR_SIZE]; + + handle = curl_easy_init(); + + curl_easy_setopt(handle, CURLOPT_NOPROGRESS, TRUE); + curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE); + curl_easy_setopt(handle, CURLOPT_AUTOREFERER, TRUE); + curl_easy_setopt(handle, CURLOPT_ENCODING, ""); /* Support everything. */ +#ifdef CURLOPT_MAXFILESIZE + curl_easy_setopt(handle, CURLOPT_MAXFILESIZE, MAX_RESPONSE_SIZE); +#endif + curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_buffer); + + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, libcurl_gmarkup_glue); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, parser); + url = activation_url(key); + curl_easy_setopt(handle, CURLOPT_URL, url); + + if (curl_easy_perform(handle) != 0) { + g_error("Problem fetching data from server:\n%s", + curl_error_buffer); + exit(EXIT_FAILURE); + } + + g_free(url); +} + +static void parser_got_text(GMarkupParseContext * context, + const char * text, + size_t text_len, + gpointer user_data, + GError ** error) { + Credentials * rval = user_data; + + const char * current_tag = g_markup_parse_context_get_element(context); + + g_assert(rval != NULL); + g_assert(*error == NULL); + + /* We use strrstr instead of strcmp because Amazon uses namespaces + * that I don't want to deal with. */ + if (g_strrstr(current_tag, "UserToken")) { + g_string_append_len(rval->user_token, text, text_len); + return; + } else if (g_strrstr(current_tag, "AWSAccessKeyId")) { + g_string_append_len(rval->access_key, text, text_len); + return; + } else if (g_strrstr(current_tag, "SecretAccessKey")) { + g_string_append_len(rval->secret_key, text, text_len); + return; + } else if (g_strrstr(current_tag, "Code")) { + /* Is it a code we know? */ + if (strncmp(text, "ExpiredActivationKey", text_len) == 0) { + g_set_error(error, G_MARKUP_ERROR, -1, + "Activation key has expired; get a new one."); + } else if (strncmp(text, "InvalidActivationKey", text_len) == 0) { + g_set_error(error, G_MARKUP_ERROR, -1, + "Activation key is not valid; double-check."); + } else { + /* Do nothing; wait for the message. */ + } + } else if (g_strrstr(current_tag, "Message")) { + g_set_error(error, G_MARKUP_ERROR, -1, "%.*s", text_len, text); + } +} + +static void parser_got_error(GMarkupParseContext * context G_GNUC_UNUSED, + GError * error, + gpointer user_data G_GNUC_UNUSED) { + g_fprintf (stderr, "Problem with Amazon response: %s\n", error->message); + exit(EXIT_FAILURE); +} + +static GMarkupParseContext * parser_init(Credentials * credentials) { + static const GMarkupParser parser_settings = { + NULL, /* start_element */ + NULL, /* end_element */ + parser_got_text, /* text */ + NULL, /* passthrough */ + parser_got_error /* error */ + }; + bzero(credentials, sizeof(*credentials)); + + credentials->user_token = g_string_new(""); + credentials->access_key = g_string_new(""); + credentials->secret_key = g_string_new(""); + + return g_markup_parse_context_new(&parser_settings, 0, credentials, NULL); +} + +static void parser_cleanup(GMarkupParseContext * context) { + GError * error = NULL; + g_markup_parse_context_end_parse(context, &error); + + if (error != NULL) { + g_fprintf (stderr, "Unexpected end of Amazon response: %s\n", + error->message); + exit(EXIT_FAILURE); + } + + g_markup_parse_context_free(context); +} + +/* This function is responsible for the whole output thing. */ +static void do_output(Credentials * rare) { + if (rare == NULL || + rare->user_token == NULL || !rare->user_token->len || + rare->access_key == NULL || !rare->access_key->len || + rare->secret_key == NULL || !rare->secret_key->len) { + g_fprintf(stderr, "Missing authentication data in response!\n"); + exit(EXIT_FAILURE); + } + + g_printf("device_property \"S3_USER_TOKEN\" \"%s\"\n" + "device_property \"S3_ACCESS_KEY\" \"%s\"\n" + "device_property \"S3_SECRET_KEY\" \"%s\"\n", + rare->user_token->str, rare->access_key->str, + rare->secret_key->str); +} + +int main(int argc, char ** argv) { + const char * key; + GMarkupParseContext * parser; + Credentials credentials; + + key = parse_commandline(argc, argv); + + curl_global_init(CURL_GLOBAL_ALL); + parser = parser_init(&credentials); + + do_server_stuff(key, parser); + + curl_global_cleanup(); + parser_cleanup(parser); + + do_output(&credentials); + + return 0; +} diff --git a/device-src/device.c b/device-src/device.c new file mode 100644 index 0000000..001db2a --- /dev/null +++ b/device-src/device.c @@ -0,0 +1,1121 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* The Device API abstracts device workings, interaction, properties, and + * capabilities from the rest of the Amanda code base. It supports + * pluggable modules for different kinds of devices. */ + +#include "amanda.h" +#include "conffile.h" + +#include + +#include "device.h" +#include "queueing.h" +#include "property.h" + +#include "null-device.h" +#include "timestamp.h" +#include "vfs-device.h" +#include "util.h" +#ifdef WANT_TAPE_DEVICE +#include "tape-device.h" +#endif +#include "rait-device.h" +#ifdef WANT_S3_DEVICE + #include "s3-device.h" +#endif + +static GHashTable* driverList = NULL; + +void device_api_init(void) { + g_type_init(); + amanda_thread_init(); + device_property_init(); + driverList = g_hash_table_new(g_str_hash, g_str_equal); + + /* register other types and devices. */ + null_device_register(); + vfs_device_register(); +#ifdef WANT_TAPE_DEVICE + tape_device_register(); +#endif + rait_device_register(); +#ifdef WANT_S3_DEVICE + s3_device_register(); +#endif +} + +void register_device(DeviceFactory factory, + const char ** device_prefix_list) { + char ** tmp; + g_assert(driverList != NULL); + g_assert(factory != NULL); + g_return_if_fail(device_prefix_list != NULL); + g_return_if_fail(*device_prefix_list != NULL); + + tmp = (char**)device_prefix_list; + while (*tmp != NULL) { + g_hash_table_insert(driverList, *tmp, (gpointer)factory); + tmp ++; + } +} + +static DeviceFactory lookup_device_factory(const char *device_name) { + gpointer key, value; + g_assert(driverList != NULL); + + if (g_hash_table_lookup_extended(driverList, device_name, &key, &value)) { + return (DeviceFactory)value; + } else { + return NULL; + } +} + +static const GFlagsValue read_label_status_flags_values[] = { + { READ_LABEL_STATUS_SUCCESS, + "READ_LABEL_STATUS_SUCCESS", + "Success" }, + { READ_LABEL_STATUS_DEVICE_MISSING, + "READ_LABEL_STATUS_DEVICE_MISSING", + "Device not found" }, + { READ_LABEL_STATUS_DEVICE_ERROR, + "READ_LABEL_STATUS_DEVICE_ERROR", + "Device error" }, + { READ_LABEL_STATUS_VOLUME_MISSING, + "READ_LABEL_STATUS_VOLUME_MISSING", + "Volume not found" }, + { READ_LABEL_STATUS_VOLUME_UNLABELED, + "READ_LABEL_STATUS_VOLUME_UNLABELED", + "Volume not labeled" }, + { READ_LABEL_STATUS_VOLUME_ERROR, + "READ_LABEL_STATUS_VOLUME_ERROR", + "Volume error" }, + { 0, NULL, NULL } +}; + +GType read_label_status_flags_get_type(void) { + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + type = g_flags_register_static("ReadLabelStatusFlags", + read_label_status_flags_values); + } + return type; +} + +/* Device class definition starts here. */ + +struct DevicePrivate_s { + /* This is the return value of the device_get_property_list() + method. */ + GArray *property_list; + GHashTable * property_response; +}; + +/* This holds the default response to a particular property. */ +typedef struct { + PropertyAccessFlags access; + GValue response; +} PropertyResponse; + +#define selfp (self->private) + +/* here are local prototypes, so we can make function pointers. */ +static void device_init (Device * o) G_GNUC_UNUSED; +static void device_class_init (DeviceClass * c) G_GNUC_UNUSED; + +static void property_response_free(PropertyResponse *o); + +static gboolean default_device_open_device(Device * self, char * device_name); +static gboolean default_device_finish(Device * self); +static gboolean default_device_start(Device * self, DeviceAccessMode mode, + char * label, char * timestamp); +static gboolean default_device_start_file (Device * self, + const dumpfile_t * jobinfo); +static gboolean default_device_write_block (Device * self, guint size, + gpointer data, gboolean last); +static gboolean default_device_write_from_fd(Device *self, int fd); +static gboolean default_device_finish_file (Device * self); +static dumpfile_t* default_device_seek_file (Device * self, guint file); +static gboolean default_device_seek_block (Device * self, guint64 block); +static int default_device_read_block (Device * self, gpointer buffer, + int * size); +static gboolean default_device_read_to_fd(Device *self, int fd); +static gboolean default_device_property_get(Device * self, DevicePropertyId ID, + GValue * value); + +/* pointer to the class of our parent */ +static GObjectClass *parent_class = NULL; + +GType +device_get_type (void) +{ + static GType type = 0; + + if G_UNLIKELY(type == 0) { + static const GTypeInfo info = { + sizeof (DeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) device_class_init, + (GClassFinalizeFunc) NULL, + NULL /* class_data */, + sizeof (Device), + 0 /* n_preallocs */, + (GInstanceInitFunc) device_init, + NULL + }; + + type = g_type_register_static (G_TYPE_OBJECT, "Device", &info, + (GTypeFlags)G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +static void device_finalize(GObject *obj_self) { + Device *self G_GNUC_UNUSED = DEVICE (obj_self); + if(G_OBJECT_CLASS(parent_class)->finalize) + (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self); + + /* Here we call device_finish() if it hasn't been done + yet. Subclasses may need to do this same check earlier. */ + if (self->access_mode != ACCESS_NULL) { + device_finish(self); + } + + amfree(self->device_name); + amfree(self->volume_label); + amfree(self->volume_time); + g_array_free(selfp->property_list, TRUE); + g_hash_table_destroy(selfp->property_response); + amfree(self->private); +} + +static void +device_init (Device * self G_GNUC_UNUSED) +{ + self->private = malloc(sizeof(DevicePrivate)); + self->device_name = NULL; + self->access_mode = ACCESS_NULL; + self->is_eof = FALSE; + self->file = -1; + self->block = 0; + self->in_file = FALSE; + self->volume_label = NULL; + self->volume_time = NULL; + selfp->property_list = g_array_new(TRUE, FALSE, sizeof(DeviceProperty)); + selfp->property_response = + g_hash_table_new_full(g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify) property_response_free); +} + +static void +device_class_init (DeviceClass * c G_GNUC_UNUSED) +{ + GObjectClass *g_object_class G_GNUC_UNUSED = (GObjectClass*) c; + + parent_class = g_type_class_ref (G_TYPE_OBJECT); + + c->open_device = default_device_open_device; + c->finish = default_device_finish; + c->read_label = NULL; + c->start = default_device_start; + c->start_file = default_device_start_file; + c->write_block = default_device_write_block; + c->write_from_fd = default_device_write_from_fd; + c->finish_file = default_device_finish_file; + c->seek_file = default_device_seek_file; + c->seek_block = default_device_seek_block; + c->read_block = default_device_read_block; + c->read_to_fd = default_device_read_to_fd; + c->property_get = default_device_property_get; + c->property_set = NULL; + c->recycle_file = NULL; + g_object_class->finalize = device_finalize; +} + +static void property_response_free(PropertyResponse * resp) { + g_value_unset(&(resp->response)); + amfree(resp); +} + +static char * +regex_message(int result, regex_t *regex) { + char * rval; + size_t size; + + size = regerror(result, regex, NULL, 0); + rval = malloc(size); + regerror(result, regex, rval, size); + + return rval; +} + +static gboolean +handle_device_regex(const char * user_name, char ** driver_name, + char ** device) { + regex_t regex; + int reg_result; + regmatch_t pmatch[3]; + static const char * regex_string = "^([a-z0-9]+):(.*)$"; + + bzero(®ex, sizeof(regex)); + + reg_result = regcomp(®ex, regex_string, REG_EXTENDED | REG_ICASE); + if (reg_result != 0) { + char * message = regex_message(reg_result, ®ex); + g_fprintf(stderr, "Error compiling regular expression \"%s\": %s\n", + regex_string, message); + amfree(message); + return FALSE; + } + + reg_result = regexec(®ex, user_name, 3, pmatch, 0); + if (reg_result != 0 && reg_result != REG_NOMATCH) { + char * message = regex_message(reg_result, ®ex); + g_fprintf(stderr, "Error applying regular expression \"%s\" to string \"%s\":\n" + "%s\n", user_name, regex_string, message); + regfree(®ex); + return FALSE; + } else if (reg_result == REG_NOMATCH) { +#ifdef WANT_TAPE_DEVICE + g_fprintf(stderr, "\"%s\" uses deprecated device naming convention; \n" + "using \"tape:%s\" instead.\n", + user_name, user_name); + *driver_name = stralloc("tape"); + *device = stralloc(user_name); +#else /* !WANT_TAPE_DEVICE */ + g_fprintf(stderr, "\"%s\" is not a valid device name.\n", user_name); + regfree(®ex); + return FALSE; +#endif /* WANT_TAPE_DEVICE */ + } else { + *driver_name = find_regex_substring(user_name, pmatch[1]); + *device = find_regex_substring(user_name, pmatch[2]); + } + regfree(®ex); + return TRUE; +} + +Device* +device_open (char * device_name) +{ + char *device_driver_name = NULL; + char *device_node_name = NULL; + DeviceFactory factory; + Device *device; + + g_return_val_if_fail (device_name != NULL, NULL); + + if (driverList == NULL) { + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, + "device_open() called without device_api_init()!\n"); + g_assert_not_reached(); + } + + if (!handle_device_regex(device_name, &device_driver_name, &device_node_name)) { + amfree(device_driver_name); + amfree(device_node_name); + return NULL; + } + + factory = lookup_device_factory(device_driver_name); + + if (factory == NULL) { + g_fprintf(stderr, "Device driver %s is not known.\n", + device_driver_name); + amfree(device_driver_name); + amfree(device_node_name); + return NULL; + } + + device = factory(device_driver_name, device_node_name); + amfree(device_driver_name); + amfree(device_node_name); + return device; +} + +void +device_add_property (Device * self, DeviceProperty * prop, GValue * response) +{ + unsigned int i; + g_return_if_fail (self != NULL); + g_return_if_fail (IS_DEVICE (self)); + g_assert(selfp->property_list != NULL); + g_assert(selfp->property_response != NULL); + + /* Delete it if it already exists. */ + for(i = 0; i < selfp->property_list->len; i ++) { + if (g_array_index(selfp->property_list, + DeviceProperty, i).base->ID == prop->base->ID) { + g_array_remove_index_fast(selfp->property_list, i); + break; + } + } + + g_array_append_val(selfp->property_list, *prop); + + if (response != NULL) { + PropertyResponse * property_response; + + g_return_if_fail(G_IS_VALUE(response)); + + property_response = malloc(sizeof(*property_response)); + property_response->access = prop->access; + bzero(&(property_response->response), + sizeof(property_response->response)); + g_value_init(&(property_response->response), + G_VALUE_TYPE(response)); + g_value_copy(response, &(property_response->response)); + + g_hash_table_insert(selfp->property_response, + GINT_TO_POINTER(prop->base->ID), + property_response); + } +} + +const DeviceProperty * +device_property_get_list (Device * self) +{ + g_return_val_if_fail (self != NULL, (const DeviceProperty * )0); + g_return_val_if_fail (IS_DEVICE (self), (const DeviceProperty * )0); + + return (const DeviceProperty*) selfp->property_list->data; +} + +guint device_write_min_size(Device * self) { + GValue g_tmp; + int block_size, min_block_size; + + bzero(&g_tmp, sizeof(g_tmp)); + device_property_get(self, PROPERTY_BLOCK_SIZE, &g_tmp); + block_size = g_value_get_int(&g_tmp); + g_value_unset(&g_tmp); + if (block_size > 0) { + return block_size; + } + + /* variable block size */ + device_property_get(self, PROPERTY_MIN_BLOCK_SIZE, &g_tmp); + min_block_size = g_value_get_uint(&g_tmp); + g_value_unset(&g_tmp); + return min_block_size; +} + +guint device_write_max_size(Device * self) { + GValue g_tmp; + int block_size, max_block_size; + + bzero(&g_tmp, sizeof(g_tmp)); + device_property_get(self, PROPERTY_BLOCK_SIZE, &g_tmp); + block_size = g_value_get_int(&g_tmp); + g_value_unset(&g_tmp); + if (block_size > 0) { + return block_size; + } + + /* variable block size */ + device_property_get(self, PROPERTY_MAX_BLOCK_SIZE, &g_tmp); + max_block_size = g_value_get_uint(&g_tmp); + g_value_unset(&g_tmp); + return max_block_size; +} + +guint device_read_max_size(Device * self) { + GValue g_tmp; + + bzero(&g_tmp, sizeof(g_tmp)); + if (device_property_get(self, PROPERTY_READ_BUFFER_SIZE, &g_tmp)) { + guint rval = g_value_get_uint(&g_tmp); + g_value_unset(&g_tmp); + return rval; + } else { + return device_write_max_size(self); + } +} + +char * device_build_amanda_header(Device * self, const dumpfile_t * info, + int * size, gboolean * oneblock) { + char *amanda_header; + unsigned int min_header_length; + unsigned int header_buffer_size; + + min_header_length = device_write_min_size(self); + amanda_header = build_header(info, min_header_length); + header_buffer_size = MAX(min_header_length, strlen(amanda_header)+1); + if (size != NULL) + *size = header_buffer_size; + if (oneblock != NULL) + *oneblock = (header_buffer_size <= device_write_max_size(self)); + return amanda_header; +} + +dumpfile_t * make_tapestart_header(Device * self, char * label, + char * timestamp) { + dumpfile_t * rval; + + g_return_val_if_fail(label != NULL, NULL); + + rval = malloc(sizeof(*rval)); + fh_init(rval); + rval->type = F_TAPESTART; + amfree(self->volume_time); + if (get_timestamp_state(timestamp) == TIME_STATE_REPLACE) { + self->volume_time = get_proper_stamp_from_time(time(NULL)); + } else { + self->volume_time = g_strdup(timestamp); + } + strncpy(rval->datestamp, self->volume_time, sizeof(rval->datestamp)); + strncpy(rval->name, label, sizeof(rval->name)); + + return rval; +} + +dumpfile_t * make_tapeend_header(void) { + dumpfile_t * rval; + char * timestamp; + + rval = malloc(sizeof(*rval)); + rval->type = F_TAPEEND; + timestamp = get_timestamp_from_time(time(NULL)); + strncpy(rval->datestamp, timestamp, sizeof(rval->datestamp)); + amfree(timestamp); + return rval; +} + +/* Try setting max/fixed blocksize on a device. Check results, fallback, and + * print messages for problems. */ +static void try_set_blocksize(Device * device, guint blocksize, + gboolean try_max_first) { + GValue val; + gboolean success; + bzero(&val, sizeof(val)); + g_value_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, blocksize); + if (try_max_first) { + success = device_property_set(device, + PROPERTY_MAX_BLOCK_SIZE, + &val); + if (!success) { + g_fprintf(stderr, "Setting MAX_BLOCK_SIZE to %u " + "not supported for device %s.\n" + "trying BLOCK_SIZE instead.\n", + blocksize, device->device_name); + } else { + g_value_unset(&val); + return; + } + } + + g_value_unset(&val); + g_value_init(&val, G_TYPE_INT); + g_value_set_int(&val, blocksize); + success = device_property_set(device, + PROPERTY_BLOCK_SIZE, + &val); + if (!success) { + g_fprintf(stderr, "Setting BLOCK_SIZE to %u " + "not supported for device %s.\n", + blocksize, device->device_name); + } + g_value_unset(&val); +} + +/* A GHFunc (callback for g_hash_table_foreach) */ +static void set_device_property(gpointer key_p, gpointer value_p, + gpointer user_data_p) { + char * property_s = key_p; + char * value_s = value_p; + Device * device = user_data_p; + const DevicePropertyBase* property_base; + GValue property_value; + + g_return_if_fail(IS_DEVICE(device)); + g_return_if_fail(property_s != NULL); + g_return_if_fail(value_s != NULL); + + property_base = device_property_get_by_name(property_s); + if (property_base == NULL) { + /* Nonexistant property name. */ + g_fprintf(stderr, _("Unknown device property name %s.\n"), property_s); + return; + } + + bzero(&property_value, sizeof(property_value)); + g_value_init(&property_value, property_base->type); + if (!g_value_set_from_string(&property_value, value_s)) { + /* Value type could not be interpreted. */ + g_fprintf(stderr, + _("Could not parse property value %s for property type %s.\n"), + value_s, g_type_name(property_base->type)); + return; + } else { + g_assert (G_VALUE_HOLDS(&property_value, property_base->type)); + } + + if (!device_property_set(device, property_base->ID, &property_value)) { + /* Device rejects property. */ + g_fprintf(stderr, _("Could not set property %s to %s on device %s.\n"), + property_base->name, value_s, device->device_name); + return; + } +} + +/* Set up first-run properties, including DEVICE_MAX_VOLUME_USAGE property + * based on the tapetype. */ +void device_set_startup_properties_from_config(Device * device) { + char * tapetype_name = getconf_str(CNF_TAPETYPE); + if (tapetype_name != NULL) { + tapetype_t * tapetype = lookup_tapetype(tapetype_name); + if (tapetype != NULL) { + GValue val; + guint64 length; + guint blocksize_kb; + gboolean success; + + bzero(&val, sizeof(GValue)); + + if (tapetype_seen(tapetype, TAPETYPE_LENGTH)) { + length = tapetype_get_length(tapetype); + g_value_init(&val, G_TYPE_UINT64); + g_value_set_uint64(&val, length * 1024); + /* If this fails, it's not really an error. */ + device_property_set(device, PROPERTY_MAX_VOLUME_USAGE, &val); + g_value_unset(&val); + } + + if (tapetype_seen(tapetype, TAPETYPE_READBLOCKSIZE)) { + blocksize_kb = tapetype_get_readblocksize(tapetype); + g_value_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, blocksize_kb * 1024); + success = device_property_set(device, + PROPERTY_READ_BUFFER_SIZE, + &val); + g_value_unset(&val); + if (!success) { + g_fprintf(stderr, "Setting READ_BUFFER_SIZE to %llu " + "not supported for device %s.\n", + 1024*(long long unsigned int)blocksize_kb, + device->device_name); + } + } + + if (tapetype_seen(tapetype, TAPETYPE_BLOCKSIZE)) { + blocksize_kb = tapetype_get_blocksize(tapetype); + try_set_blocksize(device, blocksize_kb * 1024, + !tapetype_get_file_pad(tapetype)); + } + } + } + + g_hash_table_foreach(getconf_proplist(CNF_DEVICE_PROPERTY), + set_device_property, device); +} + +void device_clear_volume_details(Device * device) { + if (device == NULL || device->access_mode != ACCESS_NULL) { + return; + } + + amfree(device->volume_label); + amfree(device->volume_time); +} + +/* Here we put default implementations of virtual functions. Since + this class is virtual, many of these functions offer at best + incomplete functionality. But they do offer the useful commonality + that all devices can expect to need. */ + +/* This function only updates access_mode, volume_label, and volume_time. */ +static gboolean +default_device_start (Device * self, DeviceAccessMode mode, char * label, + char * timestamp) { + if (mode != ACCESS_WRITE && self->volume_label == NULL) { + g_debug("default_device_start calling device_read_label with mode %d", mode); + if (device_read_label(self) != READ_LABEL_STATUS_SUCCESS) + return FALSE; + } else if (mode == ACCESS_WRITE) { + self->volume_label = newstralloc(self->volume_label, label); + self->volume_time = newstralloc(self->volume_time, timestamp); + } + self->access_mode = mode; + + return TRUE; +} + +static gboolean default_device_open_device(Device * self, + char * device_name) { + DeviceProperty prop; + guint i; + + self->device_name = stralloc(device_name); + + prop.base = &device_property_canonical_name; + prop.access = PROPERTY_ACCESS_GET_MASK; + + for(i = 0; i < selfp->property_list->len; i ++) { + if (g_array_index(selfp->property_list, + DeviceProperty, i).base->ID == prop.base->ID) { + return TRUE; + } + } + /* If we got here, the property was not registered. */ + device_add_property(self, &prop, NULL); + + return TRUE; +} + +/* This default implementation does very little. */ +static gboolean +default_device_finish (Device * self) { + self->access_mode = ACCESS_NULL; + return TRUE; +} + +/* This function updates the file, in_file, and block attributes. */ +static gboolean +default_device_start_file (Device * self, + const dumpfile_t * jobInfo G_GNUC_UNUSED) { + self->in_file = TRUE; + if (self->file <= 0) + self->file = 1; + else + self->file ++; + self->block = 0; + return TRUE; +} + +/* This function lies: It updates the block number and maybe calls + device_finish_file(), but returns FALSE. */ +static gboolean +default_device_write_block(Device * self, guint size G_GNUC_UNUSED, + gpointer data G_GNUC_UNUSED, gboolean last_block) { + self->block ++; + if (last_block) + device_finish_file(self); + return FALSE; +} + +/* This function lies: It updates the block number, but returns + -1. */ +static int +default_device_read_block(Device * self, gpointer buf G_GNUC_UNUSED, + int * size G_GNUC_UNUSED) { + self->block ++; + return -1; +} + +/* This function just updates the in_file field. */ +static gboolean +default_device_finish_file(Device * self) { + self->in_file = FALSE; + return TRUE; +} + +/* This function just updates the file number. */ +static dumpfile_t * +default_device_seek_file(Device * self, guint file) { + self->in_file = TRUE; + self->file = file; + return NULL; +} + +/* This function just updates the block number. */ +static gboolean +default_device_seek_block(Device * self, guint64 block) { + self->block = block; + return TRUE; +} + +/* This default implementation serves up static responses, and + implements a default response to the "canonical name" property. */ + +static gboolean +default_device_property_get(Device * self, DevicePropertyId ID, + GValue * value) { + const PropertyResponse * resp; + + resp = (PropertyResponse*)g_hash_table_lookup(selfp->property_response, + GINT_TO_POINTER(ID)); + if (resp == NULL) { + if (ID == PROPERTY_CANONICAL_NAME) { + g_value_unset_init(value, G_TYPE_STRING); + g_value_set_string(value, self->device_name); + return TRUE; + } else { + return FALSE; + } + } + + g_value_unset_copy(&resp->response, value); + + return TRUE; +} + +static gboolean +default_device_read_to_fd(Device *self, int fd) { + GValue val; + StreamingRequirement streaming_mode; + + /* Get the device's parameters */ + bzero(&val, sizeof(val)); + if (!device_property_get(self, PROPERTY_STREAMING, &val) + || !G_VALUE_HOLDS(&val, STREAMING_REQUIREMENT_TYPE)) { + streaming_mode = STREAMING_REQUIREMENT_REQUIRED; + } else { + streaming_mode = g_value_get_enum(&val); + } + + return QUEUE_SUCCESS == + do_consumer_producer_queue_full( + device_read_producer, + self, + fd_write_consumer, + GINT_TO_POINTER(fd), + device_read_max_size(self), + DEFAULT_MAX_BUFFER_MEMORY, + streaming_mode); +} + +static gboolean +default_device_write_from_fd(Device *self, int fd) { + GValue val; + StreamingRequirement streaming_mode; + + /* Get the device's parameters */ + bzero(&val, sizeof(val)); + if (!device_property_get(self, PROPERTY_STREAMING, &val) + || !G_VALUE_HOLDS(&val, STREAMING_REQUIREMENT_TYPE)) { + streaming_mode = STREAMING_REQUIREMENT_REQUIRED; + } else { + streaming_mode = g_value_get_enum(&val); + } + + return QUEUE_SUCCESS == + do_consumer_producer_queue_full( + fd_read_producer, + GINT_TO_POINTER(fd), + device_write_consumer, + self, + device_write_max_size(self), + DEFAULT_MAX_BUFFER_MEMORY, + streaming_mode); +} + +/* XXX WARNING XXX + * All the functions below this comment are stub functions that do nothing + * but implement the virtual function table. Call these functions and they + * will do what you expect vis-a-vis virtual functions. But don't put code + * in them beyond error checking and VFT lookup. */ + +gboolean +device_open_device (Device * self, char * device_name) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (device_name != NULL, FALSE); + klass = DEVICE_GET_CLASS(self); + + if(klass->open_device) + return (*klass->open_device)(self,device_name); + else + return FALSE; +} + +ReadLabelStatusFlags device_read_label(Device * self) { + DeviceClass * klass; + g_debug("device_read_label; mode = %d", self->access_mode); + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail(IS_DEVICE(self), FALSE); + g_return_val_if_fail(self->access_mode == ACCESS_NULL, FALSE); + + klass = DEVICE_GET_CLASS(self); + if (klass->read_label) { + return (klass->read_label)(self); + } else { + return ~ READ_LABEL_STATUS_SUCCESS; + } +} + +gboolean +device_finish (Device * self) { + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + + if (self->access_mode == ACCESS_NULL) + return TRUE; + + klass = DEVICE_GET_CLASS(self); + if (klass->finish) { + return (*klass->finish)(self); + } else { + return FALSE; + } +} + +/* For a good combination of synchronization and public simplicity, + this stub function does not take a timestamp, but the actual + implementation function does. We generate the timestamp here with + time(). */ +gboolean +device_start (Device * self, DeviceAccessMode mode, + char * label, char * timestamp) +{ + DeviceClass *klass; + + g_debug("device_start mode = %d", mode); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (mode != ACCESS_NULL, FALSE); + g_return_val_if_fail (mode != ACCESS_WRITE || label != NULL, + FALSE); + klass = DEVICE_GET_CLASS(self); + + if(klass->start) { + char * local_timestamp = NULL; + gboolean rv; + + /* fill in a timestamp if none was given */ + if (mode == ACCESS_WRITE && + get_timestamp_state(timestamp) == TIME_STATE_REPLACE) { + local_timestamp = timestamp = + get_proper_stamp_from_time(time(NULL)); + } + + rv = (*klass->start)(self, mode, label, timestamp); + amfree(local_timestamp); + g_debug("device_start done; dev->access_mode = %d, result %d", self->access_mode, rv); + return rv; + } else { + return FALSE; + } +} + +gboolean +device_write_block (Device * self, guint size, gpointer block, + gboolean short_block) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (size > 0, FALSE); + g_return_val_if_fail (short_block || + size >= device_write_min_size(self), FALSE); + g_return_val_if_fail (size <= device_write_max_size(self), FALSE); + g_return_val_if_fail (block != NULL, FALSE); + g_return_val_if_fail (IS_WRITABLE_ACCESS_MODE(self->access_mode), + FALSE); + + klass = DEVICE_GET_CLASS(self); + + if(klass->write_block) + return (*klass->write_block)(self,size, block, short_block); + else + return FALSE; +} + +gboolean +device_write_from_fd (Device * self, int fd) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (fd >= 0, FALSE); + g_return_val_if_fail (IS_WRITABLE_ACCESS_MODE(self->access_mode), + FALSE); + + klass = DEVICE_GET_CLASS(self); + + if(klass->write_from_fd) + return (*klass->write_from_fd)(self,fd); + else + return FALSE; +} + +gboolean +device_start_file (Device * self, const dumpfile_t * jobInfo) { + DeviceClass * klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (!(self->in_file), FALSE); + g_return_val_if_fail (jobInfo != NULL, FALSE); + + klass = DEVICE_GET_CLASS(self); + + if(klass->start_file) + return (*klass->start_file)(self, jobInfo ); + else + return FALSE; +} + +gboolean +device_finish_file (Device * self) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (IS_WRITABLE_ACCESS_MODE(self->access_mode), + FALSE); + g_return_val_if_fail (self->in_file, FALSE); + + klass = DEVICE_GET_CLASS(self); + + if(klass->finish_file) + return (*klass->finish_file)(self); + else + return FALSE; +} + +dumpfile_t* +device_seek_file (Device * self, guint file) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (IS_DEVICE (self), NULL); + g_return_val_if_fail (self->access_mode == ACCESS_READ, + NULL); + + klass = DEVICE_GET_CLASS(self); + + if(klass->seek_file) + return (*klass->seek_file)(self,file); + else + return FALSE; +} + +gboolean +device_seek_block (Device * self, guint64 block) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (self->access_mode == ACCESS_READ, + FALSE); + g_return_val_if_fail (self->in_file, FALSE); + + klass = DEVICE_GET_CLASS(self); + + if(klass->seek_block) + return (*klass->seek_block)(self,block); + else + return FALSE; +} + +int +device_read_block (Device * self, gpointer buffer, int * size) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, -1); + g_return_val_if_fail (IS_DEVICE (self), -1); + g_return_val_if_fail (size != NULL, -1); + g_return_val_if_fail (self->access_mode == ACCESS_READ, -1); + if (*size != 0) { + g_return_val_if_fail (buffer != NULL, -1); + } + + /* Do a quick check here, so fixed-block subclasses don't have to. */ + if (*size == 0 && + device_write_min_size(self) == device_write_max_size(self)) { + *size = device_write_min_size(self); + return 0; + } + + klass = DEVICE_GET_CLASS(self); + + if(klass->read_block) + return (*klass->read_block)(self,buffer,size); + else + return -1; +} + +gboolean +device_read_to_fd (Device * self, int fd) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (fd >= 0, FALSE); + g_return_val_if_fail (self->access_mode == ACCESS_READ, FALSE); + + klass = DEVICE_GET_CLASS(self); + + if(klass->read_to_fd) + return (*klass->read_to_fd)(self,fd); + else + return FALSE; +} + + +gboolean +device_property_get (Device * self, DevicePropertyId id, GValue * val) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (device_property_get_by_id(id) != NULL, FALSE); + + klass = DEVICE_GET_CLASS(self); + + /* FIXME: Check access flags? */ + + if(klass->property_get) + return (*klass->property_get)(self,id,val); + else + return FALSE; +} + +gboolean +device_property_set (Device * self, DevicePropertyId id, GValue * val) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + + klass = DEVICE_GET_CLASS(self); + + /* FIXME: Check access flags? */ + + if(klass->property_set) + return (*klass->property_set)(self,id,val); + else + return FALSE; +} + +gboolean +device_recycle_file (Device * self, guint filenum) +{ + DeviceClass *klass; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (IS_DEVICE (self), FALSE); + g_return_val_if_fail (self->access_mode == ACCESS_APPEND, FALSE); + + klass = DEVICE_GET_CLASS(self); + + if(klass->recycle_file) + return (*klass->recycle_file)(self,filenum); + else + return FALSE; +} + diff --git a/device-src/device.h b/device-src/device.h new file mode 100644 index 0000000..262be39 --- /dev/null +++ b/device-src/device.h @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* The Device API abstracts device workings, interaction, properties, and + * capabilities from the rest of the Amanda code base. It supports + * pluggable modules for different kinds of devices. */ + +#ifndef DEVICE_H +#define DEVICE_H + +#include +#include + +#include "property.h" +#include "fileheader.h" + +/* Device API version. */ +#define DEVICE_API_VERSION 0 + +extern void device_api_init(void); + +/* Different access modes */ +typedef enum { + ACCESS_NULL, /* Device is not yet opened. */ + ACCESS_READ, + ACCESS_WRITE, + ACCESS_APPEND +} DeviceAccessMode; + +#define IS_WRITABLE_ACCESS_MODE(mode) ((mode) == ACCESS_WRITE || \ + (mode) == ACCESS_APPEND) + +/* Device object definition follows. */ + +/* + * Type checking and casting macros + */ +#define TYPE_DEVICE (device_get_type()) +#define DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), device_get_type(), Device) +#define DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), device_get_type(), Device const) +#define DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), device_get_type(), DeviceClass) +#define IS_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), device_get_type ()) + +#define DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), device_get_type(), DeviceClass) + +typedef struct DevicePrivate_s DevicePrivate; + +/* + * Main object structure + */ +typedef struct { + GObject __parent__; + + /* You can peek at the stuff below, but only subclasses should + change these values.*/ + + /* What file, block are we at? (and are we in the middle of a + * file?) This is automatically updated by + * the default implementations of start_file, finish_file, + * write_block, read_block, seek_file, and seek_block. */ + int file; + guint64 block; + gboolean in_file; + /* Holds the user-specified device name. */ + char * device_name; + /* Holds the user-specified access-mode. */ + DeviceAccessMode access_mode; + /* In reading mode, FALSE unless all the data from the current file + * was successfully read. */ + gboolean is_eof; + /* Holds the label and time of the currently-inserted volume, + * or NULL if it has not been read/written yet. */ + char * volume_label; + char * volume_time; + + DevicePrivate * private; +} Device; + +/* Pointer to factory function for device types. The factory functions + take control of their arguments, which should be dynamically + allocated. The factory should call open_device() with this + device_name. */ +typedef Device* (*DeviceFactory)(char * device_type, + char * device_name); + +/* This function registers a new device with the allocation system. + * Call it after you register your type with the GLib type system. + * This function takes ownership of the strings inside device_prefix_list, + * but not the device_prefix_list itself. */ +extern void register_device(DeviceFactory factory, + const char ** device_prefix_list); + +/* This structure is a Flags (bitwise OR of values). Zero indicates success; + * any other value indicates some kind of problem reading the label. If + * multiple bits are set, it does not necessarily indicate that /all/ of + * the specified issues occured, but rather that /at least one/ did. */ +typedef enum { + /* When changing, Also update read_label_status_flags_values in device.c */ + READ_LABEL_STATUS_SUCCESS = 0, + READ_LABEL_STATUS_DEVICE_MISSING = (1 << 0), + READ_LABEL_STATUS_DEVICE_ERROR = (1 << 1), + READ_LABEL_STATUS_VOLUME_MISSING = (1 << 2), + READ_LABEL_STATUS_VOLUME_UNLABELED = (1 << 3), + READ_LABEL_STATUS_VOLUME_ERROR = (1 << 4), + READ_LABEL_STATUS_FLAGS_MAX = (1 << 5) +} ReadLabelStatusFlags; + +#define READ_LABEL_STATUS_FLAGS_MASK (READ_LABEL_STATUS_MAX-1) +#define READ_LABEL_STATUS_FLAGS_TYPE (read_label_status_flags_get_type()) +GType read_label_status_flags_get_type(void); + +/* + * Class definition + */ +typedef struct _DeviceClass DeviceClass; +struct _DeviceClass { + GObjectClass __parent__; + gboolean (* open_device) (Device * self, + char * device_name); /* protected */ + ReadLabelStatusFlags (* read_label)(Device * self); + gboolean (* start) (Device * self, DeviceAccessMode mode, + char * label, char * timestamp); + gboolean (* start_file) (Device * self, const dumpfile_t * info); + gboolean (* write_block) (Device * self, guint size, gpointer data, + gboolean last_block); + gboolean (* write_from_fd) (Device * self, int fd); + gboolean (* finish_file) (Device * self); + dumpfile_t* (* seek_file) (Device * self, guint file); + gboolean (* seek_block) (Device * self, guint64 block); + int (* read_block) (Device * self, gpointer buf, int * size); + gboolean (* read_to_fd) (Device * self, int fd); + gboolean (* property_get) (Device * self, DevicePropertyId id, + GValue * val); + gboolean (* property_set) (Device * self, DevicePropertyId id, + GValue * val); + gboolean (* recycle_file) (Device * self, guint filenum); + gboolean (* finish) (Device * self); +}; + + +/* + * Public methods + * + * Note to implementors: The default implementation of many of these + * methods does not follow the documentation. For example, the default + * implementation of device_read_block will always return -1, but + * nonetheless update the block index in the Device structure. In + * general, it is OK to chain up to the default implmentation after + * successfully implementing whatever appears below. The particulars + * of what the default implementations do is documented in device.c. + */ +GType device_get_type (void); + +/* This is how you get a new Device. Pass in a device name like + * file:/path/to/storage, and (assuming everything goes OK) you will get + * back a nice happy Device* that you can do operations on. Note that you + * must device_start() it before you can do anything besides talk about + * properties or read the label. device_name remains the responsibility + * of the caller. */ +Device* device_open (char * device_name); + +/* This instructs the device to read the label on the current + * volume. device->volume_label will not be initalized until after this + * is called. You are encouraged to read the label only after setting any + * properties that may affect the label-reading process. */ +ReadLabelStatusFlags device_read_label (Device * self); + +/* This tells the Device that it's OK to start reading and writing + * data. Before you call this, you can only call + * device_property_{get, set} and device_read_label. You can only call + * this a second time if you call device_finish() first. + * + * You should pass a label and timestamp if and only if you are + * opening in WRITE mode (not READ or APPEND). The label and timestamp + * remain the caller's responsibility in terms of memory management. The + * passed timestamp may be NULL, in which case it will be filled in with + * the current time. */ +gboolean device_start (Device * self, + DeviceAccessMode mode, char * label, + char * timestamp); + +/* This undoes device_start, returning you to the NULL state. Do this + * if you want to (for example) change access mode. + * + * Note to subclass implementors: Call this function first from your + * finalization function. */ +gboolean device_finish (Device * self); + +/* But you can't write any data until you call this function, too. + * This function does not take ownership of the passed dumpfile_t; you must + * free it yourself. */ +gboolean device_start_file (Device * self, + const dumpfile_t * jobInfo); + +guint device_write_min_size (Device * self); +guint device_write_max_size (Device * self); +guint device_read_max_size (Device * self); + +/* Does what you expect. size had better be inside the block size + * range, or this function will write nothing. + * + * The short_block parameter needs some additional explanation: If + * short_block is set to TRUE, then this function will accept a write + * smaller than the minimum block size, subject to the following + * caveats: + * % The block may be padded with NULL bytes, which will be present on + * restore. + * % device_write_block will automatically call device_finish_file() + * after writing this short block. + * It is permitted to use short_block with a block that is not short; + * in this case, it is equivalent to calling device_write() and then + * calling device_finish_file(). */ +gboolean device_write_block (Device * self, + guint size, + gpointer data, + gboolean short_block); + +/* This will drain the given fd (reading until EOF), and write the + * resulting data out to the device using maximally-sized blocks. */ +gboolean device_write_from_fd (Device * self, + int fd); + +/* Call this when you are finished writing a file. This function will + * write a filemark or the local equivalent, flush the buffers, and do + * whatever dirty work needs to be done at such a point in time. */ +gboolean device_finish_file (Device * self); + +/* For reading only: Seeks to the beginning of a particular + * filemark. Only do this when reading; opening in + * ACCESS_WRITE will start you out at the first file, and opening in + * ACCESS_APPEND will automatically seek to the end of the medium. + * + * If the requested file doesn't exist, this function will seek to the + * next-numbered valid file. You can check where this function seeked to + * by examining the file field of the Device structure. If the requested + * file number is exactly one more than the last valid file, this + * function returns a TAPEEND header. + * + * If an error occurs or if the requested file is two or more beyond the + * last valid file, this function returns NULL. + * + * Example results for a volume that has only files 1 and 3: + * 1 -> Seeks to file 1 + * 2 -> Seeks to file 3 + * 3 -> Seeks to file 3 + * 4 -> Returns TAPEEND + * 5 -> Returns NULL + * + * The returned dumpfile_t is yours to keep, at no extra charge. */ +dumpfile_t* device_seek_file (Device * self, + guint file); + +/* After you have called device_seek_file (and /only/ after having + * called device_seek_file), you can call this to seek to a particular + * block inside the file. It works like SEEK_SET, only in blocks. */ +gboolean device_seek_block (Device * self, + guint64 block); + +/* After you have called device_seek_file and/or device_seek_block, + * you can start calling this function. It always reads exactly one whole + * block at a time, however big that might be. You must pass in a buffer and + * specify its size. If the buffer is big enough, the read is + * performed, and both *size and the return value are equal to the + * number of bytes actually read. If the buffer is not big enough, then + * no read is performed, the function returns 0, and *size is set + * to the minimum buffer size required to read the next block. If an + * error occurs, the function returns -1 and *size is left unchanged. + * + * It is not an error if buffer == NULL and *size == 0. This should be + * treated as a query as to the possible size of the next block. */ +int device_read_block (Device * self, + gpointer buffer, + int * size); + +/* This is the reading equivalent of device_write_from_fd(). It will + * read from the device from the current location until end of file, + * and drains the results out into the specified fd. Returns FALSE if + * there is a problem writing to the fd. */ +gboolean device_read_to_fd (Device * self, + int fd); + +/* This function tells you what properties are supported by this + * device, and when you are allowed to get and set them. The return + * value is an array of DeviceProperty structs. The last struct in + * the array is zeroed, so you know when the end is (check the + * pointer element "base"). The return value from this function on any + * given object (or physical device) should be invariant. */ +const DeviceProperty * device_property_get_list (Device * self); + +/* These functions get or set a particular property. The val should be + * compatible with the DevicePropertyBase associated with the given + * DevicePropertyId, and this function should only be called when + * DeviceProperty.access says it is OK. Otherwise you will get an + * error and not the tasty property action you wanted. */ +gboolean device_property_get (Device * self, + DevicePropertyId id, + GValue * val); +gboolean device_property_set (Device * self, + DevicePropertyId id, + GValue * val); + +/* On devices that support it (check PROPERTY_PARTIAL_DELETION), + * this will free only the space associated with a particular file. + * This way, you can apply a different retention policy to every file + * on the volume, appending new data at the end and recycling anywhere + * in the middle -- even simultaneously (via different Device + * handles)! Note that you generally can't recycle a file that is presently in + * use (being read or written). + * + * To use this, open the device as DEVICE_MODE_APPEND. But you don't + * have to call device_start_file(), unless you want to write some + * data, too. */ +gboolean device_recycle_file (Device * self, + guint filenum); + +/* Protected methods. Don't call these except in subclass implementations. */ + +/* Registers a new device / property pair. Every superclass of Device + * should call this in its init() function. At the moment, any + * particular property Id can only be registered once per object. + * + * If you want to register a standard response to a property (e.g., + * whether or not the device supports compression), you can pass a + * non-NULL response. Then the default implementation of + * device_get_property (which you may override) will return this + * response. + * The contents of prop and response are copied into a private array, so the + * calling function retains ownership of all arguments. + */ +void device_add_property(Device * self, DeviceProperty * prop, + GValue * response); + +/* This method provides post-construction initalization once the + * device name is known. It should only be used by Device + * factories. It is provided here as a virtual method (instead of + * a static function) because some devices may want to chain + * initilization to their parents. */ +gboolean device_open_device (Device * self, + char * device_name); + +/* Builds a proper header based on device block size possibilities. + * If non-null, size is filled in with the number of bytes that should + * be written. + * If non-null, oneblock is filled in with TRUE if the header will fit + * in a single Device block (FALSE otherwise). */ +char * device_build_amanda_header(Device * self, const dumpfile_t * jobinfo, + int * size, gboolean * oneblock); + +/* Does what you expect. You have to free the returned header. Ensures + that self->volume_time matches the header written to tape. */ +dumpfile_t * make_tapestart_header(Device * self, char * label, + char * timestamp); + +/* Does what you expect. Uses the current time. */ +dumpfile_t * make_tapeend_header(void); + +/* Set up first-run properties from loaded configuration file, including + * DEVICE_MAX_VOLUME_USAGE property based on the tapetype. */ +void device_set_startup_properties_from_config(Device * device); + +/* Erase any stored volume information. Use this if something happens (e.g., + * a property is set) that voids previously-read volume details. + * This function is a NOOP unless the device is in the NULL state. */ +void device_clear_volume_details(Device * device); + +#endif /* DEVICE_H */ diff --git a/device-src/null-device.c b/device-src/null-device.c new file mode 100644 index 0000000..a6b1a02 --- /dev/null +++ b/device-src/null-device.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include "amanda.h" +#include "device.h" +#include "null-device.h" + +#define NULL_DEVICE_MIN_BLOCK_SIZE (1) +#define NULL_DEVICE_MAX_BLOCK_SIZE SHRT_MAX + +/* here are local prototypes */ +static void null_device_init (NullDevice * o); +static void null_device_class_init (NullDeviceClass * c); +static gboolean null_device_start (Device * self, DeviceAccessMode mode, + char * label, char * timestamp); +static gboolean null_device_write_block (Device * self, guint size, + gpointer data, gboolean last); +static Device* null_device_factory(char * device_type, + char * device_name); + +/* pointer to the class of our parent */ +static DeviceClass *parent_class = NULL; + +void null_device_register(void) { + static const char * device_prefix_list[] = { "null", NULL }; + register_device(null_device_factory, device_prefix_list); +} + +GType +null_device_get_type (void) +{ + static GType type = 0; + + if G_UNLIKELY(type == 0) { + static const GTypeInfo info = { + sizeof (NullDeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) null_device_class_init, + (GClassFinalizeFunc) NULL, + NULL /* class_data */, + sizeof (NullDevice), + 0 /* n_preallocs */, + (GInstanceInitFunc) null_device_init, + NULL + }; + + type = g_type_register_static (TYPE_DEVICE, "NullDevice", &info, + (GTypeFlags)0); + } + + return type; +} + +static void +null_device_init (NullDevice * self) +{ + Device * o; + DeviceProperty prop; + GValue response; + + o = (Device*)(self); + bzero(&response, sizeof(response)); + + /* Register properties */ + prop.base = &device_property_concurrency; + prop.access = PROPERTY_ACCESS_GET_MASK; + g_value_init(&response, CONCURRENCY_PARADIGM_TYPE); + g_value_set_enum(&response, CONCURRENCY_PARADIGM_RANDOM_ACCESS); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + + prop.base = &device_property_streaming; + g_value_init(&response, STREAMING_REQUIREMENT_TYPE); + g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_block_size; + g_value_init(&response, G_TYPE_INT); + g_value_set_int(&response, -1); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_min_block_size; + g_value_init(&response, G_TYPE_UINT); + g_value_set_uint(&response, NULL_DEVICE_MIN_BLOCK_SIZE); + device_add_property(o, &prop, &response); + + prop.base = &device_property_max_block_size; + g_value_set_uint(&response, NULL_DEVICE_MAX_BLOCK_SIZE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_appendable; + g_value_init(&response, G_TYPE_BOOLEAN); + g_value_set_boolean(&response, FALSE); + device_add_property(o, &prop, &response); + + prop.base = &device_property_partial_deletion; + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_canonical_name; + g_value_init(&response, G_TYPE_STRING); + g_value_set_static_string(&response, "null:"); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_medium_access_type; + g_value_init(&response, MEDIA_ACCESS_MODE_TYPE); + g_value_set_enum(&response, MEDIA_ACCESS_MODE_WRITE_ONLY); + device_add_property(o, &prop, &response); + g_value_unset(&response); +} + +static void +null_device_class_init (NullDeviceClass * c G_GNUC_UNUSED) +{ + DeviceClass *device_class = (DeviceClass *)c; + + parent_class = g_type_class_ref (TYPE_DEVICE); + + device_class->start = null_device_start; + device_class->write_block = null_device_write_block; +} + + +static Device* null_device_factory(char * device_type, + char * device_name G_GNUC_UNUSED) { + g_assert(0 == strcmp(device_type, "null")); + return DEVICE(g_object_new(TYPE_NULL_DEVICE, NULL)); + +} + +/* Begin virtual function overrides */ + +static gboolean +null_device_start (Device * pself, DeviceAccessMode mode, + char * label, char * timestamp) { + NullDevice * self; + self = NULL_DEVICE(pself); + g_return_val_if_fail (self != NULL, FALSE); + + if (mode == ACCESS_WRITE) { + if (parent_class->start) { + return parent_class->start((Device*)self, mode, label, timestamp); + } else { + return TRUE; + } + } else { + g_fprintf(stderr, "Can't open NULL device for reading or appending.\n"); + return FALSE; + } +} + +static gboolean +null_device_write_block (Device * pself, guint size, gpointer data, + gboolean last_block) { + NullDevice * self; + self = NULL_DEVICE(pself); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + if ((size < NULL_DEVICE_MIN_BLOCK_SIZE && !last_block) || + size > NULL_DEVICE_MAX_BLOCK_SIZE) { + return FALSE; + } else { + if (parent_class->write_block) { + /* Calls device_finish_file(). */ + parent_class->write_block((Device*)self, size, data, last_block); + } + return TRUE; + } + + g_assert_not_reached(); +} diff --git a/device-src/null-device.h b/device-src/null-device.h new file mode 100644 index 0000000..b68a824 --- /dev/null +++ b/device-src/null-device.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* The NULL device accepts data and sends it to the bit bucket. Like + /dev/null, you cannot read from the NULL device -- only + write. While useful for testing, the NULL device is incredibly + dangerous in practice (because it eats your data). So it will + generate warnings whenever you use it. */ + +#include +#include +#ifndef __NULL_DEVICE_H__ +#define __NULL_DEVICE_H__ + +/* This header file is very boring, because the class just overrides + existing methods. */ + +/* + * Type checking and casting macros + */ +#define TYPE_NULL_DEVICE (null_device_get_type()) +#define NULL_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), null_device_get_type(), NullDevice) +#define NULL_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), null_device_get_type(), NullDevice const) +#define NULL_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), null_device_get_type(), NullDeviceClass) +#define IS_NULL_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), null_device_get_type ()) + +#define NULL_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), null_device_get_type(), NullDeviceClass) + +/* + * Main object structure + */ +#ifndef __TYPEDEF_NULL_DEVICE__ +#define __TYPEDEF_NULL_DEVICE__ +typedef struct _NullDevice NullDevice; +#endif +struct _NullDevice { + Device __parent__; +}; + +/* + * Class definition + */ +typedef struct _NullDeviceClass NullDeviceClass; +struct _NullDeviceClass { + DeviceClass __parent__; + gboolean in_file; +}; + + +/* + * Public methods + */ +GType null_device_get_type (void); +void null_device_register (void); + +#endif diff --git a/device-src/property.c b/device-src/property.c new file mode 100644 index 0000000..3980a3f --- /dev/null +++ b/device-src/property.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include "amanda.h" + +#include "property.h" + +static const GEnumValue _concurrency_paradigm_values[] = { + { CONCURRENCY_PARADIGM_EXCLUSIVE, + "CONCURRENCY_PARADIGM_EXCLUSIVE", + "exclusive" }, + { CONCURRENCY_PARADIGM_SHARED_READ, + "CONCURRENCY_PARADIGM_SHARED_READ", + "shared-read" }, + { CONCURRENCY_PARADIGM_RANDOM_ACCESS, + "CONCURRENCY_PARADIGM_RANDOM_ACCESS", + "random-access" }, + { 0, NULL, NULL } +}; + +GType concurrency_paradigm_get_type (void) { + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + type = g_enum_register_static ("ConcurrencyParadigm", + _concurrency_paradigm_values); + } + return type; +} + +static const GEnumValue _streaming_requirement_values[] = { + { STREAMING_REQUIREMENT_NONE, + "STREAMING_REQUIREMENT_NONE", + "none" }, + { STREAMING_REQUIREMENT_DESIRED, + "STREAMING_REQUIREMENT_DESIRED", + "desired" }, + { STREAMING_REQUIREMENT_REQUIRED, + "STREAMING_REQUIREMENT_REQUIRED", + "required" }, + { 0, NULL, NULL } +}; + +GType streaming_requirement_get_type (void) { + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + type = g_enum_register_static ("StreamingRequirement", + _streaming_requirement_values); + } + return type; +} + +static const GEnumValue _media_access_mode_values[] = { + { MEDIA_ACCESS_MODE_READ_ONLY, + "MEDIA_ACCESS_MODE_READ_ONLY", + (char *)"read-only" }, + { MEDIA_ACCESS_MODE_WORM, + "MEDIA_ACCESS_MODE_WORM", + (char *)"write-once-read-many" }, + { MEDIA_ACCESS_MODE_READ_WRITE, + "MEDIA_ACCESS_MODE_READ_WRITE", + (char *)"read-write" }, + { MEDIA_ACCESS_MODE_WRITE_ONLY, + "MEDIA_ACCESS_MODE_WRITE_ONLY", + (char *)"write-many-read-never" }, + { 0, NULL, NULL } +}; + +GType media_access_mode_get_type (void) { + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + type = g_enum_register_static ("MediaAccessMode", + _media_access_mode_values); + } + return type; +} + +/* Copy function for GBoxed QualifiedSize. */ +static gpointer qualified_size_copy(gpointer source) { + gpointer rval = malloc(sizeof(QualifiedSize)); + memcpy(rval, source, sizeof(QualifiedSize)); + return rval; +} + +GType qualified_size_get_type (void) { + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + type = g_boxed_type_register_static ("QualifiedSize", + qualified_size_copy, + free); + } + return type; +} + +static const GFlagsValue _feature_support_flags_values[] = { + { FEATURE_STATUS_ENABLED, + "FEATURE_STATUS_ENABLED", + "enabled" }, + { FEATURE_STATUS_DISABLED, + "FEATURE_STATUS_DISABLED", + "disabled" }, + { FEATURE_SURETY_BAD, + "FEATURE_SURETY_BAD", + "bad" }, + { FEATURE_SURETY_GOOD, + "FEATURE_SURETY_GOOD", + "good" }, + { FEATURE_SOURCE_DEFAULT, + "FEATURE_SOURCE_DEFAULT", + "default" }, + { FEATURE_SOURCE_DETECTED, + "FEATURE_SOURCE_DETECTED", + "detected" }, + { FEATURE_SOURCE_USER, + "FEATURE_SOURCE_USER", + "user"}, + { 0, NULL, NULL } +}; + +GType feature_support_get_type (void) { + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + type = g_flags_register_static ("FeatureSupportFlags", + _feature_support_flags_values); + } + return type; +} + +gboolean feature_support_flags_is_valid(FeatureSupportFlags f) { + int status = 0, surety = 0, source = 0; + + if (f & FEATURE_STATUS_ENABLED) + status ++; + if (f & FEATURE_STATUS_DISABLED) + status ++; + if (f & FEATURE_SURETY_BAD) + surety ++; + if (f & FEATURE_SURETY_GOOD) + surety ++; + if (f & FEATURE_SOURCE_DEFAULT) + source ++; + if (f & FEATURE_SOURCE_DETECTED) + source ++; + if (f & FEATURE_SOURCE_USER) + source ++; + + return (!(f & ~FEATURE_SUPPORT_FLAGS_MASK) && + status == 1 && surety == 1 && source == 1); +} + +static GSList* device_property_base_list = NULL; + +const DevicePropertyBase* device_property_get_by_id(DevicePropertyId id) { + GSList *iter; + + iter = device_property_base_list; + while (iter != NULL) { + DevicePropertyBase* rval = (DevicePropertyBase*)(iter->data); + if (rval->ID == id) { + return rval; + } + iter = g_slist_next(iter); + } + + return NULL; +} + +const DevicePropertyBase* device_property_get_by_name(const char *name) { + GSList *iter = device_property_base_list; + + g_return_val_if_fail(name != NULL, NULL); + + while (iter != NULL) { + DevicePropertyBase* rval = (DevicePropertyBase*)(iter->data); + if (strcasecmp(rval->name, name) == 0) { + return rval; + } + iter = g_slist_next(iter); + } + + return NULL; +} + +DevicePropertyId device_property_register(DevicePropertyBase* base) { + static guint id = 0; + g_assert(base != NULL); + g_assert(base->ID == -1); + g_assert(base->name != NULL); + g_assert(base->description != NULL); + + base->ID = id++; + + device_property_base_list = g_slist_prepend(device_property_base_list, + base); + return id; +} + +/* Does the same thing, but fills in a new DevicePropertyBase. */ +static void +device_property_fill_and_register(DevicePropertyBase * base, + GType type, + const char * name, + const char * desc) { + base->type = type; + base->name = name; + base->description = desc; + base->ID = -1; + device_property_register(base); +} + + +void device_property_init(void) { + device_property_fill_and_register(&device_property_concurrency, + CONCURRENCY_PARADIGM_TYPE, "concurrency", + "Supported concurrency mode (none, multiple readers, multiple writers)"); + device_property_fill_and_register(&device_property_streaming, + STREAMING_REQUIREMENT_TYPE, "streaming", + "Streaming desirability (unnecessary, desired, required)"); + device_property_fill_and_register(&device_property_compression, + G_TYPE_BOOLEAN, "compression", + "Is device performing data compression?"); + device_property_fill_and_register(&device_property_compression_rate, + G_TYPE_DOUBLE, "compression_rate", + "Compression rate, " + "averaged for some (currently undefined) period of time)"); + device_property_fill_and_register(&device_property_block_size, + G_TYPE_INT, "block_size", + "Device blocking factor in bytes."); + device_property_fill_and_register(&device_property_min_block_size, + G_TYPE_UINT, "min_block_size", + "Minimum supported blocking factor."); + device_property_fill_and_register(&device_property_max_block_size, + G_TYPE_UINT, "max_block_size", + "Maximum supported blocking factor."); + device_property_fill_and_register(&device_property_appendable, + G_TYPE_BOOLEAN, "appendable", + "Does device support appending to previously-written media?"); + device_property_fill_and_register(&device_property_canonical_name, + G_TYPE_STRING, "canonical_name", + "The most reliable device name to use to refer to this device."); + device_property_fill_and_register(&device_property_medium_access_type, + MEDIA_ACCESS_MODE_TYPE, + "medium_access_type", + "What kind of media (RO/WORM/RW/WORN) do we have here?"); + device_property_fill_and_register(&device_property_partial_deletion, + G_TYPE_BOOLEAN, "partial_deletion", + "Does this device support recycling just part of a volume?" ); + device_property_fill_and_register(&device_property_free_space, + QUALIFIED_SIZE_TYPE, "free_space", + "Remaining capacity of the device."); + device_property_fill_and_register(&device_property_max_volume_usage, + G_TYPE_UINT64, "max_volume_usage", + "Artificial limit to data written to volume."); + device_property_fill_and_register(&device_property_fsf, + FEATURE_SUPPORT_FLAGS_TYPE, "fsf", + "Does this drive support the MTFSF command?"); + device_property_fill_and_register(&device_property_bsf, + FEATURE_SUPPORT_FLAGS_TYPE, "bsf", + "Does this drive support the MTBSF command?" ); + device_property_fill_and_register(&device_property_fsr, + FEATURE_SUPPORT_FLAGS_TYPE, "fsr", + "Does this drive support the MTFSR command?"); + device_property_fill_and_register(&device_property_bsr, + FEATURE_SUPPORT_FLAGS_TYPE, "bsr", + "Does this drive support the MTBSR command?"); + /* FIXME: Is this feature even useful? */ + device_property_fill_and_register(&device_property_eom, + FEATURE_SUPPORT_FLAGS_TYPE, "eom", + "Does this drive support the MTEOM command?"); + device_property_fill_and_register(&device_property_bsf_after_eom, + FEATURE_SUPPORT_FLAGS_TYPE, + "bsf_after_eom", + "Does this drive require an MTBSF after MTEOM in order to append?" ); + device_property_fill_and_register(&device_property_final_filemarks, + G_TYPE_UINT, "final_filemarks", + "How many filemarks to write after the last tape file?" ); + device_property_fill_and_register(&device_property_read_buffer_size, + G_TYPE_UINT, "read_buffer_size", + "What buffer size should be used for reading?"); + device_property_fill_and_register(&device_property_s3_secret_key, + G_TYPE_STRING, "s3_secret_key", + "Secret access key to authenticate with Amazon S3"); + device_property_fill_and_register(&device_property_s3_access_key, + G_TYPE_STRING, "s3_access_key", + "Access key ID to authenticate with Amazon S3"); +#ifdef WANT_DEVPAY + device_property_fill_and_register(&device_property_s3_user_token, + G_TYPE_STRING, "s3_user_token", + "User token for authentication Amazon devpay requests"); +#endif + device_property_fill_and_register(&device_property_verbose, + G_TYPE_BOOLEAN, "verbose", + "Should the device produce verbose output?"); +} + +DevicePropertyBase device_property_concurrency; +DevicePropertyBase device_property_streaming; +DevicePropertyBase device_property_compression; +DevicePropertyBase device_property_compression_rate; +DevicePropertyBase device_property_block_size; +DevicePropertyBase device_property_min_block_size; +DevicePropertyBase device_property_max_block_size; +DevicePropertyBase device_property_appendable; +DevicePropertyBase device_property_canonical_name; +DevicePropertyBase device_property_medium_access_type; +DevicePropertyBase device_property_partial_deletion; +DevicePropertyBase device_property_free_space; +DevicePropertyBase device_property_max_volume_usage; +DevicePropertyBase device_property_fsf; +DevicePropertyBase device_property_bsf; +DevicePropertyBase device_property_fsr; +DevicePropertyBase device_property_bsr; +DevicePropertyBase device_property_eom; +DevicePropertyBase device_property_bsf_after_eom; +DevicePropertyBase device_property_final_filemarks; +DevicePropertyBase device_property_read_buffer_size; +DevicePropertyBase device_property_s3_access_key; +DevicePropertyBase device_property_s3_secret_key; +DevicePropertyBase device_property_s3_user_token; +DevicePropertyBase device_property_verbose; diff --git a/device-src/property.h b/device-src/property.h new file mode 100644 index 0000000..8138a05 --- /dev/null +++ b/device-src/property.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#ifndef DEVICE_PROPERTY_H +#define DEVICE_PROPERTY_H + +#include +#include + +/* The properties interface defines define capabilities and other interesting + * properties. */ + +typedef enum { + PROPERTY_PHASE_BEFORE_START = (1 << 0), + PROPERTY_PHASE_BETWEEN_FILE_WRITE = (1 << 1), + PROPERTY_PHASE_INSIDE_FILE_WRITE = (1 << 2), + PROPERTY_PHASE_BETWEEN_FILE_READ = (1 << 3), + PROPERTY_PHASE_INSIDE_FILE_READ = (1 << 4), + PROPERTY_PHASE_MAX = (1 << 5) +} PropertyPhaseFlags; + +#define PROPERTY_PHASE_MASK (PROPERTY_PHASE_MAX-1) +#define PROPERTY_PHASE_SHIFT (PROPERTY_PHASE_MASK/2) + +typedef enum { + PROPERTY_ACCESS_GET_BEFORE_START = (PROPERTY_PHASE_BEFORE_START), + PROPERTY_ACCESS_GET_BETWEEN_FILE_WRITE = + (PROPERTY_PHASE_BETWEEN_FILE_WRITE), + PROPERTY_ACCESS_GET_INSIDE_FILE_WRITE = (PROPERTY_PHASE_INSIDE_FILE_WRITE), + PROPERTY_ACCESS_GET_BETWEEN_FILE_READ = + (PROPERTY_PHASE_BETWEEN_FILE_READ), + PROPERTY_ACCESS_GET_INSIDE_FILE_READ = (PROPERTY_PHASE_INSIDE_FILE_READ), + + PROPERTY_ACCESS_SET_BEFORE_START = + (PROPERTY_PHASE_BEFORE_START << PROPERTY_PHASE_SHIFT), + PROPERTY_ACCESS_SET_BETWEEN_FILE_WRITE = + (PROPERTY_PHASE_BETWEEN_FILE_WRITE << PROPERTY_PHASE_SHIFT), + PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE = + (PROPERTY_PHASE_INSIDE_FILE_WRITE << PROPERTY_PHASE_SHIFT), + PROPERTY_ACCESS_SET_BETWEEN_FILE_READ = + (PROPERTY_PHASE_BETWEEN_FILE_READ << PROPERTY_PHASE_SHIFT), + PROPERTY_ACCESS_SET_INSIDE_FILE_READ = + (PROPERTY_PHASE_INSIDE_FILE_READ << PROPERTY_PHASE_SHIFT) +} PropertyAccessFlags; + +#define PROPERTY_ACCESS_GET_MASK (PROPERTY_PHASE_MASK) +#define PROPERTY_ACCESS_SET_MASK (PROPERTY_PHASE_MASK << PROPERTY_PHASE_SHIFT) + + +/* This structure is usually statically allocated. + * It holds information about a property that is common to all devices of + * a given type. */ + +typedef int DevicePropertyId; + +typedef struct { + DevicePropertyId ID; /* Set by device_property_register() */ + GType type; + const char *name; + const char *description; +} DevicePropertyBase; + +/* This structure is usually held inside a Device object. It holds + * information about a property that is specific to the device/medium + * in question. */ +typedef struct { + const DevicePropertyBase *base; + PropertyAccessFlags access; +} DeviceProperty; + +/* Registers a new property and returns its ID. This function takes ownership + * of its argument; it must not be freed later. */ +extern DevicePropertyId device_property_register(DevicePropertyBase*); + +/* This should be called exactly once from device_api_init(). */ +extern void device_property_init(void); + +/* Gets a DevicePropertyBase from its ID. */ +extern const DevicePropertyBase* device_property_get_by_id(DevicePropertyId); +extern const DevicePropertyBase* device_property_get_by_name(const char*); + +/* Standard property value types here. + * Important: see property.c for the other half of type declarations.*/ +typedef enum { + CONCURRENCY_PARADIGM_EXCLUSIVE, + CONCURRENCY_PARADIGM_SHARED_READ, + CONCURRENCY_PARADIGM_RANDOM_ACCESS +} ConcurrencyParadigm; +#define CONCURRENCY_PARADIGM_TYPE concurrency_paradigm_get_type() +GType concurrency_paradigm_get_type (void); + +typedef enum { + STREAMING_REQUIREMENT_NONE, + STREAMING_REQUIREMENT_DESIRED, + STREAMING_REQUIREMENT_REQUIRED +} StreamingRequirement; +#define STREAMING_REQUIREMENT_TYPE streaming_requirement_get_type() +GType streaming_requirement_get_type (void); + +typedef enum { + MEDIA_ACCESS_MODE_READ_ONLY, + MEDIA_ACCESS_MODE_WORM, + MEDIA_ACCESS_MODE_READ_WRITE, + MEDIA_ACCESS_MODE_WRITE_ONLY +} MediaAccessMode; +#define MEDIA_ACCESS_MODE_TYPE media_access_mode_get_type() +GType media_access_mode_get_type (void); + +/* This one is not a Glibified enum */ +typedef enum { + SIZE_ACCURACY_UNKNOWN, + SIZE_ACCURACY_ESTIMATE, + SIZE_ACCURACY_REAL +} SizeAccuracy; + +/* But SizeAccuracy does apear in this Glibified (gBoxed) struct. */ +typedef struct { + SizeAccuracy accuracy; + guint64 bytes; +} QualifiedSize; +#define QUALIFIED_SIZE_TYPE qualified_size_get_type() +GType qualified_size_get_type (void); + +/* Some features can only be occasionally (or unreliably) detected, so + this enum allows the user to override the detected or default + setting. */ +typedef enum { + /* Feature support status. (exactly one of these is set) */ + /* Feature is supported & will be used */ + FEATURE_STATUS_ENABLED = (1 << 0), + /* Features will not be used. */ + FEATURE_STATUS_DISABLED = (1 << 1), + + /* Feature support confidence. (exactly one of these is set). */ + /* Support is not based on conclusive evidence. */ + FEATURE_SURETY_BAD = (1 << 2), + /* Support is based on conclusive evidence. */ + FEATURE_SURETY_GOOD = (1 << 3), + + /* Source of this information. (exactly one of these is set). */ + /* Source of status is from default setting. */ + FEATURE_SOURCE_DEFAULT = (1 << 4), + /* Source of status is from device query. */ + FEATURE_SOURCE_DETECTED = (1 << 5), + /* Source of status is from user override. */ + FEATURE_SOURCE_USER = (1 << 6), + + FEATURE_SUPPORT_FLAGS_MAX = (1 << 7) +} FeatureSupportFlags; + +#define FEATURE_SUPPORT_FLAGS_MASK (FEATURE_SUPPORT_FLAGS_MAX-1) +#define FEATURE_SUPPORT_FLAGS_STATUS_MASK (FEATURE_STATUS_ENABLED | \ + FEATURE_STATUS_DISABLED) +#define FEATURE_SUPPORT_FLAGS_SURETY_MASK (FEATURE_SURETY_BAD | \ + FEATURE_SURETY_GOOD) +#define FEATURE_SUPPORT_FLAGS_SOURCE_MASK (FEATURE_SOURCE_DEFAULT | \ + FEATURE_SOURCE_DETECTED | \ + FEATURE_SOURCE_USER) +/* Checks that mutually exclusive flags are not set. */ +gboolean feature_support_flags_is_valid(FeatureSupportFlags); +#define FEATURE_SUPPORT_FLAGS_TYPE feature_support_get_type() +GType feature_support_get_type (void); + +/* Standard property definitions follow. See also property.c. */ + +/* Value is a ConcurrencyParadigm */ +extern DevicePropertyBase device_property_concurrency; +#define PROPERTY_CONCURRENCY (device_property_concurrency.ID) + +/* Value is a StreamingRequirement */ +extern DevicePropertyBase device_property_streaming; +#define PROPERTY_STREAMING (device_property_streaming.ID) + +/* Value is a gboolean. */ +extern DevicePropertyBase device_property_compression; +#define PROPERTY_COMPRESSION (device_property_compression.ID) + +/* Value is a gdouble, representing (compressed size)/(original + size). The period over which this value is measured is undefined. */ +extern DevicePropertyBase device_property_compression_rate; +#define PROPERTY_COMPRESSION_RATE (device_property_compression_rate.ID) + +/* Value is a gint, where a negative number indicates variable block size. */ +extern DevicePropertyBase device_property_block_size; +#define PROPERTY_BLOCK_SIZE (device_property_block_size.ID) + +/* Value is a guint. */ +extern DevicePropertyBase device_property_min_block_size; +extern DevicePropertyBase device_property_max_block_size; +#define PROPERTY_MIN_BLOCK_SIZE (device_property_min_block_size.ID) +#define PROPERTY_MAX_BLOCK_SIZE (device_property_max_block_size.ID) + +/* Value is a gboolean. */ +extern DevicePropertyBase device_property_appendable; +#define PROPERTY_APPENDABLE (device_property_appendable.ID) + +/* Value is a string. */ +extern DevicePropertyBase device_property_canonical_name; +#define PROPERTY_CANONICAL_NAME (device_property_canonical_name.ID) + +/* Value is MediaAccessMode. */ +extern DevicePropertyBase device_property_medium_access_type; +#define PROPERTY_MEDIUM_TYPE (device_property_medium_access_type.ID) + +/* Value is a gboolean. */ +extern DevicePropertyBase device_property_partial_deletion; +#define PROPERTY_PARTIAL_DELETION (device_property_partial_deletion.ID) + +/* Value is a QualifiedSize, though the accuracy may be SIZE_ACCURACY_NONE. */ +extern DevicePropertyBase device_property_free_space; +#define PROPERTY_FREE_SPACE (device_property_free_space.ID) + +/* Value is a guint64. On devices that support it, this property will + limit the total amount of data written to a volume; attempts to + write beyond this point will cause the device to simulate "out of + space". Zero means no limit. */ +extern DevicePropertyBase device_property_max_volume_usage; +#define PROPERTY_MAX_VOLUME_USAGE (device_property_max_volume_usage.ID) + +/* Tape device properties. These properties do not exist on non-linear + devices. All of them have a value type of FeatureSupportFlags. */ +extern DevicePropertyBase device_property_fsf; +#define PROPERTY_FSF (device_property_fsf.ID) + +extern DevicePropertyBase device_property_bsf; +#define PROPERTY_BSF (device_property_bsf.ID) + +extern DevicePropertyBase device_property_fsr; +#define PROPERTY_FSR (device_property_fsr.ID) + +extern DevicePropertyBase device_property_bsr; +#define PROPERTY_BSR (device_property_bsr.ID) + +/* Is EOM supported? Must be able to read file number afterwards as + well. */ +extern DevicePropertyBase device_property_eom; +#define PROPERTY_EOM (device_property_eom.ID) + +/* Is it necessary to perform a BSF after EOM? */ +extern DevicePropertyBase device_property_bsf_after_eom; +#define PROPERTY_BSF_AFTER_EOM (device_property_bsf_after_eom.ID) + +/* How many filemarks to write at EOD? (Default is 2). + * This property is a G_TYPE_UINT, but can only really be set to 1 or 2. */ +extern DevicePropertyBase device_property_final_filemarks; +#define PROPERTY_FINAL_FILEMARKS (device_property_final_filemarks.ID) + +/* What buffer size is used for reading? */ +extern DevicePropertyBase device_property_read_buffer_size; +#define PROPERTY_READ_BUFFER_SIZE (device_property_read_buffer_size.ID) + +/* Authentication information for Amazon S3. Both of these are strings. */ +extern DevicePropertyBase device_property_s3_secret_key; +extern DevicePropertyBase device_property_s3_access_key; +#define PROPERTY_S3_SECRET_KEY (device_property_s3_secret_key.ID) +#define PROPERTY_S3_ACCESS_KEY (device_property_s3_access_key.ID) + +#ifdef WANT_DEVPAY +/* Same, but for S3 with DevPay. This directory can be relative to the + * config director, or absolute. */ +extern DevicePropertyBase device_property_s3_user_token; +#define PROPERTY_S3_USER_TOKEN (device_property_s3_user_token.ID) +#endif + +/* Should the device produce verbose output? Value is a gboolean. Not + * recognized by all devices. */ +extern DevicePropertyBase device_property_verbose; +#define PROPERTY_VERBOSE (device_property_verbose.ID) + +#endif diff --git a/device-src/queueing.c b/device-src/queueing.c new file mode 100644 index 0000000..2ec0e8c --- /dev/null +++ b/device-src/queueing.c @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include "queueing.h" +#include "device.h" +#include "semaphore.h" +#include "amanda.h" + +/* Queueing framework here. */ +typedef struct { + guint block_size; + ProducerFunctor producer; + gpointer producer_user_data; + ConsumerFunctor consumer; + gpointer consumer_user_data; + GAsyncQueue *data_queue, *free_queue; + semaphore_t *free_memory; + StreamingRequirement streaming_mode; +} queue_data_t; + +static queue_buffer_t *invent_buffer(void) { + queue_buffer_t *rval; + rval = malloc(sizeof(*rval)); + + rval->data = NULL; + rval->alloc_size = 0; + rval->data_size = 0; + rval->offset = 0; + + return rval; +} + +void free_buffer(queue_buffer_t *buf) { + if (buf != NULL) + amfree(buf->data); + amfree(buf); +} + +static queue_buffer_t * merge_buffers(queue_buffer_t *buf1, + queue_buffer_t *buf2) { + if (buf1 == NULL) + return buf2; + else if (buf2 == NULL) + return buf1; + + if (buf2->offset >= buf1->data_size) { + /* We can fit buf1 at the beginning of buf2. */ + memcpy(buf2->data + buf2->offset - buf1->data_size, + buf1->data + buf1->offset, + buf1->data_size); + buf2->offset -= buf1->data_size; + buf2->data_size += buf1->data_size; + free_buffer(buf1); + return buf2; + } else if (buf1->alloc_size - buf1->offset - buf1->data_size + >= buf2->data_size) { + /* We can fit buf2 at the end of buf1. */ + memcpy(buf1->data + buf1->offset + buf1->data_size, + buf2->data + buf2->offset, buf2->data_size); + buf1->data_size += buf2->data_size; + free_buffer(buf2); + return buf1; + } else { + /* We can grow buf1 and put everything there. */ + if (buf1->offset != 0) { + /* But first we have to fix up buf1. */ + memmove(buf1->data, buf1->data + buf1->offset, buf1->data_size); + buf1->offset = 0; + } + buf1->alloc_size = buf1->data_size + buf2->data_size; + buf1->data = realloc(buf1->data, buf1->alloc_size); + memcpy(buf1->data + buf1->data_size, buf2->data + buf2->offset, + buf2->data_size); + buf1->data_size = buf1->alloc_size; + free_buffer(buf2); + return buf1; + } +} + +/* Invalidate the first "bytes" bytes of the buffer, by adjusting the + offset and data size. */ +static void consume_buffer(queue_buffer_t* buf, int bytes) { + buf->offset += bytes; + buf->data_size -= bytes; +} + +/* Looks at the buffer to see how much free space it has. If it has more than + * twice the data size of unused space at the end, or more than four times + * the data size of unused space at the beginning, then that space is + * reclaimed. */ +static void heatshrink_buffer(queue_buffer_t *buf) { + if (buf == NULL) + return; + + if (G_UNLIKELY(buf->data_size * 4 > buf->offset)) { + /* Consolodate with memmove. We will reclaim the space in the next + * step. */ + memmove(buf->data, buf->data + buf->offset, buf->data_size); + buf->offset = 0; + } + + if (buf->alloc_size > buf->data_size*2 + buf->offset) { + buf->alloc_size = buf->data_size + buf->offset; + buf->data = realloc(buf->data, buf->alloc_size); + } +} + +static gpointer do_producer_thread(gpointer datap) { + queue_data_t* data = datap; + + for (;;) { + queue_buffer_t *buf; + gboolean result; + + semaphore_decrement(data->free_memory, 0); + buf = g_async_queue_try_pop(data->free_queue); + if (buf != NULL && buf->data == NULL) { + /* Consumer is finished, then so are we. */ + amfree(buf); + return GINT_TO_POINTER(TRUE); + } + + if (buf == NULL) { + buf = invent_buffer(); + } + buf->offset = 0; + buf->data_size = 0; + + result = data->producer(data->producer_user_data, buf, + data->block_size); + + // Producers can allocate way too much memory. + heatshrink_buffer(buf); + + if (buf->data_size > 0) { + semaphore_force_adjust(data->free_memory, -buf->alloc_size); + + g_async_queue_push(data->data_queue, buf); + buf = NULL; + } else { + g_assert(result != PRODUCER_MORE); + free_buffer(buf); + buf = NULL; + } + + + if (result == PRODUCER_MORE) { + continue; + } else { + /* We are finished (and the first to do so). */ + g_async_queue_push(data->data_queue, invent_buffer()); + semaphore_force_set(data->free_memory, INT_MIN); + + return GINT_TO_POINTER(result == PRODUCER_FINISHED); + } + } +} + +static gpointer do_consumer_thread(gpointer datap) { + queue_data_t* data = datap; + gboolean finished = FALSE; + queue_buffer_t *buf = NULL; + + if (data->streaming_mode != STREAMING_REQUIREMENT_NONE) { + semaphore_wait_empty(data->free_memory); + } + + for (;;) { + gboolean result; + + if (finished) { + return GINT_TO_POINTER(TRUE); + } + + while (buf == NULL || buf->data_size < data->block_size) { + queue_buffer_t *next_buf; + if (data->streaming_mode == STREAMING_REQUIREMENT_DESIRED) { + do { + next_buf = g_async_queue_try_pop(data->data_queue); + if (next_buf == NULL) { + semaphore_wait_empty(data->free_memory); + } + } while (next_buf == NULL); + } else { + next_buf = g_async_queue_pop(data->data_queue); + g_assert(next_buf != NULL); + } + + if (next_buf->data == NULL) { + /* Producer is finished, then so are we.*/ + free_buffer(next_buf); + if (buf != NULL) { + /* But we can't quit yet, we have a buffer to flush.*/ + finished = TRUE; + break; + } else { + /* We are so outta here. */ + return GINT_TO_POINTER(TRUE); + } + } + + semaphore_increment(data->free_memory, next_buf->alloc_size); + + buf = merge_buffers(buf, next_buf); + } + + result = data->consumer(data->consumer_user_data, buf); + + if (result > 0) { + consume_buffer(buf, result); + if (buf->data_size == 0) { + g_async_queue_push(data->free_queue, buf); + buf = NULL; + } + continue; + } else { + free_buffer(buf); + return GINT_TO_POINTER(FALSE); + } + } +} + +/* Empties a buffer queue and frees all the buffers associated with it. + * + * If full_cleanup is TRUE, then we delete the queue itself. + * If full_cleanup is FALSE, then we leave the queue around, with a + * signal element in it. */ +static void cleanup_buffer_queue(GAsyncQueue *Q, gboolean full_cleanup) { + g_async_queue_lock(Q); + for (;;) { + queue_buffer_t *buftmp; + buftmp = g_async_queue_try_pop_unlocked(Q); + if (buftmp == NULL) + break; + + free_buffer(buftmp); + } + if (!full_cleanup) + g_async_queue_push_unlocked(Q, invent_buffer()); + + g_async_queue_unlock(Q); + + if (full_cleanup) + g_async_queue_unref(Q); +} + +/* This function sacrifices performance, but will still work just + fine, on systems where threads are not supported. */ +static queue_result_flags +do_unthreaded_consumer_producer_queue(guint block_size, + ProducerFunctor producer, + gpointer producer_user_data, + ConsumerFunctor consumer, + gpointer consumer_user_data) { + queue_buffer_t *buf = NULL, *next_buf = NULL; + gboolean finished = FALSE; + queue_result_flags rval = 0; + + /* The basic theory of operation here is to read until we have + enough data to write, then write until we don't.. */ + while (!finished) { + int result; + + while ((buf == NULL || buf->data_size < block_size) && !finished) { + if (next_buf == NULL) + next_buf = invent_buffer(); + + result = producer(producer_user_data, next_buf, block_size); + + if (result != PRODUCER_MORE) { + finished = TRUE; + if (result != PRODUCER_FINISHED) { + rval |= QUEUE_PRODUCER_ERROR; + } + } + + buf = merge_buffers(buf, next_buf); + next_buf = NULL; + } + + while (buf != NULL && buf->data_size > 0 && + (buf->data_size >= block_size || finished)) { + result = consumer(consumer_user_data, buf); + + if (result > 0) { + consume_buffer(buf, result); + if (buf->data_size == 0) { + next_buf = buf; + buf = NULL; + } + } else { + finished = TRUE; + rval |= QUEUE_CONSUMER_ERROR; + break; + } + } + } + + free_buffer(buf); + free_buffer(next_buf); + return rval; +} + +gboolean do_consumer_producer_queue(ProducerFunctor producer, + gpointer producer_user_data, + ConsumerFunctor consumer, + gpointer consumer_user_data) { + return QUEUE_SUCCESS == + do_consumer_producer_queue_full(producer, producer_user_data, + consumer, consumer_user_data, + 0, DEFAULT_MAX_BUFFER_MEMORY, + STREAMING_REQUIREMENT_NONE); +} + +queue_result_flags +do_consumer_producer_queue_full(ProducerFunctor producer, + gpointer producer_user_data, + ConsumerFunctor consumer, + gpointer consumer_user_data, + int block_size, + size_t max_memory, + StreamingRequirement streaming_mode) { + GThread * producer_thread; + GThread * consumer_thread; + queue_data_t queue_data; + gpointer producer_result; + gpointer consumer_result; + queue_result_flags rval; + + if (block_size <= 0) { + block_size = DISK_BLOCK_BYTES; + } + + g_return_val_if_fail(producer != NULL, FALSE); + g_return_val_if_fail(consumer != NULL, FALSE); + + if (!g_thread_supported()) { + return do_unthreaded_consumer_producer_queue(block_size, producer, + producer_user_data, + consumer, + consumer_user_data); + } + + queue_data.block_size = block_size; + queue_data.producer = producer; + queue_data.producer_user_data = producer_user_data; + queue_data.consumer = consumer; + queue_data.consumer_user_data = consumer_user_data; + queue_data.streaming_mode = streaming_mode; + + queue_data.data_queue = g_async_queue_new(); + queue_data.free_queue = g_async_queue_new(); + + max_memory = MAX(1,MIN(max_memory, INT_MAX / 2)); + queue_data.free_memory = semaphore_new_with_value(max_memory); + + producer_thread = g_thread_create(do_producer_thread, &queue_data, + TRUE, + NULL /* FIXME: Should handle + errors. */); + consumer_thread = g_thread_create(do_consumer_thread, &queue_data, + TRUE, + NULL /* FIXME: Should handle + errors. */); + + /* The order of cleanup here is very important, to avoid deadlock. */ + /* 1) Reap the consumer. */ + consumer_result = g_thread_join(consumer_thread); + /* 2) Stop the producer. */ + semaphore_force_set(queue_data.free_memory, -1); + /* 3) Cleanup the free queue; add a signal flag. */ + cleanup_buffer_queue(queue_data.free_queue, FALSE); + /* 4) Restart the producer (so it can exit). */ + semaphore_force_set(queue_data.free_memory, INT_MAX); + /* 5) Reap the producer. */ + producer_result = g_thread_join(producer_thread); + + cleanup_buffer_queue(queue_data.free_queue, TRUE); + cleanup_buffer_queue(queue_data.data_queue, TRUE); + + semaphore_free(queue_data.free_memory); + + rval = 0; + if (!GPOINTER_TO_INT(producer_result)) { + rval |= QUEUE_PRODUCER_ERROR; + } + if (!GPOINTER_TO_INT(consumer_result)) { + rval |= QUEUE_CONSUMER_ERROR; + } + return rval; +} + +/* Commonly-useful producers and consumers below. */ + +producer_result_t device_read_producer(gpointer devicep, + queue_buffer_t *buffer, + int hint_size G_GNUC_UNUSED) { + Device* device; + + device = (Device*) devicep; + g_assert(IS_DEVICE(device)); + + buffer->offset = 0; + for (;;) { + int result, read_size; + read_size = buffer->alloc_size; + result = device_read_block(device, buffer->data, &read_size); + if (result > 0) { + buffer->data_size = read_size; + return PRODUCER_MORE; + } else if (result == 0) { + buffer->data = realloc(buffer->data, read_size); + buffer->alloc_size = read_size; + } else if (device->is_eof) { + return PRODUCER_FINISHED; + } else { + buffer->data_size = 0; + return PRODUCER_ERROR; + } + } +} + +int device_write_consumer(gpointer devicep, queue_buffer_t *buffer) { + Device* device; + unsigned int write_size; + static gboolean wrote_blocksize = FALSE; + + device = (Device*) devicep; + g_assert(IS_DEVICE(device)); + write_size = MIN(buffer->data_size, + device_write_max_size(device)); + + if (!wrote_blocksize) { + wrote_blocksize = TRUE; + dbprintf("USING BLOCKSIZE %d bytes\n", write_size); + } + + if (device_write_block(device, write_size, + buffer->data + buffer->offset, + buffer->data_size < + device_write_min_size(device))) { + /* Success! */ + return write_size; + } else { + /* Nope, really an error. */ + return -1; + } +} + +producer_result_t fd_read_producer(gpointer fdp, queue_buffer_t *buffer, + int hint_size) { + int fd; + + fd = GPOINTER_TO_INT(fdp); + g_assert(fd >= 0); + g_assert(buffer->data_size == 0); + + buffer->offset = 0; + + if (buffer->data == NULL) { + /* Set up the buffer. */ + buffer->data = malloc(hint_size); + buffer->alloc_size = hint_size; + } + + for (;;) { + int result; + result = read(fd, buffer->data, buffer->alloc_size); + + if (result > 0) { + buffer->data_size = result; + return PRODUCER_MORE; + } else if (result == 0) { + /* End of file. */ + return PRODUCER_FINISHED; + } else if (0 +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef EINTR + || errno == EINTR +#endif + ) { + /* Try again. */ + continue; + } else { + /* Error occured. */ + g_fprintf(stderr, "Error reading fd %d: %s\n", fd, strerror(errno)); + return PRODUCER_ERROR; + } + } +} + +int fd_write_consumer(gpointer fdp, queue_buffer_t *buffer) { + int fd; + + fd = GPOINTER_TO_INT(fdp); + g_assert(fd >= 0); + + g_return_val_if_fail(buffer->data_size > 0, 0); + + for (;;) { + int write_size; + write_size = write(fd, buffer->data + buffer->offset, + buffer->data_size); + + if (write_size > 0) { + return write_size; + } else if (0 +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef EINTR + || errno == EINTR +#endif + ) { + /* Try again. */ + continue; + } else { + /* Error occured. */ + g_fprintf(stderr, "Error writing fd %d: %s\n", fd, strerror(errno)); + return -1; + } + } +} diff --git a/device-src/queueing.h b/device-src/queueing.h new file mode 100644 index 0000000..4a22081 --- /dev/null +++ b/device-src/queueing.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#ifndef QUEUEING_H +#define QUEUEING_H + +/* This file contains the code for fast threaded reading and writing to/from + * media, for devices that don't require any special handling. Some + * devices (e.g., CD-ROM) may use a different method for bulk reads or + * writes. */ + +#include +#include "property.h" + +#define DEFAULT_MAX_BUFFER_MEMORY (1*1024*1024) + +/* Valid data in this structure starts at data + offset, and has size + * data_size. Allocation starts at data and has size alloc_size. */ +typedef struct { + char *data; + guint alloc_size; + guint data_size; + guint offset; +} queue_buffer_t; + +void free_buffer(queue_buffer_t*); + +typedef enum { + PRODUCER_MORE, /* Means the producer should be run again. */ + PRODUCER_FINISHED, /* Means that no error occured, but the + producer should not be run again. */ + PRODUCER_ERROR /* Means an error occured, and the producer + should not be run again. */ +} producer_result_t; + +typedef enum { + QUEUE_SUCCESS = 0, + QUEUE_PRODUCER_ERROR = 1 << 0, + QUEUE_CONSUMER_ERROR = 1 << 1, + QUEUE_INTERNAL_ERROR = 1 << 2 +} queue_result_flags; + +/* The producer takes the given buffer (which is not itself NULL, but + * may contain a NULL data segment), and fills it with data. The + * producer should feel free to allocate or reallocate data as + * necessary; the queueing system will free it when necessary. The + * result of the production operation is specified in the return + * value, but if the buffer is left without data, then that is + * interpreted as PRODUCER_ERROR. It is preferred (but not required) + * that the producer produce hint_size bytes of data, + * + * The consumer takes the given buffer (which will not be NULL, nor + * contain a NULL data segment) and processess it. If there is a + * problem consuming data (such that no further data should be + * consumed), the consumer may return -1. Otherwise, the consumer + * should return the number of bytes actually consumed. + * If an error occurs, return -1, regardless of the number of bytes consumed. + * If the amount of data written is not a full block, then this is the + * last (partial block) of data. The consumer should do whatever is + * appropriate in that case. + * + * Note that the handling of the queue_buffer_t is different between + * the two functions: The producer should update queue_buffer_t as + * necessary to corespond to read data, while the consumer should + * leave the queue_buffer_t unadjusted: The queueing framework will + * invalidate data in the buffer according to the return value of the + * consumer.*/ +typedef producer_result_t (* ProducerFunctor)(gpointer user_data, + queue_buffer_t* buffer, + int hint_size); +typedef int (* ConsumerFunctor)(gpointer user_data, + queue_buffer_t* buffer); + + +/* These functions make the magic happen. The first one assumes + reasonable defaults, the second one provides more options. + % producer : A function that provides data to write. + % producer_user_data : A pointer to pass to that function. + % consumer : A function that writes data out. + % consumer_user_data : A pointer to pass to that function. + % block_size : Size of chunks to write out to consumer. If + nonpositive, data will be written in + variable-sized chunks. + % max_memory : Amount of memory to be used for buffering. + (default is DEFAULT_MAX_BUFFER_MEMORY). + % streaming_mode : Describes streaming mode. + STREAMING_REQUIREMENT_NONE: Data will be written as fast + as possible. No prebuffering + will be done. + STREAMING_REQUIREMENT_DESIRED: max_memory bytes of data will + be prebuffered, and if the + buffer ever empties, no data + will be written until it + fills again. + STREAMING_REQUIREMENT_REQUIRED: max_memory bytes of data will + be prebuffered, and + thereafter data will be + written as fast as possible. +*/ +gboolean +do_consumer_producer_queue(ProducerFunctor producer, + gpointer producer_user_data, + ConsumerFunctor consumer, + gpointer consumer_user_data); +queue_result_flags +do_consumer_producer_queue_full(ProducerFunctor producer, + gpointer producer_user_data, + ConsumerFunctor consumer, + gpointer consumer_user_data, + int block_size, + size_t max_memory, + StreamingRequirement streaming_mode); + +/* Some commonly-useful producers and consumers.*/ + +/* These functions will call device_read_block and device_write_block + * respectively. The user data should be a Device*. + * + * device_write_consumer assumes that the block_size passed to + * do_consumer_producer_queue_full is at least device_write_min_size(); + * do_consumer_thread() will not pass a buffer of less than block_size + * to the consumer unless it has received EOF from the producer thread. + */ +producer_result_t device_read_producer(gpointer device, + queue_buffer_t *buffer, + int hint_size); +int device_write_consumer(gpointer device, queue_buffer_t *buffer); + +/* These functions will call read() or write() respectively. The user + data should be a file descriptor stored with GINT_TO_POINTER. */ +producer_result_t fd_read_producer(gpointer fd, queue_buffer_t *buffer, + int hint_size); +int fd_write_consumer(gpointer fd, queue_buffer_t *buffer); + + + +#endif /* QUEUEING_H */ diff --git a/device-src/rait-device.c b/device-src/rait-device.c new file mode 100644 index 0000000..72f7c6d --- /dev/null +++ b/device-src/rait-device.c @@ -0,0 +1,1935 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* The RAIT device encapsulates some number of other devices into a single + * redundant device. */ + +#include "rait-device.h" +#include +#include "property.h" +#include "util.h" + +typedef enum { + RAIT_STATUS_COMPLETE, /* All subdevices OK. */ + RAIT_STATUS_DEGRADED, /* One subdevice failed. */ + RAIT_STATUS_FAILED /* Two or more subdevices failed. */ +} RaitStatus; + +struct RaitDevicePrivate_s { + GPtrArray * children; + /* These flags are only relevant for reading. */ + RaitStatus status; + /* If status == RAIT_STATUS_DEGRADED, this holds the index of the + failed node. It holds a negative number otherwise. */ + int failed; + guint block_size; +}; + +#define PRIVATE(o) (o->private) + +/* here are local prototypes */ +static void rait_device_init (RaitDevice * o); +static void rait_device_class_init (RaitDeviceClass * c); +static gboolean rait_device_open_device (Device * self, char * device_name); +static gboolean rait_device_start (Device * self, DeviceAccessMode mode, + char * label, char * timestamp); +static gboolean rait_device_start_file(Device * self, const dumpfile_t * info); +static gboolean rait_device_write_block (Device * self, guint size, + gpointer data, gboolean last_block); +static gboolean rait_device_finish_file (Device * self); +static dumpfile_t * rait_device_seek_file (Device * self, guint file); +static gboolean rait_device_seek_block (Device * self, guint64 block); +static int rait_device_read_block (Device * self, gpointer buf, + int * size); +static gboolean rait_device_property_get (Device * self, DevicePropertyId id, + GValue * val); +static gboolean rait_device_property_set (Device * self, DevicePropertyId id, + GValue * val); +static gboolean rait_device_recycle_file (Device * self, guint filenum); +static gboolean rait_device_finish (Device * self); +static ReadLabelStatusFlags rait_device_read_label(Device * dself); +static void find_simple_params(RaitDevice * self, guint * num_children, + guint * data_children, int * blocksize); + +/* pointer to the class of our parent */ +static DeviceClass *parent_class = NULL; + +/* This function is replicated here in case we have GLib from before 2.4. + * It should probably go eventually. */ +#if !GLIB_CHECK_VERSION(2,4,0) +static void +g_ptr_array_foreach (GPtrArray *array, + GFunc func, + gpointer user_data) +{ + guint i; + + g_return_if_fail (array); + + for (i = 0; i < array->len; i++) + (*func) (array->pdata[i], user_data); +} +#endif + +GType +rait_device_get_type (void) +{ + static GType type = 0; + + if G_UNLIKELY(type == 0) { + static const GTypeInfo info = { + sizeof (RaitDeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) rait_device_class_init, + (GClassFinalizeFunc) NULL, + NULL /* class_data */, + sizeof (RaitDevice), + 0 /* n_preallocs */, + (GInstanceInitFunc) rait_device_init, + NULL + }; + + type = g_type_register_static (TYPE_DEVICE, "RaitDevice", &info, + (GTypeFlags)0); + } + + return type; +} + +static void g_object_unref_foreach(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + g_return_if_fail(G_IS_OBJECT(data)); + g_object_unref(data); +} + +static void +rait_device_finalize(GObject *obj_self) +{ + RaitDevice *self G_GNUC_UNUSED = RAIT_DEVICE (obj_self); + if(G_OBJECT_CLASS(parent_class)->finalize) \ + (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self); + if(self->private->children) { + g_ptr_array_foreach(self->private->children, + g_object_unref_foreach, NULL); + g_ptr_array_free (self->private->children, TRUE); + self->private->children = NULL; + } + amfree(self->private); +} + +static void +rait_device_init (RaitDevice * o G_GNUC_UNUSED) +{ + PRIVATE(o) = malloc(sizeof(RaitDevicePrivate)); + PRIVATE(o)->children = g_ptr_array_new(); + PRIVATE(o)->status = RAIT_STATUS_COMPLETE; + PRIVATE(o)->failed = -1; +} + +static void +rait_device_class_init (RaitDeviceClass * c G_GNUC_UNUSED) +{ + GObjectClass *g_object_class G_GNUC_UNUSED = (GObjectClass*) c; + DeviceClass *device_class = (DeviceClass *)c; + + parent_class = g_type_class_ref (TYPE_DEVICE); + + device_class->open_device = rait_device_open_device; + device_class->start = rait_device_start; + device_class->start_file = rait_device_start_file; + device_class->write_block = rait_device_write_block; + device_class->finish_file = rait_device_finish_file; + device_class->seek_file = rait_device_seek_file; + device_class->seek_block = rait_device_seek_block; + device_class->read_block = rait_device_read_block; + device_class->property_get = rait_device_property_get; + device_class->property_set = rait_device_property_set; + device_class->recycle_file = rait_device_recycle_file; + device_class->finish = rait_device_finish; + device_class->read_label = rait_device_read_label; + + g_object_class->finalize = rait_device_finalize; + + /* Versions of glib before 2.10.2 crash if + * g_thread_pool_set_max_unused_threads is called before the first + * invocation of g_thread_pool_new. So we make up a thread pool, but don't + * start any threads in it, and free it */ + +#if !GLIB_CHECK_VERSION(2,10,2) + { + GThreadPool *pool = g_thread_pool_new((GFunc)-1, NULL, -1, FALSE, NULL); + g_thread_pool_free(pool, TRUE, FALSE); + } +#endif + + g_thread_pool_set_max_unused_threads(-1); +} + +/* This function does something a little clever and a little + * complicated. It takes an array of operations and runs the given + * function on each element in the array. The trick is that it runs them + * all in parallel, in different threads. This is more efficient than it + * sounds because we use a GThreadPool, which means calling this function + * will probably not start any new threads at all, but rather use + * existing ones. The func is called with two gpointer arguments: The + * first from the array, the second is the data argument. + * + * When it returns, all the operations have been successfully + * executed. If you want results from your operations, do it yourself + * through the array. */ +static void do_thread_pool_op(GFunc func, GPtrArray * ops, gpointer data) { + GThreadPool * pool; + guint i; + + pool = g_thread_pool_new(func, data, -1, FALSE, NULL); + for (i = 0; i < ops->len; i ++) { + g_thread_pool_push(pool, g_ptr_array_index(ops, i), NULL); + } + + g_thread_pool_free(pool, FALSE, TRUE); +} + +/* This does the above, in a serial fashion (and without using threads) */ +static void do_unthreaded_ops(GFunc func, GPtrArray * ops, + gpointer data G_GNUC_UNUSED) { + guint i; + + for (i = 0; i < ops->len; i ++) { + func(g_ptr_array_index(ops, i), NULL); + } +} + +/* This is the one that code below should call. It switches + automatically between do_thread_pool_op and do_unthreaded_ops, + depending on g_thread_supported(). */ +static void do_rait_child_ops(GFunc func, GPtrArray * ops, gpointer data) { + if (g_thread_supported()) { + do_thread_pool_op(func, ops, data); + } else { + do_unthreaded_ops(func, ops, data); + } +} + +/* Take a text string user_name, and break it out into an argv-style + array of strings. For example, {foo,{bar,baz},bat} would return the + strings "foo", "{bar,baz}", "bat", and NULL. Returns NULL on + error. */ +static char ** parse_device_name(char * user_name) { + GPtrArray * rval; + char * cur_end = user_name; + char * cur_begin = user_name; + + rval = g_ptr_array_new(); + + /* Check opening brace. */ + if (*cur_begin != '{') + return NULL; + cur_begin ++; + + cur_end = cur_begin; + for (;;) { + switch (*cur_end) { + case ',': { + g_ptr_array_add(rval, g_strndup(cur_begin, cur_end - cur_begin)); + cur_end ++; + cur_begin = cur_end; + continue; + } + + case '{': + /* We read until the matching closing brace. */ + while (*cur_end != '}' && *cur_end != '\0') + cur_end ++; + if (*cur_end == '}') + cur_end ++; + continue; + + case '}': + g_ptr_array_add(rval, g_strndup(cur_begin, cur_end - cur_begin)); + goto OUTER_END; /* break loop, not switch */ + + case '\0': + /* Unexpected NULL; abort. */ + g_fprintf(stderr, "Invalid RAIT device name %s\n", user_name); + g_ptr_array_free_full(rval); + return NULL; + + default: + cur_end ++; + continue; + } + g_assert_not_reached(); + } + OUTER_END: + + if (cur_end[1] != '\0') { + g_fprintf(stderr, "Invalid RAIT device name %s\n", user_name); + g_ptr_array_free_full(rval); + return NULL; + } + + g_ptr_array_add(rval, NULL); + + return (char**) g_ptr_array_free(rval, FALSE); +} + +/* Find a workable block size. */ +static gboolean find_block_size(RaitDevice * self) { + uint min = 0; + uint max = G_MAXUINT; + uint result; + GValue val; + gboolean rval; + guint i; + guint data_children; + + for (i = 0; i < self->private->children->len; i ++) { + uint child_min, child_max; + GValue property_result; + bzero(&property_result, sizeof(property_result)); + + if (!device_property_get(g_ptr_array_index(self->private->children, i), + PROPERTY_MIN_BLOCK_SIZE, &property_result)) + return FALSE; + child_min = g_value_get_uint(&property_result); + g_return_val_if_fail(child_min > 0, FALSE); + if (!device_property_get(g_ptr_array_index(self->private->children, i), + PROPERTY_MAX_BLOCK_SIZE, &property_result)) + return FALSE; + child_max = g_value_get_uint(&property_result); + g_return_val_if_fail(child_max > 0, FALSE); + + if (child_min > max || child_max < min || child_min == 0) { + return FALSE; + } else { + min = MAX(min, child_min); + max = MIN(max, child_max); + } + } + + /* Now pick a number. */ + g_assert(min <= max); + if (max < MAX_TAPE_BLOCK_BYTES) + result = max; + else if (min > MAX_TAPE_BLOCK_BYTES) + result = min; + else + result = MAX_TAPE_BLOCK_BYTES; + + /* User reads and writes bigger blocks. */ + find_simple_params(self, NULL, &data_children, NULL); + self->private->block_size = result * data_children; + + bzero(&val, sizeof(val)); + g_value_init(&val, G_TYPE_INT); + g_value_set_int(&val, result); + /* We can't do device_property_set because it's disallowed + according to the registered property base. */ + rval = rait_device_property_set(DEVICE(self), PROPERTY_BLOCK_SIZE, &val); + g_value_unset(&val); + return rval; +} + +/* Register properties that belong to the RAIT device proper, and not + to subdevices. */ +static void register_rait_properties(RaitDevice * self) { + Device * o = DEVICE(self); + DeviceProperty prop; + + prop.access = PROPERTY_ACCESS_GET_MASK; + + prop.base = &device_property_min_block_size; + device_add_property(o, &prop, NULL); + + prop.base = &device_property_max_block_size; + device_add_property(o, &prop, NULL); + + prop.base = &device_property_block_size; + device_add_property(o, &prop, NULL); + + prop.base = &device_property_canonical_name; + device_add_property(o, &prop, NULL); +} + +static void property_hash_union(GHashTable * properties, + const DeviceProperty * prop) { + PropertyAccessFlags before, after; + gpointer tmp; + gboolean found; + + found = g_hash_table_lookup_extended(properties, + GUINT_TO_POINTER(prop->base->ID), + NULL, &tmp); + before = GPOINTER_TO_UINT(tmp); + + if (!found) { + after = prop->access; + } else { + after = before & prop->access; + } + + g_hash_table_insert(properties, GUINT_TO_POINTER(prop->base->ID), + GUINT_TO_POINTER(after)); +} + +/* A GHRFunc. */ +static gboolean zero_value(gpointer key G_GNUC_UNUSED, gpointer value, + gpointer user_data G_GNUC_UNUSED) { + return (0 == GPOINTER_TO_UINT(value)); +} + +/* A GHFunc */ +static void register_property_hash(gpointer key, gpointer value, + gpointer user_data) { + DevicePropertyId id = GPOINTER_TO_UINT(key); + DeviceProperty prop; + Device * device = (Device*)user_data; + + g_assert(IS_DEVICE(device)); + + prop.access = GPOINTER_TO_UINT(value); + prop.base = device_property_get_by_id(id); + + device_add_property(device, &prop, NULL); +} + +/* This function figures out which properties exist for all children, and + * exports the unioned access mask. */ +static void register_properties(RaitDevice * self) { + GHashTable * properties; /* PropertyID => PropertyAccessFlags */ + guint j; + + properties = g_hash_table_new(g_direct_hash, g_direct_equal); + + /* Iterate the device list, find all properties. */ + for (j = 0; j < self->private->children->len; j ++) { + int i; + Device * child = g_ptr_array_index(self->private->children, j); + const DeviceProperty* device_property_list; + + device_property_list = device_property_get_list(child); + for (i = 0; device_property_list[i].base != NULL; i ++) { + property_hash_union(properties, &(device_property_list[i])); + } + } + + /* Then toss properties that can't be accessed. */ + g_hash_table_foreach_remove(properties, zero_value, NULL); + g_hash_table_remove(properties, GINT_TO_POINTER(PROPERTY_BLOCK_SIZE)); + g_hash_table_remove(properties, GINT_TO_POINTER(PROPERTY_MIN_BLOCK_SIZE)); + g_hash_table_remove(properties, GINT_TO_POINTER(PROPERTY_MAX_BLOCK_SIZE)); + g_hash_table_remove(properties, GINT_TO_POINTER(PROPERTY_CANONICAL_NAME)); + + /* Finally, register the lot. */ + g_hash_table_foreach(properties, register_property_hash, self); + + g_hash_table_destroy(properties); + + /* Then we have some of our own properties to register. */ + register_rait_properties(self); +} + +/* This structure contains common fields for many operations. Not all + operations use all fields, however. */ +typedef struct { + gpointer result; /* May be a pointer; may be an integer or boolean + stored with GINT_TO_POINTER. */ + Device * child; /* The device in question. Used by all + operations. */ + guint child_index; /* For recoverable operations (read-related + operations), this field provides the number + of this child in the self->private->children + array. */ +} GenericOp; + +typedef gboolean (*BooleanExtractor)(gpointer data); + +/* A BooleanExtractor */ +static gboolean extract_boolean_generic_op(gpointer data) { + GenericOp * op = data; + return GPOINTER_TO_INT(op->result); +} + +/* A BooleanExtractor */ +static gboolean extract_boolean_pointer_op(gpointer data) { + GenericOp * op = data; + return op->result != NULL; +} + +/* Does the equivalent of this perl command: + ! (first { !extractor($_) } @_ + That is, calls extractor on each element of the array, and returns + TRUE if and only if all calls to extractor return TRUE. +*/ +static gboolean g_ptr_array_and(GPtrArray * array, + BooleanExtractor extractor) { + guint i; + if (array == NULL || array->len <= 0) + return FALSE; + + for (i = 0; i < array->len; i ++) { + if (!extractor(g_ptr_array_index(array, i))) + return FALSE; + } + + return TRUE; +} + +/* Calls extractor on each element of the array, and returns + TRUE if at least one of the calls to extractor return TRUE. +*/ +static gboolean g_ptr_array_or(GPtrArray * array, + BooleanExtractor extractor) { + guint i; + if (array == NULL || array->len <= 0) + return FALSE; + + for (i = 0; i < array->len; i ++) { + if (extractor(g_ptr_array_index(array, i))) + return TRUE; + } + + return FALSE; +} + +/* Takes a RaitDevice, and makes a GPtrArray of GenericOp. */ +static GPtrArray * make_generic_boolean_op_array(RaitDevice* self) { + GPtrArray * rval; + guint i; + + rval = g_ptr_array_sized_new(self->private->children->len); + for (i = 0; i < self->private->children->len; i ++) { + GenericOp * op; + op = malloc(sizeof(*op)); + op->child = g_ptr_array_index(self->private->children, i); + op->child_index = i; + g_ptr_array_add(rval, op); + } + + return rval; +} + +/* Takes a GPtrArray of GenericOp, and a BooleanExtractor, and does + all the proper handling for the result of operations that allow + device isolation. Returns FALSE only if an unrecoverable error + occured. */ +static gboolean g_ptr_array_union_robust(RaitDevice * self, GPtrArray * ops, + BooleanExtractor extractor) { + int nfailed; + guint i; + + /* We found one or more failed elements. See which elements failed, and + * isolate them*/ + nfailed = 0; + for (i = 0; i < ops->len; i ++) { + GenericOp * op = g_ptr_array_index(ops, i); + if (!extractor(op)) { + self->private->failed = op->child_index; + g_fprintf(stderr, "RAIT array %s isolated device %s\n", + DEVICE(self)->device_name, + op->child->device_name); + nfailed++; + } + } + + /* no failures? great! */ + if (nfailed == 0) + return TRUE; + + /* a single failure in COMPLETE just puts us in DEGRADED mode */ + if (self->private->status == RAIT_STATUS_COMPLETE && nfailed == 1) { + self->private->status = RAIT_STATUS_DEGRADED; + g_fprintf(stderr, "RAIT array %s DEGRADED\n", DEVICE(self)->device_name); + return TRUE; + } else { + self->private->status = RAIT_STATUS_FAILED; + g_fprintf(stderr, "RAIT array %s FAILED\n", DEVICE(self)->device_name); + return FALSE; + } +} + +typedef struct { + Device * result; /* IN */ + char * device_name; /* OUT */ +} OpenDeviceOp; + +/* A GFunc. */ +static void open_device_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + OpenDeviceOp * op = data; + + op->result = device_open(op->device_name); + amfree(op->device_name); +} + +/* Returns TRUE if and only if the volume label and time are equal. */ +static gboolean compare_volume_results(Device * a, Device * b) { + return (0 == compare_possibly_null_strings(a->volume_time, b->volume_time) + && 0 == compare_possibly_null_strings(a->volume_label, b->volume_label)); +} + +static gboolean +rait_device_open_device (Device * dself, char * device_name) { + char ** device_names; + GPtrArray * open_device_ops; + guint i; + gboolean failure; + RaitDevice * self; + + self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail (device_name != NULL, FALSE); + + device_names = parse_device_name(device_name); + + if (device_names == NULL) + return FALSE; + + /* Open devices in a separate thread, in case they have to rewind etc. */ + open_device_ops = g_ptr_array_new(); + + for (i = 0; device_names[i] != NULL; i ++) { + OpenDeviceOp *op; + + op = malloc(sizeof(*op)); + op->device_name = device_names[i]; + op->result = NULL; + g_ptr_array_add(open_device_ops, op); + } + + free(device_names); + do_rait_child_ops(open_device_do_op, open_device_ops, NULL); + + failure = FALSE; + /* Check results of opening devices. */ + for (i = 0; i < open_device_ops->len; i ++) { + OpenDeviceOp *op = g_ptr_array_index(open_device_ops, i); + + if (op->result != NULL) { + g_ptr_array_add(self->private->children, op->result); + } else { + failure = TRUE; + } + } + + g_ptr_array_free_full(open_device_ops); + + failure = failure || !find_block_size(self); + if (failure) + return FALSE; /* This will clean up any created children. */ + + register_properties(self); + + /* Chain up. */ + if (parent_class->open_device) { + return parent_class->open_device(dself, device_name); + } else { + return TRUE; + } +} + +/* A GFunc. */ +static void read_label_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + GenericOp * op = data; + op->result = GINT_TO_POINTER(device_read_label(op->child)); +} + +static ReadLabelStatusFlags rait_device_read_label(Device * dself) { + RaitDevice * self; + GPtrArray * ops; + ReadLabelStatusFlags failed_result = 0; + ReadLabelStatusFlags rval; + GenericOp * failed_op = NULL; /* If this is non-null, we will isolate. */ + unsigned int i; + Device * first_success = NULL; + + self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + amfree(dself->volume_label); + + ops = make_generic_boolean_op_array(self); + + do_rait_child_ops(read_label_do_op, ops, NULL); + + for (i = 0; i < ops->len; i ++) { + GenericOp * op = g_ptr_array_index(ops, i); + ReadLabelStatusFlags result = GPOINTER_TO_INT(op->result); + if (op->result == READ_LABEL_STATUS_SUCCESS) { + if (first_success == NULL) { + /* This is the first successful device. */ + first_success = op->child; + } else if (!compare_volume_results(first_success, op->child)) { + /* Doesn't match. :-( */ + g_fprintf(stderr, "Inconsistant volume labels: " + "Got %s/%s against %s/%s.\n", + first_success->volume_label, + first_success->volume_time, + op->child->volume_label, + op->child->volume_time); + failed_result |= READ_LABEL_STATUS_VOLUME_ERROR; + failed_op = NULL; + } + } else { + if (failed_result == 0 && + self->private->status == RAIT_STATUS_COMPLETE) { + /* This is the first failed device; note it and we'll isolate + later. */ + failed_op = op; + failed_result = result; + } else { + /* We've encountered multiple failures. OR them together. */ + failed_result |= result; + failed_op = NULL; + } + } + } + + if (failed_op != NULL) { + /* We have a single device to isolate. */ + failed_result = READ_LABEL_STATUS_SUCCESS; /* Recover later */ + self->private->failed = failed_op->child_index; + g_fprintf(stderr, "RAIT array %s Isolated device %s.\n", + dself->device_name, + failed_op->child->device_name); + } + + if (failed_result != READ_LABEL_STATUS_SUCCESS) { + /* We had multiple failures or an inconsistency. */ + rval = failed_result; + } else { + /* Everything peachy. */ + rval = READ_LABEL_STATUS_SUCCESS; + g_assert(first_success != NULL); + if (first_success->volume_label != NULL) { + dself->volume_label = g_strdup(first_success->volume_label); + } + if (first_success->volume_time != NULL) { + dself->volume_time = g_strdup(first_success->volume_time); + } + } + + g_ptr_array_free_full(ops); + + return rval; +} + +typedef struct { + GenericOp base; + DeviceAccessMode mode; /* IN */ + char * label; /* IN */ + char * timestamp; /* IN */ +} StartOp; + +/* A GFunc. */ +static void start_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) { + DeviceClass *klass; + StartOp * param = data; + + klass = DEVICE_GET_CLASS(param->base.child); + if (klass->start) { + param->base.result = + GINT_TO_POINTER((klass->start)(param->base.child, + param->mode, param->label, + param->timestamp)); + } else { + param->base.result = FALSE; + } +} + +static gboolean +rait_device_start (Device * dself, DeviceAccessMode mode, char * label, + char * timestamp) { + GPtrArray * ops; + guint i; + gboolean success; + RaitDevice * self; + char * label_from_device = NULL; + + self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + amfree(dself->volume_label); + amfree(dself->volume_time); + + ops = g_ptr_array_sized_new(self->private->children->len); + for (i = 0; i < self->private->children->len; i ++) { + StartOp * op; + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->mode = mode; + op->label = g_strdup(label); + op->timestamp = g_strdup(timestamp); + g_ptr_array_add(ops, op); + } + + do_rait_child_ops(start_do_op, ops, NULL); + + success = g_ptr_array_and(ops, extract_boolean_generic_op); + + /* check that all of the volume labels agree */ + if (success) { + for (i = 0; i < self->private->children->len; i ++) { + Device *child = g_ptr_array_index(self->private->children, i); + + if (child->volume_label != NULL && child->volume_time != NULL) { + if (dself->volume_label != NULL && dself->volume_time != NULL) { + if (strcmp(child->volume_label, dself->volume_label) != 0 || + strcmp(child->volume_time, dself->volume_time) != 0) { + /* Mismatch! (Two devices provided different labels) */ + g_fprintf(stderr, "%s: Label (%s/%s) is different " + "from label (%s/%s) found at " + "device %s", + child->device_name, + child->volume_label, + child->volume_time, + dself->volume_label, + dself->volume_time, + label_from_device); + success = FALSE; + } + } else { + /* First device with a volume. */ + dself->volume_label = g_strdup(child->volume_label); + dself->volume_time = g_strdup(child->volume_time); + label_from_device = g_strdup(child->device_name); + } + } else { + /* Device problem, it says it succeeded but sets no label? */ + g_fprintf(stderr, "%s: %s", + child->device_name, + "Says label read, but device->volume_label " + " is NULL."); + success = FALSE; + } + } + } + + amfree(label_from_device); + g_ptr_array_free_full(ops); + + if (!success) { + return FALSE; + } else if (parent_class->start) { + return parent_class->start(dself, mode, label, timestamp); + } else { + return TRUE; + } +} + +typedef struct { + GenericOp base; + const dumpfile_t * info; /* IN */ + int fileno; +} StartFileOp; + +/* a GFunc */ +static void start_file_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) { + StartFileOp * op = data; + op->base.result = GINT_TO_POINTER(device_start_file(op->base.child, + op->info)); + op->fileno = op->base.child->file; + if (op->fileno < 1) { + op->base.result = FALSE; + } +} + +static gboolean +rait_device_start_file (Device * dself, const dumpfile_t * info) { + GPtrArray * ops; + guint i; + gboolean success; + RaitDevice * self; + int actual_file = -1; + + self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + ops = g_ptr_array_sized_new(self->private->children->len); + for (i = 0; i < self->private->children->len; i ++) { + StartFileOp * op; + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->info = info; + g_ptr_array_add(ops, op); + } + + do_rait_child_ops(start_file_do_op, ops, NULL); + + success = g_ptr_array_and(ops, extract_boolean_generic_op); + + for (i = 0; i < self->private->children->len && success; i ++) { + StartFileOp * op = g_ptr_array_index(ops, i); + if (!op->base.result) + continue; + g_assert(op->fileno >= 1); + if (actual_file < 1) { + actual_file = op->fileno; + } + if (actual_file != op->fileno) { + /* File number mismatch! Aah, my hair is on fire! */ + g_fprintf(stderr, "File number mismatch in " + "rait_device_start_file(): " + "Child %s reported file number " + "%d, another child reported " + "file number %d.", + op->base.child->device_name, + op->fileno, actual_file); + success = FALSE; + op->base.result = FALSE; + } + } + + g_ptr_array_free_full(ops); + + g_assert(actual_file >= 1); + dself->file = actual_file - 1; /* chain-up, below, will re-increment this */ + dself->in_file = TRUE; + + if (!success) { + g_fprintf(stderr, _("One or more devices failed to start_file")); + return FALSE; + } else if (parent_class->start_file) { + return parent_class->start_file(dself, info); + } else { + return TRUE; + } +} + +static void find_simple_params(RaitDevice * self, + guint * num_children, + guint * data_children, + int * blocksize) { + int num, data; + + num = self->private->children->len; + if (num > 1) + data = num - 1; + else + data = num; + if (num_children != NULL) + *num_children = num; + if (data_children != NULL) + *data_children = data; + + if (blocksize != NULL) { + *blocksize = device_write_min_size(DEVICE(self)); + } +} + +typedef struct { + GenericOp base; + guint size; /* IN */ + gpointer data; /* IN */ + gboolean short_block; /* IN */ + gboolean data_needs_free; /* bookkeeping */ +} WriteBlockOp; + +/* a GFunc. */ +static void write_block_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + WriteBlockOp * op = data; + + op->base.result = + GINT_TO_POINTER(device_write_block(op->base.child, op->size, op->data, + op->short_block)); +} + +/* Parity block generation. Performance of this function can be improved + considerably by using larger-sized integers or + assembly-coded vector instructions. Parameters are: + % data - All data chunks in series (chunk_size * num_chunks bytes) + % parity - Allocated space for parity block (chunk_size bytes) + */ +static void make_parity_block(char * data, char * parity, + guint chunk_size, guint num_chunks) { + guint i; + bzero(parity, chunk_size); + for (i = 0; i < num_chunks - 1; i ++) { + guint j; + for (j = 0; j < chunk_size; j ++) { + parity[j] ^= data[chunk_size*i + j]; + } + } +} + +/* Does the same thing as make_parity_block, but instead of using a + single memory chunk holding all chunks, it takes a GPtrArray of + chunks. */ +static void make_parity_block_extents(GPtrArray * data, char * parity, + guint chunk_size) { + guint i; + bzero(parity, chunk_size); + for (i = 0; i < data->len; i ++) { + guint j; + char * data_chunk; + data_chunk = g_ptr_array_index(data, i); + for (j = 0; j < chunk_size; j ++) { + parity[j] ^= data_chunk[j]; + } + } +} + +/* Does the parity creation algorithm. Allocates and returns a single + device block from a larger RAIT block. chunks and chunk are 1-indexed. */ +static char * extract_data_block(char * data, guint size, + guint chunks, guint chunk) { + char * rval; + guint chunk_size; + + g_return_val_if_fail(chunks > 0 && chunk > 0 && chunk <= chunks, NULL); + g_return_val_if_fail(data != NULL, NULL); + g_return_val_if_fail(size > 0 && size % (chunks - 1) == 0, NULL); + + chunk_size = size / (chunks - 1); + rval = malloc(chunk_size); + if (chunks != chunk) { + /* data block. */ + memcpy(rval, data + chunk_size * (chunk - 1), chunk_size); + } else { + make_parity_block(data, rval, chunk_size, chunks); + } + + return rval; +} + +static gboolean +rait_device_write_block (Device * dself, guint size, gpointer data, + gboolean last_block) { + GPtrArray * ops; + guint i; + gboolean success; + guint data_children, num_children; + int blocksize; + RaitDevice * self; + + self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + find_simple_params(RAIT_DEVICE(self), &num_children, &data_children, + &blocksize); + num_children = self->private->children->len; + if (num_children != 1) + data_children = num_children - 1; + else + data_children = num_children; + + g_return_val_if_fail(size % data_children == 0 || last_block, FALSE); + + if (last_block) { + char *new_data; + + new_data = malloc(blocksize); + memcpy(new_data, data, size); + bzero(new_data + size, blocksize - size); + + data = new_data; + size = blocksize; + } + + ops = g_ptr_array_sized_new(num_children); + for (i = 0; i < self->private->children->len; i ++) { + WriteBlockOp * op; + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->short_block = last_block; + op->size = size / data_children; + if (num_children <= 2) { + op->data = data; + op->data_needs_free = FALSE; + } else { + op->data_needs_free = TRUE; + op->data = extract_data_block(data, size, num_children, i + 1); + } + g_ptr_array_add(ops, op); + } + + do_rait_child_ops(write_block_do_op, ops, NULL); + + success = g_ptr_array_and(ops, extract_boolean_generic_op); + + for (i = 0; i < self->private->children->len; i ++) { + WriteBlockOp * op = g_ptr_array_index(ops, i); + if (op->data_needs_free) + free(op->data); + } + + if (last_block) { + amfree(data); + } + + g_ptr_array_free_full(ops); + + if (!success) { + /* TODO be more specific here */ + /* TODO: handle EOF here -- if one or more (or two or more??) + * children have is_eof* set, then reflect that in our error + * status, and finish_file all of the non-EOF children. What's + * more fun is when one device fails and must be isolated at + * the same time another hits EOF. */ + g_fprintf(stderr, "One or more devices failed to write_block"); + return FALSE; + } else { + /* We don't chain up here because we must handle finish_file + differently. If we were called with last_block, then the + children have already called finish_file themselves. So we + update the device block numbers manually. */ + dself->block ++; + if (last_block) + dself->in_file = FALSE; + + return TRUE; + } +} + +/* A GFunc */ +static void finish_file_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + GenericOp * op = data; + op->result = GINT_TO_POINTER(device_finish_file(op->child)); +} + +static gboolean +rait_device_finish_file (Device * self) { + GPtrArray * ops; + gboolean success; + + ops = make_generic_boolean_op_array(RAIT_DEVICE(self)); + + do_rait_child_ops(finish_file_do_op, ops, NULL); + + success = g_ptr_array_and(ops, extract_boolean_generic_op); + + g_ptr_array_free_full(ops); + + if (!success) { + return FALSE; + } else if (parent_class->finish_file) { + return parent_class->finish_file(self); + } else { + return TRUE; + } +} + +typedef struct { + GenericOp base; + guint requested_file; /* IN */ + guint actual_file; /* OUT */ +} SeekFileOp; + +/* a GFunc. */ +static void seek_file_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) { + SeekFileOp * op = data; + op->base.result = device_seek_file(op->base.child, op->requested_file); + op->actual_file = op->base.child->file; +} + +static dumpfile_t * +rait_device_seek_file (Device * dself, guint file) { + GPtrArray * ops; + guint i; + gboolean success; + dumpfile_t * rval; + RaitDevice * self = RAIT_DEVICE(dself); + guint actual_file = 0; + g_return_val_if_fail(self != NULL, FALSE); + + ops = g_ptr_array_sized_new(self->private->children->len); + for (i = 0; i < self->private->children->len; i ++) { + SeekFileOp * op; + if ((int)i == self->private->failed) + continue; /* This device is broken. */ + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->base.child_index = i; + op->requested_file = file; + g_ptr_array_add(ops, op); + } + + do_rait_child_ops(seek_file_do_op, ops, NULL); + + /* This checks for NULL values, but we still have to check for + consistant headers. */ + success = g_ptr_array_union_robust(RAIT_DEVICE(self), + ops, extract_boolean_pointer_op); + + rval = NULL; + for (i = 0; i < self->private->children->len; i ++) { + SeekFileOp * this_op; + dumpfile_t * this_result; + guint this_actual_file; + if ((int)i == self->private->failed) + continue; + + this_op = (SeekFileOp*)g_ptr_array_index(ops, i); + this_result = this_op->base.result; + this_actual_file = this_op->actual_file; + + if (rval == NULL) { + rval = this_result; + actual_file = this_actual_file; + } else { + if (headers_are_equal(rval, this_result) && + actual_file == this_actual_file) { + /* Do nothing. */ + } else { + success = FALSE; + } + free(this_result); + } + } + + g_ptr_array_free_full(ops); + + if (!success) { + amfree(rval); + return NULL; + } else if (parent_class->seek_file) { + parent_class->seek_file(dself, file); + } + + return rval; +} + +typedef struct { + GenericOp base; + guint64 block; /* IN */ +} SeekBlockOp; + +/* a GFunc. */ +static void seek_block_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) { + SeekBlockOp * op = data; + op->base.result = + GINT_TO_POINTER(device_seek_block(op->base.child, op->block)); +} + +static gboolean +rait_device_seek_block (Device * dself, guint64 block) { + GPtrArray * ops; + guint i; + gboolean success; + + RaitDevice * self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + ops = g_ptr_array_sized_new(self->private->children->len); + for (i = 0; i < self->private->children->len; i ++) { + SeekBlockOp * op; + if ((int)i == self->private->failed) + continue; /* This device is broken. */ + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->base.child_index = i; + op->block = block; + g_ptr_array_add(ops, op); + } + + do_rait_child_ops(seek_block_do_op, ops, NULL); + + success = g_ptr_array_union_robust(RAIT_DEVICE(self), + ops, extract_boolean_generic_op); + + g_ptr_array_free_full(ops); + + if (!success) { + return FALSE; + } else if (parent_class->seek_block) { + return parent_class->seek_block(dself, block); + } else { + return success; + } +} + +typedef struct { + GenericOp base; + gpointer buffer; /* IN */ + int read_size; /* IN/OUT -- note not a pointer */ + int desired_read_size; /* bookkeeping */ +} ReadBlockOp; + +/* a GFunc. */ +static void read_block_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + ReadBlockOp * op = data; + op->base.result = + GINT_TO_POINTER(device_read_block(op->base.child, op->buffer, + &(op->read_size))); +} + +/* A BooleanExtractor. This one checks for a successful read. */ +static gboolean extract_boolean_read_block_op_data(gpointer data) { + ReadBlockOp * op = data; + return GPOINTER_TO_INT(op->base.result) == op->desired_read_size; +} + +/* A BooleanExtractor. This one checks for EOF. */ +static gboolean extract_boolean_read_block_op_eof(gpointer data) { + ReadBlockOp * op = data; + return op->base.child->is_eof; +} + +/* Counts the number of elements in an array matching a given proposition. */ +static int g_ptr_array_count(GPtrArray * array, BooleanExtractor filter) { + int rval; + unsigned int i; + rval = 0; + for (i = 0; i < array->len ; i++) { + if (filter(g_ptr_array_index(array, i))) + rval ++; + } + return rval; +} + +static gboolean raid_block_reconstruction(RaitDevice * self, GPtrArray * ops, + gpointer buf, size_t bufsize) { + guint num_children, data_children; + int blocksize, child_blocksize; + guint i; + int parity_child; + gpointer parity_block = NULL; + gboolean success; + + success = TRUE; + find_simple_params(self, &num_children, &data_children, &blocksize); + if (num_children > 1) + parity_child = num_children - 1; + else + parity_child = -1; + + child_blocksize = blocksize / data_children; + + for (i = 0; i < ops->len; i ++) { + ReadBlockOp * op = g_ptr_array_index(ops, i); + if (!extract_boolean_read_block_op_data(op)) + continue; + if ((int)(op->base.child_index) == parity_child) { + parity_block = op->buffer; + } else { + g_assert(child_blocksize * (op->base.child_index+1) <= bufsize); + memcpy((char *)buf + child_blocksize * op->base.child_index, op->buffer, + child_blocksize); + } + } + + if (self->private->status == RAIT_STATUS_COMPLETE) { + if (num_children >= 2) { + /* Verify the parity block. This code is inefficient but + does the job for the 2-device case, too. */ + gpointer constructed_parity; + GPtrArray * data_extents; + + constructed_parity = malloc(child_blocksize); + data_extents = g_ptr_array_sized_new(data_children); + for (i = 0; i < data_children; i ++) { + ReadBlockOp * op = g_ptr_array_index(ops, i); + g_assert(extract_boolean_read_block_op_data(op)); + if ((int)op->base.child_index == parity_child) + continue; + g_ptr_array_add(data_extents, op->buffer); + } + make_parity_block_extents(data_extents, constructed_parity, + child_blocksize); + + if (0 != memcmp(parity_block, constructed_parity, + child_blocksize)) { + g_fprintf(stderr, "RAIT is inconsistant: " + "Parity block did not match data blocks.\n"); + success = FALSE; + } + g_ptr_array_free(data_extents, TRUE); + amfree(constructed_parity); + } else { /* do nothing. */ } + } else if (self->private->status == RAIT_STATUS_DEGRADED) { + g_assert(self->private->failed >= 0 && self->private->failed < (int)num_children); + /* We are in degraded mode. What's missing? */ + if (self->private->failed == parity_child) { + /* do nothing. */ + } else if (num_children >= 2) { + /* Reconstruct failed block from parity block. */ + GPtrArray * data_extents = g_ptr_array_new(); + + for (i = 0; i < data_children; i ++) { + ReadBlockOp * op = g_ptr_array_index(ops, i); + if (!extract_boolean_read_block_op_data(op)) + continue; + g_ptr_array_add(data_extents, op->buffer); + } + + /* Conveniently, the reconstruction is the same procedure + as the parity generation. This even works if there is + only one remaining device! */ + make_parity_block_extents(data_extents, + (char *)buf + (child_blocksize * + self->private->failed), + child_blocksize); + + /* The array members belong to our ops argument. */ + g_ptr_array_free(data_extents, TRUE); + } else { + g_assert_not_reached(); + } + } else { + success = FALSE; + } + return success; +} + +static int +rait_device_read_block (Device * dself, gpointer buf, int * size) { + GPtrArray * ops; + guint i; + gboolean success; + guint num_children, data_children; + int blocksize; + gsize child_blocksize; + + RaitDevice * self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, -1); + + find_simple_params(self, &num_children, &data_children, + &blocksize); + + /* tell caller they haven't given us a big enough buffer */ + if (blocksize < *size) { + *size = blocksize; + return 0; + } + + g_return_val_if_fail(*size >= (int)device_write_min_size(dself), -1); + + g_assert(blocksize % data_children == 0); /* If not we are screwed */ + child_blocksize = blocksize / data_children; + + ops = g_ptr_array_sized_new(num_children); + for (i = 0; i < num_children; i ++) { + ReadBlockOp * op; + if ((int)i == self->private->failed) + continue; /* This device is broken. */ + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->base.child_index = i; + op->buffer = malloc(child_blocksize); + op->desired_read_size = op->read_size = blocksize / data_children; + g_ptr_array_add(ops, op); + } + + do_rait_child_ops(read_block_do_op, ops, NULL); + + if (g_ptr_array_count(ops, extract_boolean_read_block_op_data)) { + if (!g_ptr_array_union_robust(RAIT_DEVICE(self), + ops, + extract_boolean_read_block_op_data)) { + success = FALSE; + } else { + success = raid_block_reconstruction(RAIT_DEVICE(self), + ops, buf, (size_t)*size); + } + } else { + success = FALSE; + if (g_ptr_array_union_robust(RAIT_DEVICE(self), + ops, + extract_boolean_read_block_op_eof)) { + /* We hit EOF. */ + dself->is_eof = TRUE; + dself->in_file = FALSE; + } else { + g_fprintf(stderr, _("All child devices failed to read, but not all are at eof")); + } + } + + for (i = 0; i < ops->len; i ++) { + ReadBlockOp * op = g_ptr_array_index(ops, i); + amfree(op->buffer); + } + g_ptr_array_free_full(ops); + + if (success) { + if (parent_class->read_block) + parent_class->read_block(dself, buf, size); + *size = blocksize; + return blocksize; + } else { + return -1; + } +} + +typedef struct { + GenericOp base; + DevicePropertyId id; /* IN */ + GValue value; /* IN/OUT */ + gboolean label_changed; /* Did the device label change? OUT; _set only*/ +} PropertyOp; + +/* Creates a GPtrArray of PropertyOf for a get or set operation. */ +static GPtrArray * make_property_op_array(RaitDevice * self, + DevicePropertyId id, + GValue * value) { + guint i; + GPtrArray * ops; + ops = g_ptr_array_sized_new(self->private->children->len); + for (i = 0; i < self->private->children->len; i ++) { + PropertyOp * op; + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->id = id; + bzero(&(op->value), sizeof(op->value)); + if (value != NULL) { + g_value_unset_copy(value, &(op->value)); + } + g_ptr_array_add(ops, op); + } + + return ops; +} + +/* A GFunc. */ +static void property_get_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + PropertyOp * op = data; + + bzero(&(op->value), sizeof(op->value)); + op->base.result = + GINT_TO_POINTER(device_property_get(op->base.child, op->id, + &(op->value))); +} + +/* Merge ConcurrencyParadigm results. */ +static gboolean property_get_concurrency(GPtrArray * ops, GValue * val) { + ConcurrencyParadigm result = CONCURRENCY_PARADIGM_RANDOM_ACCESS; + guint i = 0; + + for (i = 0; i < ops->len; i ++) { + ConcurrencyParadigm cur; + PropertyOp * op = g_ptr_array_index(ops, i); + g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) == + CONCURRENCY_PARADIGM_TYPE, FALSE); + cur = g_value_get_enum(&(op->value)); + if (result == CONCURRENCY_PARADIGM_EXCLUSIVE || + cur == CONCURRENCY_PARADIGM_EXCLUSIVE) { + result = CONCURRENCY_PARADIGM_EXCLUSIVE; + } else if (result == CONCURRENCY_PARADIGM_SHARED_READ || + cur == CONCURRENCY_PARADIGM_SHARED_READ) { + result = CONCURRENCY_PARADIGM_SHARED_READ; + } else if (result == CONCURRENCY_PARADIGM_RANDOM_ACCESS && + cur == CONCURRENCY_PARADIGM_RANDOM_ACCESS) { + result = CONCURRENCY_PARADIGM_RANDOM_ACCESS; + } else { + g_return_val_if_fail(FALSE, FALSE); + } + } + + g_value_unset_init(val, CONCURRENCY_PARADIGM_TYPE); + g_value_set_enum(val, result); + return TRUE; +} + +/* Merge StreamingRequirement results. */ +static gboolean property_get_streaming(GPtrArray * ops, GValue * val) { + StreamingRequirement result = STREAMING_REQUIREMENT_NONE; + guint i = 0; + + for (i = 0; i < ops->len; i ++) { + StreamingRequirement cur; + PropertyOp * op = g_ptr_array_index(ops, i); + g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) == + STREAMING_REQUIREMENT_TYPE, FALSE); + cur = g_value_get_enum(&(op->value)); + if (result == STREAMING_REQUIREMENT_REQUIRED || + cur == STREAMING_REQUIREMENT_REQUIRED) { + result = STREAMING_REQUIREMENT_REQUIRED; + } else if (result == STREAMING_REQUIREMENT_DESIRED || + cur == STREAMING_REQUIREMENT_DESIRED) { + result = STREAMING_REQUIREMENT_DESIRED; + } else if (result == STREAMING_REQUIREMENT_NONE && + cur == STREAMING_REQUIREMENT_NONE) { + result = STREAMING_REQUIREMENT_NONE; + } else { + g_return_val_if_fail(FALSE, FALSE); + } + } + + g_value_unset_init(val, STREAMING_REQUIREMENT_TYPE); + g_value_set_enum(val, result); + return TRUE; +} + +/* Merge MediaAccessMode results. */ +static gboolean property_get_medium_type(GPtrArray * ops, GValue * val) { + MediaAccessMode result = 0; + guint i = 0; + + for (i = 0; i < ops->len; i ++) { + MediaAccessMode cur; + PropertyOp * op = g_ptr_array_index(ops, i); + g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) == + MEDIA_ACCESS_MODE_TYPE, FALSE); + cur = g_value_get_enum(&(op->value)); + + if (i == 0) { + result = cur; + } else if ((result == MEDIA_ACCESS_MODE_READ_ONLY && + cur == MEDIA_ACCESS_MODE_WRITE_ONLY) || + (result == MEDIA_ACCESS_MODE_WRITE_ONLY && + cur == MEDIA_ACCESS_MODE_READ_ONLY)) { + /* Invalid combination; one device can only read, other + can only write. */ + return FALSE; + } else if (result == MEDIA_ACCESS_MODE_READ_ONLY || + cur == MEDIA_ACCESS_MODE_READ_ONLY) { + result = MEDIA_ACCESS_MODE_READ_ONLY; + } else if (result == MEDIA_ACCESS_MODE_WRITE_ONLY || + cur == MEDIA_ACCESS_MODE_WRITE_ONLY) { + result = MEDIA_ACCESS_MODE_WRITE_ONLY; + } else if (result == MEDIA_ACCESS_MODE_WORM || + cur == MEDIA_ACCESS_MODE_WORM) { + result = MEDIA_ACCESS_MODE_WORM; + } else if (result == MEDIA_ACCESS_MODE_READ_WRITE && + cur == MEDIA_ACCESS_MODE_READ_WRITE) { + result = MEDIA_ACCESS_MODE_READ_WRITE; + } else { + g_return_val_if_fail(FALSE, FALSE); + } + } + + g_value_unset_init(val, MEDIA_ACCESS_MODE_TYPE); + g_value_set_enum(val, result); + return TRUE; +} + +/* Merge QualifiedSize results. */ +static gboolean property_get_free_space(GPtrArray * ops, GValue * val) { + QualifiedSize result; + guint i = 0; + + for (i = 0; i < ops->len; i ++) { + QualifiedSize cur; + PropertyOp * op = g_ptr_array_index(ops, i); + g_return_val_if_fail(G_VALUE_TYPE(&(op->value)) == + QUALIFIED_SIZE_TYPE, FALSE); + cur = *(QualifiedSize*)(g_value_get_boxed(&(op->value))); + + if (result.accuracy != cur.accuracy) { + result.accuracy = SIZE_ACCURACY_ESTIMATE; + } + + if (result.accuracy == SIZE_ACCURACY_UNKNOWN && + cur.accuracy != SIZE_ACCURACY_UNKNOWN) { + result.bytes = cur.bytes; + } else if (result.accuracy != SIZE_ACCURACY_UNKNOWN && + cur.accuracy == SIZE_ACCURACY_UNKNOWN) { + /* result.bytes unchanged. */ + } else { + result.bytes = MIN(result.bytes, cur.bytes); + } + } + + g_value_unset_init(val, QUALIFIED_SIZE_TYPE); + g_value_set_boxed(val, &result); + return TRUE; +} + +/* Merge boolean results by ANDing them together. */ +static gboolean property_get_boolean_and(GPtrArray * ops, GValue * val) { + gboolean result = FALSE; + guint i = 0; + + for (i = 0; i < ops->len; i ++) { + gboolean cur; + PropertyOp * op = g_ptr_array_index(ops, i); + g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&(op->value)), FALSE); + cur = g_value_get_boolean(&(op->value)); + + result = result && cur; + } + + g_value_unset_init(val, G_TYPE_BOOLEAN); + g_value_set_boolean(val, result); + return TRUE; +} + + +static gboolean +rait_device_property_get (Device * dself, DevicePropertyId id, GValue * val) { + GPtrArray * ops; + guint i; + gboolean success; + GValue result; + GValue * first_value; + RaitDevice * self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + /* Some properties are handled completely differently. */ + if (id == PROPERTY_BLOCK_SIZE) { + g_value_unset_init(val, G_TYPE_INT); + g_value_set_int(val, self->private->block_size); + return TRUE; + } else if (id == PROPERTY_MIN_BLOCK_SIZE || + id == PROPERTY_MAX_BLOCK_SIZE) { + g_value_unset_init(val, G_TYPE_UINT); + g_value_set_uint(val, self->private->block_size); + return TRUE; + } else if (id == PROPERTY_CANONICAL_NAME) { + if (parent_class->property_get != NULL) { + return parent_class->property_get(dself, id, val); + } else { + return FALSE; + } + } + + ops = make_property_op_array(self, id, NULL); + + do_rait_child_ops(property_get_do_op, ops, NULL); + + if (id == PROPERTY_CONCURRENCY) { + success = property_get_concurrency(ops, val); + } else if (id == PROPERTY_STREAMING) { + success = property_get_streaming(ops, val); + } else if (id == PROPERTY_APPENDABLE || + id == PROPERTY_PARTIAL_DELETION) { + success = property_get_boolean_and(ops, val); + } else if (id == PROPERTY_MEDIUM_TYPE) { + success = property_get_medium_type(ops, val); + } else if (id == PROPERTY_FREE_SPACE) { + success = property_get_free_space(ops, val); + } else { + /* Generic handling; if all results are the same, we succeed + and return that result. If not, we fail. */ + success = TRUE; + + /* Set up comparison value. */ + bzero(&result, sizeof(result)); + first_value = &(((PropertyOp*)g_ptr_array_index(ops,0))->value); + if (G_IS_VALUE(first_value)) { + g_value_unset_copy(first_value, &result); + } else { + success = FALSE; + } + + for (i = 0; i < ops->len; i ++) { + PropertyOp * op = g_ptr_array_index(ops, i); + if (!GPOINTER_TO_INT(op->base.result) || + !G_IS_VALUE(first_value) || + !g_value_compare(&result, &(op->value))) { + success = FALSE; + } + /* free the GValue if the child call succeeded */ + if (GPOINTER_TO_INT(op->base.result)) + g_value_unset(&(op->value)); + } + + if (success) { + memcpy(val, &result, sizeof(result)); + } else if (G_IS_VALUE(&result)) { + g_value_unset(&result); + } + } + + g_ptr_array_free_full(ops); + + return success; +} + +/* A GFunc. */ +static void property_set_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + PropertyOp * op = data; + gboolean label_set = (op->base.child->volume_label != NULL); + op->base.result = + GINT_TO_POINTER(device_property_set(op->base.child, op->id, + &(op->value))); + op->label_changed = (label_set != (op->base.child->volume_label != NULL)); +} + +/* A BooleanExtractor */ +static gboolean extract_label_changed_property_op(gpointer data) { + PropertyOp * op = data; + return op->label_changed; +} + +/* A GFunc. */ +static void clear_volume_details_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + GenericOp * op = data; + device_clear_volume_details(op->child); +} + +static gboolean +rait_device_property_set (Device * d_self, DevicePropertyId id, GValue * val) { + RaitDevice * self; + GPtrArray * ops; + gboolean success; + gboolean label_changed; + + self = RAIT_DEVICE(d_self); + g_return_val_if_fail(self != NULL, FALSE); + + /* it doesn't make sense to hand these properties down to our child devices, + * so we'll just pretend we set them. This is a 2.6.0 hack -- the device gets + * this right in 2.6.1. */ + if (id == PROPERTY_BLOCK_SIZE + || id == PROPERTY_MIN_BLOCK_SIZE + || id == PROPERTY_MAX_BLOCK_SIZE) { + return TRUE; /* lies! */ + } + + ops = make_property_op_array(self, id, val); + + do_rait_child_ops(property_set_do_op, ops, NULL); + + success = g_ptr_array_union_robust(self, ops, extract_boolean_generic_op); + label_changed = g_ptr_array_or(ops, extract_label_changed_property_op); + g_ptr_array_free_full(ops); + + if (label_changed) { + /* At least one device considered this property set a label-changing + * operation, so now we clear labels on all devices. */ + ops = make_generic_boolean_op_array(self); + do_rait_child_ops(clear_volume_details_do_op, ops, NULL); + g_ptr_array_free_full(ops); + } + + return success; +} + +typedef struct { + GenericOp base; + guint filenum; +} RecycleFileOp; + +/* A GFunc */ +static void recycle_file_do_op(gpointer data, + gpointer user_data G_GNUC_UNUSED) { + RecycleFileOp * op = data; + op->base.result = + GINT_TO_POINTER(device_recycle_file(op->base.child, op->filenum)); +} + +static gboolean +rait_device_recycle_file (Device * dself, guint filenum) { + GPtrArray * ops; + guint i; + gboolean success; + + RaitDevice * self = RAIT_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + ops = g_ptr_array_sized_new(self->private->children->len); + for (i = 0; i < self->private->children->len; i ++) { + RecycleFileOp * op; + op = malloc(sizeof(*op)); + op->base.child = g_ptr_array_index(self->private->children, i); + op->filenum = filenum; + g_ptr_array_add(ops, op); + } + + do_rait_child_ops(recycle_file_do_op, ops, NULL); + + success = g_ptr_array_and(ops, extract_boolean_generic_op); + + g_ptr_array_free_full(ops); + + if (!success) { + return FALSE; + } else if (parent_class->recycle_file) { + return parent_class->recycle_file(dself, filenum); + } else { + return TRUE; + } +} + +/* GFunc */ +static void finish_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) { + GenericOp * op = data; + op->result = GINT_TO_POINTER(device_finish(op->child)); +} + +static gboolean +rait_device_finish (Device * self) { + GPtrArray * ops; + gboolean success; + + ops = make_generic_boolean_op_array(RAIT_DEVICE(self)); + + do_rait_child_ops(finish_do_op, ops, NULL); + + success = g_ptr_array_and(ops, extract_boolean_generic_op); + + g_ptr_array_free_full(ops); + + if (!success) { + return FALSE; + } else if (parent_class->finish) { + return parent_class->finish(self); + } else { + return TRUE; + } +} + +Device * +rait_device_factory (char * type, char * name) { + Device * rval; + g_assert(0 == strcmp(type, "rait")); + rval = DEVICE(g_object_new(TYPE_RAIT_DEVICE, NULL)); + if (!device_open_device(rval, name)) { + g_object_unref(rval); + return NULL; + } else { + return rval; + } +} + +Device * rait_device_new_from_devices(Device ** devices) { + RaitDevice * rval; + int i; + gboolean success = TRUE; + + g_return_val_if_fail(devices != NULL && *devices != NULL, NULL); + + rval = RAIT_DEVICE(g_object_new(TYPE_RAIT_DEVICE, NULL)); + + for (i = 0; devices[i] != NULL; i ++) { + g_assert(IS_DEVICE(devices[i])); + if (devices[i]->access_mode != ACCESS_NULL) { + success = FALSE; + break; + } + g_object_ref(devices[i]); + g_ptr_array_add(PRIVATE(rval)->children, devices[i]); + } + + success = success && find_block_size(rval); + + if (!success) { + g_ptr_array_free(PRIVATE(rval)->children, TRUE); + return NULL; + } else { + register_properties(rval); + + return DEVICE(rval); + } +} + +void +rait_device_register (void) { + static const char * device_prefix_list[] = {"rait", NULL}; + register_device(rait_device_factory, device_prefix_list); +} diff --git a/device-src/rait-device.h b/device-src/rait-device.h new file mode 100644 index 0000000..b7df6bb --- /dev/null +++ b/device-src/rait-device.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* The RAIT device encapsulates some number of other devices into a single + * redundant device. */ + +#ifndef RAIT_DEVICE_H +#define RAIT_DEVICE_H + +#include +#include +#include "device.h" + +/* + * Type checking and casting macros + */ +#define TYPE_RAIT_DEVICE (rait_device_get_type()) +#define RAIT_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), rait_device_get_type(), RaitDevice) +#define RAIT_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), rait_device_get_type(), RaitDevice const) +#define RAIT_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), rait_device_get_type(), RaitDeviceClass) +#define IS_RAIT_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), rait_device_get_type ()) + +#define RAIT_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), rait_device_get_type(), RaitDeviceClass) + +/* + * Main object structure + */ +typedef struct RaitDevicePrivate_s RaitDevicePrivate; +typedef struct RaitDevice_s { + Device __parent__; + + RaitDevicePrivate * private; +} RaitDevice; + +/* + * Class definition + */ +typedef struct _RaitDeviceClass RaitDeviceClass; +struct _RaitDeviceClass { + DeviceClass __parent__; +}; + + +/* + * Public methods + */ +GType rait_device_get_type (void); +Device * rait_device_factory (char * type, + char * name); +/* Pass this factory a NULL-terminated array of Devices, and it will make a + RAIT out of them. The returned device refss the passed devices, so unref + them yourself. */ +Device * rait_device_new_from_devices(Device ** devices); +void rait_device_register (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/device-src/s3-device.c b/device-src/s3-device.c new file mode 100644 index 0000000..bebb6ef --- /dev/null +++ b/device-src/s3-device.c @@ -0,0 +1,1184 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* An S3 device uses Amazon's S3 service (http://www.amazon.com/s3) to store + * data. It stores data in keys named with a user-specified prefix, inside a + * user-specified bucket. Data is stored in the form of numbered (large) + * blocks. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "util.h" +#include "amanda.h" +#include "conffile.h" +#include "device.h" +#include "s3-device.h" +#include +#ifdef HAVE_OPENSSL_HMAC_H +# include +#else +# ifdef HAVE_CRYPTO_HMAC_H +# include +# else +# ifdef HAVE_HMAC_H +# include +# endif +# endif +#endif + +/* + * Constants and static data + */ + +/* Maximum key length as specified in the S3 documentation + * (*excluding* null terminator) */ +#define S3_MAX_KEY_LENGTH 1024 + +#define S3_DEVICE_MIN_BLOCK_SIZE 1024 +#define S3_DEVICE_MAX_BLOCK_SIZE (10*1024*1024) + +/* This goes in lieu of file number for metadata. */ +#define SPECIAL_INFIX "special-" + +/* pointer to the class of our parent */ +static DeviceClass *parent_class = NULL; + +/* + * prototypes + */ + +/* + * utility functions */ + +/* Given file and block numbers, return an S3 key. + * + * @param self: the S3Device object + * @param file: the file number + * @param block: the block within that file + * @returns: a newly allocated string containing an S3 key. + */ +static char * +file_and_block_to_key(S3Device *self, + int file, + guint64 block); + +/* Given the name of a special file (such as 'tapestart'), generate + * the S3 key to use for that file. + * + * @param self: the S3Device object + * @param special_name: name of the special file + * @param file: a file number to include; omitted if -1 + * @returns: a newly alocated string containing an S3 key. + */ +static char * +special_file_to_key(S3Device *self, + char *special_name, + int file); +/* Write an amanda header file to S3. + * + * @param self: the S3Device object + * @param label: the volume label + * @param timestamp: the volume timestamp + */ +static gboolean +write_amanda_header(S3Device *self, + char *label, + char * timestamp); + +/* "Fast forward" this device to the end by looking up the largest file number + * present and setting the current file number one greater. + * + * @param self: the S3Device object + */ +static gboolean +seek_to_end(S3Device *self); + +/* Find the number of the last file that contains any data (even just a header). + * + * @param self: the S3Device object + * @returns: the last file, or -1 in event of an error + */ +static int +find_last_file(S3Device *self); + +/* Delete all blocks in the given file, including the filestart block + * + * @param self: the S3Device object + * @param file: the file to delete + */ +static gboolean +delete_file(S3Device *self, + int file); + +/* Set up self->s3 as best as possible. Unless SILENT is TRUE, + * any problems will generate warnings (with g_warning). Regardless, + * the return value is TRUE iff self->s3 is useable. + * + * @param self: the S3Device object + * @param silent: silence warnings + * @returns: TRUE if the handle is set up + */ +static gboolean +setup_handle(S3Device * self, + gboolean ignore_problems); + +/* + * class mechanics */ + +static void +s3_device_init(S3Device * o); + +static void +s3_device_class_init(S3DeviceClass * c); + +static void +s3_device_finalize(GObject * o); + +static Device* +s3_device_factory(char * device_type, + char * device_name); + +/* + * virtual functions */ + +static gboolean +s3_device_open_device(Device *pself, + char *device_name); + +static ReadLabelStatusFlags s3_device_read_label(Device * self); + +static gboolean +s3_device_start(Device * self, + DeviceAccessMode mode, + char * label, + char * timestamp); + +static gboolean +s3_device_start_file(Device * self, + const dumpfile_t * jobInfo); + +static gboolean +s3_device_write_block(Device * self, + guint size, + gpointer data, + gboolean last); + +static gboolean +s3_device_finish_file(Device * self); + +static dumpfile_t* +s3_device_seek_file(Device *pself, + guint file); + +static gboolean +s3_device_seek_block(Device *pself, + guint64 block); + +static int +s3_device_read_block(Device * pself, + gpointer data, + int *size_req); + +static gboolean +s3_device_recycle_file(Device *pself, + guint file); + +static gboolean s3_device_property_set(Device * p_self, DevicePropertyId id, + GValue * val); +static gboolean s3_device_property_get(Device * p_self, DevicePropertyId id, + GValue * val); +/* + * Private functions + */ + +/* {{{ file_and_block_to_key */ +static char * +file_and_block_to_key(S3Device *self, + int file, + guint64 block) +{ + char *s3_key = g_strdup_printf("%sf%08x-b%016llx.data", + self->prefix, file, (long long unsigned int)block); + g_assert(strlen(s3_key) <= S3_MAX_KEY_LENGTH); + return s3_key; +} +/* }}} */ + +/* {{{ special_file_to_key */ +static char * +special_file_to_key(S3Device *self, + char *special_name, + int file) +{ + if (file == -1) + return g_strdup_printf("%s" SPECIAL_INFIX "%s", self->prefix, special_name); + else + return g_strdup_printf("%sf%08x-%s", self->prefix, file, special_name); +} +/* }}} */ + +/* {{{ write_amanda_header */ +static gboolean +write_amanda_header(S3Device *self, + char *label, + char * timestamp) +{ + char * amanda_header = NULL; + char * key = NULL; + int header_size; + gboolean header_fits, result; + dumpfile_t * dumpinfo = NULL; + + /* build the header */ + dumpinfo = make_tapestart_header(DEVICE(self), label, timestamp); + amanda_header = device_build_amanda_header(DEVICE(self), dumpinfo, + &header_size, &header_fits); + if (!header_fits) { + fprintf(stderr, + _("Amanda tapestart header won't fit in a single block!\n")); + g_free(amanda_header); + return FALSE; + } + + /* write out the header and flush the uploads. */ + key = special_file_to_key(self, "tapestart", -1); + result = s3_upload(self->s3, self->bucket, key, amanda_header, header_size); + g_free(amanda_header); + g_free(key); + + if (!result) { + fprintf(stderr, _("While writing amanda header: %s\n"), + s3_strerror(self->s3)); + } + return result; +} +/* }}} */ + +/* {{{ seek_to_end */ +static gboolean +seek_to_end(S3Device *self) { + int last_file; + + Device *pself = DEVICE(self); + + last_file = find_last_file(self); + if (last_file < 0) + return FALSE; + + pself->file = last_file; + + return TRUE; +} +/* }}} */ + +/* Convert an object name into a file number, assuming the given prefix + * length. Returns -1 if the object name is invalid, or 0 if the object name + * is a "special" key. */ +static int key_to_file(guint prefix_len, const char * key) { + int file; + int i; + + /* skip the prefix */ + g_return_val_if_fail(strlen(key) > prefix_len, -1); + + key += prefix_len; + + if (strncmp(key, SPECIAL_INFIX, strlen(SPECIAL_INFIX)) == 0) { + return 0; + } + + /* check that key starts with 'f' */ + g_return_val_if_fail(key[0] == 'f', -1); + key++; + + /* check that key is of the form "%08x-" */ + for (i = 0; i < 8; i++) { + if (!(key[i] >= '0' && key[i] <= '9') && + !(key[i] >= 'a' && key[i] <= 'f') && + !(key[i] >= 'A' && key[i] <= 'F')) break; + } + if (key[i] != '-') return -1; + if (i < 8) return -1; + + /* convert the file number */ + errno = 0; + file = strtoul(key, NULL, 16); + if (errno != 0) { + g_warning(_("unparseable file number '%s'"), key); + return -1; + } + + return file; +} + +/* {{{ find_last_file */ +/* Find the number of the last file that contains any data (even just a header). + * Returns -1 in event of an error + */ +static int +find_last_file(S3Device *self) { + gboolean result; + GSList *keys; + unsigned int prefix_len = strlen(self->prefix); + int last_file = 0; + + /* list all keys matching C{PREFIX*-*}, stripping the C{-*} */ + result = s3_list_keys(self->s3, self->bucket, self->prefix, "-", &keys); + if (!result) { + fprintf(stderr, _("While listing S3 keys: %s\n"), + s3_strerror(self->s3)); + return -1; + } + + for (; keys; keys = g_slist_remove(keys, keys->data)) { + int file = key_to_file(prefix_len, keys->data); + + /* and if it's the last, keep it */ + if (file > last_file) + last_file = file; + } + + return last_file; +} +/* }}} */ + +/* {{{ find_next_file */ +/* Find the number of the file following the requested one, if any. + * Returns 0 if there is no such file or -1 in event of an error + */ +static int +find_next_file(S3Device *self, int last_file) { + gboolean result; + GSList *keys; + unsigned int prefix_len = strlen(self->prefix); + int next_file = 0; + + /* list all keys matching C{PREFIX*-*}, stripping the C{-*} */ + result = s3_list_keys(self->s3, self->bucket, self->prefix, "-", &keys); + if (!result) { + fprintf(stderr, _("While listing S3 keys: %s\n"), + s3_strerror(self->s3)); + return -1; + } + + for (; keys; keys = g_slist_remove(keys, keys->data)) { + int file; + + file = key_to_file(prefix_len, (char*)keys->data); + + if (file < 0) { + /* Set this in case we don't find a next file; this is not a + * hard error, so if we can find a next file we'll return that + * instead. */ + next_file = -1; + } + + if (file < next_file && file > last_file) { + next_file = file; + } + } + + return last_file; +} +/* }}} */ + +/* {{{ delete_file */ +static gboolean +delete_file(S3Device *self, + int file) +{ + gboolean result; + GSList *keys; + char *my_prefix = g_strdup_printf("%sf%08x-", self->prefix, file); + + result = s3_list_keys(self->s3, self->bucket, my_prefix, NULL, &keys); + if (!result) { + fprintf(stderr, _("While listing S3 keys: %s\n"), + s3_strerror(self->s3)); + return FALSE; + } + + /* this will likely be a *lot* of keys */ + for (; keys; keys = g_slist_remove(keys, keys->data)) { + if (self->verbose) g_debug(_("Deleting %s"), (char*)keys->data); + if (!s3_delete(self->s3, self->bucket, keys->data)) { + fprintf(stderr, _("While deleting key '%s': %s\n"), + (char*)keys->data, s3_strerror(self->s3)); + g_slist_free(keys); + return FALSE; + } + } + + return TRUE; +} +/* }}} */ + +/* + * Class mechanics + */ + +/* {{{ s3_device_register */ +void +s3_device_register(void) +{ + static const char * device_prefix_list[] = { "s3", NULL }; + g_assert(s3_init()); + register_device(s3_device_factory, device_prefix_list); +} +/* }}} */ + +/* {{{ s3_device_get_type */ +GType +s3_device_get_type(void) +{ + static GType type = 0; + + if G_UNLIKELY(type == 0) { + static const GTypeInfo info = { + sizeof (S3DeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) s3_device_class_init, + (GClassFinalizeFunc) NULL, + NULL /* class_data */, + sizeof (S3Device), + 0 /* n_preallocs */, + (GInstanceInitFunc) s3_device_init, + NULL + }; + + type = g_type_register_static (TYPE_DEVICE, "S3Device", &info, + (GTypeFlags)0); + } + + return type; +} +/* }}} */ + +/* {{{ s3_device_init */ +static void +s3_device_init(S3Device * self) +{ + Device * o; + DeviceProperty prop; + GValue response; + + self->initializing = TRUE; + + /* Register property values */ + o = (Device*)(self); + bzero(&response, sizeof(response)); + + prop.base = &device_property_concurrency; + prop.access = PROPERTY_ACCESS_GET_MASK; + g_value_init(&response, CONCURRENCY_PARADIGM_TYPE); + g_value_set_enum(&response, CONCURRENCY_PARADIGM_SHARED_READ); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_streaming; + g_value_init(&response, STREAMING_REQUIREMENT_TYPE); + g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_block_size; + g_value_init(&response, G_TYPE_INT); + g_value_set_int(&response, -1); /* indicates a variable block size; see below */ + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_min_block_size; + g_value_init(&response, G_TYPE_UINT); + g_value_set_uint(&response, S3_DEVICE_MIN_BLOCK_SIZE); + device_add_property(o, &prop, &response); + + prop.base = &device_property_max_block_size; + g_value_set_uint(&response, S3_DEVICE_MAX_BLOCK_SIZE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_appendable; + g_value_init(&response, G_TYPE_BOOLEAN); + g_value_set_boolean(&response, TRUE); + device_add_property(o, &prop, &response); + + prop.base = &device_property_partial_deletion; + g_value_set_boolean(&response, TRUE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_canonical_name; + g_value_init(&response, G_TYPE_STRING); + g_value_set_static_string(&response, "s3:"); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_medium_access_type; + g_value_init(&response, MEDIA_ACCESS_MODE_TYPE); + g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.access = PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START; + prop.base = &device_property_s3_secret_key; + device_add_property(o, &prop, NULL); + prop.base = &device_property_s3_access_key; + device_add_property(o, &prop, NULL); +#ifdef WANT_DEVPAY + prop.base = &device_property_s3_user_token; + device_add_property(o, &prop, NULL); +#endif +} +/* }}} */ + +/* {{{ s3_device_class_init */ +static void +s3_device_class_init(S3DeviceClass * c G_GNUC_UNUSED) +{ + GObjectClass *g_object_class = (GObjectClass*) c; + DeviceClass *device_class = (DeviceClass *)c; + + parent_class = g_type_class_ref (TYPE_DEVICE); + + device_class->open_device = s3_device_open_device; + device_class->read_label = s3_device_read_label; + device_class->start = s3_device_start; + + device_class->start_file = s3_device_start_file; + device_class->write_block = s3_device_write_block; + device_class->finish_file = s3_device_finish_file; + + device_class->seek_file = s3_device_seek_file; + device_class->seek_block = s3_device_seek_block; + device_class->read_block = s3_device_read_block; + device_class->recycle_file = s3_device_recycle_file; + + device_class->property_set = s3_device_property_set; + device_class->property_get = s3_device_property_get; + + g_object_class->finalize = s3_device_finalize; +} +/* }}} */ + +/* {{{ s3_device_factory */ +static Device* +s3_device_factory(char * device_type, + char * device_name) +{ + Device *rval; + S3Device * s3_rval; + g_assert(0 == strcmp(device_type, "s3")); + rval = DEVICE(g_object_new(TYPE_S3_DEVICE, NULL)); + s3_rval = (S3Device*)rval; + + if (!device_open_device(rval, device_name)) { + g_object_unref(rval); + return NULL; + } else { + s3_rval->initializing = FALSE; + return rval; + } + +} +/* }}} */ + +/* + * Virtual function overrides + */ + +/* {{{ s3_device_open_device */ +static gboolean +s3_device_open_device(Device *pself, + char *device_name) +{ + S3Device *self = S3_DEVICE(pself); + char * name_colon; + + g_return_val_if_fail(self != NULL, FALSE); + + /* Device name may be bucket/prefix, to support multiple volumes in a + * single bucket. */ + name_colon = index(device_name, '/'); + if (name_colon == NULL) { + self->bucket = g_strdup(device_name); + self->prefix = g_strdup(""); + } else { + self->bucket = g_strndup(device_name, name_colon - device_name); + self->prefix = g_strdup(name_colon + 1); + } + + if (self->bucket == NULL || self->bucket[0] == '\0') { + fprintf(stderr, _("Empty bucket name in device %s.\n"), device_name); + amfree(self->bucket); + amfree(self->prefix); + return FALSE; + } + + g_debug(_("S3 driver using bucket '%s', prefix '%s'"), self->bucket, self->prefix); + + /* default value */ + self->verbose = FALSE; + + if (parent_class->open_device) { + parent_class->open_device(pself, device_name); + } + + return TRUE; +} +/* }}} */ + +/* {{{ s3_device_finalize */ +static void s3_device_finalize(GObject * obj_self) { + S3Device *self = S3_DEVICE (obj_self); + + if(G_OBJECT_CLASS(parent_class)->finalize) + (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self); + + if(self->s3) s3_free(self->s3); + if(self->bucket) g_free(self->bucket); + if(self->prefix) g_free(self->prefix); +} +/* }}} */ + +static gboolean setup_handle(S3Device * self, G_GNUC_UNUSED gboolean silent) { + if (self->s3 == NULL) { + if (self->access_key == NULL) { + if (!silent) fprintf(stderr, _("No S3 access key specified\n")); + return FALSE; + } + if (self->secret_key == NULL) { + if (!silent) fprintf(stderr, _("No S3 secret key specified\n")); + return FALSE; + } +#ifdef WANT_DEVPAY + if (self->user_token == NULL) { + if (!silent) fprintf(stderr, _("No S3 user token specified\n")); + return FALSE; + } +#endif + self->s3 = s3_open(self->access_key, self->secret_key +#ifdef WANT_DEVPAY + , self->user_token +#endif + ); + if (self->s3 == NULL) { + fprintf(stderr, "Internal error creating S3 handle.\n"); + return FALSE; + } + } + + s3_verbose(self->s3, self->verbose); + + return TRUE; +} + +/* {{{ s3_device_read_label */ +static ReadLabelStatusFlags +s3_device_read_label(Device *pself) { + S3Device *self = S3_DEVICE(pself); + char *key; + gpointer buf; + guint buf_size; + dumpfile_t amanda_header; + + if (!setup_handle(self, self->initializing)) + return READ_LABEL_STATUS_DEVICE_ERROR; + + key = special_file_to_key(self, "tapestart", -1); + if (!s3_read(self->s3, self->bucket, key, &buf, &buf_size, S3_DEVICE_MAX_BLOCK_SIZE)) { + guint response_code; + s3_error_code_t s3_error_code; + s3_error(self->s3, NULL, &response_code, &s3_error_code, NULL, NULL, NULL); + + /* if it's an expected error (not found), just return FALSE */ + if (response_code == 404 && + (s3_error_code == S3_ERROR_NoSuchKey || s3_error_code == S3_ERROR_NoSuchBucket)) { + g_debug(_("Amanda header not found while reading tapestart header (this is expected for empty tapes)")); + return READ_LABEL_STATUS_VOLUME_UNLABELED; + } + + /* otherwise, log it and return */ + fprintf(stderr, _("While trying to read tapestart header: %s\n"), + s3_strerror(self->s3)); + return READ_LABEL_STATUS_DEVICE_ERROR; + } + + g_assert(buf != NULL); + fh_init(&amanda_header); + parse_file_header(buf, &amanda_header, buf_size); + + g_free(buf); + + if (amanda_header.type != F_TAPESTART) { + fprintf(stderr, _("Invalid amanda header\n")); + return READ_LABEL_STATUS_VOLUME_ERROR; + } + + amfree(pself->volume_label); + pself->volume_label = g_strdup(amanda_header.name); + amfree(pself->volume_time); + pself->volume_time = g_strdup(amanda_header.datestamp); + + return READ_LABEL_STATUS_SUCCESS; +} +/* }}} */ + +/* {{{ s3_device_start */ +static gboolean +s3_device_start (Device * pself, DeviceAccessMode mode, + char * label, char * timestamp) { + S3Device * self; + int file, last_file; + + self = S3_DEVICE(pself); + g_return_val_if_fail (self != NULL, FALSE); + + if (!setup_handle(self, FALSE)) + return FALSE; + + /* try creating the bucket, in case it doesn't exist */ + if (mode != ACCESS_READ && !s3_make_bucket(self->s3, self->bucket)) { + guint response_code; + s3_error_code_t s3_error_code; + s3_error(self->s3, NULL, &response_code, &s3_error_code, NULL, NULL, NULL); + + /* if it isn't an expected error (bucket already exists), + * return FALSE */ + if (response_code != 409 || + s3_error_code != S3_ERROR_BucketAlreadyExists) { + fprintf(stderr, _("While creating new S3 bucket: %s\n"), + s3_strerror(self->s3)); + return FALSE; + } + } + + /* call up to the parent (Device) to set access_mode, volume_label, + * and volume_time, either from the arguments (ACCESS_WRITE) or by + * reading from the 0th file (otherwise) + */ + if (parent_class->start) + if (!parent_class->start((Device*)self, mode, label, timestamp)) + return FALSE; + + /* take care of any dirty work for this mode */ + switch (mode) { + case ACCESS_READ: + break; + + case ACCESS_WRITE: + /* delete all files */ + last_file = find_last_file(self); + if (last_file < 0) return FALSE; + for (file = 0; file <= last_file; file++) { + if (!delete_file(self, file)) return FALSE; + } + + /* write a new amanda header */ + if (!write_amanda_header(self, label, timestamp)) { + return FALSE; + } + break; + + case ACCESS_APPEND: + return seek_to_end(self); + break; + case ACCESS_NULL: + g_assert_not_reached(); + } + + g_assert(pself->access_mode == mode); + + return TRUE; +} +/* }}} */ + +static gboolean s3_device_property_get(Device * p_self, DevicePropertyId id, + GValue * val) { + S3Device * self; + const DevicePropertyBase * base; + + self = S3_DEVICE(p_self); + g_return_val_if_fail(self != NULL, FALSE); + + base = device_property_get_by_id(id); + g_return_val_if_fail(self != NULL, FALSE); + + g_value_unset_init(val, base->type); + + if (id == PROPERTY_S3_SECRET_KEY) { + if (self->secret_key != NULL) { + g_value_set_string(val, self->secret_key); + return TRUE; + } else { + return FALSE; + } + } else if (id == PROPERTY_S3_ACCESS_KEY) { + if (self->access_key != NULL) { + g_value_set_string(val, self->access_key); + return TRUE; + } else { + return FALSE; + } + } +#ifdef WANT_DEVPAY + else if (id == PROPERTY_S3_USER_TOKEN) { + if (self->user_token != NULL) { + g_value_set_string(val, self->user_token); + return TRUE; + } else { + return FALSE; + } + } +#endif /* WANT_DEVPAY */ + else if (id == PROPERTY_VERBOSE) { + g_value_set_boolean(val, self->verbose); + return TRUE; + } else { + /* chain up */ + if (parent_class->property_get) { + return (parent_class->property_get)(p_self, id, val); + } else { + return FALSE; + } + } + + g_assert_not_reached(); +} + +static gboolean s3_device_property_set(Device * p_self, DevicePropertyId id, + GValue * val) { + S3Device * self; + const DevicePropertyBase * base; + + self = S3_DEVICE(p_self); + g_return_val_if_fail(self != NULL, FALSE); + + base = device_property_get_by_id(id); + g_return_val_if_fail(self != NULL, FALSE); + + g_return_val_if_fail(G_VALUE_HOLDS(val, base->type), FALSE); + + if (id == PROPERTY_S3_SECRET_KEY) { + if (p_self->access_mode != ACCESS_NULL) + return FALSE; + amfree(self->secret_key); + self->secret_key = g_value_dup_string(val); + device_clear_volume_details(p_self); + return TRUE; + } else if (id == PROPERTY_S3_ACCESS_KEY) { + if (p_self->access_mode != ACCESS_NULL) + return FALSE; + amfree(self->access_key); + self->access_key = g_value_dup_string(val); + device_clear_volume_details(p_self); + return TRUE; + } +#ifdef WANT_DEVPAY + else if (id == PROPERTY_S3_USER_TOKEN) { + if (p_self->access_mode != ACCESS_NULL) + return FALSE; + amfree(self->user_token); + self->user_token = g_value_dup_string(val); + device_clear_volume_details(p_self); + return TRUE; + } +#endif /* WANT_DEVPAY */ + else if (id == PROPERTY_VERBOSE) { + self->verbose = g_value_get_boolean(val); + /* Our S3 handle may not yet have been instantiated; if so, it will + * get the proper verbose setting when it is created */ + if (self->s3) + s3_verbose(self->s3, self->verbose); + return TRUE; + } else { + if (parent_class->property_set) { + return (parent_class->property_set)(p_self, id, val); + } else { + return FALSE; + } + } + + g_assert_not_reached(); +} + +/* functions for writing */ + +/* {{{ s3_device_start_file */ + +static gboolean +s3_device_start_file (Device *pself, const dumpfile_t *jobInfo) { + S3Device *self = S3_DEVICE(pself); + char *amanda_header; + int header_size; + gboolean header_fits, result; + char *key; + + g_return_val_if_fail (self != NULL, FALSE); + + /* Build the amanda header. */ + amanda_header = device_build_amanda_header(pself, jobInfo, + &header_size, &header_fits); + g_return_val_if_fail(amanda_header != NULL, FALSE); + g_return_val_if_fail(header_fits, FALSE); + + /* set the file and block numbers correctly */ + pself->file = (pself->file > 0)? pself->file+1 : 1; + pself->block = 0; + pself->in_file = TRUE; + + /* write it out as a special block (not the 0th) */ + key = special_file_to_key(self, "filestart", pself->file); + result = s3_upload(self->s3, self->bucket, key, amanda_header, header_size); + g_free(amanda_header); + g_free(key); + if (!result) { + fprintf(stderr, _("While writing filestart header: %s\n"), + s3_strerror(self->s3)); + return FALSE; + } + + return TRUE; +} +/* }}} */ + +/* {{{ s3_device_write_block */ +static gboolean +s3_device_write_block (Device * pself, guint size, gpointer data, + gboolean last_block) { + gboolean result; + char *filename; + S3Device * self = S3_DEVICE(pself);; + + g_assert (self != NULL); + g_assert (data != NULL); + + filename = file_and_block_to_key(self, pself->file, pself->block); + + result = s3_upload(self->s3, self->bucket, filename, data, size); + g_free(filename); + if (!result) { + fprintf(stderr, _("While writing data block to S3: %s\n"), + s3_strerror(self->s3)); + return FALSE; + } + + pself->block++; + + /* if this is the last block, finish the file */ + if (last_block) { + return s3_device_finish_file(pself); + } + + return TRUE; +} +/* }}} */ + +/* {{{ s3_device_finish_file */ +static gboolean +s3_device_finish_file (Device * pself) { + /* we're not in a file anymore */ + pself->in_file = FALSE; + + return TRUE; +} +/* }}} */ + +/* {{{ s3_device_recycle_file */ +static gboolean +s3_device_recycle_file(Device *pself, guint file) { + S3Device *self = S3_DEVICE(pself); + + return delete_file(self, file); +} +/* }}} */ + +/* functions for reading */ + +/* {{{ s3_device_seek_file */ +static dumpfile_t* +s3_device_seek_file(Device *pself, guint file) { + S3Device *self = S3_DEVICE(pself); + gboolean result; + char *key; + gpointer buf; + guint buf_size; + dumpfile_t *amanda_header; + + pself->file = file; + pself->block = 0; + pself->in_file = TRUE; + + /* read it in */ + key = special_file_to_key(self, "filestart", pself->file); + result = s3_read(self->s3, self->bucket, key, &buf, &buf_size, S3_DEVICE_MAX_BLOCK_SIZE); + g_free(key); + + if (!result) { + guint response_code; + s3_error_code_t s3_error_code; + s3_error(self->s3, NULL, &response_code, &s3_error_code, NULL, NULL, NULL); + + /* if it's an expected error (not found), check what to do. */ + if (response_code == 404 && s3_error_code == S3_ERROR_NoSuchKey) { + int next_file; + pself->file = -1; + pself->in_file = FALSE; + next_file = find_next_file(self, pself->file); + if (next_file > 0) { + /* Note short-circut of dispatcher. */ + return s3_device_seek_file(pself, next_file); + } else if (next_file == 0) { + /* No next file. Check if we are one past the end. */ + key = special_file_to_key(self, "filestart", pself->file - 1); + result = s3_read(self->s3, self->bucket, key, &buf, &buf_size, + S3_DEVICE_MAX_BLOCK_SIZE); + g_free(key); + if (result) { + return make_tapeend_header(); + } else { + return NULL; + } + } + } else { + /* An error occured finding out if we are the last file. */ + return NULL; + } + } + + /* and make a dumpfile_t out of it */ + g_assert(buf != NULL); + amanda_header = g_new(dumpfile_t, 1); + fh_init(amanda_header); + parse_file_header(buf, amanda_header, buf_size); + g_free(buf); + + switch (amanda_header->type) { + case F_DUMPFILE: + case F_CONT_DUMPFILE: + case F_SPLIT_DUMPFILE: + return amanda_header; + + default: + fprintf(stderr, + _("Invalid amanda header while reading file header\n")); + g_free(amanda_header); + return NULL; + } +} +/* }}} */ + +/* {{{ s3_device_seek_block */ +static gboolean +s3_device_seek_block(Device *pself, guint64 block) { + pself->block = block; + return TRUE; +} +/* }}} */ + +/* {{{ s3_device_read_block */ +static int +s3_device_read_block (Device * pself, gpointer data, int *size_req) { + S3Device * self = S3_DEVICE(pself); + char *key; + gpointer buf; + gboolean result; + guint buf_size; + + g_assert (self != NULL); + + /* get the file*/ + key = file_and_block_to_key(self, pself->file, pself->block); + g_assert(key != NULL); + if (self->cached_key && (0 == strcmp(key, self->cached_key))) { + /* use the cached copy and clear the cache */ + buf = self->cached_buf; + buf_size = self->cached_size; + + self->cached_buf = NULL; + g_free(self->cached_key); + self->cached_key = NULL; + } else { + /* clear the cache and actually download the file */ + if (self->cached_buf) { + g_free(self->cached_buf); + self->cached_buf = NULL; + } + if (self->cached_key) { + g_free(self->cached_key); + self->cached_key = NULL; + } + + result = s3_read(self->s3, self->bucket, key, &buf, &buf_size, S3_DEVICE_MAX_BLOCK_SIZE); + if (!result) { + guint response_code; + s3_error_code_t s3_error_code; + s3_error(self->s3, NULL, &response_code, &s3_error_code, NULL, NULL, NULL); + + g_free(key); + key = NULL; + + /* if it's an expected error (not found), just return -1 */ + if (response_code == 404 && s3_error_code == S3_ERROR_NoSuchKey) { + pself->is_eof = TRUE; + pself->in_file = FALSE; + return -1; + } + + /* otherwise, log it and return FALSE */ + fprintf(stderr, _("While reading data block from S3: %s\n"), + s3_strerror(self->s3)); + return -1; + } + } + + /* INVARIANT: cache is NULL */ + g_assert(self->cached_buf == NULL); + g_assert(self->cached_key == NULL); + + /* now see how the caller wants to deal with that */ + if (data == NULL || *size_req < 0 || buf_size > (guint)*size_req) { + /* A size query or short buffer -- load the cache and return the size*/ + self->cached_buf = buf; + self->cached_key = key; + self->cached_size = buf_size; + + *size_req = buf_size; + return 0; + } else { + /* ok, all checks are passed -- copy the data */ + *size_req = buf_size; + g_memmove(data, buf, buf_size); + g_free(key); + g_free(buf); + + /* move on to the next block */ + pself->block++; + + return buf_size; + } +} +/* }}} */ diff --git a/device-src/s3-device.h b/device-src/s3-device.h new file mode 100644 index 0000000..286cb36 --- /dev/null +++ b/device-src/s3-device.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#ifndef __S3_DEVICE_H__ +#define __S3_DEVICE_H__ +#include +#include +#include +#include "s3.h" + +/* + * Constants + */ + +/* + * Type checking and casting macros + */ +#define TYPE_S3_DEVICE (s3_device_get_type()) +#define S3_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), s3_device_get_type(), S3Device) +#define S3_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), s3_device_get_type(), S3Device const) +#define S3_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), s3_device_get_type(), S3DeviceClass) +#define IS_S3_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), s3_device_get_type ()) + +#define S3_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), s3_device_get_type(), S3DeviceClass) + +/* + * Main object structure + */ +typedef struct _S3MetadataFile S3MetadataFile; + +#ifndef __TYPEDEF_S3_DEVICE__ +#define __TYPEDEF_S3_DEVICE__ +typedef struct _S3Device S3Device; +#endif +struct _S3Device { + Device __parent__; + + /* The "easy" curl handle we use to access Amazon S3 */ + S3Handle *s3; + + /* S3 access information */ + char *bucket; + char *prefix; + + /* The S3 access information. */ + char *secret_key; + char *access_key; +#ifdef WANT_DEVPAY + char *user_token; +#endif + + /* a cache for unsuccessful reads (where we get the file but the caller + * doesn't have space for it or doesn't want it), where we expect the + * next call will request the same file. + */ + char *cached_buf; + char *cached_key; + int cached_size; + + /* Produce verbose output? */ + gboolean verbose; + /* Set to FALSE once s3_device_open_device is finished. */ + gboolean initializing; +}; + +/* + * Class definition + */ +typedef struct _S3DeviceClass S3DeviceClass; +struct _S3DeviceClass { + DeviceClass __parent__; +}; + + +/* + * Public methods + */ +GType s3_device_get_type (void); +void s3_device_register (void); + +#endif diff --git a/device-src/s3.c b/device-src/s3.c new file mode 100644 index 0000000..dfd29dc --- /dev/null +++ b/device-src/s3.c @@ -0,0 +1,1397 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* TODO + * - Compute and send Content-MD5 header + * - check SSL certificate + * - collect speed statistics + * - debugging mode + */ + +#include +#include +#include +#include +#include +#include +#include +#include "util.h" +#include "amanda.h" +#include "s3.h" +#include "base64.h" +#include + +/* Constant renamed after version 7.10.7 */ +#ifndef CURLINFO_RESPONSE_CODE +#define CURLINFO_RESPONSE_CODE CURLINFO_HTTP_CODE +#endif + +/* We don't need OpenSSL's kerberos support, and it's broken in + * RHEL 3 anyway. */ +#define OPENSSL_NO_KRB5 + +#ifdef HAVE_OPENSSL_HMAC_H +# include +#else +# ifdef HAVE_CRYPTO_HMAC_H +# include +# else +# ifdef HAVE_HMAC_H +# include +# endif +# endif +#endif + +#include +#include + +/* + * Constants / definitions + */ + +/* Maximum key length as specified in the S3 documentation + * (*excluding* null terminator) */ +#define S3_MAX_KEY_LENGTH 1024 + +#define AMAZON_SECURITY_HEADER "x-amz-security-token" + +/* parameters for exponential backoff in the face of retriable errors */ + +/* start at 0.01s */ +#define EXPONENTIAL_BACKOFF_START_USEC 10000 +/* double at each retry */ +#define EXPONENTIAL_BACKOFF_BASE 2 +/* retry 15 times (for a total of about 5 minutes spent waiting) */ +#define EXPONENTIAL_BACKOFF_MAX_RETRIES 5 + +/* general "reasonable size" parameters */ +#define MAX_ERROR_RESPONSE_LEN (100*1024) + +/* Results which should always be retried */ +#define RESULT_HANDLING_ALWAYS_RETRY \ + { 400, S3_ERROR_RequestTimeout, 0, S3_RESULT_RETRY }, \ + { 409, S3_ERROR_OperationAborted, 0, S3_RESULT_RETRY }, \ + { 412, S3_ERROR_PreconditionFailed, 0, S3_RESULT_RETRY }, \ + { 500, S3_ERROR_InternalError, 0, S3_RESULT_RETRY }, \ + { 501, S3_ERROR_NotImplemented, 0, S3_RESULT_RETRY }, \ + { 0, 0, CURLE_COULDNT_CONNECT, S3_RESULT_RETRY }, \ + { 0, 0, CURLE_PARTIAL_FILE, S3_RESULT_RETRY }, \ + { 0, 0, CURLE_OPERATION_TIMEOUTED, S3_RESULT_RETRY }, \ + { 0, 0, CURLE_SEND_ERROR, S3_RESULT_RETRY }, \ + { 0, 0, CURLE_RECV_ERROR, S3_RESULT_RETRY } + +/* + * Data structures and associated functions + */ + +struct S3Handle { + /* (all strings in this struct are freed by s3_free()) */ + + char *access_key; + char *secret_key; +#ifdef WANT_DEVPAY + char *user_token; +#endif + + CURL *curl; + + gboolean verbose; + + /* information from the last request */ + char *last_message; + guint last_response_code; + s3_error_code_t last_s3_error_code; + CURLcode last_curl_code; + guint last_num_retries; + void *last_response_body; + guint last_response_body_size; +}; + +/* + * S3 errors */ + +/* (see preprocessor magic in s3.h) */ + +static char * s3_error_code_names[] = { +#define S3_ERROR(NAME) #NAME + S3_ERROR_LIST +#undef S3_ERROR +}; + +/* Convert an s3 error name to an error code. This function + * matches strings case-insensitively, and is appropriate for use + * on data from the network. + * + * @param s3_error_code: the error name + * @returns: the error code (see constants in s3.h) + */ +static s3_error_code_t +s3_error_code_from_name(char *s3_error_name); + +/* Convert an s3 error code to a string + * + * @param s3_error_code: the error code to convert + * @returns: statically allocated string + */ +static const char * +s3_error_name_from_code(s3_error_code_t s3_error_code); + +/* Does this install of curl support SSL? + * + * @returns: boolean + */ +static gboolean +s3_curl_supports_ssl(void); + +/* + * result handling */ + +/* result handling is specified by a static array of result_handling structs, + * which match based on response_code (from HTTP) and S3 error code. The result + * given for the first match is used. 0 acts as a wildcard for both response_code + * and s3_error_code. The list is terminated with a struct containing 0 for both + * response_code and s3_error_code; the result for that struct is the default + * result. + * + * See RESULT_HANDLING_ALWAYS_RETRY for an example. + */ +typedef enum { + S3_RESULT_RETRY = -1, + S3_RESULT_FAIL = 0, + S3_RESULT_OK = 1 +} s3_result_t; + +typedef struct result_handling { + guint response_code; + s3_error_code_t s3_error_code; + CURLcode curl_code; + s3_result_t result; +} result_handling_t; + +/* Lookup a result in C{result_handling}. + * + * @param result_handling: array of handling specifications + * @param response_code: response code from operation + * @param s3_error_code: s3 error code from operation, if any + * @param curl_code: the CURL error, if any + * @returns: the matching result + */ +static s3_result_t +lookup_result(const result_handling_t *result_handling, + guint response_code, + s3_error_code_t s3_error_code, + CURLcode curl_code); + +/* + * Precompiled regular expressions */ + +static const char *error_name_regex_string = "[:space:]*([^<]*)[:space:]*"; +static const char *message_regex_string = "[:space:]*([^<]*)[:space:]*"; +static regex_t error_name_regex, message_regex; + +/* + * Utility functions + */ + +/* Build a resource URI as /[bucket[/key]], with proper URL + * escaping. + * + * The caller is responsible for freeing the resulting string. + * + * @param bucket: the bucket, or NULL if none is involved + * @param key: the key within the bucket, or NULL if none is involved + * @returns: completed URI + */ +static char * +build_resource(const char *bucket, + const char *key); + +/* Create proper authorization headers for an Amazon S3 REST + * request to C{headers}. + * + * @note: C{X-Amz} headers (in C{headers}) must + * - be in lower-case + * - be in alphabetical order + * - have no spaces around the colon + * (don't yell at me -- see the Amazon Developer Guide) + * + * @param hdl: the S3Handle object + * @param verb: capitalized verb for this request ('PUT', 'GET', etc.) + * @param resource: the resource being accessed + */ +static struct curl_slist * +authenticate_request(S3Handle *hdl, + const char *verb, + const char *resource); + +/* Interpret the response to an S3 operation, assuming CURL completed its request + * successfully. This function fills in the relevant C{hdl->last*} members. + * + * @param hdl: The S3Handle object + * @param body: the response body + * @param body_len: the length of the response body + * @returns: TRUE if the response should be retried (e.g., network error) + */ +static gboolean +interpret_response(S3Handle *hdl, + CURLcode curl_code, + char *curl_error_buffer, + void *body, + guint body_len); + +/* Perform an S3 operation. This function handles all of the details + * of retryig requests and so on. + * + * @param hdl: the S3Handle object + * @param resource: the UTF-8 encoded resource to access + (without query parameters) + * @param uri: the urlencoded URI to access at Amazon (may be identical to resource) + * @param verb: the HTTP request method + * @param request_body: the request body, or NULL if none should be sent + * @param request_body_size: the length of the request body + * @param max_response_size: the maximum number of bytes to accept in the + * response, or 0 for no limit. + * @param preallocate_response_size: for more efficient operation, preallocate + * a buffer of this size for the response body. Addition space will be allocated + * if the response exceeds this size. + * @param result_handling: instructions for handling the results; see above. + * @returns: the result specified by result_handling; details of the response + * are then available in C{hdl->last*} + */ +static s3_result_t +perform_request(S3Handle *hdl, + const char *resource, + const char *uri, + const char *verb, + const void *request_body, + guint request_body_size, + guint max_response_size, + guint preallocate_response_size, + const result_handling_t *result_handling); + +/* + * Static function implementations + */ + +/* {{{ s3_error_code_from_name */ +static s3_error_code_t +s3_error_code_from_name(char *s3_error_name) +{ + int i; + + if (!s3_error_name) return S3_ERROR_Unknown; + + /* do a brute-force search through the list, since it's not sorted */ + for (i = 0; i < S3_ERROR_END; i++) { + if (strcasecmp(s3_error_name, s3_error_code_names[i]) == 0) + return i; + } + + return S3_ERROR_Unknown; +} +/* }}} */ + +/* {{{ s3_error_name_from_code */ +static const char * +s3_error_name_from_code(s3_error_code_t s3_error_code) +{ + if (s3_error_code >= S3_ERROR_END) + s3_error_code = S3_ERROR_Unknown; + + if (s3_error_code == 0) + return NULL; + + return s3_error_code_names[s3_error_code]; +} +/* }}} */ + +/* {{{ s3_curl_supports_ssl */ +static gboolean +s3_curl_supports_ssl(void) +{ + static int supported = -1; + + if (supported == -1) { +#if defined(CURL_VERSION_SSL) + curl_version_info_data *info = curl_version_info(CURLVERSION_NOW); + if (info->features & CURL_VERSION_SSL) + supported = 1; + else + supported = 0; +#else + supported = 0; +#endif + } + + return supported; +} +/* }}} */ + +/* {{{ lookup_result */ +static s3_result_t +lookup_result(const result_handling_t *result_handling, + guint response_code, + s3_error_code_t s3_error_code, + CURLcode curl_code) +{ + g_return_val_if_fail(result_handling != NULL, S3_RESULT_FAIL); + + while (result_handling->response_code + || result_handling->s3_error_code + || result_handling->curl_code) { + if ((result_handling->response_code && result_handling->response_code != response_code) + || (result_handling->s3_error_code && result_handling->s3_error_code != s3_error_code) + || (result_handling->curl_code && result_handling->curl_code != curl_code)) { + result_handling++; + continue; + } + + return result_handling->result; + } + + /* return the result for the terminator, as the default */ + return result_handling->result; +} +/* }}} */ + +/* {{{ build_resource */ +static char * +build_resource(const char *bucket, + const char *key) +{ + char *esc_bucket = NULL, *esc_key = NULL; + char *resource = NULL; + + if (bucket) + if (!(esc_bucket = curl_escape(bucket, 0))) + goto cleanup; + + if (key) + if (!(esc_key = curl_escape(key, 0))) + goto cleanup; + + if (esc_bucket) { + if (esc_key) { + resource = g_strdup_printf("/%s/%s", esc_bucket, esc_key); + } else { + resource = g_strdup_printf("/%s", esc_bucket); + } + } else { + resource = g_strdup("/"); + } +cleanup: + if (esc_bucket) curl_free(esc_bucket); + if (esc_key) curl_free(esc_key); + + return resource; +} +/* }}} */ + +/* {{{ authenticate_request */ +static struct curl_slist * +authenticate_request(S3Handle *hdl, + const char *verb, + const char *resource) +{ + time_t t; + struct tm tmp; + char date[100]; + char * buf; + HMAC_CTX ctx; + char md_value[EVP_MAX_MD_SIZE+1]; + char auth_base64[40]; + unsigned int md_len; + struct curl_slist *headers = NULL; + char * auth_string; + + /* calculate the date */ + t = time(NULL); + if (!localtime_r(&t, &tmp)) perror("localtime"); + if (!strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %Z", &tmp)) + perror("strftime"); + + /* run HMAC-SHA1 on the canonicalized string */ + HMAC_CTX_init(&ctx); + HMAC_Init_ex(&ctx, hdl->secret_key, strlen(hdl->secret_key), EVP_sha1(), NULL); + auth_string = g_strconcat(verb, "\n\n\n", date, "\n", +#ifdef WANT_DEVPAY + AMAZON_SECURITY_HEADER, ":", + hdl->user_token, ",", + STS_PRODUCT_TOKEN, "\n", +#endif + resource, NULL); + HMAC_Update(&ctx, (unsigned char*) auth_string, strlen(auth_string)); + g_free(auth_string); + md_len = EVP_MAX_MD_SIZE; + HMAC_Final(&ctx, (unsigned char*)md_value, &md_len); + HMAC_CTX_cleanup(&ctx); + base64_encode(md_value, md_len, auth_base64, sizeof(auth_base64)); + + /* append the new headers */ +#ifdef WANT_DEVPAY + /* Devpay headers are included in hash. */ + buf = g_strdup_printf(AMAZON_SECURITY_HEADER ": %s", hdl->user_token); + headers = curl_slist_append(headers, buf); + amfree(buf); + + buf = g_strdup_printf(AMAZON_SECURITY_HEADER ": %s", STS_PRODUCT_TOKEN); + headers = curl_slist_append(headers, buf); + amfree(buf); +#endif + + buf = g_strdup_printf("Authorization: AWS %s:%s", + hdl->access_key, auth_base64); + headers = curl_slist_append(headers, buf); + amfree(buf); + + buf = g_strdup_printf("Date: %s", date); + headers = curl_slist_append(headers, buf); + amfree(buf); + + return headers; +} +/* }}} */ + +/* {{{ interpret_response */ +static void +regex_error(regex_t *regex, int reg_result) +{ + char *message; + int size; + + size = regerror(reg_result, regex, NULL, 0); + message = g_malloc(size); + if (!message) abort(); /* we're really out of luck */ + regerror(reg_result, regex, message, size); + + /* this is programmer error (bad regexp), so just log + * and abort(). There's no good way to signal a + * permanaent error from interpret_response. */ + g_error(_("Regex error: %s"), message); + g_assert_not_reached(); +} + +static gboolean +interpret_response(S3Handle *hdl, + CURLcode curl_code, + char *curl_error_buffer, + void *body, + guint body_len) +{ + long response_code = 0; + regmatch_t pmatch[2]; + int reg_result; + char *error_name = NULL, *message = NULL; + char *body_copy = NULL; + + if (!hdl) return FALSE; + + if (hdl->last_message) g_free(hdl->last_message); + hdl->last_message = NULL; + + /* bail out from a CURL error */ + if (curl_code != CURLE_OK) { + hdl->last_curl_code = curl_code; + hdl->last_message = g_strdup_printf("CURL error: %s", curl_error_buffer); + return FALSE; + } + + /* CURL seems to think things were OK, so get its response code */ + curl_easy_getinfo(hdl->curl, CURLINFO_RESPONSE_CODE, &response_code); + hdl->last_response_code = response_code; + + /* 2xx and 3xx codes won't have a response body*/ + if (200 <= response_code && response_code < 400) { + hdl->last_s3_error_code = S3_ERROR_None; + return FALSE; + } + + /* Now look at the body to try to get the actual Amazon error message. Rather + * than parse out the XML, just use some regexes. */ + + /* impose a reasonable limit on body size */ + if (body_len > MAX_ERROR_RESPONSE_LEN) { + hdl->last_message = g_strdup("S3 Error: Unknown (response body too large to parse)"); + return FALSE; + } else if (!body || body_len == 0) { + hdl->last_message = g_strdup("S3 Error: Unknown (empty response body)"); + return TRUE; /* perhaps a network error; retry the request */ + } + + /* use strndup to get a zero-terminated string */ + body_copy = g_strndup(body, body_len); + if (!body_copy) goto cleanup; + + reg_result = regexec(&error_name_regex, body_copy, 2, pmatch, 0); + if (reg_result != 0) { + if (reg_result == REG_NOMATCH) { + error_name = NULL; + } else { + regex_error(&error_name_regex, reg_result); + g_assert_not_reached(); + } + } else { + error_name = find_regex_substring(body_copy, pmatch[1]); + } + + reg_result = regexec(&message_regex, body_copy, 2, pmatch, 0); + if (reg_result != 0) { + if (reg_result == REG_NOMATCH) { + message = NULL; + } else { + regex_error(&message_regex, reg_result); + g_assert_not_reached(); + } + } else { + message = find_regex_substring(body_copy, pmatch[1]); + } + + if (error_name) { + hdl->last_s3_error_code = s3_error_code_from_name(error_name); + } + + if (message) { + hdl->last_message = message; + message = NULL; /* steal the reference to the string */ + } + +cleanup: + if (body_copy) g_free(body_copy); + if (message) g_free(message); + if (error_name) g_free(error_name); + + return FALSE; +} +/* }}} */ + +/* {{{ perform_request */ +size_t buffer_readfunction(void *ptr, size_t size, + size_t nmemb, void * stream) { + CurlBuffer *data = stream; + guint bytes_desired = size * nmemb; + + /* check the number of bytes remaining, just to be safe */ + if (bytes_desired > data->buffer_len - data->buffer_pos) + bytes_desired = data->buffer_len - data->buffer_pos; + + memcpy((char *)ptr, data->buffer + data->buffer_pos, bytes_desired); + data->buffer_pos += bytes_desired; + + return bytes_desired; +} + +size_t +buffer_writefunction(void *ptr, size_t size, size_t nmemb, void *stream) +{ + CurlBuffer * data = stream; + guint new_bytes = size * nmemb; + guint bytes_needed = data->buffer_pos + new_bytes; + + /* error out if the new size is greater than the maximum allowed */ + if (data->max_buffer_size && bytes_needed > data->max_buffer_size) + return 0; + + /* reallocate if necessary. We use exponential sizing to make this + * happen less often. */ + if (bytes_needed > data->buffer_len) { + guint new_size = MAX(bytes_needed, data->buffer_len * 2); + if (data->max_buffer_size) { + new_size = MIN(new_size, data->max_buffer_size); + } + data->buffer = g_realloc(data->buffer, new_size); + data->buffer_len = new_size; + } + g_return_val_if_fail(data->buffer, 0); /* returning zero signals an error to libcurl */ + + /* actually copy the data to the buffer */ + memcpy(data->buffer + data->buffer_pos, ptr, new_bytes); + data->buffer_pos += new_bytes; + + /* signal success to curl */ + return new_bytes; +} + +static int +curl_debug_message(CURL *curl G_GNUC_UNUSED, + curl_infotype type, + char *s, + size_t len, + void *unused G_GNUC_UNUSED) +{ + char *lineprefix; + char *message; + char **lines, **line; + + switch (type) { + case CURLINFO_TEXT: + lineprefix=""; + break; + + case CURLINFO_HEADER_IN: + lineprefix="Hdr In: "; + break; + + case CURLINFO_HEADER_OUT: + lineprefix="Hdr Out: "; + break; + + default: + /* ignore data in/out -- nobody wants to see that in the + * debug logs! */ + return 0; + } + + /* split the input into lines */ + message = g_strndup(s, len); + lines = g_strsplit(message, "\n", -1); + g_free(message); + + for (line = lines; *line; line++) { + if (**line == '\0') continue; /* skip blank lines */ + g_debug("%s%s", lineprefix, *line); + } + g_strfreev(lines); + + return 0; +} + +static s3_result_t +perform_request(S3Handle *hdl, + const char *resource, + const char *uri, + const char *verb, + const void *request_body, + guint request_body_size, + guint max_response_size, + guint preallocate_response_size, + const result_handling_t *result_handling) +{ + const char *baseurl; + char *url = NULL; + s3_result_t result = S3_RESULT_FAIL; /* assume the worst.. */ + CURLcode curl_code = CURLE_OK; + char curl_error_buffer[CURL_ERROR_SIZE] = ""; + struct curl_slist *headers = NULL; + CurlBuffer readdata = { (void*)request_body, request_body_size, 0, 0 }; + CurlBuffer writedata = { NULL, 0, 0, max_response_size }; + gboolean should_retry; + guint retries = 0; + gulong backoff = EXPONENTIAL_BACKOFF_START_USEC; + + g_return_val_if_fail(hdl != NULL && hdl->curl != NULL, S3_RESULT_FAIL); + + s3_reset(hdl); + + baseurl = s3_curl_supports_ssl()? "https://s3.amazonaws.com":"http://s3.amazonaws.com"; + url = g_strconcat(baseurl, uri, NULL); + if (!url) goto cleanup; + + if (preallocate_response_size) { + writedata.buffer = g_malloc(preallocate_response_size); + if (!writedata.buffer) goto cleanup; + writedata.buffer_len = preallocate_response_size; + } + + while (1) { + /* reset things */ + if (headers) { + curl_slist_free_all(headers); + } + readdata.buffer_pos = 0; + writedata.buffer_pos = 0; + curl_error_buffer[0] = '\0'; + + /* set up the request */ + headers = authenticate_request(hdl, verb, resource); + + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_VERBOSE, hdl->verbose))) + goto curl_error; + if (hdl->verbose) + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_DEBUGFUNCTION, + curl_debug_message))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_ERRORBUFFER, + curl_error_buffer))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_NOPROGRESS, 1))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_URL, url))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_HTTPHEADER, + headers))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_CUSTOMREQUEST, + verb))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_WRITEFUNCTION, buffer_writefunction))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_WRITEDATA, &writedata))) + goto curl_error; + if (max_response_size) { +#ifdef CURLOPT_MAXFILESIZE_LARGE + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_MAXFILESIZE_LARGE, (curl_off_t)max_response_size))) + goto curl_error; +#else +# ifdef CURLOPT_MAXFILESIZE + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_MAXFILESIZE, (long)max_response_size))) + goto curl_error; +# else + /* no MAXFILESIZE option -- that's OK */ +# endif +#endif + } + + if (request_body) { + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_UPLOAD, 1))) + goto curl_error; +#ifdef CURLOPT_INFILESIZE_LARGE + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)request_body_size))) + goto curl_error; +#else + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_INFILESIZE, (long)request_body_size))) + goto curl_error; +#endif + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_READFUNCTION, buffer_readfunction))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_READDATA, &readdata))) + goto curl_error; + } else { + /* Clear request_body options. */ + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_UPLOAD, 0))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_READFUNCTION, + NULL))) + goto curl_error; + if ((curl_code = curl_easy_setopt(hdl->curl, CURLOPT_READDATA, + NULL))) + goto curl_error; + } + + /* Perform the request */ + curl_code = curl_easy_perform(hdl->curl); + + + /* interpret the response into hdl->last* */ + curl_error: /* (label for short-circuiting the curl_easy_perform call) */ + should_retry = interpret_response(hdl, curl_code, curl_error_buffer, + writedata.buffer, writedata.buffer_pos); + + /* and, unless we know we need to retry, see what we're to do now */ + if (!should_retry) { + result = lookup_result(result_handling, hdl->last_response_code, + hdl->last_s3_error_code, hdl->last_curl_code); + + /* break out of the while(1) unless we're retrying */ + if (result != S3_RESULT_RETRY) + break; + } + + if (retries >= EXPONENTIAL_BACKOFF_MAX_RETRIES) { + /* we're out of retries, so annotate hdl->last_message appropriately and bail + * out. */ + char *m = g_strdup_printf("Too many retries; last message was '%s'", hdl->last_message); + if (hdl->last_message) g_free(hdl->last_message); + hdl->last_message = m; + result = S3_RESULT_FAIL; + break; + } + + g_usleep(backoff); + retries++; + backoff *= EXPONENTIAL_BACKOFF_BASE; + } + + if (result != S3_RESULT_OK) { + g_debug(_("%s %s failed with %d/%s"), verb, url, + hdl->last_response_code, + s3_error_name_from_code(hdl->last_s3_error_code)); + } + +cleanup: + if (url) g_free(url); + if (headers) curl_slist_free_all(headers); + + /* we don't deallocate the response body -- we keep it for later */ + hdl->last_response_body = writedata.buffer; + hdl->last_response_body_size = writedata.buffer_pos; + hdl->last_num_retries = retries; + + return result; +} +/* }}} */ + +/* + * Public function implementations + */ + +/* {{{ s3_init */ +gboolean +s3_init(void) +{ + char regmessage[1024]; + int size; + int reg_result; + + reg_result = regcomp(&error_name_regex, error_name_regex_string, REG_EXTENDED | REG_ICASE); + if (reg_result != 0) { + size = regerror(reg_result, &error_name_regex, regmessage, sizeof(regmessage)); + g_error(_("Regex error: %s"), regmessage); + return FALSE; + } + + reg_result = regcomp(&message_regex, message_regex_string, REG_EXTENDED | REG_ICASE); + if (reg_result != 0) { + size = regerror(reg_result, &message_regex, regmessage, sizeof(regmessage)); + g_error(_("Regex error: %s"), regmessage); + return FALSE; + } + + return TRUE; +} +/* }}} */ + +/* {{{ s3_open */ +S3Handle * +s3_open(const char *access_key, + const char *secret_key +#ifdef WANT_DEVPAY + , + const char *user_token +#endif + ) { + S3Handle *hdl; + + hdl = g_new0(S3Handle, 1); + if (!hdl) goto error; + + hdl->verbose = FALSE; + + hdl->access_key = g_strdup(access_key); + if (!hdl->access_key) goto error; + + hdl->secret_key = g_strdup(secret_key); + if (!hdl->secret_key) goto error; + +#ifdef WANT_DEVPAY + hdl->user_token = g_strdup(user_token); + if (!hdl->user_token) goto error; +#endif + + hdl->curl = curl_easy_init(); + if (!hdl->curl) goto error; + + return hdl; + +error: + s3_free(hdl); + return NULL; +} +/* }}} */ + +/* {{{ s3_free */ +void +s3_free(S3Handle *hdl) +{ + s3_reset(hdl); + + if (hdl) { + if (hdl->access_key) g_free(hdl->access_key); + if (hdl->secret_key) g_free(hdl->secret_key); +#ifdef WANT_DEVPAY + if (hdl->user_token) g_free(hdl->user_token); +#endif + if (hdl->curl) curl_easy_cleanup(hdl->curl); + + g_free(hdl); + } +} +/* }}} */ + +/* {{{ s3_reset */ +void +s3_reset(S3Handle *hdl) +{ + if (hdl) { + /* We don't call curl_easy_reset here, because doing that in curl + * < 7.16 blanks the default CA certificate path, and there's no way + * to get it back. */ + if (hdl->last_message) { + g_free(hdl->last_message); + hdl->last_message = NULL; + } + + hdl->last_response_code = 0; + hdl->last_curl_code = 0; + hdl->last_s3_error_code = 0; + hdl->last_num_retries = 0; + + if (hdl->last_response_body) { + g_free(hdl->last_response_body); + hdl->last_response_body = NULL; + } + + hdl->last_response_body_size = 0; + } +} +/* }}} */ + +/* {{{ s3_error */ +void +s3_error(S3Handle *hdl, + const char **message, + guint *response_code, + s3_error_code_t *s3_error_code, + const char **s3_error_name, + CURLcode *curl_code, + guint *num_retries) +{ + if (hdl) { + if (message) *message = hdl->last_message; + if (response_code) *response_code = hdl->last_response_code; + if (s3_error_code) *s3_error_code = hdl->last_s3_error_code; + if (s3_error_name) *s3_error_name = s3_error_name_from_code(hdl->last_s3_error_code); + if (curl_code) *curl_code = hdl->last_curl_code; + if (num_retries) *num_retries = hdl->last_num_retries; + } else { + /* no hdl? return something coherent, anyway */ + if (message) *message = "NULL S3Handle"; + if (response_code) *response_code = 0; + if (s3_error_code) *s3_error_code = 0; + if (s3_error_name) *s3_error_name = NULL; + if (curl_code) *curl_code = 0; + if (num_retries) *num_retries = 0; + } +} +/* }}} */ + +/* {{{ s3_verbose */ +void +s3_verbose(S3Handle *hdl, gboolean verbose) +{ + hdl->verbose = verbose; +} +/* }}} */ + +/* {{{ s3_sterror */ +char * +s3_strerror(S3Handle *hdl) +{ + const char *message; + guint response_code; + const char *s3_error_name; + CURLcode curl_code; + guint num_retries; + + char s3_info[256] = ""; + char response_info[16] = ""; + char curl_info[32] = ""; + char retries_info[32] = ""; + + s3_error(hdl, &message, &response_code, NULL, &s3_error_name, &curl_code, &num_retries); + + if (!message) + message = "Unkonwn S3 error"; + if (s3_error_name) + g_snprintf(s3_info, sizeof(s3_info), " (%s)", s3_error_name); + if (response_code) + g_snprintf(response_info, sizeof(response_info), " (HTTP %d)", response_code); + if (curl_code) + g_snprintf(curl_info, sizeof(curl_info), " (CURLcode %d)", curl_code); + if (num_retries) + g_snprintf(retries_info, sizeof(retries_info), " (after %d retries)", num_retries); + + return g_strdup_printf("%s%s%s%s%s", message, s3_info, curl_info, response_info, retries_info); +} +/* }}} */ + +/* {{{ s3_upload */ +/* Perform an upload. When this function returns, KEY and + * BUFFER remain the responsibility of the caller. + * + * @param self: the s3 device + * @param key: the key to which the upload should be made + * @param buffer: the data to be uploaded + * @param buffer_len: the length of the data to upload + * @returns: false if an error ocurred + */ +gboolean +s3_upload(S3Handle *hdl, + const char *bucket, + const char *key, + gpointer buffer, + guint buffer_len) +{ + char *resource = NULL; + s3_result_t result = S3_RESULT_FAIL; + static result_handling_t result_handling[] = { + { 200, 0, 0, S3_RESULT_OK }, + RESULT_HANDLING_ALWAYS_RETRY, + { 0, 0, 0, /* default: */ S3_RESULT_FAIL } + }; + + g_return_val_if_fail(hdl != NULL, FALSE); + + resource = build_resource(bucket, key); + if (resource) { + result = perform_request(hdl, resource, resource, "PUT", + buffer, buffer_len, MAX_ERROR_RESPONSE_LEN, 0, + result_handling); + g_free(resource); + } + + return result == S3_RESULT_OK; +} +/* }}} */ + +/* {{{ s3_list_keys */ + +/* Private structure for our "thunk", which tracks where the user is in the list + * of keys. */ +struct list_keys_thunk { + GSList *filename_list; /* all pending filenames */ + + gboolean in_contents; /* look for "key" entities in here */ + gboolean in_common_prefixes; /* look for "prefix" entities in here */ + + gboolean is_truncated; + gchar *next_marker; + + gboolean want_text; + + gchar *text; + gsize text_len; +}; + +/* Functions for a SAX parser to parse the XML from Amazon */ + +static void +list_start_element(GMarkupParseContext *context G_GNUC_UNUSED, + const gchar *element_name, + const gchar **attribute_names G_GNUC_UNUSED, + const gchar **attribute_values G_GNUC_UNUSED, + gpointer user_data, + GError **error G_GNUC_UNUSED) +{ + struct list_keys_thunk *thunk = (struct list_keys_thunk *)user_data; + + thunk->want_text = 0; + if (strcasecmp(element_name, "contents") == 0) { + thunk->in_contents = 1; + } else if (strcasecmp(element_name, "commonprefixes") == 0) { + thunk->in_common_prefixes = 1; + } else if (strcasecmp(element_name, "prefix") == 0 && thunk->in_common_prefixes) { + thunk->want_text = 1; + } else if (strcasecmp(element_name, "key") == 0 && thunk->in_contents) { + thunk->want_text = 1; + } else if (strcasecmp(element_name, "istruncated")) { + thunk->want_text = 1; + } else if (strcasecmp(element_name, "nextmarker")) { + thunk->want_text = 1; + } +} + +static void +list_end_element(GMarkupParseContext *context G_GNUC_UNUSED, + const gchar *element_name, + gpointer user_data, + GError **error G_GNUC_UNUSED) +{ + struct list_keys_thunk *thunk = (struct list_keys_thunk *)user_data; + + if (strcasecmp(element_name, "contents") == 0) { + thunk->in_contents = 0; + } else if (strcasecmp(element_name, "commonprefixes") == 0) { + thunk->in_common_prefixes = 0; + } else if (strcasecmp(element_name, "key") == 0 && thunk->in_contents) { + thunk->filename_list = g_slist_prepend(thunk->filename_list, thunk->text); + thunk->text = NULL; + } else if (strcasecmp(element_name, "prefix") == 0 && thunk->in_common_prefixes) { + thunk->filename_list = g_slist_prepend(thunk->filename_list, thunk->text); + thunk->text = NULL; + } else if (strcasecmp(element_name, "istruncated") == 0) { + if (thunk->text && strncasecmp(thunk->text, "false", 5) != 0) + thunk->is_truncated = TRUE; + } else if (strcasecmp(element_name, "nextmarker") == 0) { + if (thunk->next_marker) g_free(thunk->next_marker); + thunk->next_marker = thunk->text; + thunk->text = NULL; + } +} + +static void +list_text(GMarkupParseContext *context G_GNUC_UNUSED, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error G_GNUC_UNUSED) +{ + struct list_keys_thunk *thunk = (struct list_keys_thunk *)user_data; + + if (thunk->want_text) { + if (thunk->text) g_free(thunk->text); + thunk->text = g_strndup(text, text_len); + } +} + +/* Helper function for list_fetch */ +static gboolean +list_build_url_component(char **rv, + const char *delim, + const char *key, + const char *value) +{ + char *esc_value = NULL; + char *new_rv = NULL; + + esc_value = curl_escape(value, 0); + if (!esc_value) goto cleanup; + + new_rv = g_strconcat(*rv, delim, key, "=", esc_value, NULL); + if (!new_rv) goto cleanup; + + g_free(*rv); + *rv = new_rv; + curl_free(esc_value); + + return TRUE; + +cleanup: + if (new_rv) g_free(new_rv); + if (esc_value) curl_free(esc_value); + + return FALSE; +} + +/* Perform a fetch from S3; several fetches may be involved in a + * single listing operation */ +static s3_result_t +list_fetch(S3Handle *hdl, + const char *resource, + const char *prefix, + const char *delimiter, + const char *marker, + const char *max_keys) +{ + char *urldelim = "?"; + char *uri = g_strdup(resource); + s3_result_t result = S3_RESULT_FAIL; + static result_handling_t result_handling[] = { + { 200, 0, 0, S3_RESULT_OK }, + RESULT_HANDLING_ALWAYS_RETRY, + { 0, 0, 0, /* default: */ S3_RESULT_FAIL } + }; + + /* build the URI */ + if (prefix) { + if (!list_build_url_component(&uri, urldelim, "prefix", prefix)) goto cleanup; + urldelim = "&"; + } + if (delimiter) { + if (!list_build_url_component(&uri, urldelim, "delimiter", delimiter)) goto cleanup; + urldelim = "&"; + } + if (marker) { + if (!list_build_url_component(&uri, urldelim, "marker", marker)) goto cleanup; + urldelim = "&"; + } + if (max_keys) { + if (!list_build_url_component(&uri, urldelim, "max-keys", max_keys)) goto cleanup; + urldelim = "&"; + } + + /* and perform the request on that URI */ + result = perform_request(hdl, resource, uri, "GET", NULL, + 0, MAX_ERROR_RESPONSE_LEN, 0, result_handling); + +cleanup: + if (uri) g_free(uri); + return result; +} + +gboolean +s3_list_keys(S3Handle *hdl, + const char *bucket, + const char *prefix, + const char *delimiter, + GSList **list) +{ + char *resource = NULL; + struct list_keys_thunk thunk; + GMarkupParseContext *ctxt = NULL; + static GMarkupParser parser = { list_start_element, list_end_element, list_text, NULL, NULL }; + GError *err = NULL; + s3_result_t result = S3_RESULT_FAIL; + + g_assert(list); + *list = NULL; + thunk.filename_list = NULL; + thunk.text = NULL; + thunk.next_marker = NULL; + + resource = build_resource(bucket, NULL); + if (!resource) goto cleanup; + + /* Loop until S3 has given us the entire picture */ + do { + /* get some data from S3 */ + result = list_fetch(hdl, resource, prefix, delimiter, thunk.next_marker, NULL); + if (result != S3_RESULT_OK) goto cleanup; + + /* run the parser over it */ + thunk.in_contents = FALSE; + thunk.in_common_prefixes = FALSE; + thunk.is_truncated = FALSE; + thunk.want_text = FALSE; + + ctxt = g_markup_parse_context_new(&parser, 0, (gpointer)&thunk, NULL); + + if (!g_markup_parse_context_parse(ctxt, hdl->last_response_body, + hdl->last_response_body_size, &err)) { + if (hdl->last_message) g_free(hdl->last_message); + hdl->last_message = g_strdup(err->message); + result = S3_RESULT_FAIL; + goto cleanup; + } + + if (!g_markup_parse_context_end_parse(ctxt, &err)) { + if (hdl->last_message) g_free(hdl->last_message); + hdl->last_message = g_strdup(err->message); + result = S3_RESULT_FAIL; + goto cleanup; + } + + g_markup_parse_context_free(ctxt); + ctxt = NULL; + } while (thunk.next_marker); + +cleanup: + if (err) g_error_free(err); + if (thunk.text) g_free(thunk.text); + if (thunk.next_marker) g_free(thunk.next_marker); + if (resource) g_free(resource); + if (ctxt) g_markup_parse_context_free(ctxt); + + if (result != S3_RESULT_OK) { + g_slist_free(thunk.filename_list); + return FALSE; + } else { + *list = thunk.filename_list; + return TRUE; + } +} +/* }}} */ + +/* {{{ s3_read */ +gboolean +s3_read(S3Handle *hdl, + const char *bucket, + const char *key, + gpointer *buf_ptr, + guint *buf_size, + guint max_size) +{ + char *resource = NULL; + s3_result_t result = S3_RESULT_FAIL; + static result_handling_t result_handling[] = { + { 200, 0, 0, S3_RESULT_OK }, + RESULT_HANDLING_ALWAYS_RETRY, + { 0, 0, 0, /* default: */ S3_RESULT_FAIL } + }; + + g_return_val_if_fail(hdl != NULL, FALSE); + g_assert(buf_ptr != NULL); + g_assert(buf_size != NULL); + + *buf_ptr = NULL; + *buf_size = 0; + + resource = build_resource(bucket, key); + if (resource) { + result = perform_request(hdl, resource, resource, + "GET", NULL, 0, max_size, 0, result_handling); + g_free(resource); + + /* copy the pointer to the result parameters and remove + * our reference to it */ + if (result == S3_RESULT_OK) { + *buf_ptr = hdl->last_response_body; + *buf_size = hdl->last_response_body_size; + + hdl->last_response_body = NULL; + hdl->last_response_body_size = 0; + } + } + + return result == S3_RESULT_OK; +} +/* }}} */ + +/* {{{ s3_delete */ +gboolean +s3_delete(S3Handle *hdl, + const char *bucket, + const char *key) +{ + char *resource = NULL; + s3_result_t result = S3_RESULT_FAIL; + static result_handling_t result_handling[] = { + { 204, 0, 0, S3_RESULT_OK }, + RESULT_HANDLING_ALWAYS_RETRY, + { 0, 0, 0, /* default: */ S3_RESULT_FAIL } + }; + + g_return_val_if_fail(hdl != NULL, FALSE); + + resource = build_resource(bucket, key); + if (resource) { + result = perform_request(hdl, resource, resource, "DELETE", NULL, 0, + MAX_ERROR_RESPONSE_LEN, 0, result_handling); + g_free(resource); + } + + return result == S3_RESULT_OK; +} +/* }}} */ + +/* {{{ s3_make_bucket */ +gboolean +s3_make_bucket(S3Handle *hdl, + const char *bucket) +{ + char *resource = NULL; + s3_result_t result = result = S3_RESULT_FAIL; + static result_handling_t result_handling[] = { + { 200, 0, 0, S3_RESULT_OK }, + RESULT_HANDLING_ALWAYS_RETRY, + { 0, 0, 0, /* default: */ S3_RESULT_FAIL } + }; + + g_return_val_if_fail(hdl != NULL, FALSE); + + resource = build_resource(bucket, NULL); + if (resource) { + result = perform_request(hdl, resource, resource, "PUT", NULL, 0, + MAX_ERROR_RESPONSE_LEN, 0, result_handling); + g_free(resource); + } + + return result == S3_RESULT_OK; +} +/* }}} */ diff --git a/device-src/s3.h b/device-src/s3.h new file mode 100644 index 0000000..086b6f0 --- /dev/null +++ b/device-src/s3.h @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#ifndef __S3_H__ +#define __S3_H__ +#include +#include + +/* + * Data types + */ + +/* An opaque handle. S3Handles should only be accessed from a single + * thread at any given time, although it is fine to use different handles + * in different threads simultaneously. */ +typedef struct S3Handle S3Handle; + +/* + * Constants + */ + +#ifdef WANT_DEVPAY +/* These are assumed to be already URL-escaped. */ +# define STS_BASE_URL "https://sts.amazonaws.com/" +# define STS_PRODUCT_TOKEN "{ProductToken}AAAGQXBwVGtu4geoGybuwuk8VEEPzJ9ZANpu0yzbf9g4Gs5Iarzff9B7qaDBEEaWcAzWpcN7zmdMO765jOtEFc4DWTRNkpPSzUnTdkHbdYUamath73OreaZtB86jy/JF0gsHZfhxeKc/3aLr8HNT//DsX3r272zYHLDPWWUbFguOwqNjllnt6BshYREx59l8RrWABLSa37dyJeN+faGvz3uQxiDakZRn3LfInOE6d9+fTFl50LPoP08LCqI/SJfpouzWix7D/cep3Jq8yYNyM1rgAOTF7/wh7r8OuPDLJ/xZUDLfykePIAM=" +#endif + +/* This preprocessor magic will enumerate constants named S3_ERROR_XxxYyy for + * each of the errors in parentheses. + * + * see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorCodeList.html + * for Amazon's breakdown of error responses. + */ +#define S3_ERROR_LIST \ + S3_ERROR(None), \ + S3_ERROR(AccountProblem), \ + S3_ERROR(AllAccessDisabled), \ + S3_ERROR(AmbiguousGrantByEmailAddress), \ + S3_ERROR(OperationAborted), \ + S3_ERROR(BadDigest), \ + S3_ERROR(BucketAlreadyExists), \ + S3_ERROR(BucketNotEmpty), \ + S3_ERROR(CredentialsNotSupported), \ + S3_ERROR(EntityTooLarge), \ + S3_ERROR(IncompleteBody), \ + S3_ERROR(InternalError), \ + S3_ERROR(InvalidAccessKeyId), \ + S3_ERROR(InvalidArgument), \ + S3_ERROR(InvalidBucketName), \ + S3_ERROR(InvalidDigest), \ + S3_ERROR(InvalidRange), \ + S3_ERROR(InvalidSecurity), \ + S3_ERROR(InvalidSOAPRequest), \ + S3_ERROR(InvalidStorageClass), \ + S3_ERROR(InvalidTargetBucketForLogging), \ + S3_ERROR(KeyTooLong), \ + S3_ERROR(InvalidURI), \ + S3_ERROR(MalformedACLError), \ + S3_ERROR(MaxMessageLengthExceeded), \ + S3_ERROR(MetadataTooLarge), \ + S3_ERROR(MethodNotAllowed), \ + S3_ERROR(MissingAttachment), \ + S3_ERROR(MissingContentLength), \ + S3_ERROR(MissingSecurityElement), \ + S3_ERROR(MissingSecurityHeader), \ + S3_ERROR(NoLoggingStatusForKey), \ + S3_ERROR(NoSuchBucket), \ + S3_ERROR(NoSuchKey), \ + S3_ERROR(NotImplemented), \ + S3_ERROR(NotSignedUp), \ + S3_ERROR(PreconditionFailed), \ + S3_ERROR(RequestTimeout), \ + S3_ERROR(RequestTimeTooSkewed), \ + S3_ERROR(RequestTorrentOfBucketError), \ + S3_ERROR(SignatureDoesNotMatch), \ + S3_ERROR(TooManyBuckets), \ + S3_ERROR(UnexpectedContent), \ + S3_ERROR(UnresolvableGrantByEmailAddress), \ + S3_ERROR(Unknown), \ + S3_ERROR(END) + +typedef enum { +#define S3_ERROR(NAME) S3_ERROR_ ## NAME + S3_ERROR_LIST +#undef S3_ERROR +} s3_error_code_t; + +/* + * Functions + */ + +/* Initialize S3 operation + * + * As a requirement of C{curl_global_init}, which this function calls, + * s3_init I{must} be called before any other threads are started. + * + * If an error occurs in this function, diagnostic information is + * printed to stderr. + * + * @returns: false if an error occurred + */ +gboolean +s3_init(void); + +/* Set up an S3Handle. + */ +S3Handle * +s3_open(const char * access_key, const char *secret_key +#ifdef WANT_DEVPAY + , const char * user_token +#endif + ); + +/* Deallocate an S3Handle + * + * @param hdl: the S3Handle object + */ +void +s3_free(S3Handle *hdl); + +/* Reset the information about the last request, including + * freeing any allocated memory. The S3Handle itself is not + * freed and may be used again. This function is called + * automatically as needed, and should be called to free memory + * when the handle will not be used for some time. + * + * @param hdl: the S3Handle object + */ +void +s3_reset(S3Handle *hdl); + +/* Get the error information for the last operation + * + * All results are returned via result parameters. If any parameter is + * NULL, that result will not be returned. Caller is not responsible for + * freeing any returned strings, although the results are only valid until + * the next call to an S3 function with this handle. + * + * @param hdl: the S3Handle object + * @param message: (result) the error message, or NULL if none exists + * @param response_code: (result) the HTTP response code (or 0 if none exists) + * @param s3_error_code: (result) the S3 error code (see constants, above) + * @param s3_error_name: (result) the S3 error name (e.g., "RequestTimeout"), + * or NULL if none exists + * @param curl_code: (result) the curl error code (or 0 if none exists) + * @param num_retries: (result) number of retries + */ +void +s3_error(S3Handle *hdl, + const char **message, + guint *response_code, + s3_error_code_t *s3_error_code, + const char **s3_error_name, + CURLcode *curl_code, + guint *num_retries); + +/* Control verbose output of HTTP transactions, etc. + * + * @param hdl: the S3Handle object + * @param verbose: if true, send HTTP transactions, etc. to debug output + */ +void +s3_verbose(S3Handle *hdl, + gboolean verbose); + +/* Get the error information from the last operation on this handle, + * formatted as a string. + * + * Caller is responsible for freeing the resulting string. + * + * @param hdl: the S3Handle object + * @returns: string, or NULL if no error occurred + */ +char * +s3_strerror(S3Handle *hdl); + +/* Perform an upload. + * + * When this function returns, KEY and BUFFER remain the + * responsibility of the caller. + * + * @param hdl: the S3Handle object + * @param bucket: the bucket to which the upload should be made + * @param key: the key to which the upload should be made + * @param buffer: the data to be uploaded + * @param buffer_len: the length of the data to upload + * @returns: false if an error ocurred + */ +gboolean +s3_upload(S3Handle *hdl, + const char *bucket, + const char *key, + gpointer buffer, + guint buffer_len); + +/* List all of the files matching the pseudo-glob C{PREFIX*DELIMITER*}, + * returning only that portion which matches C{PREFIX*DELIMITER}. S3 supports + * this particular semantics, making it quite efficient. The returned list + * should be freed by the caller. + * + * @param hdl: the S3Handle object + * @param bucket: the bucket to list + * @param prefix: the prefix + * @param delimiter: delimiter (any length string) + * @param list: (output) the list of files + * @returns: FALSE if an error occurs + */ +gboolean +s3_list_keys(S3Handle *hdl, + const char *bucket, + const char *prefix, + const char *delimiter, + GSList **list); + +/* Read an entire file. The buffer returned is the responsibility of the caller. A + * buffer is only returned if no error occurred, and will be NULL otherwise. + * + * @param hdl: the S3Handle object + * @param bucket: the bucket to read from + * @param key: the key to read from + * @param buf_ptr: (result) a pointer to a C{gpointer} which will contain a pointer to + * the block read + * @param buf_size: (result) a pointer to a C{guint} which will contain the size of the + * block read + * @param max_size: maximum size of the file + * @returns: FALSE if an error occurs + */ +gboolean +s3_read(S3Handle *hdl, + const char *bucket, + const char *key, + gpointer *buf_ptr, + guint *buf_size, + guint max_size); + +/* Delete a file. + * + * @param hdl: the S3Handle object + * @param bucket: the bucket to delete from + * @param key: the key to delete + * @returns: FALSE if an error occurs; a non-existent file is I{not} considered an error. + */ +gboolean +s3_delete(S3Handle *hdl, + const char *bucket, + const char *key); + +/* Create a bucket. + * + * @param hdl: the S3Handle object + * @param bucket: the bucket to create + * @returns: FALSE if an error occurs + */ +gboolean +s3_make_bucket(S3Handle *hdl, + const char *bucket); + +/* Attempt a RefreshAWSSecurityToken on a token; if it succeeds, the old + * token will be freed and replaced by the new. If it fails, the old + * token is left unchanged and FALSE is returned. */ +gboolean sts_refresh_token(char ** token, const char * directory); + +/* These functions are for if you want to use curl on your own. You get more + * control, but it's a lot of work that way: */ +typedef struct { + char *buffer; + guint buffer_len; + guint buffer_pos; + guint max_buffer_size; +} CurlBuffer; + +/* a CURLOPT_READFUNCTION to read data from a buffer. */ +size_t buffer_readfunction(void *ptr, size_t size, + size_t nmemb, void * stream); + +/* a CURLOPT_WRITEFUNCTION to write data to a buffer. */ +size_t +buffer_writefunction(void *ptr, size_t size, size_t nmemb, void *stream); + +/* Adds a null termination to a buffer. */ +void terminate_buffer(CurlBuffer *); + +#endif diff --git a/device-src/semaphore.c b/device-src/semaphore.c new file mode 100644 index 0000000..20a2a95 --- /dev/null +++ b/device-src/semaphore.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* GLib does not provide semaphores, which are useful in queue.c. + So, we implement it here. */ + +#include "semaphore.h" +#include "amanda.h" + +semaphore_t* semaphore_new_with_value(int value) { + semaphore_t *rval; + + if (!g_thread_supported()) + return NULL; + + rval = malloc(sizeof(*rval)); + rval->value = value; + rval->mutex = g_mutex_new(); + rval->decrement_cond = g_cond_new(); + rval->zero_cond = g_cond_new(); + + if (rval->mutex == NULL || rval->decrement_cond == NULL || + rval->zero_cond == NULL) { + semaphore_free(rval); + return NULL; + } else { + return rval; + } +} + +void semaphore_free(semaphore_t* o) { + g_mutex_free(o->mutex); + g_cond_free(o->decrement_cond); + g_cond_free(o->zero_cond); + free(o); +} + +/* This function checks if the semaphore would is zero or negative. + * If so, the zero_cond is signalled. We assume that the mutex is + * locked. */ +static void check_empty(semaphore_t * o) { + if (o->value <= 0) { + g_cond_broadcast(o->zero_cond); + } +} + +void semaphore_increment(semaphore_t* o, unsigned int inc) { + g_return_if_fail(o != NULL); + g_return_if_fail(inc != 0); + + semaphore_force_adjust(o, inc); +} + +void semaphore_decrement(semaphore_t* o, unsigned int dec) { + int sdec; + g_return_if_fail(o != NULL); + sdec = (int) dec; + g_return_if_fail(sdec >= 0); + + g_mutex_lock(o->mutex); + while (o->value < sdec) { + g_cond_wait(o->decrement_cond, o->mutex); + } + o->value -= sdec; + check_empty(o); + g_mutex_unlock(o->mutex); +} + +void semaphore_force_adjust(semaphore_t* o, int inc) { + g_return_if_fail(o != NULL); + + g_mutex_lock(o->mutex); + o->value += inc; + if (inc < 0) + check_empty(o); + else + g_cond_broadcast(o->decrement_cond); + g_mutex_unlock(o->mutex); + +} + +void semaphore_force_set(semaphore_t* o, int value) { + int oldvalue; + g_return_if_fail(o != NULL); + + g_mutex_lock(o->mutex); + oldvalue = o->value; + o->value = value; + if (value < oldvalue) + check_empty(o); + else + g_cond_broadcast(o->decrement_cond); + g_mutex_unlock(o->mutex); + +} + +void semaphore_wait_empty(semaphore_t * o) { + g_return_if_fail(o != NULL); + + g_mutex_lock(o->mutex); + while (o->value > 0) { + g_cond_wait(o->zero_cond, o->mutex); + } + g_mutex_unlock(o->mutex); +} diff --git a/device-src/semaphore.h b/device-src/semaphore.h new file mode 100644 index 0000000..17d41fe --- /dev/null +++ b/device-src/semaphore.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* GLib does not provide semaphores, which are useful in queue.c. + So, we implement it here. */ + +#include + +#ifndef SEMAPHORE_H + +typedef struct { + int value; + GMutex *mutex; + GCond * decrement_cond; + GCond * zero_cond; +} semaphore_t; + +/* Create a new semaphore object with the given value. + * + * @param value: new value + * @returns: newly allocated semaphore_t + */ +semaphore_t* semaphore_new_with_value(int value); + +/* Shortcut to make a new semaphore with value 1. + */ +#define semaphore_new() semaphore_new_with_value(1) + +/* Free a semaphore allocated by semaphore_with_new_value(). Be sure the + * semaphore is no longer in use by any threads. + * + * @param sem: the semaphore to free + */ +void semaphore_free(semaphore_t *sem); + +/* Increment the value of the semaphore by incr. This corresponds to + * Dijkstra's V(), or the typical semaphore's release(). + * + * This function will not block, but may wake other threads waiting + * on semaphore_decrement(). + * + * @param sem: the semaphore + * @param incr: added to the semaphore's value + */ +void semaphore_increment(semaphore_t *sem, unsigned int incr); + +/* Shortcut to increment the semaphore by 1. + */ +#define semaphore_up(semaphore) semphore_increment(semaphore,1) + +/* Decrement the value of the semaphore by incr. If this operation + * would make the semaphore zero or less, block until the semaphore + * value is large enough, then perform the decerement operation. Threads + * waiting on semaphore_wait_empty() may be awakened if the value + * reaches 0. + * + * @param sem: the semaphore + * @param decr: subtracted from the semaphore's value + */ +void semaphore_decrement(semaphore_t *sem, unsigned int decr); + +/* Shortcut to decrement the semaphore by 1. + */ +#define semaphore_down(semaphore) semaphore_decrement(semaphore, 1) + +/* Increment or decrement (with a negative incr) the value without + * blocking. Threads waiting on semaphore_decrement() or + * semaphore_wait_empty() will be awakened if necessary. + * + * @param sem: the semaphore + * @param incr: added to the semaphore's value + */ +void semaphore_force_adjust(semaphore_t *sem, int incr); + +/* Set the semaphore to a given value without blocking. Threads + * waiting on semaphore_decrement() or semaphore_wait_empty() + * will be awakened if necessary. + * + * @param sem: the semaphore + * @param value: the new value + */ +void semaphore_force_set(semaphore_t *sem, int value); + +/* Block until the semaphore's value is zero. + * + * @param sem: the semaphore + */ +void semaphore_wait_empty(semaphore_t *sem); + +#endif /* SEMAPHORE_H */ diff --git a/device-src/tape-aix.c b/device-src/tape-aix.c new file mode 100644 index 0000000..a9665a7 --- /dev/null +++ b/device-src/tape-aix.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include +#include "tape-ops.h" + +/* Tape operations for AIX systems. Most of this stuff is based on + documentation from + http://publibn.boulder.ibm.com/doc_link/Ja_JP/a_doc_lib/files/aixfiles/rmt.htm */ + +/* Uncomment to test compilation on non-AIX systems. */ +/* --- +#undef MTIOCTOP +#define STIOCTOP 0 +#define stop mtop +#define st_op mt_op +#define st_count mt_count +#define STREW MTREW +#define STFSF MTFSF +#define STRSF MTBSF +#define STFSR MTFSR +#define STRSR MTBSR +#define STWEOF MTWEOF +--- */ + +gboolean tape_rewind(int fd) { + struct stop st; + st.st_op = STREW; + st.st_count = 1; + return 0 == ioctl(fd, STIOCTOP, &st); +} + +gboolean tape_fsf(int fd, guint count) { + struct stop st; + st.st_op = STFSF; + st.st_count = count; + return 0 == ioctl(fd, STIOCTOP, &st); +} + +gboolean tape_bsf(int fd, guint count) { + struct stop st; + st.st_op = STRSF; + st.st_count = count; + return 0 == ioctl(fd, STIOCTOP, &st); +} + +gboolean tape_fsr(int fd, guint count) { + struct stop st; + st.st_op = STFSR; + st.st_count = count; + return 0 == ioctl(fd, STIOCTOP, &st); +} + +gboolean tape_bsr(int fd, guint count) { + struct stop st; + st.st_op = STRSR; + st.st_count = count; + return 0 == ioctl(fd, STIOCTOP, &st); +} + +gint tape_eod(int fd) { + g_assert_not_reached(); + return TAPE_OP_ERROR; +} + +gboolean tape_weof(int fd, guint8 count) { + struct stop st; + st.st_op = STWEOF; + st.st_count = count; + return 0 == ioctl(fd, STIOCTOP, &st); +} + +gboolean tape_setcompression(int fd, gboolean on) { + return FALSE; +} + +ReadLabelStatusFlags tape_is_tape_device(int fd) { + /* AIX doesn't have a no-op. */ + return READ_LABEL_STATUS_SUCCESS; +} + +TapeCheckResult tape_is_ready(int fd) { + return TAPE_CHECK_UNKNOWN; +} + +void tape_device_discover_capabilities(TapeDevice * t_self) { + Device * self; + GValue val; + + self = DEVICE(t_self); + g_return_if_fail(self != NULL); + + bzero(&val, sizeof(val)); + g_value_init(&val, FEATURE_SUPPORT_FLAGS_TYPE); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_DISABLED | FEATURE_SURETY_GOOD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_EOM, &val); + + g_value_unset_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 2); + device_property_set(self, PROPERTY_FINAL_FILEMARKS, &val); +} diff --git a/device-src/tape-device.c b/device-src/tape-device.c new file mode 100644 index 0000000..1274fcd --- /dev/null +++ b/device-src/tape-device.c @@ -0,0 +1,1347 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include /* memset() */ +#include "util.h" +#include "tape-device.h" +#include "tape-ops.h" + +/* This is equal to 2*1024*1024*1024 - 16*1024*1024 - 1, but written + explicitly to avoid overflow issues. */ +#define RESETOFS_THRESHOLD (0x7effffff) + +/* Largest possible block size on SCSI systems. */ +#define LARGEST_BLOCK_ESTIMATE (16 * 1024 * 1024) + +struct TapeDevicePrivate_s { + /* This holds the total number of bytes written to the device, + modulus RESETOFS_THRESHOLD. */ + int write_count; +}; + +/* Possible (abstracted) results from a system I/O operation. */ +typedef enum { + RESULT_SUCCESS, + RESULT_ERROR, /* Undefined error. */ + RESULT_SMALL_BUFFER, /* Tried to read with a buffer that is too + small. */ + RESULT_NO_DATA, /* End of File, while reading */ + RESULT_NO_SPACE, /* Out of space. Sometimes we don't know if + it was this or I/O error, but this is the + preferred explanation. */ + RESULT_MAX +} IoResult; + +/* here are local prototypes */ +static void tape_device_init (TapeDevice * o); +static void tape_device_class_init (TapeDeviceClass * c); +static gboolean tape_device_open_device (Device * self, char * device_name); +static ReadLabelStatusFlags tape_device_read_label(Device * self); +static gboolean tape_device_write_block(Device * self, guint size, + gpointer data, gboolean short_block); +static int tape_device_read_block(Device * self, gpointer buf, + int * size_req); +static gboolean tape_device_start (Device * self, DeviceAccessMode mode, + char * label, char * timestamp); +static gboolean tape_device_start_file (Device * self, const dumpfile_t * ji); +static dumpfile_t * tape_device_seek_file (Device * self, guint file); +static gboolean tape_device_seek_block (Device * self, guint64 block); +static gboolean tape_device_property_get (Device * self, DevicePropertyId id, + GValue * val); +static gboolean tape_device_property_set (Device * self, DevicePropertyId id, + GValue * val); +static gboolean tape_device_finish (Device * self); +static IoResult tape_device_robust_read (TapeDevice * self, void * buf, + int * count); +static IoResult tape_device_robust_write (TapeDevice * self, void * buf, int count); +static gboolean tape_device_fsf (TapeDevice * self, guint count); +static gboolean tape_device_bsf (TapeDevice * self, guint count, guint file); +static gboolean tape_device_fsr (TapeDevice * self, guint count); +static gboolean tape_device_bsr (TapeDevice * self, guint count, guint file, guint block); +static gboolean tape_device_eod (TapeDevice * self); + +/* pointer to the class of our parent */ +static DeviceClass *parent_class = NULL; + +GType tape_device_get_type (void) +{ + static GType type = 0; + + if G_UNLIKELY(type == 0) { + static const GTypeInfo info = { + sizeof (TapeDeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) tape_device_class_init, + (GClassFinalizeFunc) NULL, + NULL /* class_data */, + sizeof (TapeDevice), + 0 /* n_preallocs */, + (GInstanceInitFunc) tape_device_init, + NULL + }; + + type = g_type_register_static (TYPE_DEVICE, "TapeDevice", + &info, (GTypeFlags)0); + } + + return type; +} + +static void +tape_device_init (TapeDevice * self) { + Device * device_self; + DeviceProperty prop; + GValue response; + + device_self = (Device*)self; + bzero(&response, sizeof(response)); + + self->private = malloc(sizeof(TapeDevicePrivate)); + + /* Clear all fields. */ + self->min_block_size = self->fixed_block_size = 32768; + self->max_block_size = self->read_block_size = MAX_TAPE_BLOCK_BYTES; + + self->fd = -1; + + self->fsf = self->bsf = self->fsr = self->bsr = self->eom = + self->bsf_after_eom = self->compression = self->first_file = 0; + self->final_filemarks = 2; + + self->private->write_count = 0; + + /* Register properites */ + prop.base = &device_property_concurrency; + prop.access = PROPERTY_ACCESS_GET_MASK; + g_value_init(&response, CONCURRENCY_PARADIGM_TYPE); + g_value_set_enum(&response, CONCURRENCY_PARADIGM_EXCLUSIVE); + device_add_property(device_self, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_streaming; + g_value_init(&response, STREAMING_REQUIREMENT_TYPE); + g_value_set_enum(&response, STREAMING_REQUIREMENT_DESIRED); + device_add_property(device_self, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_appendable; + g_value_init(&response, G_TYPE_BOOLEAN); + g_value_set_boolean(&response, TRUE); + device_add_property(device_self, &prop, &response); + + prop.base = &device_property_partial_deletion; + g_value_set_boolean(&response, FALSE); + device_add_property(device_self, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_medium_access_type; + g_value_init(&response, MEDIA_ACCESS_MODE_TYPE); + g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE); + device_add_property(device_self, &prop, &response); + g_value_unset(&response); + + prop.access = PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_MASK; + prop.base = &device_property_compression; + device_add_property(device_self, &prop, NULL); + + prop.access = PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START; + prop.base = &device_property_min_block_size; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_max_block_size; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_block_size; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_fsf; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_bsf; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_fsr; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_bsr; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_eom; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_bsf_after_eom; + device_add_property(device_self, &prop, NULL); + prop.base = &device_property_final_filemarks; + device_add_property(device_self, &prop, NULL); + + prop.access = PROPERTY_ACCESS_GET_MASK; + prop.base = &device_property_canonical_name; + device_add_property(device_self, &prop, NULL); +} + +static void tape_device_finalize(GObject * obj_self) { + TapeDevice * self = TAPE_DEVICE(obj_self); + + if(G_OBJECT_CLASS(parent_class)->finalize) \ + (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self); + + robust_close(self->fd); + self->fd = -1; + amfree(self->private); +} + +static void +tape_device_class_init (TapeDeviceClass * c) +{ + DeviceClass *device_class = (DeviceClass *)c; + GObjectClass *g_object_class = (GObjectClass *)c; + + parent_class = g_type_class_ref (TYPE_DEVICE); + + device_class->open_device = tape_device_open_device; + device_class->read_label = tape_device_read_label; + device_class->write_block = tape_device_write_block; + device_class->read_block = tape_device_read_block; + device_class->start = tape_device_start; + device_class->start_file = tape_device_start_file; + device_class->seek_file = tape_device_seek_file; + device_class->seek_block = tape_device_seek_block; + device_class->property_get = tape_device_property_get; + device_class->property_set = tape_device_property_set; + device_class->finish = tape_device_finish; + + g_object_class->finalize = tape_device_finalize; +} + +void tape_device_register(void) { + static const char * device_prefix_list[] = { "tape", NULL }; + register_device(tape_device_factory, device_prefix_list); +} + +/* Open the tape device, trying various combinations of O_RDWR and + O_NONBLOCK. Returns -1 and sets status_result for errors */ +static int try_open_tape_device(TapeDevice * self, char * device_filename, + ReadLabelStatusFlags *status_result) { + int fd; + int save_errno; + ReadLabelStatusFlags new_status; + TapeCheckResult tcr; + *status_result = READ_LABEL_STATUS_SUCCESS; + +#ifdef O_NONBLOCK + fd = robust_open(device_filename, O_RDWR | O_NONBLOCK, 0); + save_errno = errno; + if (fd < 0 && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) { + /* Maybe we don't support O_NONBLOCK for tape devices. */ + fd = robust_open(device_filename, O_RDWR, 0); + save_errno = errno; + } +#else + fd = robust_open(device_filename, O_RDWR); + save_errno = errno; +#endif + if (fd >= 0) { + self->write_open_errno = 0; + } else { + if (errno == EACCES || errno == EPERM) { + /* Device is write-protected. */ + self->write_open_errno = errno; +#ifdef O_NONBLOCK + fd = robust_open(device_filename, O_RDONLY | O_NONBLOCK, 0); + save_errno = errno; + if (fd < 0 && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) { + fd = robust_open(device_filename, O_RDONLY, 0); + save_errno = errno; + } +#else + fd = robust_open(device_filename, O_RDONLY); + save_errno = errno; +#endif + } + } +#ifdef O_NONBLOCK + /* Clear O_NONBLOCK for operations from now on. */ + if (fd >= 0) + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); + errno = save_errno; + /* function continues after #endif */ + +#endif /* O_NONBLOCK */ + + if (fd < 0) { + g_fprintf(stderr, _("Can't open tape device %s: %s\n"), + DEVICE(self)->device_name, strerror(errno)); + *status_result = READ_LABEL_STATUS_DEVICE_ERROR; + return -1; + } + + /* Check that this is actually a tape device. */ + new_status = tape_is_tape_device(fd); + if (new_status & (READ_LABEL_STATUS_DEVICE_ERROR | READ_LABEL_STATUS_VOLUME_MISSING)) { + g_fprintf(stderr, _("File %s is not a tape device\n"), + DEVICE(self)->device_name); + robust_close(fd); + *status_result = new_status; + return -1; + } + + tcr = tape_is_ready(fd); + if (new_status == TAPE_CHECK_FAILURE) { + g_fprintf(stderr, _("Tape device %s is not ready or is empty\n"), + DEVICE(self)->device_name); + robust_close(fd); + *status_result = READ_LABEL_STATUS_DEVICE_ERROR; + return -1; + } + + return fd; +} + +static gboolean +tape_device_open_device (Device * d_self, char * device_name) { + TapeDevice * self; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (device_name != NULL, FALSE); + + /* Get tape drive/OS info */ + tape_device_discover_capabilities(self); + + /* And verify the above. */ + g_assert(feature_support_flags_is_valid(self->fsf)); + g_assert(feature_support_flags_is_valid(self->bsf)); + g_assert(feature_support_flags_is_valid(self->fsr)); + g_assert(feature_support_flags_is_valid(self->bsr)); + g_assert(feature_support_flags_is_valid(self->eom)); + g_assert(feature_support_flags_is_valid(self->bsf_after_eom)); + g_assert(self->final_filemarks == 1 || + self->final_filemarks == 2); + + /* Chain up */ + if (parent_class->open_device) { + if (!(parent_class->open_device)(d_self, device_name)) { + robust_close(self->fd); + return FALSE; + } + } + + return TRUE; +} + +static ReadLabelStatusFlags tape_device_read_label(Device * dself) { + TapeDevice * self; + char * header_buffer; + int buffer_len; + IoResult result; + dumpfile_t header; + + self = TAPE_DEVICE(dself); + g_return_val_if_fail(self != NULL, FALSE); + + amfree(dself->volume_label); + amfree(dself->volume_time); + + if (self->fd == -1) { + ReadLabelStatusFlags status; + self->fd = try_open_tape_device(self, dself->device_name, &status); + if (self->fd == -1) + return status; + } + + /* Rewind it. */ + if (!tape_rewind(self->fd)) { + g_fprintf(stderr, "Error rewinding device %s\n", + dself->device_name); + return (READ_LABEL_STATUS_DEVICE_ERROR | + READ_LABEL_STATUS_VOLUME_ERROR); + } + + buffer_len = self->read_block_size; + header_buffer = malloc(buffer_len); + result = tape_device_robust_read(self, header_buffer, &buffer_len); + + if (result != RESULT_SUCCESS) { + free(header_buffer); + tape_rewind(self->fd); + /* I/O error. */ + g_fprintf(stderr, "Error reading Amanda header.\n"); + if (result == RESULT_NO_DATA) { + return (READ_LABEL_STATUS_VOLUME_ERROR | + READ_LABEL_STATUS_VOLUME_UNLABELED); + } else { + return (READ_LABEL_STATUS_DEVICE_ERROR | + READ_LABEL_STATUS_VOLUME_ERROR | + READ_LABEL_STATUS_VOLUME_UNLABELED); + } + } + + parse_file_header(header_buffer, &header, buffer_len); + amfree(header_buffer); + if (header.type != F_TAPESTART) { + return READ_LABEL_STATUS_VOLUME_UNLABELED; + } + + dself->volume_label = g_strdup(header.name); + dself->volume_time = g_strdup(header.datestamp); + + if (parent_class->read_label) { + return parent_class->read_label(dself); + } else { + return READ_LABEL_STATUS_SUCCESS; + } +} + +static gboolean +tape_device_write_block(Device * pself, guint size, + gpointer data, gboolean short_block) { + TapeDevice * self; + char *replacement_buffer = NULL; + IoResult result; + + self = TAPE_DEVICE(pself); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->fd >= 0, FALSE); + + if (short_block && self->min_block_size > size) { + replacement_buffer = malloc(self->min_block_size); + memcpy(replacement_buffer, data, size); + bzero(replacement_buffer+size, self->min_block_size-size); + + data = replacement_buffer; + size = self->min_block_size; + } + + result = tape_device_robust_write(self, data, size); + if (result == RESULT_SUCCESS) { + if (parent_class->write_block) { + (parent_class->write_block)(pself, size, data, short_block); + } + amfree(replacement_buffer); + return TRUE; + } else { + amfree(replacement_buffer); + return FALSE; + } + + g_assert_not_reached(); +} + +static int tape_device_read_block (Device * pself, gpointer buf, + int * size_req) { + TapeDevice * self; + int size; + IoResult result; + + self = TAPE_DEVICE(pself); + g_return_val_if_fail (self != NULL, -1); + + if (buf == NULL || *size_req < (int)self->read_block_size) { + /* Just a size query. */ + *size_req = self->read_block_size; + return 0; + } + + size = *size_req; + result = tape_device_robust_read(self, buf, &size); + switch (result) { + case RESULT_SUCCESS: + *size_req = size; + return size; + case RESULT_SMALL_BUFFER: { + int new_size; + /* If this happens, it means that we have: + * (next block size) > (buffer size) >= (read_block_size) + * The solution is to ask for an even bigger buffer. We also play + * some games to refrain from reading above the SCSI limit or from + * integer overflow. */ + new_size = MIN(INT_MAX/2 - 1, *size_req) * 2; + if (new_size > LARGEST_BLOCK_ESTIMATE && + *size_req < LARGEST_BLOCK_ESTIMATE) { + new_size = LARGEST_BLOCK_ESTIMATE; + } + if (new_size <= *size_req) { + return -1; + } else { + *size_req = new_size; + return 0; + } + } + case RESULT_NO_DATA: + pself->is_eof = TRUE; + pself->in_file = FALSE; + return -1; + + default: + return -1; + } + + g_assert_not_reached(); +} + +/* Just a helper function for tape_device_start(). */ +static gboolean write_tapestart_header(TapeDevice * self, char * label, + char * timestamp) { + IoResult result; + dumpfile_t * header; + char * header_buf; + int header_size; + gboolean header_fits; + Device * d_self = (Device*)self; + tape_rewind(self->fd); + + header = make_tapestart_header(d_self, label, timestamp); + g_assert(header != NULL); + header_buf = device_build_amanda_header(d_self, header, &header_size, + &header_fits); + amfree(header); + g_assert(header_buf != NULL); + + if (!header_fits) { + amfree(header_buf); + g_fprintf(stderr, "Tapestart header won't fit in a single block!\n"); + return FALSE; + } + + g_assert(header_size >= (int)self->min_block_size); + result = tape_device_robust_write(self, header_buf, header_size); + amfree(header_buf); + return (result == RESULT_SUCCESS); +} + +static gboolean +tape_device_start (Device * d_self, DeviceAccessMode mode, char * label, + char * timestamp) { + TapeDevice * self; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail(self != NULL, FALSE); + + if (self->fd == -1) { + ReadLabelStatusFlags status; + self->fd = try_open_tape_device(self, d_self->device_name, &status); + if (self->fd == -1) + return FALSE; /* can't do anything with status here */ + } + + if (mode != ACCESS_WRITE && d_self->volume_label == NULL) { + /* we need a labeled volume for APPEND and READ */ + if (tape_device_read_label(d_self) != READ_LABEL_STATUS_SUCCESS) + return FALSE; + } + + d_self->access_mode = mode; + d_self->in_file = FALSE; + + if (IS_WRITABLE_ACCESS_MODE(mode)) { + if (self->write_open_errno != 0) { + /* We tried and failed to open the device in write mode. */ + g_fprintf(stderr, "Can't open tape device %s for writing: %s\n", + d_self->device_name, strerror(self->write_open_errno)); + return FALSE; + } else if (!tape_rewind(self->fd)) { + g_fprintf(stderr, "Couldn't rewind device: %s\n", + strerror(errno)); + } + } + + /* Position the tape */ + switch (mode) { + case ACCESS_APPEND: + if (!tape_device_eod(self)) + return FALSE; + self->first_file = TRUE; + break; + + case ACCESS_READ: + if (!tape_rewind(self->fd)) { + g_fprintf(stderr, "Error rewinding device %s\n", + d_self->device_name); + return FALSE; + } + d_self->file = 0; + break; + + case ACCESS_WRITE: + if (!write_tapestart_header(self, label, timestamp)) { + return FALSE; + } + self->first_file = TRUE; + break; + + default: + g_assert_not_reached(); + } + + if (parent_class->start) { + return parent_class->start(d_self, mode, label, timestamp); + } else { + return TRUE; + } +} + +static gboolean tape_device_start_file(Device * d_self, + const dumpfile_t * info) { + TapeDevice * self; + IoResult result; + char * amanda_header; + int header_size; + gboolean header_fits; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail (self->fd >= 0, FALSE); + + if (!(d_self->access_mode == ACCESS_APPEND && self->first_file)) { + if (!tape_weof(self->fd, 1)) { + g_fprintf(stderr, "Error writing filemark: %s\n", strerror(errno)); + return FALSE; + } + } + + self->first_file = FALSE; + + /* Make the Amanda header suitable for writing to the device. */ + /* Then write the damn thing. */ + amanda_header = device_build_amanda_header(d_self, info, + &header_size, &header_fits); + g_return_val_if_fail(amanda_header != NULL, FALSE); + g_return_val_if_fail(header_fits, FALSE); + result = tape_device_robust_write(self, amanda_header, header_size); + amfree(amanda_header); + if (result == RESULT_SUCCESS) { + /* Chain up. */ + if (parent_class->start_file) { + parent_class->start_file(d_self, info); + } + return TRUE; + } else { + return FALSE; + } +} + +static dumpfile_t * +tape_device_seek_file (Device * d_self, guint file) { + TapeDevice * self; + int difference; + char * header_buffer; + dumpfile_t * rval; + int buffer_len; + IoResult result; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail(d_self != NULL, NULL); + + d_self->in_file = FALSE; + + difference = file - d_self->file; + + /* Check if we already read a filemark. */ + if (d_self->is_eof) { + difference --; + } + + if (difference > 0) { + /* Seeking forwards */ + if (!tape_device_fsf(self, difference)) { + tape_rewind(self->fd); + return NULL; + } + } else if (difference < 0) { + /* Seeking backwards */ + if (!tape_device_bsf(self, -difference, d_self->file)) { + tape_rewind(self->fd); + return NULL; + } + } + + buffer_len = self->read_block_size; + header_buffer = malloc(buffer_len); + d_self->is_eof = FALSE; + result = tape_device_robust_read(self, header_buffer, &buffer_len); + + if (result != RESULT_SUCCESS) { + free(header_buffer); + tape_rewind(self->fd); + if (result == RESULT_NO_DATA) { + /* If we read 0 bytes, that means we encountered a double + * filemark, which indicates end of tape. This should + * work even with QIC tapes on operating systems with + * proper support. */ + return make_tapeend_header(); + } + /* I/O error. */ + g_fprintf(stderr, "Error reading Amanda header.\n"); + return FALSE; + } + + rval = malloc(sizeof(*rval)); + parse_file_header(header_buffer, rval, buffer_len); + amfree(header_buffer); + switch (rval->type) { + case F_DUMPFILE: + case F_CONT_DUMPFILE: + case F_SPLIT_DUMPFILE: + d_self->in_file = TRUE; + d_self->file = file; + return rval; + default: + tape_rewind(self->fd); + amfree(rval); + return NULL; + } +} + +static gboolean +tape_device_seek_block (Device * d_self, guint64 block) { + TapeDevice * self; + int difference; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail(d_self != NULL, FALSE); + + difference = block - d_self->block; + + if (difference > 0) { + if (!tape_device_fsr(self, difference)) + return FALSE; + } else if (difference < 0) { + if (!tape_device_bsr(self, difference, d_self->file, d_self->block)) + return FALSE; + } + + if (parent_class->seek_block) { + return (parent_class->seek_block)(d_self, block); + } else { + return TRUE; + } +} + +/* Just checks that the flag is valid before setting it. */ +static gboolean get_feature_flag(GValue * val, FeatureSupportFlags f) { + if (feature_support_flags_is_valid(f)) { + g_value_set_flags(val, f); + return TRUE; + } else { + return FALSE; + } +} + +static gboolean +tape_device_property_get (Device * d_self, DevicePropertyId id, GValue * val) { + TapeDevice * self; + const DevicePropertyBase * base; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail(self != NULL, FALSE); + + base = device_property_get_by_id(id); + g_return_val_if_fail(self != NULL, FALSE); + + g_value_unset_init(val, base->type); + + if (id == PROPERTY_COMPRESSION) { + g_value_set_boolean(val, self->compression); + return TRUE; + } else if (id == PROPERTY_MIN_BLOCK_SIZE) { + g_value_set_uint(val, self->min_block_size); + return TRUE; + } else if (id == PROPERTY_MAX_BLOCK_SIZE) { + g_value_set_uint(val, self->max_block_size); + return TRUE; + } else if (id == PROPERTY_BLOCK_SIZE) { + if (self->fixed_block_size == 0) { + g_value_set_int(val, -1); + } else { + g_value_set_int(val, self->fixed_block_size); + } + return TRUE; + } else if (id == PROPERTY_FSF) { + return get_feature_flag(val, self->fsf); + } else if (id == PROPERTY_BSF) { + return get_feature_flag(val, self->bsf); + } else if (id == PROPERTY_FSR) { + return get_feature_flag(val, self->fsr); + } else if (id == PROPERTY_BSR) { + return get_feature_flag(val, self->bsr); + } else if (id == PROPERTY_EOM) { + return get_feature_flag(val, self->eom); + } else if (id == PROPERTY_BSF_AFTER_EOM) { + return get_feature_flag(val, self->bsf_after_eom); + } else if (id == PROPERTY_FINAL_FILEMARKS) { + g_value_set_uint(val, self->final_filemarks); + return TRUE; + } else { + /* Chain up */ + if (parent_class->property_get) { + return (parent_class->property_get)(d_self, id, val); + } else { + return FALSE; + } + } + + g_assert_not_reached(); +} + +/* We don't allow overriding of flags with _GOOD surety. That way, if + e.g., a feature has no matching IOCTL on a given platform, we don't + ever try to set it. */ +static gboolean flags_settable(FeatureSupportFlags request, + FeatureSupportFlags existing) { + if (!feature_support_flags_is_valid(request)) + return FALSE; + else if (!feature_support_flags_is_valid(existing)) + return TRUE; + else if (request == existing) + return TRUE; + else if (existing & FEATURE_SURETY_GOOD) + return FALSE; + else + return TRUE; +} + +/* If the access listed is NULL, and the provided flags can override the + existing ones, then do it and return TRUE. */ +static gboolean try_set_feature(DeviceAccessMode mode, + FeatureSupportFlags request, + FeatureSupportFlags * existing) { + if (mode != ACCESS_NULL) { + return FALSE; + } else if (flags_settable(request, *existing)) { + *existing = request; + return TRUE; + } else { + return FALSE; + } +} + +static gboolean +tape_device_property_set (Device * d_self, DevicePropertyId id, GValue * val) { + TapeDevice * self; + FeatureSupportFlags feature_request_flags = 0; + const DevicePropertyBase * base; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail(self != NULL, FALSE); + + base = device_property_get_by_id(id); + g_return_val_if_fail(self != NULL, FALSE); + + g_return_val_if_fail(G_VALUE_HOLDS(val, base->type), FALSE); + + if (base->type == FEATURE_SUPPORT_FLAGS_TYPE) { + feature_request_flags = g_value_get_flags(val); + g_return_val_if_fail( + feature_support_flags_is_valid(feature_request_flags), FALSE); + } + + if (id == PROPERTY_COMPRESSION) { + /* We allow this property to be set at any time. This is mostly + * because setting compression is a hit-and-miss proposition + * at any time; some drives accept the mode setting but don't + * actually support compression, while others do support + * compression but do it via density settings or some other + * way. Set this property whenever you want, but all we'll do + * is report whether or not the ioctl succeeded. */ + gboolean request = g_value_get_boolean(val); + if (tape_setcompression(self->fd, request)) { + self->compression = request; + device_clear_volume_details(d_self); + return TRUE; + } else { + return FALSE; + } + } else if (id == PROPERTY_MIN_BLOCK_SIZE) { + if (d_self->access_mode != ACCESS_NULL) + return FALSE; + self->min_block_size = g_value_get_uint(val); + device_clear_volume_details(d_self); + return TRUE; + } else if (id == PROPERTY_MAX_BLOCK_SIZE) { + if (d_self->access_mode != ACCESS_NULL) + return FALSE; + self->max_block_size = g_value_get_uint(val); + device_clear_volume_details(d_self); + return TRUE; + } else if (id == PROPERTY_BLOCK_SIZE) { + if (d_self->access_mode != ACCESS_NULL) + return FALSE; + + self->fixed_block_size = g_value_get_int(val); + device_clear_volume_details(d_self); + return TRUE; + } else if (id == PROPERTY_READ_BUFFER_SIZE) { + if (d_self->access_mode != ACCESS_NULL) + return FALSE; + self->read_block_size = g_value_get_uint(val); + device_clear_volume_details(d_self); + return TRUE; + } else if (id == PROPERTY_FSF) { + return try_set_feature(d_self->access_mode, + feature_request_flags, + &(self->fsf)); + } else if (id == PROPERTY_BSF) { + return try_set_feature(d_self->access_mode, + feature_request_flags, + &(self->bsf)); + } else if (id == PROPERTY_FSR) { + return try_set_feature(d_self->access_mode, + feature_request_flags, + &(self->fsr)); + } else if (id == PROPERTY_BSR) { + return try_set_feature(d_self->access_mode, + feature_request_flags, + &(self->bsr)); + } else if (id == PROPERTY_EOM) { + /* Setting this to disabled also clears BSF after EOM. */ + if (try_set_feature(d_self->access_mode, + feature_request_flags, + &(self->eom))) { + feature_request_flags &= ~FEATURE_SUPPORT_FLAGS_STATUS_MASK; + feature_request_flags |= FEATURE_STATUS_DISABLED; + self->bsf_after_eom = feature_request_flags; + return TRUE; + } else { + return FALSE; + } + } else if (id == PROPERTY_BSF_AFTER_EOM) { + /* You can only set this if EOM is enabled. */ + if (self->bsf | FEATURE_STATUS_DISABLED) + return FALSE; + else + return try_set_feature(d_self->access_mode, + feature_request_flags, + &(self->bsf_after_eom)); + } else if (id == PROPERTY_FINAL_FILEMARKS) { + guint request = g_value_get_uint(val); + if (request == 1 || request == 2) { + self->final_filemarks = request; + return TRUE; + } else { + return FALSE; + } + } else { + /* Chain up */ + if (parent_class->property_set) { + return (parent_class->property_set)(d_self, id, val); + } else { + return FALSE; + } + } + + g_assert_not_reached(); +} + +static gboolean +tape_device_finish (Device * d_self) { + TapeDevice * self; + + self = TAPE_DEVICE(d_self); + g_return_val_if_fail(self != NULL, FALSE); + + /* Polish off this file, if relevant. */ + if (d_self->in_file && IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) { + if (!device_finish_file(d_self)) + return FALSE; + } + + /* Write an extra filemark, if needed. The OS will give us one for + sure. */ + if (self->final_filemarks > 1 && + IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) { + if (!tape_weof(self->fd, 1)) { + g_fprintf(stderr, "Error writing final filemark: %s\n", + strerror(errno)); + return FALSE; + } + } + + /* Rewind. */ + if (!tape_rewind(self->fd)) { + g_fprintf(stderr, "Error rewinding tape: %s\n", strerror(errno)); + return FALSE; + } + + d_self->access_mode = ACCESS_NULL; + + if (parent_class->finish) { + return (parent_class->finish)(d_self); + } else { + return TRUE; + } + +} + +/* Works just like read(), except for the following: + * 1) Retries on EINTR & friends. + * 2) Stores count in parameter, not return value. + * 3) Provides explicit return result. */ +static IoResult +tape_device_robust_read (TapeDevice * self, void * buf, int * count) { + Device * d_self; + int result; + + d_self = (Device*)self; + g_return_val_if_fail(self != NULL, RESULT_ERROR); + g_return_val_if_fail(*count >= 0, RESULT_ERROR); + /* Callers should ensure this. */ + g_assert((guint)(*count) <= self->read_block_size); + + for (;;) { + result = read(self->fd, buf, *count); + if (result > 0) { + /* Success. By definition, we read a full block. */ + *count = result; + return RESULT_SUCCESS; + } else if (result == 0) { + return RESULT_NO_DATA; + } else { + if (0 +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef EINTR + || errno == EINTR +#endif + ) { + /* Interrupted system call */ + continue; + } else if ((self->fixed_block_size == 0) && + (0 +#ifdef ENOMEM + || errno == ENOMEM /* bad user-space buffer */ +#endif +#ifdef EOVERFLOW + || errno == EOVERFLOW /* bad kernel-space buffer */ +#endif +#ifdef EINVAL + || errno == EINVAL /* ??? */ +#endif + )) { + /* Buffer too small. */ + return RESULT_SMALL_BUFFER; + } else { + g_fprintf(stderr, "Error reading %d bytes from %s: %s\n", + *count, d_self->device_name, strerror(errno)); + return RESULT_ERROR; + } + } + + } + + g_assert_not_reached(); +} + +/* Kernel workaround: If needed, poke the kernel so it doesn't fail. + at the 2GB boundry. Parameters are G_GNUC_UNUSED in case NEED_RESETOFS + is not defined. */ +static void check_resetofs(TapeDevice * self G_GNUC_UNUSED, + int count G_GNUC_UNUSED) { +#ifdef NEED_RESETOFS + int result; + + self->private->write_count += count; + if (self->private->write_count < RESETOFS_THRESHOLD) { + return; + } + + result = lseek(self->fd, 0, SEEK_SET); + if (result < 0) { + g_fprintf(stderr, + "Warning: lseek() failed during kernel 2GB workaround.\n"); + } +#endif +} + +static IoResult +tape_device_robust_write (TapeDevice * self, void * buf, int count) { + Device * d_self; + int result; + + g_return_val_if_fail(self != NULL, RESULT_ERROR); + d_self = (Device*)self; + + check_resetofs(self, count); + + for (;;) { + result = write(self->fd, buf, count); + + if (result == count) { + /* Success. */ + + self->private->write_count ++; + return RESULT_SUCCESS; + } else if (result >= 0) { + /* write() returned a short count. This should not happen. */ + g_fprintf(stderr, + "Mysterious short write on tape device: Tried %d, got %d.\n", + count, result); + return RESULT_ERROR; + } else if (0 +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef EINTR + || errno == EINTR +#endif + ) { + /* Interrupted system call */ + continue; + } else if (0 +#ifdef ENOSPC + || errno == ENOSPC +#endif +#ifdef EIO + || errno == EIO +#endif + ) { + /* Probably EOT. Print a message if we got EIO. */ +#ifdef EIO + if (errno == EIO) { + g_fprintf(stderr, "Got EIO on %s, assuming end of tape.\n", + d_self->device_name); + } +#endif + return RESULT_NO_SPACE; + } else { + /* WTF */ + g_fprintf(stderr, + "Kernel gave unexpected write() result of \"%s\" on device %s.\n", + strerror(errno), d_self->device_name); + return RESULT_ERROR; + } + } + + g_assert_not_reached(); +} + +/* Reads some number of tape blocks into the bit-bucket. If the count + is negative, then we read the rest of the entire file. Returns the + number of blocks read, or -1 if an error occured. If we encounter + EOF (as opposed to some other error) we return the number of blocks + actually read. */ +static int drain_tape_blocks(TapeDevice * self, int count) { + char * buffer; + int buffer_size; + int i; + + buffer_size = self->read_block_size; + + buffer = malloc(sizeof(buffer_size)); + + for (i = 0; i < count || count < 0;) { + int result; + + result = read(self->fd, buffer, buffer_size); + if (result > 0) { + i ++; + continue; + } else if (result == 0) { + free(buffer); + return i; + } else { + /* First check for interrupted system call. */ + if (0 +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef EINTR + || errno == EINTR +#endif + ) { + /* Interrupted system call */ + continue; + } else if (0 +#ifdef ENOSPC + || errno == ENOSPC /* bad user-space buffer */ +#endif +#ifdef EOVERFLOW + || errno == EOVERFLOW /* bad kernel-space buffer */ +#endif +#ifdef EINVAL + || errno == EINVAL /* ??? */ +#endif + ) { + /* The buffer may not be big enough. But the OS is not + 100% clear. We double the buffer and try again, but + in no case allow a buffer bigger than 32 MB. */ + buffer_size *= 2; + + if (buffer_size > 32*1024*1024) { + free(buffer); + return -1; + } else { + buffer = realloc(buffer, buffer_size); + continue; + } + } + } + } + + return count; +} + +/* FIXME: Make sure that there are no cycles in reimplementation + dependencies. */ + +static gboolean +tape_device_fsf (TapeDevice * self, guint count) { + g_return_val_if_fail (self != NULL, (gboolean )0); + g_return_val_if_fail (IS_TAPE_DEVICE (self), (gboolean )0); + + if (self->fsf & FEATURE_STATUS_ENABLED) { + return tape_fsf(self->fd, count); + } else { + guint i; + for (i = 0; i < count; i ++) { + if (drain_tape_blocks(self, -1) < 0) + return FALSE; + } + return TRUE; + } +} + +/* Seek back over count + 1 filemarks to the start of the given file. */ +static gboolean +tape_device_bsf (TapeDevice * self, guint count, guint file) { + g_return_val_if_fail (self != NULL, (gboolean )0); + g_return_val_if_fail (IS_TAPE_DEVICE (self), (gboolean )0); + + if (self->bsf & FEATURE_STATUS_ENABLED) { + /* The BSF operation is not very smart; it includes the + filemark of the present file as part of the count, and seeks + to the wrong (BOT) side of the filemark. We compensate for + this by seeking one filemark too many, then FSFing back over + it. + + If this procedure fails for some reason, we can still try + the backup plan. */ + if (tape_bsf(self->fd, count + 1) && + tape_device_fsf(self, 1)) + return TRUE; + } /* Fall through to backup plan. */ + + /* We rewind the tape, then seek forward the given number of + files. */ + if (!tape_rewind(self->fd)) + return FALSE; + + return tape_device_fsf(self, file); +} + + +static gboolean +tape_device_fsr (TapeDevice * self, guint count) { + g_return_val_if_fail (self != NULL, (gboolean )0); + g_return_val_if_fail (IS_TAPE_DEVICE (self), (gboolean )0); + + if (self->fsr & FEATURE_STATUS_ENABLED) { + return tape_fsr(self->fd, count); + } else { + int result = drain_tape_blocks(self, count); + return result > 0 && (int)count == result; + } +} + +/* Seek back the given number of blocks to block number block within + * the current file, numbered file. */ + +static gboolean +tape_device_bsr (TapeDevice * self, guint count, guint file, guint block) { + g_return_val_if_fail (self != NULL, (gboolean )0); + g_return_val_if_fail (IS_TAPE_DEVICE (self), (gboolean )0); + + g_return_val_if_fail (self != NULL, (gboolean )0); + g_return_val_if_fail (IS_TAPE_DEVICE (self), (gboolean )0); + + if (self->bsr & FEATURE_STATUS_ENABLED) { + return tape_bsr(self->fd, count); + } else { + /* We BSF, then FSR. */ + if (!tape_device_bsf(self, 0, file)) + return FALSE; + + return tape_device_fsr(self, block); + } + g_assert_not_reached(); +} + +/* Go to the right place to write more data, and update the file + number if possible. */ +static gboolean +tape_device_eod (TapeDevice * self) { + Device * d_self; + g_return_val_if_fail (self != NULL, (gboolean )0); + g_return_val_if_fail (IS_TAPE_DEVICE (self), (gboolean )0); + d_self = (Device*)self; + + if (self->eom & FEATURE_STATUS_ENABLED) { + int result; + result = tape_eod(self->fd); + if (result == TAPE_OP_ERROR) { + return FALSE; + } else if (result == TAPE_POSITION_UNKNOWN) { + d_self->file = -1; + } else { + /* We drop by 1 because Device will increment the first + time the user does start_file. */ + d_self->file = result - 1; + } + return TRUE; + } else { + int count = 0; + if (!tape_rewind(self->fd)) + return FALSE; + + for (;;) { + /* We alternately read a block and FSF. If the read is + successful, then we are not there yet and should FSF + again. */ + int result; + result = drain_tape_blocks(self, 1); + if (result == 1) { + /* More data, FSF. */ + tape_device_fsf(self, 1); + count ++; + } else if (result == 0) { + /* Finished. */ + d_self->file = count; + return TRUE; + } else { + return FALSE; + } + } + } +} + +Device * +tape_device_factory (char * device_type, char * device_name) { + Device * rval; + g_assert(0 == strcmp(device_type, "tape")); + rval = DEVICE(g_object_new(TYPE_TAPE_DEVICE, NULL)); + if (!device_open_device(rval, device_name)) { + g_object_unref(rval); + return NULL; + } else { + return rval; + } +} diff --git a/device-src/tape-device.h b/device-src/tape-device.h new file mode 100644 index 0000000..7bfa1da --- /dev/null +++ b/device-src/tape-device.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#ifndef TAPE_DEVICE_H +#define TAPE_DEVICE_H + +#include + +/* + * Type checking and casting macros + */ +#define TYPE_TAPE_DEVICE (tape_device_get_type()) +#define TAPE_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), tape_device_get_type(), TapeDevice) +#define TAPE_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), tape_device_get_type(), TapeDevice const) +#define TAPE_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), tape_device_get_type(), TapeDeviceClass) +#define IS_TAPE_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), tape_device_get_type ()) + +#define TAPE_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), tape_device_get_type(), TapeDeviceClass) + +/* + * Main object structure + */ +typedef struct TapeDevicePrivate_s TapeDevicePrivate; +typedef struct _TapeDevice { + Device __parent__; + + /* It should go without saying that all this stuff is + * look-but-don't-touch. */ + guint min_block_size, max_block_size, fixed_block_size, read_block_size; + FeatureSupportFlags fsf, bsf, fsr, bsr, eom, bsf_after_eom; + int final_filemarks; + gboolean compression; + /* 0 if we opened with O_RDWR; error otherwise. */ + gboolean write_open_errno; + gboolean first_file; /* Is this the first file in append mode? */ + int fd; + + TapeDevicePrivate * private; +} TapeDevice; + +/* + * Class definition + */ +typedef struct _TapeDeviceClass TapeDeviceClass; +struct _TapeDeviceClass { + DeviceClass __parent__; +}; + + +/* + * Public methods + */ +GType tape_device_get_type (void); +Device* tape_device_factory (char * type, + char * name); +void tape_device_register (void); + +#endif diff --git a/device-src/tape-ops.h b/device-src/tape-ops.h new file mode 100644 index 0000000..bebe28a --- /dev/null +++ b/device-src/tape-ops.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#ifndef TAPE_OPS_H + +#include +#include "tape-device.h" +#include "amanda.h" + +#ifdef HAVE_SYS_TAPE_H +# include +#endif +#ifdef HAVE_SYS_MTIO_H +# include +#endif + +/* Return codes for tape_eod */ +#define TAPE_OP_ERROR -1 +#define TAPE_POSITION_UNKNOWN -2 + +/* Real Operations (always return FALSE if not implemented). These are + * implemented in one of tape-{uware,aix,xenix,posix}.c, depending on + * the platform. */ +gboolean tape_rewind(int fd); +gboolean tape_fsf(int fd, guint count); +gboolean tape_bsf(int fd, guint count); +gboolean tape_fsr(int fd, guint count); +gboolean tape_bsr(int fd, guint count); +/* Returns tape position file number, or one of the return codes above. */ +gint tape_eod(int fd); +gboolean tape_weof(int fd, guint8 count); +gboolean tape_setcompression(int fd, gboolean on); + +typedef enum { + TAPE_CHECK_SUCCESS, + TAPE_CHECK_UNKNOWN, + TAPE_CHECK_FAILURE +} TapeCheckResult; +ReadLabelStatusFlags tape_is_tape_device(int fd); +TapeCheckResult tape_is_ready(int fd); + +/* Also implemented in above files. Sets properties on the device. */ +void tape_device_discover_capabilities(TapeDevice * self); + +#endif + diff --git a/device-src/tape-posix.c b/device-src/tape-posix.c new file mode 100644 index 0000000..70e9480 --- /dev/null +++ b/device-src/tape-posix.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include "amanda.h" +#include "util.h" +#include "tape-ops.h" +#include "property.h" +#include + +/* Having one name for every operation would be too easy. */ +#if !defined(MTCOMPRESSION) && defined(MTCOMP) +# define MTCOMPRESSION MTCOMP +#endif + +#if !defined(MTSETBLK) && defined(MTSETBSIZ) +# define MTSETBLK MTSETBSIZ +#endif + +#if !defined(MTEOM) && defined(MTEOD) +# define MTEOM MTEOD +#endif + +#ifdef HAVE_LIMITS_H +# include +#endif + +gboolean tape_rewind(int fd) { + int count = 5; + time_t stop_time; + + /* We will retry this for up to 30 seconds or 5 retries, + whichever is less, because some hardware/software combinations + (notably EXB-8200 on FreeBSD) can fail to rewind. */ + stop_time = time(NULL) + 30; + + while (--count >= 0 && time(NULL) < stop_time) { + struct mtop mt; + mt.mt_op = MTREW; + mt.mt_count = 1; + + if (0 == ioctl(fd, MTIOCTOP, &mt)) + return TRUE; + + sleep(3); + } + + return FALSE; +} + +gboolean tape_fsf(int fd, guint count) { + struct mtop mt; + mt.mt_op = MTFSF; + mt.mt_count = count; + return 0 == ioctl(fd, MTIOCTOP, &mt); +} + +gboolean tape_bsf(int fd, guint count) { + struct mtop mt; + mt.mt_op = MTBSF; + mt.mt_count = count; + return 0 == ioctl(fd, MTIOCTOP, &mt); +} + +gboolean tape_fsr(int fd, guint count) { + struct mtop mt; + mt.mt_op = MTFSR; + mt.mt_count = count; + return 0 == ioctl(fd, MTIOCTOP, &mt); +} + +gboolean tape_bsr(int fd, guint count) { + struct mtop mt; + mt.mt_op = MTBSR; + mt.mt_count = count; + return 0 == ioctl(fd, MTIOCTOP, &mt); +} + +gint tape_eod(int fd) { + struct mtop mt; + struct mtget get; + mt.mt_op = MTEOM; + mt.mt_count = 1; + if (0 != ioctl(fd, MTIOCTOP, &mt)) + return TAPE_OP_ERROR; + + /* Ignored result. This is just to flush buffers. */ + mt.mt_op = MTNOP; + ioctl(fd, MTIOCTOP, &mt); + + if (0 != ioctl(fd, MTIOCGET, &get)) + return TAPE_POSITION_UNKNOWN; + if (get.mt_fileno < 0) + return TAPE_POSITION_UNKNOWN; + else + return get.mt_fileno; +} + +gboolean tape_weof(int fd, guint8 count) { + struct mtop mt; + mt.mt_op = MTWEOF; + mt.mt_count = count; + return 0 == ioctl(fd, MTIOCTOP, &mt); +} + +gboolean tape_setcompression(int fd G_GNUC_UNUSED, + gboolean on G_GNUC_UNUSED) { +#ifdef MTCOMPRESSION + struct mtop mt; + mt.mt_op = MTCOMPRESSION; + mt.mt_count = on; + return 0 == ioctl(fd, MTIOCTOP, &mt); +#else + return 0; +#endif +} + +ReadLabelStatusFlags tape_is_tape_device(int fd) { + struct mtop mt; + mt.mt_op = MTNOP; + mt.mt_count = 1; + if (0 == ioctl(fd, MTIOCTOP, &mt)) { + return READ_LABEL_STATUS_SUCCESS; + } else { + dbprintf("tape_is_tape_device: ioctl(MTIOCTOP/MTNOP) failed: %s", + strerror(errno)); + if (errno == EIO) { + /* some devices return EIO while the drive is busy loading */ + return READ_LABEL_STATUS_DEVICE_ERROR|READ_LABEL_STATUS_VOLUME_MISSING; + } else { + return READ_LABEL_STATUS_DEVICE_ERROR; + } + } +} + +TapeCheckResult tape_is_ready(int fd) { + struct mtget get; + if (0 == ioctl(fd, MTIOCGET, &get)) { +#if defined(GMT_DR_OPEN) + if (!GMT_DR_OPEN(get.mt_gstat)) { + return TAPE_CHECK_SUCCESS; + } else { + dbprintf("tape_is_read: ioctl(MTIOCGET) failed: %s", strerror(errno)); + return TAPE_CHECK_FAILURE; + } +#else /* Neither macro is defined. */ + return TAPE_CHECK_UNKNOWN; +#endif + } else { + return TAPE_CHECK_FAILURE; + } +} + +void tape_device_discover_capabilities(TapeDevice * t_self) { + Device * self; + GValue val; + + self = DEVICE(t_self); + g_return_if_fail(self != NULL); + + bzero(&val, sizeof(val)); + g_value_init(&val, FEATURE_SUPPORT_FLAGS_TYPE); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_EOM, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_DISABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSF_AFTER_EOM, &val); + + g_value_unset_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 2); + device_property_set(self, PROPERTY_FINAL_FILEMARKS, &val); +} diff --git a/device-src/tape-uware.c b/device-src/tape-uware.c new file mode 100644 index 0000000..0b86761 --- /dev/null +++ b/device-src/tape-uware.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* Tape operations for SVR4 systems. Most of this stuff is based on + documentation from http://docsrv.sco.com/cgi-bin/man/man?sdi+7 */ + +#include +#include + +/* Uncomment to test on non-SYSV4 systems. */ +/* --- +#undef MTIOCTOP +#define T_RWD 0 +#define T_SFF 0 +#define T_SFB 0 +#define T_SBF 0 +#define T_SBB 0 +#define T_WRFILEM 0 +#define T_RDBLKLEN 0 +#define T_WRBLKLEN 0 +#define T_SETCOMP 0 + +struct blklen { + int min_blen, max_blen; +}; + + --- */ + +gboolean tape_rewind(int fd) { + return 0 == ioctl(fd, T_RWD); +} + +gboolean tape_fsf(int fd, guint count) { + return 0 == ioctl(fd, T_SFF, count); +} + +gboolean tape_bsf(int fd, guint count) { + return 0 == ioctl(fd, T_SFB, count); +} + +gboolean tape_fsr(int fd, guint count) { + return 0 == ioctl(fd, T_SBF, count); +} + +gboolean tape_bsr(int fd, guint count) { + return 0 == ioctl(fd, T_SBB, count); +} + +int tape_eod(int fd) { + g_assert_not_reached(); + return TAPE_OP_ERROR; +} + +gboolean tape_weof(int fd, guint8 count) { + return 0 == ioctl(fd, T_WRFILEM, count); +} + +gboolean tape_setcompression(int fd, gboolean on) { + int cmd; + if (on) { + cmd = 3; + } else { + cmd = 2; + } + + return 0 == ioctl(fd, T_SETCOMP, cmd); +} + +ReadLabelStatusFlags tape_is_tape_device(int fd) { + /* If we can read block information, it's probably a tape device. */ + struct blklen result; + if (0 == ioctl(fd, T_RDBLKLEN, &result)) { + return READ_LABEL_STATUS_SUCCESS; + } else { + dbprintf("tape_is_tape_device: ioctl(MTIOCTOP/MTNOP) failed: %s", + strerror(errno)); + return READ_LABEL_STATUS_DEVICE_ERROR; + } +} + +TapeCheckResult tape_is_tape_ready(int fd) { + return TAPE_CHECK_UNKNOWN; +} + +void tape_device_discover_capabilities(TapeDevice * t_self) { + Device * self; + GValue val; + + self = DEVICE(t_self); + g_return_if_fail(self != NULL); + + bzero(&val, sizeof(val)); + g_value_init(&val, FEATURE_SUPPORT_FLAGS_TYPE); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_DISABLED | FEATURE_SURETY_GOOD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_EOM, &val); + + g_value_unset_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 2); + device_property_set(self, PROPERTY_FINAL_FILEMARKS, &val); +} diff --git a/device-src/tape-xenix.c b/device-src/tape-xenix.c new file mode 100644 index 0000000..1890cd2 --- /dev/null +++ b/device-src/tape-xenix.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* Tape operations for XENIX systems. Most of this stuff is based on + documentation from + http://www.ifthenfi.nl:8080/cgi-bin/ssl_getmanpage?tape+HW+XNX234+tape +*/ + +#include +#include + +/* Uncomment to test compilation on non-XENIX systems. */ +/* --- +#undef MTIOCTOP +#define MT_REWIND 0 +#define MT_STATUS 0 +#define T_RFM 0 +#define T_WFM 0 +struct tape_info {}; + --- */ + +gboolean tape_rewind(int fd) { + return 0 == ioctl(fd, MT_REWIND); +} + +gboolean tape_fsf(int fd, guint count) { + while (--count >= 0) { + if (0 != ioctl(fd, T_RFM)) + return FALSE; + } + return TRUE; +} + +gboolean tape_bsf(int fd, guint count) { + g_assert_not_reached(); + return FALSE; +} + +gboolean tape_fsr(int fd, guint count) { + g_assert_not_reached(); + return FALSE; +} + +gboolean tape_bsr(int fd, guint count) { + g_assert_not_reached(); + return FALSE; +} + +gint tape_eod(int fd) { + g_assert_not_reached(); + return TAPE_OP_ERROR; +} + +gboolean tape_weof(int fd, guint8 count) { + while (count -- > 0) { + if (0 != ioctl(fd, T_WFM)) + return FALSE; + } + + return TRUE; +} + +gboolean tape_setcompression(int fd, gboolean on) { + return FALSE; +} + +ReadLabelStatusFlags tape_is_tape_device(int fd) { + struct tape_info result; + if (0 == ioctl(fd, MT_STATUS, &result)) { + return READ_LABEL_STATUS_SUCCESS; + } else { + dbprintf("tape_is_tape_device: ioctl(MTIOCTOP/MTNOP) failed: %s", + strerror(errno)); + return READ_LABEL_STATUS_DEVICE_ERROR; + } +} + +TapeCheckResult tape_is_ready(int fd) { + /* We can probably do better. */ + return TAPE_CHECK_UNKNOWN; +} + +void tape_device_discover_capabilities(TapeDevice * t_self) { + Device * self; + GValue val; + + self = DEVICE(t_self); + g_return_if_fail(self != NULL); + + bzero(&val, sizeof(val)); + g_value_init(&val, FEATURE_SUPPORT_FLAGS_TYPE); + + g_value_set_flags(&val, + FEATURE_STATUS_ENABLED | FEATURE_SURETY_BAD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_DISABLED | FEATURE_SURETY_GOOD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSF, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_DISABLED | FEATURE_SURETY_GOOD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_FSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_DISABLED | FEATURE_SURETY_GOOD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_BSR, &val); + + g_value_set_flags(&val, + FEATURE_STATUS_DISABLED | FEATURE_SURETY_GOOD | + FEATURE_SOURCE_DEFAULT); + device_property_set(self, PROPERTY_EOM, &val); + + g_value_unset_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 2); + device_property_set(self, PROPERTY_FINAL_FILEMARKS, &val); +} diff --git a/device-src/tests/Makefile.am b/device-src/tests/Makefile.am new file mode 100644 index 0000000..9c54473 --- /dev/null +++ b/device-src/tests/Makefile.am @@ -0,0 +1,28 @@ +# Makefile for Amanda tape library. + +INCLUDES = -I$(top_builddir)/common-src \ + -I$(top_srcdir)/common-src \ + -I$(top_srcdir)/gnulib \ + -I$(top_srcdir)/device-src + +# automake-style tests + +noinst_PROGRAMS = queue_test device_test $(TESTS) + +### +# Because libamanda includes routines (e.g. regex) provided by some system +# libraries, and because of the way libtool sets up the command line, we +# need to list libamanda twice here, first to override the system library +# routines, and second to pick up any references in the other libraries. +### +LDADD = ../../common-src/libamanda.la \ + ../libamdevice.la \ + ../../common-src/libamanda.la \ + ../../gnulib/libgnu.la + + +TESTS = semaphore-test vfs_test + +semaphore_test_SOURCES = semaphore-test.c + +vfs_test_SOURCES = vfs_test.c diff --git a/device-src/tests/Makefile.in b/device-src/tests/Makefile.in new file mode 100644 index 0000000..37fe55e --- /dev/null +++ b/device-src/tests/Makefile.in @@ -0,0 +1,964 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for Amanda tape library. + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = queue_test$(EXEEXT) device_test$(EXEEXT) \ + $(am__EXEEXT_1) +TESTS = semaphore-test$(EXEEXT) vfs_test$(EXEEXT) +subdir = device-src/tests +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/config/macro-archive/ac_define_dir.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_perl_version.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_swig.m4 \ + $(top_srcdir)/config/macro-archive/ax_compare_version.m4 \ + $(top_srcdir)/config/macro-archive/docbook-dtd.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt-min.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt.m4 \ + $(top_srcdir)/config/macro-archive/xsltproc.m4 \ + $(top_srcdir)/config/amanda/amplot.m4 \ + $(top_srcdir)/config/amanda/bsd-security.m4 \ + $(top_srcdir)/config/amanda/bsdtcp-security.m4 \ + $(top_srcdir)/config/amanda/bsdudp-security.m4 \ + $(top_srcdir)/config/amanda/changer.m4 \ + $(top_srcdir)/config/amanda/components.m4 \ + $(top_srcdir)/config/amanda/compress.m4 \ + $(top_srcdir)/config/amanda/config.m4 \ + $(top_srcdir)/config/amanda/debugging.m4 \ + $(top_srcdir)/config/amanda/defaults.m4 \ + $(top_srcdir)/config/amanda/devprefix.m4 \ + $(top_srcdir)/config/amanda/dirs.m4 \ + $(top_srcdir)/config/amanda/documentation.m4 \ + $(top_srcdir)/config/amanda/dumpers.m4 \ + $(top_srcdir)/config/amanda/flags.m4 \ + $(top_srcdir)/config/amanda/flock.m4 \ + $(top_srcdir)/config/amanda/funcs.m4 \ + $(top_srcdir)/config/amanda/getfsent.m4 \ + $(top_srcdir)/config/amanda/i18n.m4 \ + $(top_srcdir)/config/amanda/ipv6.m4 \ + $(top_srcdir)/config/amanda/krb4-security.m4 \ + $(top_srcdir)/config/amanda/krb5-security.m4 \ + $(top_srcdir)/config/amanda/lfs.m4 \ + $(top_srcdir)/config/amanda/libs.m4 \ + $(top_srcdir)/config/amanda/net.m4 \ + $(top_srcdir)/config/amanda/progs.m4 \ + $(top_srcdir)/config/amanda/readdir.m4 \ + $(top_srcdir)/config/amanda/readline.m4 \ + $(top_srcdir)/config/amanda/rsh-security.m4 \ + $(top_srcdir)/config/amanda/s3-device.m4 \ + $(top_srcdir)/config/amanda/shmem.m4 \ + $(top_srcdir)/config/amanda/socklen_t_equiv.m4 \ + $(top_srcdir)/config/amanda/ssh-security.m4 \ + $(top_srcdir)/config/amanda/summary.m4 \ + $(top_srcdir)/config/amanda/swig.m4 \ + $(top_srcdir)/config/amanda/syshacks.m4 \ + $(top_srcdir)/config/amanda/tape.m4 \ + $(top_srcdir)/config/amanda/types.m4 \ + $(top_srcdir)/config/amanda/userid.m4 \ + $(top_srcdir)/config/amanda/version.m4 \ + $(top_srcdir)/config/gnulib/alloca.m4 \ + $(top_srcdir)/config/gnulib/arpa_inet_h.m4 \ + $(top_srcdir)/config/gnulib/base64.m4 \ + $(top_srcdir)/config/gnulib/eoverflow.m4 \ + $(top_srcdir)/config/gnulib/extensions.m4 \ + $(top_srcdir)/config/gnulib/float_h.m4 \ + $(top_srcdir)/config/gnulib/fsusage.m4 \ + $(top_srcdir)/config/gnulib/getaddrinfo.m4 \ + $(top_srcdir)/config/gnulib/gettimeofday.m4 \ + $(top_srcdir)/config/gnulib/gnulib-comp.m4 \ + $(top_srcdir)/config/gnulib/include_next.m4 \ + $(top_srcdir)/config/gnulib/inet_ntop.m4 \ + $(top_srcdir)/config/gnulib/intmax_t.m4 \ + $(top_srcdir)/config/gnulib/lock.m4 \ + $(top_srcdir)/config/gnulib/longlong.m4 \ + $(top_srcdir)/config/gnulib/malloc.m4 \ + $(top_srcdir)/config/gnulib/mkdtemp.m4 \ + $(top_srcdir)/config/gnulib/netinet_in_h.m4 \ + $(top_srcdir)/config/gnulib/onceonly_2_57.m4 \ + $(top_srcdir)/config/gnulib/physmem.m4 \ + $(top_srcdir)/config/gnulib/safe-read.m4 \ + $(top_srcdir)/config/gnulib/safe-write.m4 \ + $(top_srcdir)/config/gnulib/snprintf.m4 \ + $(top_srcdir)/config/gnulib/socklen.m4 \ + $(top_srcdir)/config/gnulib/sockpfaf.m4 \ + $(top_srcdir)/config/gnulib/ssize_t.m4 \ + $(top_srcdir)/config/gnulib/stdbool.m4 \ + $(top_srcdir)/config/gnulib/stdint.m4 \ + $(top_srcdir)/config/gnulib/stdio_h.m4 \ + $(top_srcdir)/config/gnulib/stdlib_h.m4 \ + $(top_srcdir)/config/gnulib/strdup.m4 \ + $(top_srcdir)/config/gnulib/string_h.m4 \ + $(top_srcdir)/config/gnulib/sys_socket_h.m4 \ + $(top_srcdir)/config/gnulib/sys_stat_h.m4 \ + $(top_srcdir)/config/gnulib/sys_time_h.m4 \ + $(top_srcdir)/config/gnulib/tempname.m4 \ + $(top_srcdir)/config/gnulib/ulonglong.m4 \ + $(top_srcdir)/config/gnulib/unistd_h.m4 \ + $(top_srcdir)/config/gnulib/vasnprintf.m4 \ + $(top_srcdir)/config/gnulib/visibility.m4 \ + $(top_srcdir)/config/gnulib/wchar.m4 \ + $(top_srcdir)/config/gettext-macros/gettext.m4 \ + $(top_srcdir)/config/gettext-macros/iconv.m4 \ + $(top_srcdir)/config/gettext-macros/inttypes_h.m4 \ + $(top_srcdir)/config/gettext-macros/lib-ld.m4 \ + $(top_srcdir)/config/gettext-macros/lib-link.m4 \ + $(top_srcdir)/config/gettext-macros/lib-prefix.m4 \ + $(top_srcdir)/config/gettext-macros/longlong.m4 \ + $(top_srcdir)/config/gettext-macros/nls.m4 \ + $(top_srcdir)/config/gettext-macros/po.m4 \ + $(top_srcdir)/config/gettext-macros/progtest.m4 \ + $(top_srcdir)/config/gettext-macros/size_max.m4 \ + $(top_srcdir)/config/gettext-macros/stdint_h.m4 \ + $(top_srcdir)/config/gettext-macros/wchar_t.m4 \ + $(top_srcdir)/config/gettext-macros/wint_t.m4 \ + $(top_srcdir)/config/gettext-macros/xsize.m4 \ + $(top_srcdir)/config/libtool.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +am__EXEEXT_1 = semaphore-test$(EXEEXT) vfs_test$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +device_test_SOURCES = device_test.c +device_test_OBJECTS = device_test.$(OBJEXT) +device_test_LDADD = $(LDADD) +device_test_DEPENDENCIES = ../../common-src/libamanda.la \ + ../libamdevice.la ../../common-src/libamanda.la \ + ../../gnulib/libgnu.la +queue_test_SOURCES = queue_test.c +queue_test_OBJECTS = queue_test.$(OBJEXT) +queue_test_LDADD = $(LDADD) +queue_test_DEPENDENCIES = ../../common-src/libamanda.la \ + ../libamdevice.la ../../common-src/libamanda.la \ + ../../gnulib/libgnu.la +am_semaphore_test_OBJECTS = semaphore-test.$(OBJEXT) +semaphore_test_OBJECTS = $(am_semaphore_test_OBJECTS) +semaphore_test_LDADD = $(LDADD) +semaphore_test_DEPENDENCIES = ../../common-src/libamanda.la \ + ../libamdevice.la ../../common-src/libamanda.la \ + ../../gnulib/libgnu.la +am_vfs_test_OBJECTS = vfs_test.$(OBJEXT) +vfs_test_OBJECTS = $(am_vfs_test_OBJECTS) +vfs_test_LDADD = $(LDADD) +vfs_test_DEPENDENCIES = ../../common-src/libamanda.la \ + ../libamdevice.la ../../common-src/libamanda.la \ + ../../gnulib/libgnu.la +DEFAULT_INCLUDES = -I. -I$(top_builddir)/config@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = device_test.c queue_test.c $(semaphore_test_SOURCES) \ + $(vfs_test_SOURCES) +DIST_SOURCES = device_test.c queue_test.c $(semaphore_test_SOURCES) \ + $(vfs_test_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMANDA_DBGDIR = @AMANDA_DBGDIR@ +AMANDA_DEBUG_DAYS = @AMANDA_DEBUG_DAYS@ +AMANDA_STATIC_LDFLAGS = @AMANDA_STATIC_LDFLAGS@ +AMANDA_TMPDIR = @AMANDA_TMPDIR@ +AMANDA_WARNING_CFLAGS = @AMANDA_WARNING_CFLAGS@ +AMLINT = @AMLINT@ +AMLINTFLAGS = @AMLINTFLAGS@ +AMPLOT_CAT_COMPRESS = @AMPLOT_CAT_COMPRESS@ +AMPLOT_CAT_GZIP = @AMPLOT_CAT_GZIP@ +AMPLOT_CAT_PACK = @AMPLOT_CAT_PACK@ +AMPLOT_COMPRESS = @AMPLOT_COMPRESS@ +AMTAR = @AMTAR@ +AR = @AR@ +ARPA_INET_H = @ARPA_INET_H@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH = @BASH@ +BINARY_OWNER = @BINARY_OWNER@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +CAT = @CAT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CHIO = @CHIO@ +CHS = @CHS@ +CLIENT_LOGIN = @CLIENT_LOGIN@ +CLIENT_SCRIPTS_OPT = @CLIENT_SCRIPTS_OPT@ +COMPRESS = @COMPRESS@ +CONFIG_DIR = @CONFIG_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL_CONFIG = @CURL_CONFIG@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DD = @DD@ +DEFAULT_AMANDATES_FILE = @DEFAULT_AMANDATES_FILE@ +DEFAULT_CHANGER_DEVICE = @DEFAULT_CHANGER_DEVICE@ +DEFAULT_CONFIG = @DEFAULT_CONFIG@ +DEFAULT_SERVER = @DEFAULT_SERVER@ +DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@ +DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOC_BUILD_DATE = @DOC_BUILD_DATE@ +DUMP = @DUMP@ +DUMPER_DIR = @DUMPER_DIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EOVERFLOW = @EOVERFLOW@ +EXAMPLE_TAPEDEV = @EXAMPLE_TAPEDEV@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FLOAT_H = @FLOAT_H@ +GETCONF = @GETCONF@ +GETTEXT = @GETTEXT@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNUPLOT = @GNUPLOT@ +GNUTAR = @GNUTAR@ +GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GZIP = @GZIP@ +HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_MKDIR = @HAVE_DECL_MKDIR@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_IO_H = @HAVE_IO_H@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRNDUP = @HAVE_STRNDUP@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE__BOOL = @HAVE__BOOL@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBS = @LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAILER = @MAILER@ +MAKEINFO = @MAKEINFO@ +MAXTAPEBLOCKSIZE = @MAXTAPEBLOCKSIZE@ +MCUTIL = @MCUTIL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MT = @MT@ +MTX = @MTX@ +MT_FILE_FLAG = @MT_FILE_FLAG@ +NETINET_IN_H = @NETINET_IN_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCAT = @PCAT@ +PERL = @PERL@ +PERLEXTLIBS = @PERLEXTLIBS@ +PERL_INC = @PERL_INC@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +PRINT = @PRINT@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_FCHDIR = @REPLACE_FCHDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +RESTORE = @RESTORE@ +SAMBA_CLIENT = @SAMBA_CLIENT@ +SERVICE_SUFFIX = @SERVICE_SUFFIX@ +SETUID_GROUP = @SETUID_GROUP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SNAPSHOT_STAMP = @SNAPSHOT_STAMP@ +SORT = @SORT@ +SSH = @SSH@ +STDBOOL_H = @STDBOOL_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SVN = @SVN@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYS_SOCKET_H = @SYS_SOCKET_H@ +SYS_STAT_H = @SYS_STAT_H@ +SYS_TIME_H = @SYS_TIME_H@ +USE_NLS = @USE_NLS@ +USE_VERSION_SUFFIXES = @USE_VERSION_SUFFIXES@ +VDUMP = @VDUMP@ +VERSION = @VERSION@ +VERSION_COMMENT = @VERSION_COMMENT@ +VERSION_MAJOR = @VERSION_MAJOR@ +VERSION_MINOR = @VERSION_MINOR@ +VERSION_PATCH = @VERSION_PATCH@ +VERSION_SUFFIX = @VERSION_SUFFIX@ +VRESTORE = @VRESTORE@ +VXDUMP = @VXDUMP@ +VXRESTORE = @VXRESTORE@ +WCHAR_H = @WCHAR_H@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XFSDUMP = @XFSDUMP@ +XFSRESTORE = @XFSRESTORE@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XSLREL = @XSLREL@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +amincludedir = @amincludedir@ +amlibdir = @amlibdir@ +amlibexecdir = @amlibexecdir@ +amperldir = @amperldir@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I$(top_builddir)/common-src \ + -I$(top_srcdir)/common-src \ + -I$(top_srcdir)/gnulib \ + -I$(top_srcdir)/device-src + + +### +# Because libamanda includes routines (e.g. regex) provided by some system +# libraries, and because of the way libtool sets up the command line, we +# need to list libamanda twice here, first to override the system library +# routines, and second to pick up any references in the other libraries. +### +LDADD = ../../common-src/libamanda.la \ + ../libamdevice.la \ + ../../common-src/libamanda.la \ + ../../gnulib/libgnu.la + +semaphore_test_SOURCES = semaphore-test.c +vfs_test_SOURCES = vfs_test.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu device-src/tests/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu device-src/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +device_test$(EXEEXT): $(device_test_OBJECTS) $(device_test_DEPENDENCIES) + @rm -f device_test$(EXEEXT) + $(LINK) $(device_test_OBJECTS) $(device_test_LDADD) $(LIBS) +queue_test$(EXEEXT): $(queue_test_OBJECTS) $(queue_test_DEPENDENCIES) + @rm -f queue_test$(EXEEXT) + $(LINK) $(queue_test_OBJECTS) $(queue_test_LDADD) $(LIBS) +semaphore-test$(EXEEXT): $(semaphore_test_OBJECTS) $(semaphore_test_DEPENDENCIES) + @rm -f semaphore-test$(EXEEXT) + $(LINK) $(semaphore_test_OBJECTS) $(semaphore_test_LDADD) $(LIBS) +vfs_test$(EXEEXT): $(vfs_test_OBJECTS) $(vfs_test_DEPENDENCIES) + @rm -f vfs_test$(EXEEXT) + $(LINK) $(vfs_test_OBJECTS) $(vfs_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/device_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/semaphore-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfs_test.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *$$ws$$tst$$ws*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *$$ws$$tst$$ws*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/device-src/tests/device_test.c b/device-src/tests/device_test.c new file mode 100644 index 0000000..9a46fee --- /dev/null +++ b/device-src/tests/device_test.c @@ -0,0 +1,198 @@ +#include +#include +#include + +int blocksize; +unsigned int seed = 0; + +static char * make_rand_buf(int size) { + char * rval; + unsigned int i; + + rval = malloc(size); + i = size; + while (i > sizeof(int)) { + int rand; + rand = rand_r(&seed); + memcpy(rval + size - i, &rand, sizeof(int)); + i -= sizeof(int); + } + + if (size > 0) { + int rand; + rand = rand_r(&seed); + memcpy(rval + size - i, &rand, i); + } + + return rval; +} + +static gboolean write_whole_file(Device * device) { + dumpfile_t dumpfile; + char * tmp; + int i; + + fh_init(&dumpfile); + dumpfile.type = F_DUMPFILE; + tmp = get_timestamp_from_time(time(NULL)); + strcpy(dumpfile.datestamp, tmp); + amfree(tmp); + strcpy(dumpfile.name, "localhost"); + tmp = g_get_current_dir(); + strcpy(dumpfile.disk, tmp); + amfree(tmp); + strcpy(dumpfile.program, "TESTER"); + strcpy(dumpfile.recover_cmd, "recover_cmd"); + + blocksize = device_write_max_size(device); + + g_return_val_if_fail(device_start_file(device, &dumpfile), FALSE); + + for (i = 0; i < 1000; i ++) { + int size; + char * buf; + if (i == 999) + size = blocksize / 2; + else + size = blocksize; + buf = make_rand_buf(size); + g_return_val_if_fail(device_write_block(device, size, buf, i == 999), + FALSE); + amfree(buf); + } + + g_return_val_if_fail(device->in_file == FALSE, FALSE); + + return TRUE; +} + +static gboolean read_whole_file(Device * device, int fileno) { + int size = 0; + dumpfile_t * file = device_seek_file(device, fileno + 1); + int i; + char *buf; + + if (file == NULL) + g_assert_not_reached(); + else + amfree(file); + + g_return_val_if_fail(device_seek_block(device, 0), FALSE); + + g_return_val_if_fail(0 == device_read_block(device, NULL, &size), + FALSE); + g_assert(size >= blocksize); + + for (i = 0; i < 1000; i ++) { + int size, size2; + char buf2[blocksize]; + size2 = blocksize; + if (i == 999) + size = blocksize/2; + else + size = blocksize; + buf = make_rand_buf(size); + + g_return_val_if_fail(device_read_block(device, buf2, &size2), + FALSE); + g_assert(size2 == size || size2 == blocksize); + g_assert(memcmp(buf, buf2, size) == 0); + amfree(buf); + } + + size = blocksize; + buf = malloc(blocksize); + g_assert(-1 == device_read_block(device, &buf, &size)); + g_return_val_if_fail(device->is_eof, FALSE); + free(buf); + + return TRUE; +} + +static MediaAccessMode get_medium_type(Device * device) { + GValue value; + MediaAccessMode rval; + + bzero(&value, sizeof(value)); + + g_return_val_if_fail(device_property_get(device, PROPERTY_MEDIUM_TYPE, + &value), 0); + + rval = g_value_get_enum(&value); + g_value_unset(&value); + return rval; +} + +int main(int argc, char ** argv) { + Device * device; + int h; + MediaAccessMode medium_type; + + g_return_val_if_fail(argc == 2, 1); + + device_api_init(); + + device = device_open(argv[1]); + g_return_val_if_fail(device != NULL, 2); + + medium_type = get_medium_type(device); + + if (device->volume_label) { + printf("Last header: %s %s\n", device->volume_label, + device->volume_time); + } + + if (medium_type != MEDIA_ACCESS_MODE_READ_ONLY) { + g_return_val_if_fail(device_start(device, ACCESS_WRITE, + "foo", NULL), + 2); + + for (h = 0; h < 10; h ++) { + gboolean appendable; + GValue value; + g_return_val_if_fail(write_whole_file(device), 3); + + bzero(&value, sizeof(value)); + g_return_val_if_fail(device_property_get(device, + PROPERTY_APPENDABLE, + &value), 4); + appendable = g_value_get_boolean(&value); + g_value_unset(&value); + + if (appendable && h == 5) { + g_object_unref(device); + + device = device_open(argv[1]); + g_return_val_if_fail(device != NULL, 6); + + g_return_val_if_fail(device_start(device, ACCESS_APPEND, + "foo", NULL), + 2); + } + } + + g_object_unref(device); + + device = device_open(argv[1]); + g_return_val_if_fail(device != NULL, 6); + } + + /* Fixme: check for readable access mode. */ + if (medium_type != MEDIA_ACCESS_MODE_WRITE_ONLY) { + g_return_val_if_fail(device->volume_label, 7); + printf("This header: %s %s\n", device->volume_label, + device->volume_time); + + g_return_val_if_fail(device_start(device, ACCESS_READ, + "foo", NULL), + 2); + seed = 0; + for (h = 0; h < 10; h ++) { + g_return_val_if_fail(read_whole_file(device, h), 8); + } + } + + g_object_unref(device); + + return 0; +} diff --git a/device-src/tests/queue_test.c b/device-src/tests/queue_test.c new file mode 100644 index 0000000..f6cef95 --- /dev/null +++ b/device-src/tests/queue_test.c @@ -0,0 +1,21 @@ +#include +#include +#include + +int main(void) { + /* ignore SIGPIPE */ + signal(SIGPIPE, SIG_IGN); + + /* Comment out this line to disable threads. */ + device_api_init(); + + /* The integer here is the block size to use. Set it to something + * bigger for better performance. */ + return !do_consumer_producer_queue_full(fd_read_producer, + GINT_TO_POINTER(0), + fd_write_consumer, + GINT_TO_POINTER(1), + 1, /* Block size */ + 10, /* Buffer size. */ + STREAMING_REQUIREMENT_DESIRED); +} diff --git a/device-src/tests/semaphore-test.c b/device-src/tests/semaphore-test.c new file mode 100644 index 0000000..2e523c7 --- /dev/null +++ b/device-src/tests/semaphore-test.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include "semaphore.h" +#include "amanda.h" +#include "util.h" + +/* + * test that decrement waits properly + */ + +struct test_decr_wait_data { + semaphore_t *sem; + gboolean increment_called; +}; + +static gpointer +test_decr_wait_thread(gpointer datap) +{ + struct test_decr_wait_data *data = datap; + + /* should block */ + semaphore_decrement(data->sem, 20); + + /* if increment hasn't been called yet, that's an error. */ + if (!data->increment_called) + return GINT_TO_POINTER(0); + + return GINT_TO_POINTER(1); +} + +static gboolean +test_decr_wait(void) +{ + GThread *th; + struct test_decr_wait_data data = { NULL, FALSE }; + int rv; + + data.sem = semaphore_new_with_value(10), + + /* die after 10 seconds (default signal disposition is to fail) */ + alarm(10); + + th = g_thread_create(test_decr_wait_thread, (gpointer)&data, TRUE, NULL); + + /* sleep to give semaphore_decrement() a chance to block (or not). */ + g_usleep(G_USEC_PER_SEC / 4); + + /* and then increment the semaphore enough that the decrement can succeed */ + data.increment_called = TRUE; + semaphore_increment(data.sem, 10); + + /* join the thread and see how it fared. */ + rv = GPOINTER_TO_INT(g_thread_join(th)); + + semaphore_free(data.sem); + + if (rv == 1) { + printf(" PASS: semaphore-test.test_decr_wait\n"); + return TRUE; + } else { + printf(" FAIL: semaphore-test.test_decr_wait\n"); + return FALSE; + } +} + + +/* + * test that semaphore_wait_empty waits properly + */ + +static gpointer +test_wait_empty_thread(gpointer datap) +{ + semaphore_t *sem = datap; + + /* should block */ + semaphore_decrement(sem, 20); + + /* value should be 10 now (decremented from 30) */ + if (sem->value != 10) + return GINT_TO_POINTER(1); + + /* sleep for a bit */ + g_usleep(G_USEC_PER_SEC / 4); + + /* decrement those last 10, which should trigger the zero */ + semaphore_decrement(sem, 10); + + return GINT_TO_POINTER(0); +} + +static gboolean +test_wait_empty(void) +{ + GThread *th; + semaphore_t *sem = semaphore_new_with_value(10); + int rv; + + /* die after 10 seconds (default signal disposition is to fail) */ + alarm(10); + + th = g_thread_create(test_wait_empty_thread, (gpointer)sem, TRUE, NULL); + + /* sleep to give semaphore_decrement() a chance to block (or not). */ + g_usleep(G_USEC_PER_SEC / 4); + + /* add another 10, so decrement can hit zero next time it's called */ + semaphore_increment(sem, 10); + + /* and wait on the semaphore emptying */ + semaphore_wait_empty(sem); + + /* join the thread and see how it fared. */ + rv = GPOINTER_TO_INT(g_thread_join(th)); + + semaphore_free(sem); + + if (rv == 1) { + printf(" PASS: semaphore-test.test_wait_empty\n"); + return TRUE; + } else { + printf(" FAIL: semaphore-test.test_wait_empty\n"); + return FALSE; + } +} + +/* + * test that semaphore_force_adjust correctly wakes both + * semaphore_decrement and semaphore_wait_empty. + */ + +static gpointer +test_force_adjust_thread(gpointer datap) +{ + semaphore_t *sem = datap; + + /* this should block */ + semaphore_decrement(sem, 20); + + /* and this should block, too - it's fun */ + semaphore_wait_empty(sem); + + return NULL; +} + +static gboolean +test_force_adjust(void) +{ + GThread *th; + semaphore_t *sem = semaphore_new_with_value(10); + + /* die after 10 seconds (default signal disposition is to fail) */ + alarm(10); + + th = g_thread_create(test_force_adjust_thread, (gpointer)sem, TRUE, NULL); + + /* sleep to give semaphore_decrement() a chance to block (or not). */ + g_usleep(G_USEC_PER_SEC / 4); + + /* add another 20, so decrement can proceed, but leave the value at 10 */ + semaphore_force_adjust(sem, 20); + + /* sleep to give semaphore_wait_empty() a chance to block (or not). */ + g_usleep(G_USEC_PER_SEC / 4); + + /* and empty out the semaphore */ + semaphore_force_adjust(sem, -10); + + g_thread_join(th); + + semaphore_free(sem); + + /* it we didn't hang yet, it's all good */ + printf(" PASS: semaphore-test.test_force_adjust\n"); + return TRUE; +} + +/* + * test that semaphore_force_set correctly wakes both + * semaphore_decrement and semaphore_wait_empty. + */ + +static gpointer +test_force_set_thread(gpointer datap) +{ + semaphore_t *sem = datap; + + /* this should block */ + semaphore_decrement(sem, 20); + + /* and this should block, too - it's fun */ + semaphore_wait_empty(sem); + + return NULL; +} + +static gboolean +test_force_set(void) +{ + GThread *th; + semaphore_t *sem = semaphore_new_with_value(10); + + /* die after 10 seconds (default signal disposition is to fail) */ + alarm(10); + + th = g_thread_create(test_force_set_thread, (gpointer)sem, TRUE, NULL); + + /* sleep to give semaphore_decrement() a chance to block (or not). */ + g_usleep(G_USEC_PER_SEC / 4); + + /* set it to 30, so decrement can proceed, but leave the value at 10 */ + semaphore_force_set(sem, 30); + + /* sleep to give semaphore_wait_empty() a chance to block (or not). */ + g_usleep(G_USEC_PER_SEC / 4); + + /* and empty out the semaphore */ + semaphore_force_set(sem, 0); + + g_thread_join(th); + + semaphore_free(sem); + + /* it we didn't hang yet, it's all good */ + printf(" PASS: semaphore-test.test_force_set\n"); + return TRUE; +} + +/* + * Main loop + */ + +int +main(void) +{ + gboolean pass = TRUE; + +#if defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE) + amanda_thread_init(); + + pass = test_decr_wait() && pass; + pass = test_wait_empty() && pass; + pass = test_force_adjust() && pass; + pass = test_force_set() && pass; + + return pass?0:1; +#else + printf("No thread support on this platform -- nothing to test\n"); + return 0; +#endif +} diff --git a/device-src/tests/vfs_test.c b/device-src/tests/vfs_test.c new file mode 100644 index 0000000..b05ee78 --- /dev/null +++ b/device-src/tests/vfs_test.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include +#include +#include "util.h" + +/* global so the 'atexit' handler can access it */ + +static void +cleanup_vtape_dir(char *device_path) +{ + char *quoted = g_shell_quote(device_path); + char *cmd = vstralloc("rm -rf ", quoted, NULL); + + /* would you rather write 'rm -rf' here? */ + if (system(cmd) == -1) { + exit(1); + } + + amfree(cmd); + amfree(quoted); +} + +static char * +setup_vtape_dir(void) +{ + char *cwd = g_get_current_dir(); + char *device_path = NULL; + char *data_dir = NULL; + + device_path = vstralloc(cwd, "/vfs-test-XXXXXX", NULL); + amfree(cwd); + + if (mkdtemp(device_path) == NULL) { + fprintf(stderr, "Could not create temporary directory in %s\n", cwd); + return NULL; + } + + /* append "/data/" to that for the VFS device*/ + data_dir = vstralloc(device_path, "/data/", NULL); + if (mkdir(data_dir, 0777) == -1) { + fprintf(stderr, "Could not create %s: %s\n", cwd, strerror(errno)); + amfree(data_dir); + return NULL; + } + + amfree(data_dir); + return device_path; +} + +static Device * +setup_device(char *device_path) +{ + Device *device; + char *device_name = NULL; + + device_name = vstralloc("file:", device_path, NULL); + device = device_open(device_name); + if (!device) { + fprintf(stderr, "Could not open device %s\n", device_name); + } + + amfree(device_name); + return device; +} + +static gboolean +check_free_space(Device *device) +{ + GValue value; + QualifiedSize qsize; + + bzero(&value, sizeof(value)); + if (!device_property_get(device, PROPERTY_FREE_SPACE, &value)) { + fprintf(stderr, "Could not get property_free_space\n"); + return FALSE; + } + + qsize = *(QualifiedSize*)g_value_get_boxed(&value); + g_value_unset(&value); + + if (qsize.accuracy != SIZE_ACCURACY_REAL) { + fprintf(stderr, "property_free_space accuracy is not SIZE_ACCURACY_REAL\n"); + return FALSE; + } + + if (qsize.bytes == 0) { + fprintf(stderr, "property_free_space returned bytes=0\n"); + return FALSE; + } + + return TRUE; +} + +int +main(int argc G_GNUC_UNUSED, char **argv G_GNUC_UNUSED) +{ + Device *device = NULL; + gboolean ok = TRUE; + char *device_path = NULL; + pid_t pid; + amwait_t status; + + amanda_thread_init(); + + device_path = setup_vtape_dir(); + + /* run the tests in a subprocess so we can clean up even if they fail */ + switch (pid = fork()) { + case -1: /* error */ + perror("fork"); + g_assert_not_reached(); + + case 0: /* child */ + device_api_init(); + + device = setup_device(device_path); + if (!device) + return 1; + + ok = ok && check_free_space(device); + + g_object_unref(device); + + if (!ok) exit(1); + exit(0); + g_assert_not_reached(); + + default: /* parent */ + if (waitpid(pid, &status, 0) == -1) + perror("waitpid"); + + /* cleanup */ + cleanup_vtape_dir(device_path); + amfree(device_path); + + /* figure our own return status */ + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else if (WIFSIGNALED(status)) { + fprintf(stderr, "Test failed with signal %d\n", (int)WTERMSIG(status)); + return 1; + } else { + /* weird.. */ + return 1; + } + g_assert_not_reached(); + } +} diff --git a/device-src/vfs-device.c b/device-src/vfs-device.c new file mode 100644 index 0000000..a69b584 --- /dev/null +++ b/device-src/vfs-device.c @@ -0,0 +1,1269 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +#include /* memset() */ + +#include "amanda.h" +#include "vfs-device.h" +#include "fsusage.h" +#include "util.h" +#include + +/* This regex will match all VfsDevice files in a directory. We use it + for cleanup and verification. Note that this regex does NOT match + the volume label. */ +#define VFS_DEVICE_FILE_REGEX "^[0-9]+[\\.-]" + +/* The name of the volume lockfile. Should be the same as that + generated by lockfile_name(0). */ +#define VOLUME_LOCKFILE_NAME "00000-lock" + +/* Possible (abstracted) results from a system I/O operation. */ +typedef enum { + RESULT_SUCCESS, + RESULT_ERROR, /* Undefined error. */ + RESULT_NO_DATA, /* End of File, while reading */ + RESULT_NO_SPACE, /* Out of space. Sometimes we don't know if + it was this or I/O error, but this is the + preferred explanation. */ + RESULT_MAX +} IoResult; + +/* here are local prototypes */ +static void vfs_device_init (VfsDevice * o); +static void vfs_device_class_init (VfsDeviceClass * c); +static void vfs_device_finalize (GObject * o); + +static gboolean vfs_device_start(Device * pself, DeviceAccessMode mode, + char * label, char * timestamp); +static gboolean vfs_device_open_device (Device * pself, + char * device_name); +static gboolean vfs_device_start_file (Device * pself, const dumpfile_t * ji); +static gboolean vfs_device_finish_file (Device * pself); +static dumpfile_t * vfs_device_seek_file (Device * self, guint file); +static gboolean vfs_device_seek_block (Device * self, guint64 block); +static gboolean vfs_device_property_get (Device * pself, DevicePropertyId ID, + GValue * val); +static gboolean vfs_device_property_set (Device * pself, DevicePropertyId ID, + GValue * val); +static gboolean vfs_device_recycle_file (Device * pself, guint filenum); +static Device * vfs_device_factory(char * device_type, + char * device_name); +static ReadLabelStatusFlags vfs_device_read_label(Device * dself); +static gboolean vfs_device_write_block(Device * self, guint size, + gpointer data, gboolean last_block); +static int vfs_device_read_block(Device * self, gpointer data, int * size_req); +static IoResult vfs_device_robust_write(VfsDevice * self, char *buf, + int count); +static IoResult vfs_device_robust_read(VfsDevice * self, char *buf, + int *count); + +/* Various helper functions. */ +static void release_file(VfsDevice * self); +static gboolean check_is_dir(const char * name, gboolean printmsg); +static char* file_number_to_file_name(VfsDevice * self, guint file); +static gboolean file_number_to_file_name_functor(const char * filename, + gpointer datap); +//static char* lockfile_name(VfsDevice * self, guint file); +static gboolean open_lock(VfsDevice * self, int file, gboolean exclusive); +static void promote_volume_lock(VfsDevice * self); +static void demote_volume_lock(VfsDevice * self); +static gboolean delete_vfs_files(VfsDevice * self); +static gboolean delete_vfs_files_functor(const char * filename, + gpointer self); +static gboolean check_dir_empty_functor(const char * filename, + gpointer self); +static gboolean clear_and_prepare_label(VfsDevice * self, char * label, + char * timestamp); +static gint get_last_file_number(VfsDevice * self); +static gboolean get_last_file_number_functor(const char * filename, + gpointer datap); +static char * make_new_file_name(VfsDevice * self, const dumpfile_t * ji); +static gboolean try_unlink(const char * file); + +/* pointer to the classes of our parents */ +static DeviceClass *parent_class = NULL; + +void vfs_device_register(void) { + static const char * device_prefix_list[] = { "file", NULL }; + register_device(vfs_device_factory, device_prefix_list); +} + +GType +vfs_device_get_type (void) +{ + static GType type = 0; + + if G_UNLIKELY(type == 0) { + static const GTypeInfo info = { + sizeof (VfsDeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) vfs_device_class_init, + (GClassFinalizeFunc) NULL, + NULL /* class_data */, + sizeof (VfsDevice), + 0 /* n_preallocs */, + (GInstanceInitFunc) vfs_device_init, + NULL + }; + + type = g_type_register_static (TYPE_DEVICE, "VfsDevice", + &info, (GTypeFlags)0); + } + + return type; +} + +static void +vfs_device_init (VfsDevice * self) { + Device * o; + DeviceProperty prop; + GValue response; + + self->dir_handle = NULL; + self->dir_name = self->file_name = NULL; + self->file_lock_name = self->volume_lock_name = NULL; + self->file_lock_fd = self->volume_lock_fd = self->open_file_fd = -1; + self->block_size = VFS_DEVICE_DEFAULT_BLOCK_SIZE; + self->volume_bytes = 0; + self->volume_limit = 0; + + /* Register Properties */ + o = DEVICE(self); + bzero(&response, sizeof(response)); + prop.base = &device_property_concurrency; + prop.access = PROPERTY_ACCESS_GET_MASK; + g_value_init(&response, CONCURRENCY_PARADIGM_TYPE); + g_value_set_enum(&response, CONCURRENCY_PARADIGM_RANDOM_ACCESS); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_streaming; + g_value_init(&response, STREAMING_REQUIREMENT_TYPE); + g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_min_block_size; + g_value_init(&response, G_TYPE_UINT); + g_value_set_uint(&response, VFS_DEVICE_MIN_BLOCK_SIZE); + device_add_property(o, &prop, &response); + + prop.base = &device_property_max_block_size; + g_value_set_uint(&response, VFS_DEVICE_MAX_BLOCK_SIZE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + prop.base = &device_property_appendable; + g_value_init(&response, G_TYPE_BOOLEAN); + g_value_set_boolean(&response, TRUE); + device_add_property(o, &prop, &response); + + prop.base = &device_property_partial_deletion; + device_add_property(o, &prop, &response); + g_value_unset(&response); + + /* This one is handled by Device's get_property handler. */ + prop.base = &device_property_canonical_name; + device_add_property(o, &prop, NULL); + + prop.base = &device_property_medium_access_type; + g_value_init(&response, MEDIA_ACCESS_MODE_TYPE); + g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE); + device_add_property(o, &prop, &response); + g_value_unset(&response); + + /* These are dynamic, handled in vfs_device_property_xxx */ + prop.base = &device_property_block_size; + prop.access = PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START; + device_add_property(o, &prop, NULL); + + prop.base = &device_property_max_volume_usage; + prop.access = + (PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_MASK) & + (~ PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE); + device_add_property(o, &prop, NULL); +} + +static void +vfs_device_class_init (VfsDeviceClass * c G_GNUC_UNUSED) +{ + GObjectClass *g_object_class = (GObjectClass*) c; + DeviceClass *device_class = (DeviceClass *)c; + + parent_class = g_type_class_ref(TYPE_DEVICE); + + device_class->open_device = vfs_device_open_device; + device_class->start = vfs_device_start; + device_class->start_file = vfs_device_start_file; + device_class->read_label = vfs_device_read_label; + device_class->write_block = vfs_device_write_block; + device_class->read_block = vfs_device_read_block; + device_class->finish_file = vfs_device_finish_file; + device_class->seek_file = vfs_device_seek_file; + device_class->seek_block = vfs_device_seek_block; + device_class->property_get = vfs_device_property_get; + device_class->property_set = vfs_device_property_set; + device_class->recycle_file = vfs_device_recycle_file; + g_object_class->finalize = vfs_device_finalize; +} + +/* Drops everything associated with the volume file: Its name and fd, + its lock, and its lock's name and fd. */ +static void release_file(VfsDevice * self) { + /* Doesn't hurt. */ + robust_close(self->open_file_fd); + amfree(self->file_name); + + if (self->file_lock_fd > 0) { + amfunlock(self->file_lock_fd, self->file_lock_name); + close(self->file_lock_fd); + amfree(self->file_lock_name); + } + self->file_lock_fd = self->open_file_fd = -1; +} + +static void vfs_device_finalize(GObject * obj_self) { + VfsDevice *self = VFS_DEVICE (obj_self); + Device * d_self = (Device*)self; + + if (d_self->access_mode != ACCESS_NULL) { + device_finish(d_self); + } + + if(G_OBJECT_CLASS(parent_class)->finalize) + (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self); + + amfree(self->dir_name); + + if(self->dir_handle) { + closedir (self->dir_handle); + self->dir_handle = NULL; + } + + release_file(self); + + if (self->volume_lock_fd >= 0) { + amfunlock(self->volume_lock_fd, self->volume_lock_name); + close(self->volume_lock_fd); + } + + amfree(self->volume_lock_name); +} + +static Device * vfs_device_factory(char * device_type, + char * device_name) { + Device * rval; + g_assert(0 == strcmp(device_type, "file")); + rval = DEVICE(g_object_new(TYPE_VFS_DEVICE, NULL)); + if (!device_open_device(rval, device_name)) { + g_object_unref(rval); + return NULL; + } else { + return rval; + } +} + +static gboolean check_is_dir(const char * name, gboolean printmsg) { + struct stat dir_status; + + if (stat(name, &dir_status) < 0) { +#ifdef EINTR + if (errno == EINTR) { + return check_is_dir(name, printmsg); + } +#endif /* EINTR */ + if (printmsg) { + g_fprintf(stderr, "Error checking directory %s: %s\n", + name, strerror(errno)); + } + return FALSE; + } else if (!S_ISDIR(dir_status.st_mode)) { + if (printmsg) { + g_fprintf(stderr, "VFS Device path %s is not a directory.\n", + name); + } + return FALSE; + } else { + return TRUE; + } +} + +typedef struct { + VfsDevice * self; + int count; + char * result; +} fnfn_data; + +/* A SearchDirectoryFunctor. */ +static gboolean file_number_to_file_name_functor(const char * filename, + gpointer datap) { + char * result_tmp; + struct stat file_status; + fnfn_data *data = (fnfn_data*)datap; + + result_tmp = vstralloc(data->self->dir_name, "/", filename, NULL); + + /* Just to be thorough, let's check that it's a real + file. */ + if (0 != stat(result_tmp, &file_status)) { + g_fprintf(stderr, "Cannot stat file %s (%s), ignoring it.\n", + result_tmp, strerror(errno)); + } else if (!S_ISREG(file_status.st_mode)) { + g_fprintf(stderr, "%s is not a regular file, ignoring it.\n", + result_tmp); + } else { + data->count ++; + if (data->result == NULL) { + data->result = result_tmp; + result_tmp = NULL; + } + } + amfree(result_tmp); + return TRUE; +} + +/* This function finds the filename for a given file number. We search + * for a filesystem file matching the regex /^0*$device_file\./; if + * there is more than one such file we make a warning and take an + * arbitrary one. */ +static char * file_number_to_file_name(VfsDevice * self, guint device_file) { + char * regex; + fnfn_data data; + + g_return_val_if_fail(self != NULL, NULL); + data.self = self; + data.count = 0; + data.result = NULL; + + regex = g_strdup_printf("^0*%u\\.", device_file); + + search_directory(self->dir_handle, regex, + file_number_to_file_name_functor, &data); + + amfree(regex); + + if (data.count == 0) { + g_assert(data.result == NULL); + return NULL; + } else if (data.count > 1) { + g_fprintf(stderr, + "Found multiple names for file number %d, choosing file %s.\n", + device_file, data.result); + return data.result; + } else { + g_assert(data.result != NULL); + return data.result; + } + g_assert_not_reached(); +} + +/* This function returns the dynamically-allocated lockfile name for a + given file number. */ +/* +static char * lockfile_name(VfsDevice * self, guint number) { + return g_strdup_printf("%s/%05d-lock", self->dir_name, number); +} +*/ + +/* Does what you expect. If the lock already exists, it is released + * and regained, in case the mode is changing. + * The file field has several options: + * - file > 0: Open a lock on a real volume file. + * - file = 0: Open the volume lock as a volume file (for setup). + * - file < 0: Open the volume lock as a volume lock (persistantly). + */ +static gboolean open_lock(G_GNUC_UNUSED VfsDevice * self, + G_GNUC_UNUSED int file, + G_GNUC_UNUSED gboolean exclusive) { + + /* At the moment, file locking is horribly broken. */ + return TRUE; + +/* + int fd; + char * name; + if (file < 0) { + if (self->volume_lock_name == NULL) { + self->volume_lock_name = lockfile_name(self, 0); + } else if (self->volume_lock_fd >= 0) { + amfunlock(self->volume_lock_fd, self->volume_lock_name); + close(self->volume_lock_fd); + } + name = self->volume_lock_name; + } else { + if (self->file_lock_fd >= 0 && self->file_lock_name != NULL) { + amfunlock(self->file_lock_fd, self->file_lock_name); + } + amfree(self->file_lock_name); + close(self->file_lock_fd); + name = self->file_lock_name = lockfile_name(self, file); + } + + + fd = robust_open(name, O_CREAT | O_WRONLY, VFS_DEVICE_CREAT_MODE); + + if (fd < 0) { + g_fprintf(stderr, "Can't open lock file %s: %s\n", + name, strerror(errno)); + return FALSE; + } + + if (exclusive) { + amflock(fd, name); + } else { + amroflock(fd, name); + } + + if (file < 0) { + self->volume_lock_fd = fd; + } else { + self->file_lock_fd = fd; + } + return TRUE; +*/ +} + +/* For now, does it the bad way. */ +static void promote_volume_lock(VfsDevice * self) { + amfunlock(self->volume_lock_fd, self->volume_lock_name); + amflock(self->volume_lock_fd, self->volume_lock_name); +} + +static void demote_volume_lock(VfsDevice * self) { + amfunlock(self->volume_lock_fd, self->volume_lock_name); + amroflock(self->volume_lock_fd, self->volume_lock_name); +} + +/* A SearchDirectoryFunctor */ +static gboolean update_volume_size_functor(const char * filename, + gpointer user_data) { + char * full_filename; + struct stat stat_buf; + VfsDevice * self = user_data; + g_return_val_if_fail(IS_VFS_DEVICE(self), FALSE); + + full_filename = vstralloc(self->dir_name, "/", filename, NULL); + + if (stat(full_filename, &stat_buf) < 0) { + /* Log it and keep going. */ + g_fprintf(stderr, "Couldn't stat file %s: %s\n", + full_filename, strerror(errno)); + amfree(full_filename); + return TRUE; + } + + amfree(full_filename); + self->volume_bytes += stat_buf.st_size; + + return TRUE; +} + +static void update_volume_size(VfsDevice * self) { + self->volume_bytes = 0; + search_directory(self->dir_handle, "^[0-9]+\\.", + update_volume_size_functor, self); + +} + +static gboolean +vfs_device_open_device (Device * pself, char * device_name) { + VfsDevice * self; + dumpfile_t * rval; + + self = VFS_DEVICE(pself); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (device_name != NULL, FALSE); + + /* We don't have to free this ourselves; it will be freed by + * vfs_device_finalize whether we succeed here or not. */ + self->dir_name = g_strconcat(device_name, "/data/", NULL); + if (!check_is_dir(self->dir_name, TRUE)) { + return FALSE; + } + + /* Next open the directory itself. */ + self->dir_handle = opendir(self->dir_name); + if (self->dir_handle == NULL) { + g_fprintf(stderr, "Couldn't open directory %s for reading: %s\n", + device_name, strerror(errno)); + return FALSE; + } + + if (!open_lock(self, -1, FALSE)) + return FALSE; + + /* Not an error if this fails. Note that we ignore the class hierarchy. + */ + rval = vfs_device_seek_file(pself, 0); + amfree(rval); + + if (parent_class->open_device) { + /* Will call vfs_device_read_label. */ + return (parent_class->open_device)(pself, device_name); + } else { + return TRUE; + } +} + +/* A SearchDirectoryFunctor */ +static gboolean delete_vfs_files_functor(const char * filename, + gpointer user_data) { + VfsDevice * self; + char * path_name; + + self = VFS_DEVICE(user_data); + g_return_val_if_fail(self != NULL, FALSE); + + /* Skip the volume lock. */ + if (strcmp(filename, VOLUME_LOCKFILE_NAME) == 0) + return TRUE; + + path_name = vstralloc(self->dir_name, "/", filename, NULL); + if (unlink(path_name) != 0) { + g_fprintf(stderr, "Error unlinking %s: %s\n", path_name, + strerror(errno)); + } + amfree(path_name); + return TRUE; +} + +/* delete_vfs_files deletes all VfsDevice files in the directory except the + volume lockfile. */ +static gboolean delete_vfs_files(VfsDevice * self) { + g_assert(self != NULL); + g_assert(self->dir_handle != NULL); + + /* This function assumes that the volume is locked! */ + search_directory(self->dir_handle, VFS_DEVICE_FILE_REGEX, + delete_vfs_files_functor, self); + return TRUE; +} + +/* This is a functor suitable for search_directory. It simply prints a + warning. It also dodges the volume lockfile. */ +static gboolean check_dir_empty_functor(const char * filename, + gpointer user_data) { + VfsDevice * self; + char * path_name; + + self = VFS_DEVICE(user_data); + g_return_val_if_fail(self != NULL, FALSE); + + if (strcmp(filename, VOLUME_LOCKFILE_NAME) == 0) + return TRUE; + + path_name = vstralloc(self->dir_name, "/", filename, NULL); + + g_fprintf(stderr, "Found spurious storage file %s\n", path_name); + + amfree(path_name); + return TRUE; +} + +/* This function is used to write volume and dump headers. */ +static gboolean write_amanda_header(VfsDevice * self, + const dumpfile_t * header) { + char * label_buffer; + IoResult result; + + g_return_val_if_fail(header != NULL, FALSE); + g_return_val_if_fail(self != NULL, FALSE); + label_buffer = build_header(header, VFS_DEVICE_LABEL_SIZE); + if (strlen(label_buffer)+1 > VFS_DEVICE_LABEL_SIZE) { + amfree(label_buffer); + g_fprintf(stderr, "Amanda header header won't fit on VFS device!\n"); + return FALSE; + } + + result = vfs_device_robust_write(self, label_buffer, VFS_DEVICE_LABEL_SIZE); + amfree(label_buffer); + return (result == RESULT_SUCCESS); +} + +/* clear_and_label will erase the contents of the directory, and write + * this label in its place. This function assumes we already have a volume + * label write lock in place (e.g., promote_lock() has been called.) */ +static gboolean clear_and_prepare_label(VfsDevice * self, char * label, + char * timestamp) { + dumpfile_t * label_header; + + release_file(self); + + /* Delete any extant data, except our volume lock. */ + if (!delete_vfs_files(self)) { + return FALSE; + } + + /* Print warnings about any remaining files. */ + search_directory(self->dir_handle, VFS_DEVICE_FILE_REGEX, + check_dir_empty_functor, self); + + self->file_name = g_strdup_printf("%s/00000.%s", self->dir_name, label); + + self->open_file_fd = robust_open(self->file_name, + O_CREAT | O_EXCL | O_WRONLY, + VFS_DEVICE_CREAT_MODE); + if (self->open_file_fd < 0) { + g_fprintf(stderr, "Can't open file %s: %s\n", self->file_name, + strerror(errno)); + return FALSE; + } + + label_header = make_tapestart_header(DEVICE(self), label, timestamp); + if (write_amanda_header(self, label_header)) { + amfree(label_header); + self->volume_bytes = VFS_DEVICE_LABEL_SIZE; + return TRUE; + } else { + amfree(label_header); + return FALSE; + } +} + +static ReadLabelStatusFlags vfs_device_read_label(Device * dself) { + dumpfile_t * amanda_header; + VfsDevice * self; + + self = VFS_DEVICE(dself); + g_return_val_if_fail(self != NULL, ~READ_LABEL_STATUS_SUCCESS); + + amanda_header = vfs_device_seek_file(dself, 0); + if (amanda_header == NULL) { + /* This means an error occured getting locks or opening the header + * file. */ + return (READ_LABEL_STATUS_DEVICE_ERROR | + READ_LABEL_STATUS_VOLUME_ERROR | + READ_LABEL_STATUS_VOLUME_UNLABELED); + } + + if (amanda_header->type != F_TAPESTART) { + /* This is an error, and should not happen. */ + g_fprintf(stderr, "Got a bad volume label\n"); + amfree(amanda_header); + return READ_LABEL_STATUS_VOLUME_ERROR; + } + + dself->volume_label = g_strdup(amanda_header->name); + dself->volume_time = g_strdup(amanda_header->datestamp); + amfree(amanda_header); + + update_volume_size(self); + + if (parent_class->read_label) { + return (parent_class->read_label)(dself); + } else { + return READ_LABEL_STATUS_SUCCESS; + } +} + +static gboolean vfs_device_write_block(Device * pself, guint size, + gpointer data, gboolean last_block) { + VfsDevice * self = VFS_DEVICE(pself); + IoResult result; + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail(last_block || size >= (guint)self->block_size, FALSE); + g_return_val_if_fail(pself->in_file, FALSE); + g_assert(self->open_file_fd >= 0); + + if (self->volume_limit > 0 && + self->volume_bytes + size > self->volume_limit) { + /* Simulate EOF. */ + pself->is_eof = TRUE; + return FALSE; + } + + result = vfs_device_robust_write(self, data, size); + if (result == RESULT_SUCCESS) { + self->volume_bytes += size; + if (parent_class->write_block) { + (parent_class->write_block)(pself, size, data, last_block); + } + return TRUE; + } else { + return FALSE; + } +} + +static int +vfs_device_read_block(Device * pself, gpointer data, int * size_req) { + VfsDevice * self; + int size; + IoResult result; + + self = VFS_DEVICE(pself); + g_return_val_if_fail (self != NULL, -1); + + if (data == NULL || *size_req < self->block_size) { + /* Just a size query. */ + *size_req = self->block_size; + return 0; + } + + size = self->block_size; + result = vfs_device_robust_read(self, data, &size); + switch (result) { + case RESULT_SUCCESS: + *size_req = size; + return size; + case RESULT_NO_DATA: + pself->is_eof = TRUE; + pself->in_file = FALSE; + return -1; + default: + return -1; + } + + g_assert_not_reached(); +} + +static gboolean vfs_device_start(Device * pself, + DeviceAccessMode mode, char * label, + char * timestamp) { + VfsDevice * self; + self = VFS_DEVICE(pself); + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail(parent_class->start != NULL, FALSE); + + if (mode == ACCESS_WRITE) { + promote_volume_lock(self); + if (!clear_and_prepare_label(self, label, timestamp)) { + demote_volume_lock(self); + return FALSE; + } + demote_volume_lock(self); + } + + release_file(self); + + if (parent_class->start) { + return parent_class->start(pself, mode, label, timestamp); + } else { + return TRUE; + } +} + +typedef struct { + VfsDevice * self; + int rval; +} glfn_data; + +/* A SearchDirectoryFunctor. */ +static gboolean get_last_file_number_functor(const char * filename, + gpointer datap) { + guint64 file; + glfn_data * data = (glfn_data*)datap; + g_return_val_if_fail(IS_VFS_DEVICE(data->self), FALSE); + file = g_ascii_strtoull(filename, NULL, 10); /* Guaranteed to work. */ + if (file > G_MAXINT) { + g_fprintf(stderr, "Super-large device file %s found, ignoring.\n", + filename); + return TRUE; + } + /* This condition is needlessly complex due to sign issues. */ + if (data->rval < 0 || ((guint)data->rval) < file) { + data->rval = file; + } + return TRUE; +} + +static gint get_last_file_number(VfsDevice * self) { + glfn_data data; + int count; + data.self = self; + data.rval = -1; + + count = search_directory(self->dir_handle, "^[0-9]+\\.", + get_last_file_number_functor, &data); + + if (count <= 0) { + /* Somebody deleted something important while we weren't looking. */ + g_fprintf(stderr, "Error identifying VFS device contents!\n"); + return -1; + } else { + g_assert(data.rval >= 0); + } + + return data.rval; +} + +typedef struct { + VfsDevice * self; + guint request; + int best_found; +} gnfn_data; + +/* A SearchDirectoryFunctor. */ +static gboolean get_next_file_number_functor(const char * filename, + gpointer datap) { + guint file; + gnfn_data * data = (gnfn_data*)datap; + g_return_val_if_fail(IS_VFS_DEVICE(data->self), FALSE); + file = g_ascii_strtoull(filename, NULL, 10); /* Guaranteed to work. */ + if (file > G_MAXINT) { + g_fprintf(stderr, "Super-large device file %s found, ignoring.\n", + filename); + return TRUE; + } + /* This condition is needlessly complex due to sign issues. */ + if (file >= data->request && + (data->best_found < 0 || file < (guint)data->best_found)) { + data->best_found = file; + } + return TRUE; +} + +/* Returns the file number equal to or greater than the given requested + * file number. */ +static gint get_next_file_number(VfsDevice * self, guint request) { + gnfn_data data; + int count; + data.self = self; + data.request = request; + data.best_found = -1; + + count = search_directory(self->dir_handle, "^[0-9]+\\.", + get_next_file_number_functor, &data); + + if (count <= 0) { + /* Somebody deleted something important while we weren't looking. */ + g_fprintf(stderr, "Error identifying VFS device contents!\n"); + return -1; + } + + /* Could be -1. */ + return data.best_found; +} + +/* Finds the file number, acquires a lock, and returns the new file name. */ +static +char * make_new_file_name(VfsDevice * self, const dumpfile_t * ji) { + char * rval; + char *base, *sanitary_base; + int fileno; + + for (;;) { + fileno = 1 + get_last_file_number(self); + if (fileno <= 0) + return NULL; + + if (open_lock(self, fileno, TRUE)) { + break; + } else { + continue; + } + } + + /* record that we're at this filenum now */ + DEVICE(self)->file = fileno; + + base = g_strdup_printf("%05d.%s.%s.%d", fileno, ji->name, ji->disk, + ji->dumplevel); + sanitary_base = sanitise_filename(base); + amfree(base); + rval = g_strdup_printf("%s/%s", self->dir_name, sanitary_base); + amfree(sanitary_base); + return rval; +} + +static gboolean +vfs_device_start_file (Device * pself, const dumpfile_t * ji) { + VfsDevice * self; + + self = VFS_DEVICE(pself); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (ji != NULL, FALSE); + + if (self->volume_limit > 0 && + self->volume_bytes + VFS_DEVICE_LABEL_SIZE > self->volume_limit) { + /* No more room. */ + return FALSE; + } + + /* The basic idea here is thus: + 1) Try to get a lock on the next filenumber. + 2) If that fails, update our idea of "next filenumber" and try again. + 3) Then open the file itself. + 4) Write the label. + 5) Chain up. */ + + self->file_name = make_new_file_name(self, ji); + if (self->file_name == NULL) + return FALSE; + + self->open_file_fd = robust_open(self->file_name, + O_CREAT | O_EXCL | O_RDWR, + VFS_DEVICE_CREAT_MODE); + if (self->open_file_fd < 0) { + g_fprintf(stderr, "Can't create file %s: %s\n", self->file_name, + strerror(errno)); + release_file(self); + return FALSE; + } + + + if (!write_amanda_header(self, ji)) { + release_file(self); + return FALSE; + } + + self->volume_bytes += VFS_DEVICE_LABEL_SIZE; + /* make_new_file_name set pself->file for us, but the parent class will increment it, so decrement it now */ + pself->file--; + + if (parent_class->start_file) { + parent_class->start_file(pself, ji); + } + return TRUE; +} + +static gboolean +vfs_device_finish_file (Device * pself) { + VfsDevice * self; + self = VFS_DEVICE(pself); + g_return_val_if_fail(self != NULL, FALSE); + + release_file(self); + + if (parent_class->finish_file) { + return parent_class->finish_file(pself); + } else { + return TRUE; + } + g_assert_not_reached(); +} + +/* This function is used for two purposes, rather than one. In + * addition to its documented behavior, we also use it to open the + * volume label for reading at startup. In that second case, we avoid + * FdDevice-related side effects. */ +static dumpfile_t * +vfs_device_seek_file (Device * pself, guint requested_file) { + VfsDevice * self; + int file; + dumpfile_t * rval; + char header_buffer[VFS_DEVICE_LABEL_SIZE]; + int header_buffer_size = sizeof(header_buffer); + IoResult result; + + self = VFS_DEVICE(pself); + g_return_val_if_fail (self != NULL, NULL); + + pself->in_file = FALSE; + + release_file(self); + + if (requested_file > 0) { + file = get_next_file_number(self, requested_file); + } else { + file = requested_file; + } + + if (file < 0) { + /* Did they request one past the end? */ + char * tmp_file_name; + tmp_file_name = file_number_to_file_name(self, requested_file - 1); + if (tmp_file_name != NULL) { + free(tmp_file_name); + return make_tapeend_header(); + } else { + return NULL; + } + } + + if (!open_lock(self, file, FALSE)) { + return NULL; + } + + self->file_name = file_number_to_file_name(self, file); + if (self->file_name == NULL) { + release_file(self); + return NULL; + } + + self->open_file_fd = robust_open(self->file_name, O_RDONLY, 0); + if (self->open_file_fd <= 0) { + g_fprintf(stderr, "Couldn't open file %s: %s\n", self->file_name, + strerror(errno)); + amfree(self->file_name); + release_file(self); + return NULL; + } + + result = vfs_device_robust_read(self, header_buffer, + &header_buffer_size); + if (result != RESULT_SUCCESS) { + g_fprintf(stderr, "Problem reading Amanda header.\n"); + release_file(self); + return NULL; + } + + rval = malloc(sizeof(*rval)); + parse_file_header(header_buffer, rval, header_buffer_size); + if (file > 0) { + switch (rval->type) { + case F_DUMPFILE: + case F_CONT_DUMPFILE: + case F_SPLIT_DUMPFILE: + /* Chain up. */ + if (parent_class->seek_file) { + parent_class->seek_file(pself, file); + } + return rval; + default: + amfree(rval); + release_file(self); + return NULL; + } + } else if (file == 0) { + return rval; + } else { + amfree(rval); + return NULL; + } +} + +static gboolean +vfs_device_seek_block (Device * pself, guint64 block) { + VfsDevice * self; + off_t result; + + self = VFS_DEVICE(pself); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->open_file_fd >= 0, FALSE); + g_assert(sizeof(off_t) >= sizeof(guint64)); + + /* Pretty simple. We figure out the blocksize and use that. */ + result = lseek(self->open_file_fd, + (block) * self->block_size + VFS_DEVICE_LABEL_SIZE, + SEEK_SET); + return (result != (off_t)(-1)); +} + +static gboolean +vfs_device_property_get (Device * pself, DevicePropertyId ID, GValue * val) { + VfsDevice * self; + self = VFS_DEVICE(pself); + g_return_val_if_fail(self != NULL, FALSE); + if (ID == PROPERTY_BLOCK_SIZE) { + g_value_unset_init(val, G_TYPE_INT); + g_value_set_int(val, self->block_size); + return TRUE; + } else if (ID == PROPERTY_MAX_VOLUME_USAGE) { + g_value_unset_init(val, G_TYPE_UINT64); + g_value_set_uint64(val, self->volume_limit); + return TRUE; + } else if (ID == PROPERTY_FREE_SPACE) { + QualifiedSize qsize; + struct fs_usage fsusage; + guint64 bytes_avail; + + if (get_fs_usage(self->dir_name, NULL, &fsusage) == 0) { + if (fsusage.fsu_bavail_top_bit_set) + bytes_avail = 0; + else + bytes_avail = fsusage.fsu_bavail * fsusage.fsu_blocksize; + if (self->volume_limit && (guint64)self->volume_limit < bytes_avail / 1024) + bytes_avail = (guint64)self->volume_limit * 1024; + + qsize.accuracy = SIZE_ACCURACY_REAL; + qsize.bytes = bytes_avail; + } else { + g_warning(_("get_fs_usage('%s') failed: %s"), self->dir_name, strerror(errno)); + qsize.accuracy = SIZE_ACCURACY_UNKNOWN; + qsize.bytes = 0; + } + g_value_unset_init(val, QUALIFIED_SIZE_TYPE); + g_value_set_boxed(val, &qsize); + return TRUE; + } else { + if (parent_class->property_get) { + return parent_class->property_get(pself, ID, val); + } else { + return FALSE; + } + } + g_assert_not_reached(); +} + +static gboolean +vfs_device_property_set (Device * pself, DevicePropertyId ID, GValue * val) { + VfsDevice * self; + self = VFS_DEVICE(pself); + g_return_val_if_fail(self != NULL, FALSE); + if (ID == PROPERTY_BLOCK_SIZE) { + int block_size = g_value_get_int(val); + g_return_val_if_fail(block_size > 0, FALSE); + self->block_size = block_size; + return TRUE; + } else if (ID == PROPERTY_MAX_VOLUME_USAGE) { + self->volume_limit = g_value_get_uint64(val); + return TRUE; + } else { + if (parent_class->property_set) { + return parent_class->property_set(pself, ID, val); + } else { + return FALSE; + } + } + g_assert_not_reached(); +} + +static gboolean try_unlink(const char * file) { + if (unlink(file) < 0) { + g_fprintf(stderr, "Can't unlink file %s: %s\n", file, strerror(errno)); + return FALSE; + } else { + return TRUE; + } +} + +static gboolean +vfs_device_recycle_file (Device * pself, guint filenum) { + VfsDevice * self; + struct stat file_status; + off_t file_size; + + self = VFS_DEVICE(pself); + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail(!(pself->in_file), FALSE); + + /* Game Plan: + * 1) Get a write lock on the file in question. + * 2) Unlink the file in question. + * 3) Unlink the lock. + * 4) Release the lock. + * FIXME: Is it OK to unlink the lockfile? + */ + + self->file_name = file_number_to_file_name(self, filenum); + + if (self->file_name == NULL) + return FALSE; + + if (!open_lock(self, filenum, TRUE)) + return FALSE; + + if (0 != stat(self->file_name, &file_status)) { + fprintf(stderr, "Cannot stat file %s (%s), so not removing.\n", + self->file_name, strerror(errno)); + return FALSE; + } + file_size = file_status.st_size; + + if (!try_unlink(self->file_name) || + !try_unlink(self->file_lock_name)) { + release_file(self); + return FALSE; + } + + self->volume_bytes -= file_size; + release_file(self); + return TRUE; +} + +static IoResult vfs_device_robust_read(VfsDevice * self, char *buf, + int *count) { + int fd = self->open_file_fd; + int want = *count, got = 0; + + while (got < want) { + int result; + result = read(fd, buf + got, want - got); + if (result > 0) { + got += result; + } else if (result == 0) { + /* end of file */ + if (got == 0) { + return RESULT_NO_DATA; + } else { + *count = got; + return RESULT_SUCCESS; + } + } else if (0 +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef EINTR + || errno == EINTR +#endif + ) { + /* Try again. */ + continue; + } else { + /* Error occured. */ + g_fprintf(stderr, "Error reading fd %d: %s\n", fd, strerror(errno)); + *count = got; + return -1; + } + } + + *count = got; + return RESULT_SUCCESS; +} + +static IoResult +vfs_device_robust_write(VfsDevice * self, char *buf, int count) { + int fd = self->open_file_fd; + int rval = 0; + + while (rval < count) { + int result; + result = write(fd, buf + rval, count - rval); + if (result > 0) { + rval += result; + continue; + } else if (0 +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef EINTR + || errno == EINTR +#endif + ) { + /* Try again. */ + continue; + } else if (0 +#ifdef EFBIG + || errno == EFBIG +#endif +#ifdef ENOSPC + || errno == ENOSPC +#endif + ) { + /* We are definitely out of space. */ + return RESULT_NO_SPACE; + } else { + /* Error occured. Note that here we handle EIO as an error. */ + g_fprintf(stderr, "Error writing device fd %d: %s\n", + fd, strerror(errno)); + + return RESULT_ERROR; + } + } + return RESULT_SUCCESS; +} diff --git a/device-src/vfs-device.h b/device-src/vfs-device.h new file mode 100644 index 0000000..6b5796f --- /dev/null +++ b/device-src/vfs-device.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +/* The VFS device is the driver formerly known as the vtape driver or + * the file driver. It uses a directory on the UNIX filesystem as a + * data store. */ + +#include +#include +#include "device.h" +#include + +#ifndef VFS_DEVICE_H +#define VFS_DEVICE_H + +#define VFS_DEVICE_MIN_BLOCK_SIZE (1) +#define VFS_DEVICE_MAX_BLOCK_SIZE (INT_MAX) +#define VFS_DEVICE_DEFAULT_BLOCK_SIZE (MAX_TAPE_BLOCK_BYTES) +#define VFS_DEVICE_LABEL_SIZE (32768) + +/* This looks dangerous, but is actually modified by the umask. */ +#define VFS_DEVICE_CREAT_MODE 0666 + +/* + * Type checking and casting macros + */ +#define TYPE_VFS_DEVICE (vfs_device_get_type()) +#define VFS_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), vfs_device_get_type(), VfsDevice) +#define VFS_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), vfs_device_get_type(), VfsDevice const) +#define VFS_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), vfs_device_get_type(), VfsDeviceClass) +#define IS_VFS_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), vfs_device_get_type ()) + +#define VFS_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), vfs_device_get_type(), VfsDeviceClass) + +/* + * Main object structure + */ +typedef struct { + Device __parent__; + + /*< private >*/ + DIR * dir_handle; + char * dir_name; + char * file_name; + int file_lock_fd; + char * file_lock_name; + int volume_lock_fd; + char * volume_lock_name; + int open_file_fd; + + /* Properties */ + int block_size; + guint64 volume_bytes; + guint64 volume_limit; +} VfsDevice; + +/* + * Class definition + */ +typedef struct { + DeviceClass __parent__; +} VfsDeviceClass; + + +/* + * Public methods + */ +GType vfs_device_get_type (void); +void vfs_device_register (void); + +#endif + diff --git a/dumper-src/amgtar.pl b/dumper-src/amgtar.pl new file mode 100644 index 0000000..8fe9024 --- /dev/null +++ b/dumper-src/amgtar.pl @@ -0,0 +1,326 @@ +#!@PERL@ -T +# + +# Run perl. +eval '(exit $?0)' && eval 'exec @PERL@ -S $0 ${1+"$@"}' + & eval 'exec @PERL@ -S $0 $argv:q' + if 0; + +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'}; +$ENV{'PATH'} = "/usr/bin:/usr/sbin:/sbin:/bin"; + +$debug=1; +push(@INC, ".", "@DUMPER_DIR@"); + +use File::Copy; +use IPC::Open3; +use Sys::Hostname; + + +open(DEBUG,">>@AMANDA_DBGDIR@/amgtar.$$.debug") if ($debug==1); + +$prefix='@prefix@'; +$prefix = $prefix; +$exec_prefix="@exec_prefix@"; +$exec_prefix=$exec_prefix; +$amlibexecdir="@amlibexecdir@"; +$amlibexecdir=$amlibexecdir; + +$USE_VERSION_SUFFIXES='@USE_VERSION_SUFFIXES@'; +$suf = ''; +if ( $USE_VERSION_SUFFIXES =~ /^yes$/i ) { + $suf='-@VERSION@'; +} + +$myhost = hostname; +$myhost =~ s/\..*$//; +$runtar="${amlibexecdir}/runtar${suf}"; +$gnulist = '@GNUTAR_LISTED_INCREMENTAL_DIR@'; +$gnutar = '@GNUTAR@'; + + + +$max_level = 9; +$index_line = 1; +$index_xml = 0; +$message_line = 1; +$message_xml = 0; +$record = 1; +$include_file = 1; +$include_list = 1; +$exclude_file = 1; +$exclude_list = 1; +$collection = 0; + +#$user_support = ""; +#$group_support = ""; + +#$user_selfcheck = ""; +#$group_selfcheck = ""; + +#$user_estimate = ""; +#$group_estimate = ""; + +#$user_estimate_parse = ""; +#$group_estimate_parse = ""; + +$user_backup = "root"; +#$group_backup = ""; + +#$user_backup_parse = ""; +#$group_backup_parse = ""; + +#$user_index_from_output = ""; +#$group_index_from_output = ""; + +#$user_index_from_image = ""; +#$group_index_from_image = ""; + +#$user_restore = ""; +#$group_restore = ""; + +#$user_print_command = ""; +#$group_print_command = ""; + +$user_default = "amanda"; +$group_default = "amanda"; + + +sub command_support { + my($config, $host, $disk, $device, $level) = @_; + print "CONFIG YES\n"; + print DEBUG "STDOUT: CONFIG YES\n" if ($debug == 1); + print "HOST YES\n"; + print DEBUG "STDOUT: HOST YES\n" if ($debug == 1); + print "DISK YES\n"; + print DEBUG "STDOUT: DISK YES\n" if ($debug == 1); + print "MAX-LEVEL 9\n"; + print DEBUG "STDOUT: MAX-LEVEL 9\n" if ($debug == 1); + print "INDEX-LINE YES\n"; + print DEBUG "STDOUT: INDEX-LINE YES\n" if ($debug == 1); + print "INDEX-XML NO\n"; + print DEBUG "STDOUT: INDEX-XML NO\n" if ($debug == 1); + print "MESSAGE-LINE YES\n"; + print DEBUG "STDOUT: MESSAGE-LINE YES\n" if ($debug == 1); + print "MESSAGE-XML NO\n"; + print DEBUG "STDOUT: MESSAGE-XML NO\n" if ($debug == 1); + print "RECORD YES\n"; + print DEBUG "STDOUT: RECORD YES\n" if ($debug == 1); + print "INCLUDE-FILE YES\n"; + print "INCLUDE-LIST YES\n"; + print "EXCLUDE-FILE YES\n"; + print "EXCLUDE-LIST YES\n"; + print "COLLECTION NO\n"; +} + +sub command_selfcheck { + my($config, $host, $disk, $device, $level) = @_; + print DEBUG "STDOUT: OK $disk\n" if ($debug == 1); + print DEBUG "STDOUT: OK $device\n" if ($debug == 1); + print "OK $disk\n"; + print "OK $device\n"; + #check binary + #check statefile + #check amdevice + #check property include/exclude +} + +sub command_estimate { + my($config, $host, $disk, $device, $level) = @_; + my($listdir) = "$host$disk"; + $listdir =~ s/\//_/g; + if($level == 0) { + open(GNULIST, ">${gnulist}/${listdir}_${level}.new") || die(); + close(GNULIST) || die(); + } + else { + my($prev_level) = $level - 1; + if (-f "${gnulist}/${listdir}_${prev_level}") { + copy("${gnulist}/${listdir}_${prev_level}", "${gnulist}/${listdir}_${level}.new"); + } else { + open(GNULIST, ">${gnulist}/${listdir}_${level}.new") || die(); + close(GNULIST) || die(); + #print "ERROR file ${gnulist}/${listdir}_${level}.new doesn't exist\n"; + } + } + command_estimate_opt_direct($config, $host, $disk, $device, $level, $listdir); +} + + +sub command_estimate_opt_direct { + my($config, $host, $disk, $device, $level, $listdir) = @_; + my($size) = -1; + my(@cmd) = ($runtar, $config, $gnutar, "--create", "--directory", $device, "--listed-incremental", "${gnulist}/${listdir}_${level}.new", "--sparse", "--one-file-system", "--ignore-failed-read", "--totals", "--file", "/dev/null", "."); + #my(@cmd) = ($gnutar, "--create", "--directory", $device, "--listed-incremental", "${gnulist}/${listdir}_${level}.new", "--sparse", "--one-file-system", "--ignore-failed-read", "--totals", "--file", "/dev/null", "."); + print DEBUG "cmd:" , join(" ", @cmd), "\n" if ($debug == 1); + open3(\*WTRFH, '>&STDOUT', \*ESTIMATE, @cmd); + + $size = parse_estimate(ESTIMATE); + close(ESTIMATE); + output_size($size); + unlink "${gnulist}/${listdir}_${level}.new"; + exit 0; +} + +sub parse_estimate { + my($fh) = @_; + my($size) = -1; + while(<$fh>) { +print DEBUG "READ 2: $_" if ($debug == 1); + if ($_ =~ /^Total bytes written: (\d*)/) { + $size = $1; + last; + } + } + return $size; +} + +sub output_size { + my($size) = @_; + if($size == -1) { + print DEBUG "STDOUT A: -1 -1\n" if ($debug == 1); + print "-1 -1\n"; + exit 2; + } + else { + my($ksize) = int $size / (1024); + $ksize=32 if ($ksize<32); + print DEBUG "STDOUT B: $ksize 1\n" if ($debug == 1); + print "$ksize 1\n"; + } +} + +sub command_backup { + my($config, $host, $disk, $device, $level) = @_; + my($listdir) = "$host$disk"; + my($verbose) = ""; + $listdir =~ s/\//_/g; + +print DEBUG "config =" . $config . "\n" if ($debug == 1); +print DEBUG "host =" . $host . "\n" if ($debug == 1); +print DEBUG "disk =" . $disk . "\n" if ($debug == 1); +print DEBUG "device =" . $device . "\n" if ($debug == 1); +print DEBUG "level =" . $level . "\n" if ($debug == 1); + + if($level == 0) { + open(GNULIST, ">${gnulist}/${listdir}_${level}.new") || die(); + close(GNULIST) || die(); + } + else { + my($prev_level) = $level - 1; + copy("${gnulist}/${listdir}_${prev_level}", + "${gnulist}/${listdir}_${level}.new"); + } + + if(defined($opt_index)) { + $verbose = "--verbose"; + } + my(@cmd) = ($runtar, $config, $gnutar, "--create", $verbose, "--directory", $device, "--listed-incremental", "${gnulist}/${listdir}_${level}.new", "--sparse", "--one-file-system", "--ignore-failed-read", "--totals", "--file", "-", "."); + #my(@cmd) = ($gnutar, "--create", $verbose, "--directory", $device, "--listed-incremental", "${gnulist}/${listdir}_${level}.new", "--sparse", "--one-file-system", "--ignore-failed-read", "--totals", "--file", "-", "."); + + print DEBUG "cmd:" , join(" ", @cmd), "\n" if ($debug == 1); + + open3(\*WTRFH, '>&STDOUT', \*INDEX, @cmd) || die(); + + if(defined($opt_index)) { + open(INDEXOUT, '>&=3') || die(); + parse_backup(INDEX, STDERR, INDEXOUT); + close(INDEXOUT); + } + else { + parse_backup(INDEX, STDERR, undef); + } + close(INDEX); + close(WTRFH); + + if(defined($opt_record)) { + rename "${gnulist}/${listdir}_${level}.new", + "${gnulist}/${listdir}_${level}"; + } + else { + unlink "${gnulist}/${listdir}_${level}.new"; + } + exit 0; +} + +sub parse_backup { + my($fhin, $fhout, $indexout) = @_; + my($size) = -1; + while(<$fhin>) { +print DEBUG "READ 3: $_" if ($debug == 1); + if ( /^\.\//) { + if(defined($indexout)) { + if(defined($opt_index)) { + s/^\.//; +print DEBUG "INDEXOUT: $_" if ($debug == 1); + print $indexout $_; + } + } + } + else { + if (/^Total bytes written: (\d*)/) { + $size = $1; + $ksize = int ($size / 1024); + } + elsif(defined($fhout)) { + next if /: Directory is new$/; +print DEBUG "FHOUT 2: $_" if ($debug == 1); + print $fhout $_; + } + } + } + if(defined($fhout)) { + if ($size == -1) { +print DEBUG "FHOUT 4: $command -1 -1\n" if ($debug == 1); + print $fhout "$command -1 -1\n"; + } + else { + my($ksize) = int ($size/1024); +print DEBUG "FHOUT 5: sendbackup: size $ksize\n" if ($debug == 1); + print $fhout "sendbackup: size $ksize\n"; +print DEBUG "FHOUT 5: sendbackup: end\n" if ($debug == 1); + print $fhout "sendbackup: end\n"; + } + } +} + +sub command_index_from_output { + index_from_output(STDIN, STDOUT); + exit 0; +} + +sub index_from_output { + my($fhin, $fhout) = @_; + my($size) = -1; + while(<$fhin>) { +print DEBUG "READ 4: $_" if ($debug == 1); + next if /^Total bytes written:/; + next if !/^\.\//; + s/^\.//; +print DEBUG "FHOUT 6: $_" if ($debug == 1); + print $fhout $_; + } +} + +sub command_index_from_image { + my($config, $host, $disk, $device, $level) = @_; + open(INDEX, "$gnutar --list --file - |") || die(); + index_from_output(INDEX, STDOUT); +} + +sub command_restore { + my($config, $host, $disk, $device, $level) = @_; + +# $ARGV[0] = undef; + my(@cmd) = ($gnutar, "--numeric-owner", "-xpGvf", "-"); + for($i=1;defined $ARGV[$i]; $i++) { + push @cmd, $ARGV[$i]; + } + print DEBUG "cmd:" , join(" ", @cmd), "\n" if ($debug == 1); + exec @cmd; +} + +sub command_print_command { +} + +require "generic-dumper" diff --git a/dumper-src/generic-dumper.pl b/dumper-src/generic-dumper.pl new file mode 100644 index 0000000..f1fc6d3 --- /dev/null +++ b/dumper-src/generic-dumper.pl @@ -0,0 +1,273 @@ +require "newgetopt.pl"; +use Text::ParseWords; + +print DEBUG "FHOUT 6: ARGV[0]=" . $ARGV[0] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[1]=" . $ARGV[1] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[2]=" . $ARGV[2] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[3]=" . $ARGV[3] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[4]=" . $ARGV[4] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[5]=" . $ARGV[5] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[6]=" . $ARGV[6] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[7]=" . $ARGV[7] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[8]=" . $ARGV[8] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: ARGV[9]=" . $ARGV[9] . "\n" if ($debug == 1); + +$result = &NGetOpt ("config=s", "host=s", "disk=s", "device=s", "level=s", "index=s", "message=s", "collection", "record"); +$result = $result; + +print DEBUG "FHOUT 6: config =" . $opt_config . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: disk =" . $opt_disk . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: host =" . $opt_host . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: device =" . $opt_device . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: level =" . $opt_level . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: index =" . $opt_index . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: message =" . $opt_message. "\n" if ($debug == 1); +print DEBUG "FHOUT 6: collection=" . $opt_collection. "\n" if ($debug == 1); +print DEBUG "FHOUT 6: record =" . $opt_record . "\n" if ($debug == 1); + +print DEBUG "FHOUT 6: A-ARGV[0]=" . $ARGV[0] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: A-ARGV[1]=" . $ARGV[1] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: A-ARGV[2]=" . $ARGV[2] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: A-ARGV[3]=" . $ARGV[3] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: A-ARGV[4]=" . $ARGV[4] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: A-ARGV[5]=" . $ARGV[5] . "\n" if ($debug == 1); +print DEBUG "FHOUT 6: A-ARGV[6]=" . $ARGV[6] . "\n" if ($debug == 1); + +if (defined $opt_config) { + $opt_config =~ /^([\_\.A-Za-z0-9]*)$/; + $opt_config = $1; +} + +if (defined $opt_host) { + $opt_host =~ /^([\_\.A-Za-z0-9]*)$/; + $opt_host = $1; +} + +if (defined $opt_disk) { + $opt_disk =~ /^([\/\_\:\.A-Za-z0-9]*)$/; + $opt_disk = $1; +} + +if (defined $opt_device) { + $opt_device =~ /^([\/\_\:\.A-Za-z0-9]*)$/; + $opt_device = $1; +} + +if (defined $opt_level) { + $opt_level =~ /^(\d)$/; + $opt_level = $1; +} + +# Read tool property + +$command = $ARGV[0]; + +%property = (); +while($property_line = ) { + chomp $property_line; + ($prop_name, $prop_value) = shellwords($property_line); + push @{$property{$prop_name}}, $prop_value; + print DEBUG "$prop_name = $prop_value\n" if ($debug == 1); +} + +if ($debug == 1) { + foreach $prop_name (keys(%property)) { + print DEBUG "PROPERTY: $prop_name\n"; + print DEBUG " VALUE: ", join(',',@{$property{$prop_name}}) , "\n"; + } +} + +sub wrapper_support(); +sub wrapper_selfcheck(); +sub wrapper_estimate(); +sub wrapper_backup(); +sub wrapper_restore(); + +if ($command eq "support") { + wrapper_support(); +} +elsif ($command eq "selfcheck") { + wrapper_selfcheck(); +} +elsif ($command eq "estimate") { + wrapper_estimate(); +} +elsif ($command eq "backup") { + wrapper_backup(); +} +elsif ($command eq "restore") { + wrapper_restore(); +} +else { + printf STDERR "Unknown command `$command'.\n"; + exit 1; +} + + +sub wrapper_support() { + if(defined(&command_support)) { + command_support($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + exit 0; + } + print "LEVEL 0-", $max_level , "\n" if defined($max_level); + print "INDEX-LINE YES\n" if defined($index_line) && $index_line == 1; + print "INDEX-XML NO\n" if defined($index_xml) && $index_xml == 1; + print "MESSAGE-LINE YES\n" if defined($message_line) && $message_line == 1; + print "MESSAGE-XML NO\n" if defined($message_xml) && $message_xml == 1; + print "RECORD YES\n" if defined($record) && $record == 1; + print "INCLUDE-FILE NO\n" if defined($include_file) && $include_file == 1; + print "INCLUDE-LIST NO\n" if defined($include_list) && $include_list == 1; + print "EXCLUDE-FILE NO\n" if defined($exclude_file) && $exclude_file == 1; + print "EXCLUDE-LIST NO\n" if defined($exclude_list) && $exclude_list == 1; + print "COLLECTION NO\n" if defined($collection) && $collection == 1; + exit 1; +} + +sub wrapper_selfcheck() { + if(defined(&command_selfcheck)) { + command_selfcheck($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } + else { + exit 1; + } +} + +sub wrapper_estimate() { + if(defined(&command_estimate)) { + command_estimate($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } else { + exit 1; + } +} + +sub wrapper_estimate_parse() { + if(defined(&command_estimate_parse)) { + command_estimate_parse($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } + else { + printf STDERR "`estimate-parse' is not supported.\n"; + exit 1; + } +} + +sub wrapper_backup() { + if(defined(&command_backup)) { + command_backup($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } else { +print DEBUG "wrapper_backup: !defined(command_backup)\n" if ($debug == 1); + exit 1; + } +} + +sub wrapper_backup_parse() { + if(defined(&command_backup_parse)) { + command_backup_parse($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } + else { + printf STDERR "`backup-parse' is not supported.\n"; + exit 1; + } +} + +sub wrapper_index_from_output() { + if(defined(&command_index_from_output)) { + command_index_from_output($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } + else { + printf STDERR "`index-from-output' is not supported.\n"; + exit 1; + } +} + +sub wrapper_index_from_image() { + if(defined(&command_index_from_image)) { + command_index_from_image($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } + else { + printf STDERR "command `index-from-image' is not supported.\n"; + exit 1; + } +} + +sub wrapper_restore() { + if(defined(&command_restore)) { + command_restore($opt_config, $opt_host, $opt_disk, $opt_device, $opt_level); + } + else { + printf STDERR "`restore' is not supported.\n"; + exit 1; + } +} + +sub parse_options() { + my($no_option) = @_; + my($options, @options, $option, $name, $option_name, $value); + + while($no_option <= $#ARGV) { + $options = $ARGV[${no_option}]; + @options = split (/;/,$options); + foreach $option (@options) { + if( $option =~ /=/ ) { + ($name,$value) = split(/=/,$option); + } + else { + $name = $option; + $value = 1; + } + $option_name = "option_$name"; + $option_name =~ s/\-/\_/g; + $$option_name = $value; + } + $no_option++; + } +} + +sub check_file { + my($filename, $mode) = @_; + + stat($filename); + + if($mode eq "e") { + if( -e _ ) { + print "OK $filename exists\n"; + } + else { + print "ERROR [can not find $filename]\n"; + } + } + elsif($mode eq "x") { + if( -x _ ) { + print "OK $filename executable\n"; + } + else { + print "ERROR [can not execute $filename]\n"; + } + } + elsif($mode eq "r") { + if( -r _ ) { + print "OK $filename readable\n"; + } + else { + print "ERROR [can not read $filename]\n"; + } + } + elsif($mode eq "w") { + if( -w _ ) { + print "OK $filename writable\n"; + } + else { + print "ERROR [can not write $filename]\n"; + } + } + else { + print "ERROR [check_file: unknow mode $mode]\n"; + } +} + +sub check_dir { +} + +sub check_suid { +} + +1; diff --git a/example/DLT-A4.ps b/example/DLT-A4.ps new file mode 100644 index 0000000..fed0893 --- /dev/null +++ b/example/DLT-A4.ps @@ -0,0 +1,263 @@ +%! +%%BoundingBox: 0 0 595 842 +%%Title: AMANDA ExaLabel +%%Pages: 1 +%%EndComments + +%%%% +%%%% This is a template file used by AMANDA to create PostScript tape +%%%% labels for each dump. This file is set up for DAT 4mm tapes, +%%%% but you can edit it to work with anything. +%%%% +%%%% NOTE: this is quick-hack for DAT TAPES; it is simply a scaled +%%%% version of the Exabyte version. +%%%% + +% +% The label is made up of 6 parts: statistics, tape name, date, +% header, filesystem list, and the logo. Geometrically, the label +% looks like this: +% +% +------------------------+ +% |statistics | <- section 'A' +% +----+-------------------+ +% |logo| TAPE_NAME | <- section 'B' (logo) <- section 'F' +% | | version date | <- section 'C' +% +----+--+--------+-------+ +% | h fs l | h fs l | <- section 'D' +% +-------+--------+-------+ +% | | | <- section 'E' +% | | | +% v v v +% +% Sections D and E, which hold the bulk of the information are +% cut into columns. +% + +% Quick-hack for DAT tapes +% + +72 25.4 div dup scale %% scale to millimeters + +% section 'A' font, start position, and line separation +% +/StatFont { /Courier findfont 4.5 scalefont setfont } def +/StatPos { 30 255 } def +/StatSep { 4 } def + +% section 'B' font and position (text centered around this point) +% +/TitleFont { /Helvetica-Bold findfont 10 scalefont setfont } def +/TitlePos { 115 230 } def + +% section 'C' font, position of the date (left justified) and the version +% +/DateFont { /Palatino-Bold findfont 5 scalefont setfont } def +/DatePos { 190 222 } def +/VersFont { /Palatino-Bold findfont 5 scalefont setfont } def +/VersPos { 43 222 } def + +% section 'D' font, and field positions (x coord is relative to each column) +% + +/HeadingFont { /Palatino-Bold findfont 5 scalefont setfont } def +/HeadingHostPos { 1 212 } def +/HeadingFsPos { 17 212 } def +/HeadingLvlPos { 57 212 } def + +% section 'E' font, and line separation +% +/HostFont { /Courier findfont 2.6 scalefont setfont } def +/HostSep { 2.5 } def + + +% the following rectangles separate the regions +% +/StatBox { 200 260 15 240 } def +/TitleBox { 200 240 15 220 } def +/LogoBox { 35 240 15 220 } def +/HeadingBox { 200 220 15 210 } def +/HostBox { 200 210 15 0 } def +% Punckmark marks center of page height to aid punching holes for ring binder +/PunchMark { 13 130 15 130 } def + +% number of columns for section 'E,' column width, position of first +% entry in first column, y coordinate of top and bottom of dividing lines +% +/NumColumns { 3 } def +/ColumnWidth { 60 } def +/ColumnBasePos { 16 200 } def +/TopColDivLine { 201 } def +/BotColDivLine { 2 } def + +% 5 + +%%%% +%%%% END OF USER-CONFIGURABLE OPTIONS +%%%% +%%%% the rest of this file contains the internal functions that are used +%%%% by genlabel to draw the label +%%%% + + +% +% Initial Setup... draws everything that is the same for all labels +% + +% function to draw a box +% +/box { + /ury exch def + /urx exch def + /lly exch def + /llx exch def + + llx lly moveto + llx ury lineto + urx ury lineto + urx lly lineto + closepath +} def + + +% move the origin up a bit +% +0 19 translate + +% draw all of the boxes +% +0 setgray +.3 setlinewidth % thick lines +StatBox box stroke +TitleBox box stroke +LogoBox box stroke +HeadingBox box stroke +HostBox box stroke +% and the PunchMark to aid puching ring binder holes +PunchMark box stroke + +% draw the column dividers +% +0.2 setlinewidth % thin lines +/i 1 def +{ + NumColumns i sub 0 le { exit } if % no lines if this last col. + /xoff ColumnBasePos pop % get x base position + i ColumnWidth mul add def % offset for this column + xoff TopColDivLine moveto + xoff BotColDivLine lineto stroke + /i i 1 add def +} loop + + +% draw the heading names +% +/i 0 def +HeadingFont +{ + NumColumns i sub 0 le { exit } if + /xoff ColumnBasePos pop + i ColumnWidth mul add def + HeadingHostPos exch xoff add exch moveto + (Host) show + HeadingFsPos exch xoff add exch moveto + (Fs) show + HeadingLvlPos exch xoff add exch moveto + (*) show + /i i 1 add def +} loop + + +% +% the following functions draw strings for each kind of information +% + +/CurrStatY StatPos exch pop def +ColumnBasePos /CurrColumnY exch def + /CurrColumnX exch def + + +% DrawStat draws the string on the top of the stack in the next position +% in section 'A' +% +/DrawStat { + StatFont + StatPos pop CurrStatY moveto + show + /CurrStatY CurrStatY StatSep sub def +} def + + +% DrawTitle draws the string on the top of the stack in section 'B' +% +/DrawTitle { + TitleFont + TitlePos moveto + dup stringwidth pop 2 div neg 0 rmoveto + show +} def + + +% DrawDate draws the string on the top of the stack in section 'C' +% +/DrawDate { + DateFont + DatePos moveto + dup stringwidth pop neg 0 rmoveto + show +} def + + +% DrawVers draws the string on the top of the stack in section 'C' +% +/DrawVers { + VersFont + VersPos moveto + show +} def + + +/StripDomain { + +(.) search { + 3 1 roll pop pop +} if + +} def + +/TrimFs { + +dup length 25 gt { + dup (* ) dup 4 2 roll length 24 sub 24 getinterval 1 exch putinterval +} if + +} def + + +% DrawHost expects five strings to be on the stack; right now it +% uses only the first three. The strings are Host Name, Partition Name, +% Dump Level, Tape File Number, and Output Size. +% +/DrawHost { + HostFont + pop pop pop % discard sizes and fileno + CurrColumnX HeadingLvlPos pop add CurrColumnY moveto + show + CurrColumnX HeadingFsPos pop add CurrColumnY moveto + TrimFs + show + CurrColumnX HeadingHostPos pop add CurrColumnY moveto + StripDomain + show + /CurrColumnY CurrColumnY HostSep sub def + CurrColumnY BotColDivLine lt { + /CurrColumnY ColumnBasePos exch pop def + /CurrColumnX CurrColumnX ColumnWidth add def + } if +} def + + +%%%% +%%%% END OF TEMPLATE FILE +%%%% + diff --git a/example/amanda-client.conf b/example/amanda-client.conf new file mode 100644 index 0000000..2179acb --- /dev/null +++ b/example/amanda-client.conf @@ -0,0 +1,24 @@ +# +# amanda.conf - sample Amanda client configuration file. +# +# This file normally goes in /etc/amanda/amanda-client.conf. +# + +conf "DailySet1" # your config name + +index_server "kdc.localdomain" # your amindexd server +tape_server "kdc.localdomain" # your amidxtaped server +#tapedev "tape:/dev/YOUR-TAPE-DEVICE-HERE" # your tape device + # if not set, Use configure or ask server. + # if set to empty string "", ask server + # amrecover will use the changer if set to the value + # of 'amrecover_changer' in the server amanda.conf. + +# auth - authentication scheme to use between server and client. +# Valid values are "bsd", "bsdudp", "bsdtcp", "krb5", "local", +# "rsh" and "ssh". +# Default: [auth "bsdtcp"] +auth "bsdtcp" + +ssh_keys "" # your ssh keys file if you use ssh auth + diff --git a/example/inetd.conf.amandaclient b/example/inetd.conf.amandaclient new file mode 100644 index 0000000..d103b6d --- /dev/null +++ b/example/inetd.conf.amandaclient @@ -0,0 +1,2 @@ +#amanda stream tcp nowait amandabackup /usr/lib/amanda/amandad -auth=bsdtcp amdump +amanda stream tcp nowait amandabackup /usr/lib/amanda/amandad amandad -auth=bsdtcp amdump diff --git a/example/template.d/README b/example/template.d/README new file mode 100644 index 0000000..162f5d1 --- /dev/null +++ b/example/template.d/README @@ -0,0 +1,38 @@ +README for template.d directory +------------------------------- + +This directory contains seven files that are used by amserverconfig. + +amanda-harddisk.conf: contains common parameters for a typical Amanda configuration using + virtual tapes. + +amanda-single-tape.conf: contains common parameters for a typical Amanda configuration using + one tape. + +amanda-tape-changer.conf: contains common parameters for a typical Amanda configuration using + tape changer. + +advanced.conf: contains advanced Amanda parameters that are not usually changed by a site. + +dumptypes: contains Amanda dumptype definitions. + +tapetypes: contains Amanda tapetype definitions. + +README: this file. + + +amserverconfig will create a Amanda configuration in the following directory structure: + +/etc/amanda/template.d: +dumptypes +tapetypes + +/etc/amanda/$config_name: +amanda.conf [ it's a copy of amanda-harddisk.conf, amanda-single-tape.conf or amanda-tape-changer.conf ] +advanced.conf + + +See amserverconfig(8) or amaddclient(8) for detail. + + + diff --git a/example/template.d/advanced.conf b/example/template.d/advanced.conf new file mode 100644 index 0000000..6036089 --- /dev/null +++ b/example/template.d/advanced.conf @@ -0,0 +1,160 @@ +dumpuser "martinea" # the user to run dumps under +inparallel 4 # maximum dumpers that will run in parallel (max 63) + # this maximum can be increased at compile-time, + # modifying MAX_DUMPERS in server-src/driverio.h + +dumporder "sssS" # specify the priority order of each dumper + # s -> smallest size + # S -> biggest size + # t -> smallest time + # T -> biggest time + # b -> smallest bandwidth + # B -> biggest bandwitdh + # try "BTBTBTBTBTBT" if you are not holding + # disk constrained + +taperalgo first # The algorithm used to choose which dump image to send + # to the taper. + + # Possible values: [first|firstfit|largest|largestfit|smallest|last] + # Default: first. + + # first First in - first out. + # firstfit The first dump image that will fit on the current tape. + # largest The largest dump image. + # largestfit The largest dump image that will fit on the current tape. + # smallest The smallest dump image. + # last Last in - first out. +displayunit "m" # Possible values: "k|m|g|t" + # Default: k. + # The unit used to print many numbers. + # k=kilo, m=mega, g=giga, t=tera +netusage 8000 Kbps # maximum net bandwidth for Amanda, in KB per sec + +bumpsize 20 Mb # minimum savings (threshold) to bump level 1 -> 2 +bumppercent 20 # minimum savings (threshold) to bump level 1 -> 2 +bumpdays 1 # minimum days at each level + +# By default, Amanda can only track at most one run per calendar day. When +# the usetimestamps option is enabled, however, Amanda can track as many +# runs as you care to make. +# WARNING: This option is not backward-compatible. Do not enable it if you +# intend to downgrade your server installation to any version +# earlier than Amanda 2.5.1 +usetimestamps yes + +device_output_buffer_size 1280k + # amount of buffer space to use when writing to devices + +# If you want Amanda to automatically label any non-Amanda tapes it +# encounters, uncomment the line below. Note that this will ERASE any +# non-Amanda tapes you may have, and may also ERASE any near-failing tapes. +# Use with caution. +## label_new_tapes "DailySet1-%%%" + +maxdumpsize -1 # Maximum number of bytes the planner will schedule + # for a run (default: runtapes * tape_length). +amrecover_do_fsf yes # amrecover will call amrestore with the + # -f flag for faster positioning of the tape. +amrecover_check_label yes # amrecover will call amrestore with the + # -l flag to check the label. +bumpmult 4 # threshold = bumpsize * bumpmult^(level-1) + + + +amrecover_changer "changer" # amrecover will use the changer if you restore + # from this device. It could be a string like 'changer' and amrecover will use your + # changer if you set your tape to 'changer' with 'setdevice changer' or via + # 'tapedev "changer"' in amanda-client.conf + + + + +# If amanda cannot find a tape on which to store backups, it will run +# as many backups as it can to the holding disks. In order to save +# space for unattended backups, by default, amanda will only perform +# incremental backups in this case, i.e., it will reserve 100% of the +# holding disk space for the so-called degraded mode backups. +# However, if you specify a different value for the `reserve' +# parameter, amanda will not degrade backups if they will fit in the +# non-reserved portion of the holding disk. + +# reserve 30 # percent +# This means save at least 30% of the holding disk space for degraded +# mode backups. + +autoflush no +# if autoflush is set to yes, then amdump will schedule all dump on +# holding disks to be flush to tape during the run. + +# Amanda needs a few Mb of diskspace for the log and debug files, +# as well as a database. This stuff can grow large, so the conf directory +# isn't usually appropriate. Some sites use /usr/local/var and some /usr/adm. +# Create an amanda directory under there. You need a separate infofile and +# logdir for each configuration, so create subdirectories for each conf and +# put the files there. Specify the locations below. + +# Note that, although the keyword below is infofile, it is only so for +# historic reasons, since now it is supposed to be a directory (unless +# you have selected some database format other than the `text' default) +infofile "/etc/amanda/DailySet1/curinfo" # database DIRECTORY +logdir "/etc/amanda/DailySet1" # log directory +indexdir "/etc/amanda/DailySet1/index" # index directory +#tapelist "@CONFIG_DIR/DailySet1/tapelist" # list of used tapes +# tapelist is stored, by default, in the directory that contains amanda.conf + +# Specify holding disks. These are used as a temporary staging area for +# dumps before they are written to tape and are recommended for most sites. +# The advantages include: tape drive is more likely to operate in streaming +# mode (which reduces tape and drive wear, reduces total dump time); multiple +# dumps can be done in parallel (which can dramatically reduce total dump time. +# The main disadvantage is that dumps on the holding disk need to be flushed +# (with amflush) to tape after an operating system crash or a tape failure. +# If no holding disks are specified then all dumps will be written directly +# to tape. If a dump is too big to fit on the holding disk than it will be +# written directly to tape. If more than one holding disk is specified then +# they will all be used based on activity and available space. + +#holdingdisk hd1 { +# comment "main holding disk" +# directory "/dumps/amanda" # where the holding disk is +# use -100 Mb # how much space can we use on it +# # a non-positive value means: +# # use all space but that value +# chunksize 1Gb # size of chunk if you want big dump to be +# # dumped on multiple files on holding disks +# # N Kb/Mb/Gb split images in chunks of size N +# # The maximum value should be +# # (MAX_FILE_SIZE - 1Mb) +# # 0 same as INT_MAX bytes +# } +#holdingdisk hd2 { +# directory "/dumps2/amanda" +# use 1000 Mb +# } + +# network interfaces +# +# These are referred to by the disklist file. They define the attributes +# of the network interface that the remote machine is accessed through. +# Notes: - netusage above defines the attributes t +# disklist entry doesn't specify otherwise. +# - the values below are only samples. +# - specifying an interface does not force the traffic to pass +# through that interface. Your OS routing tables do that. This +# is just a mechanism to stop Amanda trashing your network. +# Attributes are: +# use - bandwidth above which amanda won't start +# backups using this interface. Note that if +# a single backup will take more than that, +# amanda won't try to make it run slower! + +define interface local { + comment "a local disk" + use 8000 kbps +} + +#define interface le0 { +# comment "10 Mbps ethernet" +# use 400 kbps +#} diff --git a/example/template.d/advanced.conf.in b/example/template.d/advanced.conf.in new file mode 100644 index 0000000..19b963e --- /dev/null +++ b/example/template.d/advanced.conf.in @@ -0,0 +1,160 @@ +dumpuser "@CLIENT_LOGIN@" # the user to run dumps under +inparallel 4 # maximum dumpers that will run in parallel (max 63) + # this maximum can be increased at compile-time, + # modifying MAX_DUMPERS in server-src/driverio.h + +dumporder "sssS" # specify the priority order of each dumper + # s -> smallest size + # S -> biggest size + # t -> smallest time + # T -> biggest time + # b -> smallest bandwidth + # B -> biggest bandwitdh + # try "BTBTBTBTBTBT" if you are not holding + # disk constrained + +taperalgo first # The algorithm used to choose which dump image to send + # to the taper. + + # Possible values: [first|firstfit|largest|largestfit|smallest|last] + # Default: first. + + # first First in - first out. + # firstfit The first dump image that will fit on the current tape. + # largest The largest dump image. + # largestfit The largest dump image that will fit on the current tape. + # smallest The smallest dump image. + # last Last in - first out. +displayunit "m" # Possible values: "k|m|g|t" + # Default: k. + # The unit used to print many numbers. + # k=kilo, m=mega, g=giga, t=tera +netusage 8000 Kbps # maximum net bandwidth for Amanda, in KB per sec + +bumpsize 20 Mb # minimum savings (threshold) to bump level 1 -> 2 +bumppercent 20 # minimum savings (threshold) to bump level 1 -> 2 +bumpdays 1 # minimum days at each level + +# By default, Amanda can only track at most one run per calendar day. When +# the usetimestamps option is enabled, however, Amanda can track as many +# runs as you care to make. +# WARNING: This option is not backward-compatible. Do not enable it if you +# intend to downgrade your server installation to any version +# earlier than Amanda 2.5.1 +usetimestamps yes + +device_output_buffer_size 1280k + # amount of buffer space to use when writing to devices + +# If you want Amanda to automatically label any non-Amanda tapes it +# encounters, uncomment the line below. Note that this will ERASE any +# non-Amanda tapes you may have, and may also ERASE any near-failing tapes. +# Use with caution. +## label_new_tapes "DailySet1-%%%" + +maxdumpsize -1 # Maximum number of bytes the planner will schedule + # for a run (default: runtapes * tape_length). +amrecover_do_fsf yes # amrecover will call amrestore with the + # -f flag for faster positioning of the tape. +amrecover_check_label yes # amrecover will call amrestore with the + # -l flag to check the label. +bumpmult 4 # threshold = bumpsize * bumpmult^(level-1) + + + +amrecover_changer "changer" # amrecover will use the changer if you restore + # from this device. It could be a string like 'changer' and amrecover will use your + # changer if you set your tape to 'changer' with 'setdevice changer' or via + # 'tapedev "changer"' in amanda-client.conf + + + + +# If amanda cannot find a tape on which to store backups, it will run +# as many backups as it can to the holding disks. In order to save +# space for unattended backups, by default, amanda will only perform +# incremental backups in this case, i.e., it will reserve 100% of the +# holding disk space for the so-called degraded mode backups. +# However, if you specify a different value for the `reserve' +# parameter, amanda will not degrade backups if they will fit in the +# non-reserved portion of the holding disk. + +# reserve 30 # percent +# This means save at least 30% of the holding disk space for degraded +# mode backups. + +autoflush no +# if autoflush is set to yes, then amdump will schedule all dump on +# holding disks to be flush to tape during the run. + +# Amanda needs a few Mb of diskspace for the log and debug files, +# as well as a database. This stuff can grow large, so the conf directory +# isn't usually appropriate. Some sites use /usr/local/var and some /usr/adm. +# Create an amanda directory under there. You need a separate infofile and +# logdir for each configuration, so create subdirectories for each conf and +# put the files there. Specify the locations below. + +# Note that, although the keyword below is infofile, it is only so for +# historic reasons, since now it is supposed to be a directory (unless +# you have selected some database format other than the `text' default) +infofile "@CONFIG_DIR@/@DEFAULT_CONFIG@/curinfo" # database DIRECTORY +logdir "@CONFIG_DIR@/@DEFAULT_CONFIG@" # log directory +indexdir "@CONFIG_DIR@/@DEFAULT_CONFIG@/index" # index directory +#tapelist "@CONFIG_DIR/DailySet1/tapelist" # list of used tapes +# tapelist is stored, by default, in the directory that contains amanda.conf + +# Specify holding disks. These are used as a temporary staging area for +# dumps before they are written to tape and are recommended for most sites. +# The advantages include: tape drive is more likely to operate in streaming +# mode (which reduces tape and drive wear, reduces total dump time); multiple +# dumps can be done in parallel (which can dramatically reduce total dump time. +# The main disadvantage is that dumps on the holding disk need to be flushed +# (with amflush) to tape after an operating system crash or a tape failure. +# If no holding disks are specified then all dumps will be written directly +# to tape. If a dump is too big to fit on the holding disk than it will be +# written directly to tape. If more than one holding disk is specified then +# they will all be used based on activity and available space. + +#holdingdisk hd1 { +# comment "main holding disk" +# directory "/dumps/amanda" # where the holding disk is +# use -100 Mb # how much space can we use on it +# # a non-positive value means: +# # use all space but that value +# chunksize 1Gb # size of chunk if you want big dump to be +# # dumped on multiple files on holding disks +# # N Kb/Mb/Gb split images in chunks of size N +# # The maximum value should be +# # (MAX_FILE_SIZE - 1Mb) +# # 0 same as INT_MAX bytes +# } +#holdingdisk hd2 { +# directory "/dumps2/amanda" +# use 1000 Mb +# } + +# network interfaces +# +# These are referred to by the disklist file. They define the attributes +# of the network interface that the remote machine is accessed through. +# Notes: - netusage above defines the attributes t +# disklist entry doesn't specify otherwise. +# - the values below are only samples. +# - specifying an interface does not force the traffic to pass +# through that interface. Your OS routing tables do that. This +# is just a mechanism to stop Amanda trashing your network. +# Attributes are: +# use - bandwidth above which amanda won't start +# backups using this interface. Note that if +# a single backup will take more than that, +# amanda won't try to make it run slower! + +define interface local { + comment "a local disk" + use 8000 kbps +} + +#define interface le0 { +# comment "10 Mbps ethernet" +# use 400 kbps +#} diff --git a/example/template.d/amanda-S3.conf b/example/template.d/amanda-S3.conf new file mode 100644 index 0000000..70297b0 --- /dev/null +++ b/example/template.d/amanda-S3.conf @@ -0,0 +1,54 @@ +org "DailySet1" # your organization name for reports +mailto "martinea" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-multi" # the tape-changer glue script +tapedev "S3:" # the no-rewind tape device to be used +changerfile "/etc/amanda/DailySet1/changer.conf" +#changerdev "/dev/sg1" +tapetype HARDDISK # what kind of tape it is (see tapetypes below) + +holdingdisk hd2 { + directory "/var/lib/amanda/holdings/DailySet1" + use 1000 Mb + } + +label_new_tapes "DailySet1-%%%%" # Enable auto labeling +labelstr "^DailySet1-[0-9][0-9]*$" # label constraint regex: all tapes must match + +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +define tapetype HARDDISK { + comment "Virtual Tapes" + length 5000 mbytes +} + + +includefile "./advanced.conf" +includefile "/etc/amanda/template.d/dumptypes" +includefile "/etc/amanda/template.d/tapetypes" + diff --git a/example/template.d/amanda-S3.conf.in b/example/template.d/amanda-S3.conf.in new file mode 100644 index 0000000..96592d6 --- /dev/null +++ b/example/template.d/amanda-S3.conf.in @@ -0,0 +1,54 @@ +org "@DEFAULT_CONFIG@" # your organization name for reports +mailto "@CLIENT_LOGIN@" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-multi" # the tape-changer glue script +tapedev "S3:" # the no-rewind tape device to be used +changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/changer.conf" +#changerdev "/dev/sg1" +tapetype HARDDISK # what kind of tape it is (see tapetypes below) + +holdingdisk hd2 { + directory "/var/lib/amanda/holdings/@DEFAULT_CONFIG@" + use 1000 Mb + } + +label_new_tapes "@DEFAULT_CONFIG@-%%%%" # Enable auto labeling +labelstr "^@DEFAULT_CONFIG@-[0-9][0-9]*$" # label constraint regex: all tapes must match + +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +define tapetype HARDDISK { + comment "Virtual Tapes" + length 5000 mbytes +} + + +includefile "./advanced.conf" +includefile "@CONFIG_DIR@/template.d/dumptypes" +includefile "@CONFIG_DIR@/template.d/tapetypes" + diff --git a/example/template.d/amanda-harddisk.conf b/example/template.d/amanda-harddisk.conf new file mode 100644 index 0000000..395a836 --- /dev/null +++ b/example/template.d/amanda-harddisk.conf @@ -0,0 +1,44 @@ +org "DailySet1" # your organization name for reports +mailto "martinea" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-disk" # the tape-changer glue script +tapedev "file://var/lib/amanda/vtapes/DailySet1" # the no-rewind tape device to be used +changerfile "/etc/amanda/DailySet1/changer.conf" +changerdev "/dev/null" +tapetype HARDDISK # what kind of tape it is +labelstr "^DailySet1-[0-9][0-9]*$" # label constraint regex: all tapes must match +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +define tapetype HARDDISK { + comment "Virtual Tapes" + length 5000 mbytes +} + +includefile "./advanced.conf" +includefile "/etc/amanda/template.d/dumptypes" +includefile "/etc/amanda/template.d/tapetypes" diff --git a/example/template.d/amanda-harddisk.conf.in b/example/template.d/amanda-harddisk.conf.in new file mode 100644 index 0000000..e1c920b --- /dev/null +++ b/example/template.d/amanda-harddisk.conf.in @@ -0,0 +1,44 @@ +org "@DEFAULT_CONFIG@" # your organization name for reports +mailto "@CLIENT_LOGIN@" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-disk" # the tape-changer glue script +tapedev "file://var/lib/amanda/vtapes/@DEFAULT_CONFIG@" # the no-rewind tape device to be used +changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/changer.conf" +changerdev "/dev/null" +tapetype HARDDISK # what kind of tape it is +labelstr "^@DEFAULT_CONFIG@-[0-9][0-9]*$" # label constraint regex: all tapes must match +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +define tapetype HARDDISK { + comment "Virtual Tapes" + length 5000 mbytes +} + +includefile "./advanced.conf" +includefile "@CONFIG_DIR@/template.d/dumptypes" +includefile "@CONFIG_DIR@/template.d/tapetypes" diff --git a/example/template.d/amanda-single-tape.conf b/example/template.d/amanda-single-tape.conf new file mode 100644 index 0000000..8cd47c9 --- /dev/null +++ b/example/template.d/amanda-single-tape.conf @@ -0,0 +1,47 @@ +org "DailySet1" # your organization name for reports +mailto "martinea" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle + +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-manual" # the tape-changer glue script +tapedev "tape:/dev/nst0" # the no-rewind tape device to be used +changerfile "/etc/amanda/DailySet1/chg-manual.conf" +changerdev "/dev/null" +tapetype HP-DAT # what kind of tape it is (see tapetypes below) +holdingdisk hd2 { + directory "/var/lib/amanda/holdings/DailySet1" + use 1000 Mb + } + +labelstr "^DailySet1-[0-9][0-9]*$" # label constraint regex: all tapes must match + +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +includefile "./advanced.conf" +includefile "/etc/amanda/template.d/dumptypes" +includefile "/etc/amanda/template.d/tapetypes" diff --git a/example/template.d/amanda-single-tape.conf.in b/example/template.d/amanda-single-tape.conf.in new file mode 100644 index 0000000..6012305 --- /dev/null +++ b/example/template.d/amanda-single-tape.conf.in @@ -0,0 +1,47 @@ +org "@DEFAULT_CONFIG@" # your organization name for reports +mailto "@CLIENT_LOGIN@" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle + +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-manual" # the tape-changer glue script +tapedev "tape:/dev/nst0" # the no-rewind tape device to be used +changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/chg-manual.conf" +changerdev "/dev/null" +tapetype HP-DAT # what kind of tape it is (see tapetypes below) +holdingdisk hd2 { + directory "/var/lib/amanda/holdings/@DEFAULT_CONFIG@" + use 1000 Mb + } + +labelstr "^@DEFAULT_CONFIG@-[0-9][0-9]*$" # label constraint regex: all tapes must match + +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +includefile "./advanced.conf" +includefile "@CONFIG_DIR@/template.d/dumptypes" +includefile "@CONFIG_DIR@/template.d/tapetypes" diff --git a/example/template.d/amanda-tape-changer.conf b/example/template.d/amanda-tape-changer.conf new file mode 100644 index 0000000..382259f --- /dev/null +++ b/example/template.d/amanda-tape-changer.conf @@ -0,0 +1,47 @@ +org "DailySet1" # your organization name for reports +mailto "martinea" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-zd-mtx" # the tape-changer glue script +tapedev "tape:/dev/nst0" # the no-rewind tape device to be used +changerfile "/etc/amanda/DailySet1/changer.conf" +changerdev "/dev/sg1" +tapetype HP-DAT # what kind of tape it is (see tapetypes below) + +holdingdisk hd2 { + directory "/var/lib/amanda/holdings/DailySet1" + use 1000 Mb + } + +labelstr "^DailySet1-[0-9][0-9]*$" # label constraint regex: all tapes must match + +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +includefile "./advanced.conf" +includefile "/etc/amanda/template.d/dumptypes" +includefile "/etc/amanda/template.d/tapetypes" + diff --git a/example/template.d/amanda-tape-changer.conf.in b/example/template.d/amanda-tape-changer.conf.in new file mode 100644 index 0000000..f46e729 --- /dev/null +++ b/example/template.d/amanda-tape-changer.conf.in @@ -0,0 +1,47 @@ +org "@DEFAULT_CONFIG@" # your organization name for reports +mailto "@CLIENT_LOGIN@" # space separated list of operators at your site +dumpcycle 1 week # the number of days in the normal dump cycle +runspercycle 5 # the number of amdump runs in dumpcycle days + # (1 week * 5 amdump runs per week -- just weekdays) +tapecycle 10 tapes # the number of tapes in rotation + # 1 week (dumpcycle) times 5 tapes per week (just + # the weekdays) plus a few to handle errors that + # need amflush and so we do not overwrite the full + # backups performed at the beginning of the previous + # cycle +runtapes 1 # number of tapes to be used in a single run of amdump +tpchanger "chg-zd-mtx" # the tape-changer glue script +tapedev "tape:/dev/nst0" # the no-rewind tape device to be used +changerfile "@CONFIG_DIR@/@DEFAULT_CONFIG@/changer.conf" +changerdev "/dev/sg1" +tapetype HP-DAT # what kind of tape it is (see tapetypes below) + +holdingdisk hd2 { + directory "/var/lib/amanda/holdings/@DEFAULT_CONFIG@" + use 1000 Mb + } + +labelstr "^@DEFAULT_CONFIG@-[0-9][0-9]*$" # label constraint regex: all tapes must match + +dtimeout 1800 # number of idle seconds before a dump is aborted. +ctimeout 30 # maximum number of seconds that amcheck waits + # for each client host +etimeout 300 # number of seconds per filesystem for estimates. + +define dumptype global { + comment "Global definitions" + auth "bsdtcp" +} + +define dumptype gui-base { + global + program "GNUTAR" + comment "gui base dumptype dumped with tar" + compress none + index yes +} + +includefile "./advanced.conf" +includefile "@CONFIG_DIR@/template.d/dumptypes" +includefile "@CONFIG_DIR@/template.d/tapetypes" + diff --git a/example/template.d/chg-manual.conf b/example/template.d/chg-manual.conf new file mode 100644 index 0000000..4fb86f2 --- /dev/null +++ b/example/template.d/chg-manual.conf @@ -0,0 +1,10 @@ +# +#configuration used by chg-manual +# +resend_mail=3600 # every hour +timeout_mail=43200 # 12 hours +#request="tty" # Use the tty to ask the user to change tape. + # Can't be use by cron +#request="email" # Send an email to ask the user to change tape. +request="tty_email" # Send request through tty if it exists. + # Otherwise, it will send an email. diff --git a/example/template.d/dumptypes b/example/template.d/dumptypes new file mode 100644 index 0000000..d0f2ae8 --- /dev/null +++ b/example/template.d/dumptypes @@ -0,0 +1,422 @@ +# dumptypes +# +# These are referred to by the disklist file. The dumptype specifies +# certain parameters for dumping including: +# auth - authentication scheme to use between server and client. +# Valid values are "bsd", "bsdudp", "bsdtcp", "krb5", "local", +# "rsh" and "ssh" +# Default: [auth bsd] +# comment - just a comment string +# comprate - set default compression rate. Should be followed by one or +# two numbers, optionally separated by a comma. The 1st is +# the full compression rate; the 2nd is the incremental rate. +# If the second is omitted, it is assumed equal to the first. +# The numbers represent the amount of the original file the +# compressed file is expected to take up. +# Default: [comprate 0.50, 0.50] +# compress - specify compression of the backed up data. Valid values are: +# "none" - don't compress the dump output. +# "client best" - compress on the client using the best (and +# probably slowest) algorithm. +# "client fast" - compress on the client using fast algorithm. +# "client custom" - compress using your custom client compression program. +# use client_custom_compress "PROG" to specify +# the custom compression program. +# PROG must not contain white space. +# "server best" - compress on the tape host using the best (and +# probably slowest) algorithm. +# "server fast" - compress on the tape host using a fast +# algorithm. This may be useful when a fast +# tape host is backing up slow clients. +# "server custom" - compress using your server custom compression program. +# use server_custom_compress "PROG" to specify +# the custom compression program. +# PROG must not contain white space. +# Default: [compress client fast] +# dumpcycle - set the number of days in the dump cycle, ie, set how often a +# full dump should be performed. Default: from DUMPCYCLE variable +# estimate Determine the way AMANDA does it's estimate. +# "client" - Use the same program as the dumping program, +# this is the most accurate way to do estimates, +# but it can take a long time. +# "calcsize" - Use a faster program to do estimates, but the +# result is less accurate. +# "server" - Use only statistics from the previous run to +# give an estimate, +# it takes only a few seconds but the result is not +# accurate if your disk usage changes from day to day. +# Default: [client] +# encrypt - specify encryption of the backed up data. Valid values are: +# "none" - don't encrypt the dump output. +# "client" - encrypt on the client using the program specified by +# client_encrypt "PROG". +# Use client_decrypt_option to specify the decrypt- +# parameter, default is "-d". +# PROG and decrypt-parameter must not contain white space. +# "server" - encrypt on the server using the program specified by +# server_encrypt "PROG". +# Use server_decrypt_option to specify the decrypt- +# parameter, default is "-d". +# PROG and decrypt-parameter must not contain white space. +# Default: [none] +# exclude - specify files and directories to be excluded from the dump. +# Useful with gnutar only; silently ignored by dump and samba. +# Valid values are: +# "pattern" - a shell glob pattern defining which files +# to exclude. +# gnutar gets --exclude="pattern" +# list "filename" - a file (on the client!) containing patterns +# re's (1 per line) defining which files to +# exclude. +# gnutar gets --exclude-from="filename" +# Note that the `full pathname' of a file within its +# filesystem starts with `./', because of the way amanda runs +# gnutar: `tar -C $mountpoint -cf - --lots-of-options .' (note +# the final dot!) Thus, if you're backing up `/usr' with a +# diskfile entry like ``host /usr gnutar-root', but you don't +# want to backup /usr/tmp, your exclude list should contain +# the pattern `./tmp', as this is relative to the `/usr' above. +# Please refer to the man-page of gnutar for more information. +# If a relative pathname is specified as the exclude list, +# it is searched from within the directory that is +# going to be backed up. +# Default: include all files +# holdingdisk - should the holding disk be used for this dump. Useful for +# dumping the holding disk itself. Default: [holdingdisk auto] +# "never" - Never use the holding disk. +# "auto" - Use the holding disk if possible. +# "required" - Always use the holding disk. +# ignore - do not back this filesystem up. Useful for sharing a single +# disklist in several configurations. +# index - keep an index of the files backed up. Default: [index no] +# kencrypt - encrypt the data stream between the client and server. +# Default: [kencrypt no] +# maxdumps - max number of concurrent dumps to run on the client. +# Default: [maxdumps 1] +# maxpromoteday - max number of day for a promotion, set it 0 if you don't +# want promotion, set it to 1 or 2 if your disk get +# overpromoted. +# Default: [10000] +# priority - priority level of the dump. Valid levels are "low", "medium" +# or "high". These are really only used when Amanda has no +# tape to write to because of some error. In that "degraded +# mode", as many incrementals as will fit on the holding disk +# are done, higher priority first, to insure the important +# disks are at least dumped. Default: [priority medium] +# program - specify the dump system to use. Valid values are "DUMP" +# "STAR" and "GNUTAR". Default: [program "DUMP"]. +# record - record the backup in the time-stamp-database of the backup +# program (e.g. /etc/dumpdates for DUMP or +# /var/lib/amanda/gnutar-lists for GNUTAR.). +# Default: [record yes] +# skip-full - skip the disk when a level 0 is due, to allow full backups +# outside Amanda, eg when the machine is in single-user mode. +# skip-incr - skip the disk when the level 0 is NOT due. This is used in +# archive configurations, where only full dumps are done and +# the tapes saved. +# starttime - delay the start of the dump? Default: no delay +# strategy - set the dump strategy. Valid strategies are currently: +# "standard" - the standard one. +# "nofull" - do level 1 dumps every time. This can be used, +# for example, for small root filesystems that +# only change slightly relative to a site-wide +# prototype. Amanda then backs up just the +# changes. +# "noinc" - do level 0 dumps every time. +# "skip" - skip all dumps. Useful for sharing a single +# disklist in several configurations. +# "incronly" - do only incremental dumps. This is similar +# to strategy 'nofull', but will increase +# the dump level as usual. Full dumps will +# only be performed when an 'amadmin force' +# has been issued +# Default: [strategy standard] +# tape_splitsize - (optional) split dump file into pieces of a specified size. +# This allows dumps to be spread across multiple tapes, and can +# potentially make more efficient use of tape space. Note that +# if this value is too large (more than half the size of the +# average dump being split), substantial tape space can be +# wasted. If too small, large dumps will be split into +# innumerable tiny dumpfiles, adding to restoration complexity. +# A good rule of thumb, usually, is 1/10 of the size of your +# tape. Default: [disabled] +# split_diskbuffer - (optional) When dumping a split dump in PORT-WRITE +# mode (usually meaning "no holding disk"), buffer the split +# chunks to a file in the directory specified by this option. +# Default: [none] +# fallback_splitsize - (optional) When dumping a split dump in PORT-WRITE +# mode, if no split_diskbuffer is specified (or if we somehow +# fail to use our split_diskbuffer), we must buffer split +# chunks in memory. This specifies the maximum size split +# chunks can be in this scenario, and thus the maximum amount +# of memory consumed for in-memory splitting. Default: [10m] +# +# +# Note that you may specify previously defined dumptypes as a shorthand way +# of defining parameters. + +# dumptype global defined in $config/amanda.conf + +define dumptype always-full { + global + comment "Full dump of this filesystem always" + compress none + priority high + dumpcycle 0 +} + +# Dumptypes for star +define dumptype root-star { + global + program "STAR" + comment "root partitions dumped with star" + compress none + index +# exclude list "/var/lib/amanda/exclude.star" + priority low +} + +define dumptype user-star { + root-star + comment "user partitions dumped with star" + priority medium +} + +define dumptype user-star-span { + root-star + tape_splitsize 3 Gb + comment "tape-spanning user partitions dumped with star" + priority medium +} + +define dumptype high-star { + root-star + comment "partitions dumped with star" + priority high +} + +define dumptype comp-root-star { + root-star + comment "Root partitions with compression" + compress client fast +} + +define dumptype comp-user-star { + user-star + compress client fast +} + +define dumptype comp-user-star-span { + user-star-span + compress client fast +} + +# Dumptypes for gnutar + +define dumptype root-tar { + global + program "GNUTAR" + comment "root partitions dumped with tar" + compress none + index + priority low +} + + +define dumptype user-tar { + root-tar + comment "user partitions dumped with tar" + priority medium +} + + +define dumptype user-tar-span { + root-tar + tape_splitsize 3 Gb + comment "tape-spanning user partitions dumped with tar" + priority medium +} + + +define dumptype high-tar { + root-tar + comment "partitions dumped with tar" + priority high +} + +define dumptype comp-root-tar { + root-tar + comment "Root partitions with compression dumped with tar" + compress client fast +} + +define dumptype comp-user-tar { + user-tar + compress client fast +} + +define dumptype comp-user-tar-span { + user-tar-span + compress client fast +} + + +define dumptype holding-disk { + global + comment "The master-host holding disk itself" + holdingdisk never # do not use the holding disk + priority medium +} + +define dumptype comp-user { + global + comment "Non-root partitions on reasonably fast machines" + compress client fast + priority medium +} + +define dumptype comp-user-span { + global + tape_splitsize 5 Gb + comment "Tape-spanning non-root partitions on reasonably fast machines" + compress client fast + priority medium +} + + +define dumptype nocomp-user { + comp-user + comment "Non-root partitions on slow machines" + compress none +} + +define dumptype nocomp-user-span { + comp-user-span + comment "Tape-spanning non-root partitions on slow machines" + compress none +} + + +define dumptype comp-root { + global + comment "Root partitions with compression" + compress client fast + priority low +} + +define dumptype nocomp-root { + comp-root + comment "Root partitions without compression" + compress none +} + +define dumptype comp-high { + global + comment "very important partitions on fast machines" + compress client best + priority high +} + +define dumptype nocomp-high { + comp-high + comment "very important partitions on slow machines" + compress none +} + +define dumptype nocomp-test { + global + comment "test dump without compression, no /etc/dumpdates recording" + compress none + record no + priority medium +} + +define dumptype comp-test { + nocomp-test + comment "test dump with compression, no /etc/dumpdates recording" + compress client fast +} + +define dumptype nocomp-ssh { + root-tar + comment "ssh authorization and dumped with tar" + auth "ssh" + ssh_keys "/var/lib/amanda/.ssh/id_rsa_amdump" + compress none +} + + +define dumptype custom-compress { + root-tar + comment "custom client compression, dumped with tar" + compress client custom + client_custom_compress "/usr/bin/bzip2" +} + +# amcrypt requires aespipe and uuencode +define dumptype encrypt-fast { + root-tar + comment "fast client compression and server symmetric encryption, dumped with tar" + compress client fast + encrypt server + server_encrypt "/usr/sbin/amcrypt" + server_decrypt_option "-d" +} + + +# amcryptsimple use gpg symmetric encryption. gpg does compress with zlib by default. +# Thus, specify compress none. +define dumptype encrypt-simple-nocomp { + root-tar + comment "client simple symmetric encryption, dumped with tar" + compress none + encrypt client + client_encrypt "/usr/sbin/amcryptsimple" + client_decrypt_option "-d" +} + +# To use gpg public-key encryption, gpg does compress with zlib by default. +# Thus, specify compress none. + +define dumptype gpg-encrypt-nocomp { + root-tar + comment "server public-key encryption, dumped with tar" + compress none + encrypt server + server_encrypt "/usr/sbin/amgpgcrypt" + server_decrypt_option "-d" +} + +# The following dumptypes are for ZMC +# dumptype gui-base defined in $config/amanda.conf + +define dumptype gui-default { + gui-base + comment "gui default dumptype" + compress none + encrypt none +} + +define dumptype gui-compress { + gui-base + comment "gui dumptype with compression" + compress client fast + encrypt none +} + +define dumptype gui-encrypt { + gui-base + comment "gui dumptype with encryption" + compress none + encrypt server + server_encrypt "/usr/sbin/amcryptsimple" +} + +define dumptype gui-encrypt-compress { + gui-base + comment "gui dumptype with compression and encryption" + compress client fast + encrypt server + server_encrypt "/usr/sbin/amcryptsimple" +} + diff --git a/example/template.d/tapetypes b/example/template.d/tapetypes new file mode 100644 index 0000000..effaeed --- /dev/null +++ b/example/template.d/tapetypes @@ -0,0 +1,308 @@ +# tapetypes + +# Define the type of tape you use here, and use it in "tapetype" +# above. Some typical types of tapes are included here. The tapetype +# tells amanda how many MB will fit on the tape, how big the filemarks +# are, and how fast the tape device is. + +# A filemark is the amount of wasted space every time a tape section +# ends. If you run `make tapetype' in tape-src, you'll get a program +# that generates tapetype entries, but it is slow as hell, use it only +# if you really must and, if you do, make sure you post the data to +# the amanda mailing list, so that others can use what you found out +# by searching the archives. + +# For completeness Amanda should calculate the inter-record gaps too, +# but it doesn't. For EXABYTE and DAT tapes this is ok. Anyone using +# 9 tracks for amanda and need IRG calculations? Drop me a note if +# so. + +# If you want amanda to print postscript paper tape labels +# add a line after the comment in the tapetype of the form +# lbl-templ "/path/to/postscript/template/label.ps" + +# if you want the label to go to a printer other than the default +# for your system, you can also add a line above for a different +# printer. (i usually add that line after the dumpuser specification) + +# dumpuser "operator" # the user to run dumps under +# printer "mypostscript" # printer to print paper label on + +# here is an example of my definition for an EXB-8500 + +# define tapetype EXB-8500 { +# ... +# lbl-templ "/usr/local/amanda/config/lbl.exabyte.ps" +# } + +# HARDDISK defintion in amanda.conf + +define tapetype DLT-S4 { + comment "just produced by tapetype prog, compression off" + length 772096 mbytes + filemark 0 kbytes + speed 33596 kps +} + +define tapetype DLT8000 { + comment "Quantum DLT8000 created by tapetype" + length 38130 mbytes + filemark 29 kbytes + speed 5627 kps +} + +define tapetype QUANTUM-DLT4000 { + comment "Quantum DLT4000, compression off" + length 19534 mbytes + filemark 4 kbytes + speed 1096 kps +} + + +define tapetype SDLT600 { + comment "Quantum SDLT600 with 10MB/s" + length 306789 mbytes + filemark 0 kbytes + speed 8247 kps +} + + +define tapetype SDLT320 { + comment "HP Super DLTtape I, data cartridge, C7980A, compression on" + length 139776 mbytes + filemark 0 kbytes + speed 13980 kps +} + +define tapetype SDLT220NOCOMP { + comment "Quantum SDLT 220, compression off" + length 109539 mbytes + filemark 0 kbytes + speed 10351 kps +} + +define tapetype Quantum-DLT-V4 { + comment "Quantum-DLT-V4 on Adaptec 29160" + length 157284 mbytes + filemark 0 kbytes + speed 9936 kps +} + +define tapetype AIT1{ + comment "Sony AIT-1 with 170m tapes" + length 21568 mbytes + filemark 0 kbytes + speed 2699 kps +} + +define tapetype AIT1-35 { + comment "Sony AIT1 cartridge 35/70 Gbyte, compression off" + length 33400 mbytes # rounded down + filemark 500 kbytes + speed 2890 kps +} + +define tapetype LTO { + comment "Dell PowerVault 122T, Seagate Ultrium, IBM 3581-H17, compression off" + length 101376 mbytes + filemark 0 kbytes + speed 13872 kps +} + +define tapetype QUANTUM-LTO2 { + comment " Quantum LTO-2 HH, compression off" + length 186368 mbytes + filemark 0 kbytes + speed 2781 kps +} + +define tapetype LTO2 { + comment "HP Ultrium 448, hardware compression off" + length 193024 mbytes + filemark 0 kbytes + speed 20355 kps +} + +define tapetype DELL-LTO3-400 { + comment "Dell PV124T LTO3, compression off" + length 402432 mbytes + filemark 0 kbytes + speed 71189 kps +} + +define tapetype DELL-LTO2-200 { + comment "Dell PV132T LTO2, hardware compression" + length 201216 mbytes + filemark 0 kbytes + speed 31343 kps +} + +define tapetype IBM-ULTRIUM-3582 { + comment "IBM Ultrium 3582, compression on" + length 199168 mbytes + filemark 0 kbytes + speed 30760 kps +} + +define tapetype LTO3-400 { + comment "LTO Ultrium 3 400/800, compression off" + length 402432 mbytes + filemark 0 kbytes + speed 71702 kps +} + +define tapetype HP-ULTRIUM-960 { + comment "HP Ultrium 960, compression off" + length 386048 mbytes + filemark 0 kbytes + speed 67629 kps +} + +define tapetype SEAGATE-ULTRIUM-LTO { + comment "SEAGATE ULTRIUM 06242 LTO, compression off" + length 99584 mbytes + filemark 0 kbytes + speed 11288 kps +} + +define tapetype QS3LTO-3 { + comment "Quantum Super Loader 3 LTO-3 16 tape library" + length 448369 mbytes + filemark 6403 kbytes + speed 37739 kps +} + +define tapetype DDS90 { + comment "DDS tapes drives - 90 meter tapes" + length 1900000 kbytes # rounded down + filemark 111 kbytes + speed 380 kps +} + +define tapetype DDS120 { + comment "DDS tape drives - 120 meter tapes" + length 3850000 # rounded down + filemark 111 kbytes + speed 380 kps +} + +define tapetype IBM-DAT-72 { + comment "DDS5, compression on" + length 30227 mbytes + filemark 0 kbytes + speed 2559 kps +} + +define tapetype HP-DAT-72 { + comment "DDS5, /dev/rmt/0ln, HP C7438A Rev V309, compression on" + length 30227 mbytes + filemark 0 kbytes + speed 2551 kps +} + +define tapetype DLT1 { + comment "HP DLT1, DLT IV Tape C5141F, compression on" + length 34818 mbytes + filemark 32 kbytes + speed 2879 kps +} + +define tapetype ARCvault24 { + comment "Overland ARCvault, compression off" + length 386048 mbytes + filemark 0 kbytes + speed 38246 kps +} + +define tapetype QIC-60 { + comment "Archive Viper" + length 60 mbytes + filemark 100 kbytes + speed 100 kbytes +} + +define tapetype CD650 { + comment "CD-R 650MB sized vtape" + length 681984000 bytes + filemark 4 Kbytes +} + + +define tapetype CD700 { + comment "CD-R 700MB sized vtape" + length 737280000 bytes + filemark 4 Kbytes +} + +define tapetype DVD47 { + comment "A 4.7 Gbyte DVD-sized vtape" + length 4482 mbytes + filemark 4 kbytes +} + +define tapetype DVD85 { + comment "A 8.5 GB DVD double layer" + length 8100 mbytes # approximately - exact value not found + filemark 4 kbytes +} + + +define tapetype DEC-DLT2000 { + comment "DEC Differential Digital Linear Tape 2000" + length 15000 mbytes + filemark 8 kbytes + speed 1250 kbytes +} + +# goluboff@butch.Colorado.EDU +# in amanda-users (Thu Dec 26 01:55:38 MEZ 1996) +define tapetype DLT { + comment "DLT tape drives" + length 20000 mbytes # 20 Gig tapes + filemark 2000 kbytes + speed 1536 kbytes +} + +define tapetype SURESTORE-1200E { + comment "HP AutoLoader" + length 3900 mbytes + filemark 100 kbytes + speed 500 kbytes +} + +define tapetype EXB-8500 { + comment "Exabyte EXB-8500 drive on decent machine" + length 4200 mbytes + filemark 48 kbytes + speed 474 kbytes +} + +define tapetype EXB-8200 { + comment "Exabyte EXB-8200 drive on decent machine" + length 2200 mbytes + filemark 2130 kbytes + speed 240 kbytes +} + +define tapetype HP-DAT { + comment "DAT tape drives" + # data provided by Rob Browning + length 1930 mbytes + filemark 111 kbytes + speed 468 kbytes +} + +define tapetype DAT { + comment "DAT tape drives" + length 1000 mbytes # these numbers are not accurate + filemark 100 kbytes # but you get the idea + speed 100 kbytes +} + +define tapetype MIMSY-MEGATAPE { + comment "Megatape (Exabyte based) drive through Emulex on Vax 8600" + length 2200 mbytes + filemark 2130 kbytes + speed 170 kbytes # limited by the Emulex bus interface, ugh +} + diff --git a/example/xinetd.amandaclient b/example/xinetd.amandaclient new file mode 100644 index 0000000..7747b0f --- /dev/null +++ b/example/xinetd.amandaclient @@ -0,0 +1,19 @@ +# default: on +# +# description: The Amanda backup client should be enabled for systems +# which will be backed up by an Amanda backup server. + +service amanda +{ + disable = no + flags = IPv4 + flags = IPv6 + socket_type = stream + protocol = tcp + wait = no + user = amandabackup + group = disk + groups = yes + server = /usr/libexec/amanda/amandad + server_args = -auth=bsdtcp amdump +} diff --git a/example/xinetd.amandaserver b/example/xinetd.amandaserver new file mode 100644 index 0000000..8279d4e --- /dev/null +++ b/example/xinetd.amandaserver @@ -0,0 +1,19 @@ +# default: on +# +# description: Amanda services for Amanda server and client. +# + +service amanda +{ + disable = no + flags = IPv4 + flags = IPv6 + socket_type = stream + protocol = tcp + wait = no + user = amandabackup + group = disk + groups = yes + server = /usr/libexec/amanda/amandad + server_args = -auth=bsdtcp amdump amindexd amidxtaped +} diff --git a/gnulib/base64.c b/gnulib/base64.c new file mode 100644 index 0000000..f237cd6 --- /dev/null +++ b/gnulib/base64.c @@ -0,0 +1,425 @@ +/* base64.c -- Encode binary data using printable characters. + Copyright (C) 1999, 2000, 2001, 2004, 2005, 2006 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Simon Josefsson. Partially adapted from GNU MailUtils + * (mailbox/filter_trans.c, as of 2004-11-28). Improved by review + * from Paul Eggert, Bruno Haible, and Stepan Kasal. + * + * See also RFC 3548 . + * + * Be careful with error checking. Here is how you would typically + * use these functions: + * + * bool ok = base64_decode_alloc (in, inlen, &out, &outlen); + * if (!ok) + * FAIL: input was not valid base64 + * if (out == NULL) + * FAIL: memory allocation error + * OK: data in OUT/OUTLEN + * + * size_t outlen = base64_encode_alloc (in, inlen, &out); + * if (out == NULL && outlen == 0 && inlen != 0) + * FAIL: input too long + * if (out == NULL) + * FAIL: memory allocation error + * OK: data in OUT/OUTLEN. + * + */ + +#include + +/* Get prototype. */ +#include "base64.h" + +/* Get malloc. */ +#include + +/* Get UCHAR_MAX. */ +#include + +/* C89 compliant way to cast 'char' to 'unsigned char'. */ +static inline unsigned char +to_uchar (char ch) +{ + return ch; +} + +/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN. + If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as + possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero + terminate the output buffer. */ +void +base64_encode (const char *restrict in, size_t inlen, + char *restrict out, size_t outlen) +{ + static const char b64str[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + while (inlen && outlen) + { + *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f]; + if (!--outlen) + break; + *out++ = b64str[((to_uchar (in[0]) << 4) + + (--inlen ? to_uchar (in[1]) >> 4 : 0)) + & 0x3f]; + if (!--outlen) + break; + *out++ = + (inlen + ? b64str[((to_uchar (in[1]) << 2) + + (--inlen ? to_uchar (in[2]) >> 6 : 0)) + & 0x3f] + : '='); + if (!--outlen) + break; + *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '='; + if (!--outlen) + break; + if (inlen) + inlen--; + if (inlen) + in += 3; + } + + if (outlen) + *out = '\0'; +} + +/* Allocate a buffer and store zero terminated base64 encoded data + from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e., + the length of the encoded data, excluding the terminating zero. On + return, the OUT variable will hold a pointer to newly allocated + memory that must be deallocated by the caller. If output string + length would overflow, 0 is returned and OUT is set to NULL. If + memory allocation failed, OUT is set to NULL, and the return value + indicates length of the requested memory block, i.e., + BASE64_LENGTH(inlen) + 1. */ +size_t +base64_encode_alloc (const char *in, size_t inlen, char **out) +{ + size_t outlen = 1 + BASE64_LENGTH (inlen); + + /* Check for overflow in outlen computation. + * + * If there is no overflow, outlen >= inlen. + * + * If the operation (inlen + 2) overflows then it yields at most +1, so + * outlen is 0. + * + * If the multiplication overflows, we lose at least half of the + * correct value, so the result is < ((inlen + 2) / 3) * 2, which is + * less than (inlen + 2) * 0.66667, which is less than inlen as soon as + * (inlen > 4). + */ + if (inlen > outlen) + { + *out = NULL; + return 0; + } + + *out = malloc (outlen); + if (!*out) + return outlen; + + base64_encode (in, inlen, *out, outlen); + + return outlen - 1; +} + +/* With this approach this file works independent of the charset used + (think EBCDIC). However, it does assume that the characters in the + Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX + 1003.1-2001 require that char and unsigned char are 8-bit + quantities, though, taking care of that problem. But this may be a + potential problem on non-POSIX C99 platforms. + + IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_" + as the formal parameter rather than "x". */ +#define B64(_) \ + ((_) == 'A' ? 0 \ + : (_) == 'B' ? 1 \ + : (_) == 'C' ? 2 \ + : (_) == 'D' ? 3 \ + : (_) == 'E' ? 4 \ + : (_) == 'F' ? 5 \ + : (_) == 'G' ? 6 \ + : (_) == 'H' ? 7 \ + : (_) == 'I' ? 8 \ + : (_) == 'J' ? 9 \ + : (_) == 'K' ? 10 \ + : (_) == 'L' ? 11 \ + : (_) == 'M' ? 12 \ + : (_) == 'N' ? 13 \ + : (_) == 'O' ? 14 \ + : (_) == 'P' ? 15 \ + : (_) == 'Q' ? 16 \ + : (_) == 'R' ? 17 \ + : (_) == 'S' ? 18 \ + : (_) == 'T' ? 19 \ + : (_) == 'U' ? 20 \ + : (_) == 'V' ? 21 \ + : (_) == 'W' ? 22 \ + : (_) == 'X' ? 23 \ + : (_) == 'Y' ? 24 \ + : (_) == 'Z' ? 25 \ + : (_) == 'a' ? 26 \ + : (_) == 'b' ? 27 \ + : (_) == 'c' ? 28 \ + : (_) == 'd' ? 29 \ + : (_) == 'e' ? 30 \ + : (_) == 'f' ? 31 \ + : (_) == 'g' ? 32 \ + : (_) == 'h' ? 33 \ + : (_) == 'i' ? 34 \ + : (_) == 'j' ? 35 \ + : (_) == 'k' ? 36 \ + : (_) == 'l' ? 37 \ + : (_) == 'm' ? 38 \ + : (_) == 'n' ? 39 \ + : (_) == 'o' ? 40 \ + : (_) == 'p' ? 41 \ + : (_) == 'q' ? 42 \ + : (_) == 'r' ? 43 \ + : (_) == 's' ? 44 \ + : (_) == 't' ? 45 \ + : (_) == 'u' ? 46 \ + : (_) == 'v' ? 47 \ + : (_) == 'w' ? 48 \ + : (_) == 'x' ? 49 \ + : (_) == 'y' ? 50 \ + : (_) == 'z' ? 51 \ + : (_) == '0' ? 52 \ + : (_) == '1' ? 53 \ + : (_) == '2' ? 54 \ + : (_) == '3' ? 55 \ + : (_) == '4' ? 56 \ + : (_) == '5' ? 57 \ + : (_) == '6' ? 58 \ + : (_) == '7' ? 59 \ + : (_) == '8' ? 60 \ + : (_) == '9' ? 61 \ + : (_) == '+' ? 62 \ + : (_) == '/' ? 63 \ + : -1) + +static const signed char b64[0x100] = { + B64 (0), B64 (1), B64 (2), B64 (3), + B64 (4), B64 (5), B64 (6), B64 (7), + B64 (8), B64 (9), B64 (10), B64 (11), + B64 (12), B64 (13), B64 (14), B64 (15), + B64 (16), B64 (17), B64 (18), B64 (19), + B64 (20), B64 (21), B64 (22), B64 (23), + B64 (24), B64 (25), B64 (26), B64 (27), + B64 (28), B64 (29), B64 (30), B64 (31), + B64 (32), B64 (33), B64 (34), B64 (35), + B64 (36), B64 (37), B64 (38), B64 (39), + B64 (40), B64 (41), B64 (42), B64 (43), + B64 (44), B64 (45), B64 (46), B64 (47), + B64 (48), B64 (49), B64 (50), B64 (51), + B64 (52), B64 (53), B64 (54), B64 (55), + B64 (56), B64 (57), B64 (58), B64 (59), + B64 (60), B64 (61), B64 (62), B64 (63), + B64 (64), B64 (65), B64 (66), B64 (67), + B64 (68), B64 (69), B64 (70), B64 (71), + B64 (72), B64 (73), B64 (74), B64 (75), + B64 (76), B64 (77), B64 (78), B64 (79), + B64 (80), B64 (81), B64 (82), B64 (83), + B64 (84), B64 (85), B64 (86), B64 (87), + B64 (88), B64 (89), B64 (90), B64 (91), + B64 (92), B64 (93), B64 (94), B64 (95), + B64 (96), B64 (97), B64 (98), B64 (99), + B64 (100), B64 (101), B64 (102), B64 (103), + B64 (104), B64 (105), B64 (106), B64 (107), + B64 (108), B64 (109), B64 (110), B64 (111), + B64 (112), B64 (113), B64 (114), B64 (115), + B64 (116), B64 (117), B64 (118), B64 (119), + B64 (120), B64 (121), B64 (122), B64 (123), + B64 (124), B64 (125), B64 (126), B64 (127), + B64 (128), B64 (129), B64 (130), B64 (131), + B64 (132), B64 (133), B64 (134), B64 (135), + B64 (136), B64 (137), B64 (138), B64 (139), + B64 (140), B64 (141), B64 (142), B64 (143), + B64 (144), B64 (145), B64 (146), B64 (147), + B64 (148), B64 (149), B64 (150), B64 (151), + B64 (152), B64 (153), B64 (154), B64 (155), + B64 (156), B64 (157), B64 (158), B64 (159), + B64 (160), B64 (161), B64 (162), B64 (163), + B64 (164), B64 (165), B64 (166), B64 (167), + B64 (168), B64 (169), B64 (170), B64 (171), + B64 (172), B64 (173), B64 (174), B64 (175), + B64 (176), B64 (177), B64 (178), B64 (179), + B64 (180), B64 (181), B64 (182), B64 (183), + B64 (184), B64 (185), B64 (186), B64 (187), + B64 (188), B64 (189), B64 (190), B64 (191), + B64 (192), B64 (193), B64 (194), B64 (195), + B64 (196), B64 (197), B64 (198), B64 (199), + B64 (200), B64 (201), B64 (202), B64 (203), + B64 (204), B64 (205), B64 (206), B64 (207), + B64 (208), B64 (209), B64 (210), B64 (211), + B64 (212), B64 (213), B64 (214), B64 (215), + B64 (216), B64 (217), B64 (218), B64 (219), + B64 (220), B64 (221), B64 (222), B64 (223), + B64 (224), B64 (225), B64 (226), B64 (227), + B64 (228), B64 (229), B64 (230), B64 (231), + B64 (232), B64 (233), B64 (234), B64 (235), + B64 (236), B64 (237), B64 (238), B64 (239), + B64 (240), B64 (241), B64 (242), B64 (243), + B64 (244), B64 (245), B64 (246), B64 (247), + B64 (248), B64 (249), B64 (250), B64 (251), + B64 (252), B64 (253), B64 (254), B64 (255) +}; + +#if UCHAR_MAX == 255 +# define uchar_in_range(c) true +#else +# define uchar_in_range(c) ((c) <= 255) +#endif + +/* Return true if CH is a character from the Base64 alphabet, and + false otherwise. Note that '=' is padding and not considered to be + part of the alphabet. */ +bool +isbase64 (char ch) +{ + return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)]; +} + +/* Decode base64 encoded input array IN of length INLEN to output + array OUT that can hold *OUTLEN bytes. Return true if decoding was + successful, i.e. if the input was valid base64 data, false + otherwise. If *OUTLEN is too small, as many bytes as possible will + be written to OUT. On return, *OUTLEN holds the length of decoded + bytes in OUT. Note that as soon as any non-alphabet characters are + encountered, decoding is stopped and false is returned. This means + that, when applicable, you must remove any line terminators that is + part of the data stream before calling this function. */ +bool +base64_decode (const char *restrict in, size_t inlen, + char *restrict out, size_t *outlen) +{ + size_t outleft = *outlen; + + while (inlen >= 2) + { + if (!isbase64 (in[0]) || !isbase64 (in[1])) + break; + + if (outleft) + { + *out++ = ((b64[to_uchar (in[0])] << 2) + | (b64[to_uchar (in[1])] >> 4)); + outleft--; + } + + if (inlen == 2) + break; + + if (in[2] == '=') + { + if (inlen != 4) + break; + + if (in[3] != '=') + break; + + } + else + { + if (!isbase64 (in[2])) + break; + + if (outleft) + { + *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0) + | (b64[to_uchar (in[2])] >> 2)); + outleft--; + } + + if (inlen == 3) + break; + + if (in[3] == '=') + { + if (inlen != 4) + break; + } + else + { + if (!isbase64 (in[3])) + break; + + if (outleft) + { + *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0) + | b64[to_uchar (in[3])]); + outleft--; + } + } + } + + in += 4; + inlen -= 4; + } + + *outlen -= outleft; + + if (inlen != 0) + return false; + + return true; +} + +/* Allocate an output buffer in *OUT, and decode the base64 encoded + data stored in IN of size INLEN to the *OUT buffer. On return, the + size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL, + if the caller is not interested in the decoded length. *OUT may be + NULL to indicate an out of memory error, in which case *OUTLEN + contains the size of the memory block needed. The function returns + true on successful decoding and memory allocation errors. (Use the + *OUT and *OUTLEN parameters to differentiate between successful + decoding and memory error.) The function returns false if the + input was invalid, in which case *OUT is NULL and *OUTLEN is + undefined. */ +bool +base64_decode_alloc (const char *in, size_t inlen, char **out, + size_t *outlen) +{ + /* This may allocate a few bytes too much, depending on input, + but it's not worth the extra CPU time to compute the exact amount. + The exact amount is 3 * inlen / 4, minus 1 if the input ends + with "=" and minus another 1 if the input ends with "==". + Dividing before multiplying avoids the possibility of overflow. */ + size_t needlen = 3 * (inlen / 4) + 2; + + *out = malloc (needlen); + if (!*out) + return true; + + if (!base64_decode (in, inlen, *out, &needlen)) + { + free (*out); + *out = NULL; + return false; + } + + if (outlen) + *outlen = needlen; + + return true; +} diff --git a/gnulib/base64.h b/gnulib/base64.h new file mode 100644 index 0000000..6bb9a97 --- /dev/null +++ b/gnulib/base64.h @@ -0,0 +1,45 @@ +/* base64.h -- Encode binary data using printable characters. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef BASE64_H +# define BASE64_H + +/* Get size_t. */ +# include + +/* Get bool. */ +# include + +/* This uses that the expression (n+(k-1))/k means the smallest + integer >= n/k, i.e., the ceiling of n/k. */ +# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4) + +extern bool isbase64 (char ch); + +extern void base64_encode (const char *restrict in, size_t inlen, + char *restrict out, size_t outlen); + +extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out); + +extern bool base64_decode (const char *restrict in, size_t inlen, + char *restrict out, size_t *outlen); + +extern bool base64_decode_alloc (const char *in, size_t inlen, + char **out, size_t *outlen); + +#endif /* BASE64_H */ diff --git a/gnulib/float+.h b/gnulib/float+.h new file mode 100644 index 0000000..4de25a9 --- /dev/null +++ b/gnulib/float+.h @@ -0,0 +1,148 @@ +/* Supplemental information about the floating-point formats. + Copyright (C) 2007 Free Software Foundation, Inc. + Written by Bruno Haible , 2007. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _FLOATPLUS_H +#define _FLOATPLUS_H + +#include +#include + +/* Number of bits in the mantissa of a floating-point number, including the + "hidden bit". */ +#if FLT_RADIX == 2 +# define FLT_MANT_BIT FLT_MANT_DIG +# define DBL_MANT_BIT DBL_MANT_DIG +# define LDBL_MANT_BIT LDBL_MANT_DIG +#elif FLT_RADIX == 4 +# define FLT_MANT_BIT (FLT_MANT_DIG * 2) +# define DBL_MANT_BIT (DBL_MANT_DIG * 2) +# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2) +#elif FLT_RADIX == 16 +# define FLT_MANT_BIT (FLT_MANT_DIG * 4) +# define DBL_MANT_BIT (DBL_MANT_DIG * 4) +# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4) +#endif + +/* Bit mask that can be used to mask the exponent, as an unsigned number. */ +#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7) +#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) +#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7) + +/* Number of bits used for the exponent of a floating-point number, including + the exponent's sign. */ +#define FLT_EXP_BIT \ + (FLT_EXP_MASK < 0x100 ? 8 : \ + FLT_EXP_MASK < 0x200 ? 9 : \ + FLT_EXP_MASK < 0x400 ? 10 : \ + FLT_EXP_MASK < 0x800 ? 11 : \ + FLT_EXP_MASK < 0x1000 ? 12 : \ + FLT_EXP_MASK < 0x2000 ? 13 : \ + FLT_EXP_MASK < 0x4000 ? 14 : \ + FLT_EXP_MASK < 0x8000 ? 15 : \ + FLT_EXP_MASK < 0x10000 ? 16 : \ + FLT_EXP_MASK < 0x20000 ? 17 : \ + FLT_EXP_MASK < 0x40000 ? 18 : \ + FLT_EXP_MASK < 0x80000 ? 19 : \ + FLT_EXP_MASK < 0x100000 ? 20 : \ + FLT_EXP_MASK < 0x200000 ? 21 : \ + FLT_EXP_MASK < 0x400000 ? 22 : \ + FLT_EXP_MASK < 0x800000 ? 23 : \ + FLT_EXP_MASK < 0x1000000 ? 24 : \ + FLT_EXP_MASK < 0x2000000 ? 25 : \ + FLT_EXP_MASK < 0x4000000 ? 26 : \ + FLT_EXP_MASK < 0x8000000 ? 27 : \ + FLT_EXP_MASK < 0x10000000 ? 28 : \ + FLT_EXP_MASK < 0x20000000 ? 29 : \ + FLT_EXP_MASK < 0x40000000 ? 30 : \ + FLT_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) +#define DBL_EXP_BIT \ + (DBL_EXP_MASK < 0x100 ? 8 : \ + DBL_EXP_MASK < 0x200 ? 9 : \ + DBL_EXP_MASK < 0x400 ? 10 : \ + DBL_EXP_MASK < 0x800 ? 11 : \ + DBL_EXP_MASK < 0x1000 ? 12 : \ + DBL_EXP_MASK < 0x2000 ? 13 : \ + DBL_EXP_MASK < 0x4000 ? 14 : \ + DBL_EXP_MASK < 0x8000 ? 15 : \ + DBL_EXP_MASK < 0x10000 ? 16 : \ + DBL_EXP_MASK < 0x20000 ? 17 : \ + DBL_EXP_MASK < 0x40000 ? 18 : \ + DBL_EXP_MASK < 0x80000 ? 19 : \ + DBL_EXP_MASK < 0x100000 ? 20 : \ + DBL_EXP_MASK < 0x200000 ? 21 : \ + DBL_EXP_MASK < 0x400000 ? 22 : \ + DBL_EXP_MASK < 0x800000 ? 23 : \ + DBL_EXP_MASK < 0x1000000 ? 24 : \ + DBL_EXP_MASK < 0x2000000 ? 25 : \ + DBL_EXP_MASK < 0x4000000 ? 26 : \ + DBL_EXP_MASK < 0x8000000 ? 27 : \ + DBL_EXP_MASK < 0x10000000 ? 28 : \ + DBL_EXP_MASK < 0x20000000 ? 29 : \ + DBL_EXP_MASK < 0x40000000 ? 30 : \ + DBL_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) +#define LDBL_EXP_BIT \ + (LDBL_EXP_MASK < 0x100 ? 8 : \ + LDBL_EXP_MASK < 0x200 ? 9 : \ + LDBL_EXP_MASK < 0x400 ? 10 : \ + LDBL_EXP_MASK < 0x800 ? 11 : \ + LDBL_EXP_MASK < 0x1000 ? 12 : \ + LDBL_EXP_MASK < 0x2000 ? 13 : \ + LDBL_EXP_MASK < 0x4000 ? 14 : \ + LDBL_EXP_MASK < 0x8000 ? 15 : \ + LDBL_EXP_MASK < 0x10000 ? 16 : \ + LDBL_EXP_MASK < 0x20000 ? 17 : \ + LDBL_EXP_MASK < 0x40000 ? 18 : \ + LDBL_EXP_MASK < 0x80000 ? 19 : \ + LDBL_EXP_MASK < 0x100000 ? 20 : \ + LDBL_EXP_MASK < 0x200000 ? 21 : \ + LDBL_EXP_MASK < 0x400000 ? 22 : \ + LDBL_EXP_MASK < 0x800000 ? 23 : \ + LDBL_EXP_MASK < 0x1000000 ? 24 : \ + LDBL_EXP_MASK < 0x2000000 ? 25 : \ + LDBL_EXP_MASK < 0x4000000 ? 26 : \ + LDBL_EXP_MASK < 0x8000000 ? 27 : \ + LDBL_EXP_MASK < 0x10000000 ? 28 : \ + LDBL_EXP_MASK < 0x20000000 ? 29 : \ + LDBL_EXP_MASK < 0x40000000 ? 30 : \ + LDBL_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) + +/* Number of bits used for a floating-point number: the mantissa (not + counting the "hidden bit", since it may or may not be explicit), the + exponent, and the sign. */ +#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1) +#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1) +#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1) + +/* Number of bytes used for a floating-point number. + This can be smaller than the 'sizeof'. For example, on i386 systems, + 'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence + LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but + sizeof (long double) = 12 or = 16. */ +#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) +#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) +#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) + +/* Verify that SIZEOF_FLT <= sizeof (float) etc. */ +typedef int verify_sizeof_flt[2 * (SIZEOF_FLT <= sizeof (float)) - 1]; +typedef int verify_sizeof_dbl[2 * (SIZEOF_DBL <= sizeof (double)) - 1]; +typedef int verify_sizeof_ldbl[2 * (SIZEOF_LDBL <= sizeof (long double)) - 1]; + +#endif /* _FLOATPLUS_H */ diff --git a/gnulib/float_.h b/gnulib/float_.h new file mode 100644 index 0000000..d61d630 --- /dev/null +++ b/gnulib/float_.h @@ -0,0 +1,59 @@ +/* A correct . + + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _GL_FLOAT_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_FLOAT_H@ + +#ifndef _GL_FLOAT_H +#define _GL_FLOAT_H + +/* 'long double' properties. */ +#if defined __i386__ && defined __BEOS__ +/* Number of mantissa units, in base FLT_RADIX. */ +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 64 +/* Number of decimal digits that is sufficient for representing a number. */ +# undef LDBL_DIG +# define LDBL_DIG 18 +/* x-1 where x is the smallest representable number > 1. */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 1.0842021724855044340E-19L +/* Minimum e such that FLT_RADIX^(e-1) is a normalized number. */ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number. */ +# undef LDBL_MAX_EXP +# define LDBL_MAX_EXP 16384 +/* Minimum positive normalized number. */ +# undef LDBL_MIN +# define LDBL_MIN 3.3621031431120935063E-4932L +/* Maximum representable finite number. */ +# undef LDBL_MAX +# define LDBL_MAX 1.1897314953572317650E+4932L +/* Minimum e such that 10^e is in the range of normalized numbers. */ +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP (-4931) +/* Maximum e such that 10^e is in the range of representable finite numbers. */ +# undef LDBL_MAX_10_EXP +# define LDBL_MAX_10_EXP 4932 +#endif + +#endif /* _GL_FLOAT_H */ +#endif /* _GL_FLOAT_H */ diff --git a/gnulib/fsusage.c b/gnulib/fsusage.c new file mode 100644 index 0000000..337bf53 --- /dev/null +++ b/gnulib/fsusage.c @@ -0,0 +1,264 @@ +/* fsusage.c -- return space usage of mounted file systems + + Copyright (C) 1991, 1992, 1996, 1998, 1999, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +#include "fsusage.h" + +#include +#include + +#if STAT_STATVFS /* POSIX 1003.1-2001 (and later) with XSI */ +# include +#else +/* Don't include backward-compatibility files unless they're needed. + Eventually we'd like to remove all this cruft. */ +# include +# include +# include +# if HAVE_SYS_PARAM_H +# include +# endif +# if HAVE_SYS_MOUNT_H +# include +# endif +# if HAVE_SYS_VFS_H +# include +# endif +# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ +# include +# endif +# if defined HAVE_SYS_FILSYS_H && !defined _CRAY +# include /* SVR2 */ +# endif +# if HAVE_SYS_STATFS_H +# include +# endif +# if HAVE_DUSTAT_H /* AIX PS/2 */ +# include +# endif +# include "full-read.h" +#endif + +/* The results of open() in this file are not used with fchdir, + therefore save some unnecessary work in fchdir.c. */ +#undef open +#undef close + +/* Many space usage primitives use all 1 bits to denote a value that is + not applicable or unknown. Propagate this information by returning + a uintmax_t value that is all 1 bits if X is all 1 bits, even if X + is unsigned and narrower than uintmax_t. */ +#define PROPAGATE_ALL_ONES(x) \ + ((sizeof (x) < sizeof (uintmax_t) \ + && (~ (x) == (sizeof (x) < sizeof (int) \ + ? - (1 << (sizeof (x) * CHAR_BIT)) \ + : 0))) \ + ? UINTMAX_MAX : (uintmax_t) (x)) + +/* Extract the top bit of X as an uintmax_t value. */ +#define EXTRACT_TOP_BIT(x) ((x) \ + & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1))) + +/* If a value is negative, many space usage primitives store it into an + integer variable by assignment, even if the variable's type is unsigned. + So, if a space usage variable X's top bit is set, convert X to the + uintmax_t value V such that (- (uintmax_t) V) is the negative of + the original value. If X's top bit is clear, just yield X. + Use PROPAGATE_TOP_BIT if the original value might be negative; + otherwise, use PROPAGATE_ALL_ONES. */ +#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) + +/* Fill in the fields of FSP with information about space usage for + the file system on which FILE resides. + DISK is the device on which FILE is mounted, for space-getting + methods that need to know it. + Return 0 if successful, -1 if not. When returning -1, ensure that + ERRNO is either a system error value, or zero if DISK is NULL + on a system that requires a non-NULL value. */ +int +get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) +{ +#if defined STAT_STATVFS /* POSIX */ + + struct statvfs fsd; + + if (statvfs (file, &fsd) < 0) + return -1; + + /* f_frsize isn't guaranteed to be supported. */ + fsp->fsu_blocksize = (fsd.f_frsize + ? PROPAGATE_ALL_ONES (fsd.f_frsize) + : PROPAGATE_ALL_ONES (fsd.f_bsize)); + +#elif defined STAT_STATFS2_FS_DATA /* Ultrix */ + + struct fs_data fsd; + + if (statfs (file, &fsd) != 1) + return -1; + + fsp->fsu_blocksize = 1024; + fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0; + fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree); + +#elif defined STAT_READ_FILSYS /* SVR2 */ +# ifndef SUPERBOFF +# define SUPERBOFF (SUPERB * 512) +# endif + + struct filsys fsd; + int fd; + + if (! disk) + { + errno = 0; + return -1; + } + + fd = open (disk, O_RDONLY); + if (fd < 0) + return -1; + lseek (fd, (off_t) SUPERBOFF, 0); + if (full_read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd) + { + close (fd); + return -1; + } + close (fd); + + fsp->fsu_blocksize = (fsd.s_type == Fs2b ? 1024 : 512); + fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.s_fsize); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.s_tfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.s_tfree); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.s_tfree) != 0; + fsp->fsu_files = (fsd.s_isize == -1 + ? UINTMAX_MAX + : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1)); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode); + +#elif defined STAT_STATFS3_OSF1 + + struct statfs fsd; + + if (statfs (file, &fsd, sizeof (struct statfs)) != 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); + +#elif defined STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ + + struct statfs fsd; + + if (statfs (file, &fsd) < 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); + +# ifdef STATFS_TRUNCATES_BLOCK_COUNTS + + /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the + struct statfs are truncated to 2GB. These conditions detect that + truncation, presumably without botching the 4.1.1 case, in which + the values are not truncated. The correct counts are stored in + undocumented spare fields. */ + if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0) + { + fsd.f_blocks = fsd.f_spare[0]; + fsd.f_bfree = fsd.f_spare[1]; + fsd.f_bavail = fsd.f_spare[2]; + } +# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ + +#elif defined STAT_STATFS2_FSIZE /* 4.4BSD */ + + struct statfs fsd; + + if (statfs (file, &fsd) < 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); + +#elif defined STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ + +# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN +# define f_bavail f_bfree +# endif + + struct statfs fsd; + + if (statfs (file, &fsd, sizeof fsd, 0) < 0) + return -1; + + /* Empirically, the block counts on most SVR3 and SVR3-derived + systems seem to always be in terms of 512-byte blocks, + no matter what value f_bsize has. */ +# if _AIX || defined _CRAY + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); +# else + fsp->fsu_blocksize = 512; +# endif + +#endif + +#if (defined STAT_STATVFS \ + || (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS)) + + fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0; + fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree); + +#endif + + return 0; +} + +#if defined _AIX && defined _I386 +/* AIX PS/2 does not supply statfs. */ + +int +statfs (char *file, struct statfs *fsb) +{ + struct stat stats; + struct dustat fsd; + + if (stat (file, &stats) != 0) + return -1; + if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) + return -1; + fsb->f_type = 0; + fsb->f_bsize = fsd.du_bsize; + fsb->f_blocks = fsd.du_fsize - fsd.du_isize; + fsb->f_bfree = fsd.du_tfree; + fsb->f_bavail = fsd.du_tfree; + fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb; + fsb->f_ffree = fsd.du_tinode; + fsb->f_fsid.val[0] = fsd.du_site; + fsb->f_fsid.val[1] = fsd.du_pckno; + return 0; +} + +#endif /* _AIX && _I386 */ diff --git a/gnulib/fsusage.h b/gnulib/fsusage.h new file mode 100644 index 0000000..7fa9f8d --- /dev/null +++ b/gnulib/fsusage.h @@ -0,0 +1,41 @@ +/* fsusage.h -- declarations for file system space usage info + + Copyright (C) 1991, 1992, 1997, 2003, 2004, 2005, 2006 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Space usage statistics for a file system. Blocks are 512-byte. */ + +#if !defined FSUSAGE_H_ +# define FSUSAGE_H_ + +# include +# include + +struct fs_usage +{ + uintmax_t fsu_blocksize; /* Size of a block. */ + uintmax_t fsu_blocks; /* Total blocks. */ + uintmax_t fsu_bfree; /* Free blocks available to superuser. */ + uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */ + bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */ + uintmax_t fsu_files; /* Total file nodes. */ + uintmax_t fsu_ffree; /* Free file nodes. */ +}; + +int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp); + +#endif diff --git a/gnulib/full-read.c b/gnulib/full-read.c new file mode 100644 index 0000000..8c3472a --- /dev/null +++ b/gnulib/full-read.c @@ -0,0 +1,19 @@ +/* An interface to read that retries after partial reads and interrupts. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#define FULL_READ +#include "full-write.c" diff --git a/gnulib/full-read.h b/gnulib/full-read.h new file mode 100644 index 0000000..05d83a7 --- /dev/null +++ b/gnulib/full-read.h @@ -0,0 +1,24 @@ +/* An interface to read() that reads all it is asked to read. + + Copyright (C) 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, read to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +/* Read COUNT bytes at BUF to descriptor FD, retrying if interrupted + or if partial reads occur. Return the number of bytes successfully + read, setting errno if that is less than COUNT. errno = 0 means EOF. */ +extern size_t full_read (int fd, void *buf, size_t count); diff --git a/gnulib/full-write.c b/gnulib/full-write.c new file mode 100644 index 0000000..cc16872 --- /dev/null +++ b/gnulib/full-write.c @@ -0,0 +1,81 @@ +/* An interface to read and write that retries (if necessary) until complete. + + Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + 2004, 2005, 2006 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +/* Specification. */ +#ifdef FULL_READ +# include "full-read.h" +#else +# include "full-write.h" +#endif + +#include + +#ifdef FULL_READ +# include "safe-read.h" +# define safe_rw safe_read +# define full_rw full_read +# undef const +# define const /* empty */ +#else +# include "safe-write.h" +# define safe_rw safe_write +# define full_rw full_write +#endif + +#ifdef FULL_READ +/* Set errno to zero upon EOF. */ +# define ZERO_BYTE_TRANSFER_ERRNO 0 +#else +/* Some buggy drivers return 0 when one tries to write beyond + a device's end. (Example: Linux 1.2.13 on /dev/fd0.) + Set errno to ENOSPC so they get a sensible diagnostic. */ +# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC +#endif + +/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if + interrupted or if a partial write(read) occurs. Return the number + of bytes transferred. + When writing, set errno if fewer than COUNT bytes are written. + When reading, if fewer than COUNT bytes are read, you must examine + errno to distinguish failure from EOF (errno == 0). */ +size_t +full_rw (int fd, const void *buf, size_t count) +{ + size_t total = 0; + const char *ptr = (const char *) buf; + + while (count > 0) + { + size_t n_rw = safe_rw (fd, ptr, count); + if (n_rw == (size_t) -1) + break; + if (n_rw == 0) + { + errno = ZERO_BYTE_TRANSFER_ERRNO; + break; + } + total += n_rw; + ptr += n_rw; + count -= n_rw; + } + + return total; +} diff --git a/gnulib/full-write.h b/gnulib/full-write.h new file mode 100644 index 0000000..d20d2fe --- /dev/null +++ b/gnulib/full-write.h @@ -0,0 +1,35 @@ +/* An interface to write() that writes all it is asked to write. + + Copyright (C) 2002-2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted + or if partial writes occur. Return the number of bytes successfully + written, setting errno if that is less than COUNT. */ +extern size_t full_write (int fd, const void *buf, size_t count); + + +#ifdef __cplusplus +} +#endif diff --git a/gnulib/gettimeofday.c b/gnulib/gettimeofday.c new file mode 100644 index 0000000..bd5576c --- /dev/null +++ b/gnulib/gettimeofday.c @@ -0,0 +1,142 @@ +/* Provide gettimeofday for systems that don't have it or for which it's broken. + + Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* written by Jim Meyering */ + +#include + +/* Specification. */ +#include + +#include + +#if HAVE_SYS_TIMEB_H +# include +#endif + +#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME + +/* Work around the bug in some systems whereby gettimeofday clobbers + the static buffer that localtime uses for its return value. The + gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has + this problem. The tzset replacement is necessary for at least + Solaris 2.5, 2.5.1, and 2.6. */ + +static struct tm tm_zero_buffer; +static struct tm *localtime_buffer_addr = &tm_zero_buffer; + +/* This is a wrapper for localtime. It is used only on systems for which + gettimeofday clobbers the static buffer used for localtime's result. + + On the first call, record the address of the static buffer that + localtime uses for its result. */ + +struct tm * +localtime (time_t const *timep) +{ +#undef localtime + extern struct tm *localtime (time_t const *); + struct tm *tm = localtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +/* Same as above, since gmtime and localtime use the same buffer. */ +struct tm * +gmtime (time_t const *timep) +{ +#undef gmtime + extern struct tm *gmtime (time_t const *); + struct tm *tm = gmtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */ + +#if TZSET_CLOBBERS_LOCALTIME +/* This is a wrapper for tzset, for systems on which tzset may clobber + the static buffer used for localtime's result. */ +void +tzset (void) +{ +#undef tzset + extern void tzset (void); + + /* Save and restore the contents of the buffer used for localtime's + result around the call to tzset. */ + struct tm save = *localtime_buffer_addr; + tzset (); + *localtime_buffer_addr = save; +} +#endif + +/* This is a wrapper for gettimeofday. It is used only on systems + that lack this function, or whose implementation of this function + causes problems. */ + +int +rpl_gettimeofday (struct timeval *restrict tv, void *restrict tz) +{ +#undef gettimeofday +#if HAVE_GETTIMEOFDAY +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + /* Save and restore the contents of the buffer used for localtime's + result around the call to gettimeofday. */ + struct tm save = *localtime_buffer_addr; +# endif + + int result = gettimeofday (tv, tz); + +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + *localtime_buffer_addr = save; +# endif + + return result; + +#else + +# if HAVE__FTIME + + struct _timeb timebuf; + _ftime (&timebuf); + tv->tv_sec = timebuf.time; + tv->tv_usec = timebuf.millitm * 1000; + +# else + +# if !defined OK_TO_USE_1S_CLOCK +# error "Only 1-second nominal clock resolution found. Is that intended?" \ + "If so, compile with the -DOK_TO_USE_1S_CLOCK option." +# endif + tv->tv_sec = time (NULL); + tv->tv_usec = 0; + +# endif + + return 0; + +#endif +} diff --git a/gnulib/malloc.c b/gnulib/malloc.c new file mode 100644 index 0000000..eba131d --- /dev/null +++ b/gnulib/malloc.c @@ -0,0 +1,57 @@ +/* malloc() function that is glibc compatible. + + Copyright (C) 1997, 1998, 2006, 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* written by Jim Meyering and Bruno Haible */ + +#include +/* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h. */ +#ifdef malloc +# define NEED_MALLOC_GNU +# undef malloc +#endif + +/* Specification. */ +#include + +#include + +/* Call the system's malloc below. */ +#undef malloc + +/* Allocate an N-byte block of memory from the heap. + If N is zero, allocate a 1-byte block. */ + +void * +rpl_malloc (size_t n) +{ + void *result; + +#ifdef NEED_MALLOC_GNU + if (n == 0) + n = 1; +#endif + + result = malloc (n); + +#if !HAVE_MALLOC_POSIX + if (result == NULL) + errno = ENOMEM; +#endif + + return result; +} diff --git a/gnulib/mkdtemp.c b/gnulib/mkdtemp.c new file mode 100644 index 0000000..36b6c75 --- /dev/null +++ b/gnulib/mkdtemp.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1999, 2001-2003, 2006-2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Extracted from misc/mkdtemp.c. */ + +#include + +/* Specification. */ +#include + +#include "tempname.h" + +/* Generate a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + The directory is created, mode 700, and its name is returned. + (This function comes from OpenBSD.) */ +char * +mkdtemp (char *template) +{ + if (gen_tempname (template, GT_DIR)) + return NULL; + else + return template; +} diff --git a/gnulib/netinet_in_.h b/gnulib/netinet_in_.h new file mode 100644 index 0000000..aa00e45 --- /dev/null +++ b/gnulib/netinet_in_.h @@ -0,0 +1,43 @@ +/* Substitute for . + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _GL_NETINET_IN_H + +#if @HAVE_NETINET_IN_H@ + +/* On many platforms, assumes prior inclusion of + . */ +# include + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_NETINET_IN_H@ + +#endif + +#ifndef _GL_NETINET_IN_H +#define _GL_NETINET_IN_H + +#if !@HAVE_NETINET_IN_H@ + +/* A platform that lacks . */ + +# include + +#endif + +#endif /* _GL_NETINET_IN_H */ +#endif /* _GL_NETINET_IN_H */ diff --git a/gnulib/physmem.c b/gnulib/physmem.c new file mode 100644 index 0000000..844817b --- /dev/null +++ b/gnulib/physmem.c @@ -0,0 +1,305 @@ +/* Calculate the size of physical memory. + + Copyright (C) 2000, 2001, 2003, 2005, 2006 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Paul Eggert. */ + +#include + +#include "physmem.h" + +#include + +#if HAVE_SYS_PSTAT_H +# include +#endif + +#if HAVE_SYS_SYSMP_H +# include +#endif + +#if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H +# include +# include +#endif + +#if HAVE_SYS_TABLE_H +# include +#endif + +#include + +#if HAVE_SYS_PARAM_H +# include +#endif + +#if HAVE_SYS_SYSCTL_H +# include +#endif + +#if HAVE_SYS_SYSTEMCFG_H +# include +#endif + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +/* MEMORYSTATUSEX is missing from older windows headers, so define + a local replacement. */ +typedef struct +{ + DWORD dwLength; + DWORD dwMemoryLoad; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + DWORDLONG ullAvailExtendedVirtual; +} lMEMORYSTATUSEX; +typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); +#endif + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +/* Return the total amount of physical memory. */ +double +physmem_total (void) +{ +#if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE + { /* This works on linux-gnu, solaris2 and cygwin. */ + double pages = sysconf (_SC_PHYS_PAGES); + double pagesize = sysconf (_SC_PAGESIZE); + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } +#endif + +#if HAVE_PSTAT_GETSTATIC + { /* This works on hpux11. */ + struct pst_static pss; + if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)) + { + double pages = pss.physical_memory; + double pagesize = pss.page_size; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE + { /* This works on irix6. */ + struct rminfo realmem; + if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) + { + double pagesize = sysconf (_SC_PAGESIZE); + double pages = realmem.physmem; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_GETSYSINFO && defined GSI_PHYSMEM + { /* This works on Tru64 UNIX V4/5. */ + int physmem; + + if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem), + NULL, NULL, NULL) == 1) + { + double kbytes = physmem; + + if (0 <= kbytes) + return kbytes * 1024.0; + } + } +#endif + +#if HAVE_SYSCTL && defined HW_PHYSMEM + { /* This works on *bsd and darwin. */ + unsigned int physmem; + size_t len = sizeof physmem; + static int mib[2] = { CTL_HW, HW_PHYSMEM }; + + if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0 + && len == sizeof (physmem)) + return (double) physmem; + } +#endif + +#if HAVE__SYSTEM_CONFIGURATION + /* This works on AIX. */ + return _system_configuration.physmem; +#endif + +#if defined _WIN32 + { /* this works on windows */ + PFN_MS_EX pfnex; + HMODULE h = GetModuleHandle ("kernel32.dll"); + + if (!h) + return 0.0; + + /* Use GlobalMemoryStatusEx if available. */ + if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) + { + lMEMORYSTATUSEX lms_ex; + lms_ex.dwLength = sizeof lms_ex; + if (!pfnex (&lms_ex)) + return 0.0; + return (double) lms_ex.ullTotalPhys; + } + + /* Fall back to GlobalMemoryStatus which is always available. + but returns wrong results for physical memory > 4GB. */ + else + { + MEMORYSTATUS ms; + GlobalMemoryStatus (&ms); + return (double) ms.dwTotalPhys; + } + } +#endif + + /* Guess 64 MB. It's probably an older host, so guess small. */ + return 64 * 1024 * 1024; +} + +/* Return the amount of physical memory available. */ +double +physmem_available (void) +{ +#if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE + { /* This works on linux-gnu, solaris2 and cygwin. */ + double pages = sysconf (_SC_AVPHYS_PAGES); + double pagesize = sysconf (_SC_PAGESIZE); + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } +#endif + +#if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC + { /* This works on hpux11. */ + struct pst_static pss; + struct pst_dynamic psd; + if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0) + && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0)) + { + double pages = psd.psd_free; + double pagesize = pss.page_size; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE + { /* This works on irix6. */ + struct rminfo realmem; + if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0) + { + double pagesize = sysconf (_SC_PAGESIZE); + double pages = realmem.availrmem; + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_TABLE && defined TBL_VMSTATS + { /* This works on Tru64 UNIX V4/5. */ + struct tbl_vmstats vmstats; + + if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1) + { + double pages = vmstats.free_count; + double pagesize = vmstats.pagesize; + + if (0 <= pages && 0 <= pagesize) + return pages * pagesize; + } + } +#endif + +#if HAVE_SYSCTL && defined HW_USERMEM + { /* This works on *bsd and darwin. */ + unsigned int usermem; + size_t len = sizeof usermem; + static int mib[2] = { CTL_HW, HW_USERMEM }; + + if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0 + && len == sizeof (usermem)) + return (double) usermem; + } +#endif + +#if defined _WIN32 + { /* this works on windows */ + PFN_MS_EX pfnex; + HMODULE h = GetModuleHandle ("kernel32.dll"); + + if (!h) + return 0.0; + + /* Use GlobalMemoryStatusEx if available. */ + if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx"))) + { + lMEMORYSTATUSEX lms_ex; + lms_ex.dwLength = sizeof lms_ex; + if (!pfnex (&lms_ex)) + return 0.0; + return (double) lms_ex.ullAvailPhys; + } + + /* Fall back to GlobalMemoryStatus which is always available. + but returns wrong results for physical memory > 4GB */ + else + { + MEMORYSTATUS ms; + GlobalMemoryStatus (&ms); + return (double) ms.dwAvailPhys; + } + } +#endif + + /* Guess 25% of physical memory. */ + return physmem_total () / 4; +} + + +#if DEBUG + +# include +# include + +int +main (void) +{ + printf ("%12.f %12.f\n", physmem_total (), physmem_available ()); + exit (0); +} + +#endif /* DEBUG */ + +/* +Local Variables: +compile-command: "gcc -DDEBUG -g -O -Wall -W physmem.c" +End: +*/ diff --git a/gnulib/physmem.h b/gnulib/physmem.h new file mode 100644 index 0000000..931aede --- /dev/null +++ b/gnulib/physmem.h @@ -0,0 +1,27 @@ +/* Calculate the size of physical memory. + + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Paul Eggert. */ + +#ifndef PHYSMEM_H_ +# define PHYSMEM_H_ 1 + +double physmem_total (void); +double physmem_available (void); + +#endif /* PHYSMEM_H_ */ diff --git a/gnulib/regenerate/no-error.patch.BACKUP.7723.patch b/gnulib/regenerate/no-error.patch.BACKUP.7723.patch new file mode 100644 index 0000000..6dcbd67 --- /dev/null +++ b/gnulib/regenerate/no-error.patch.BACKUP.7723.patch @@ -0,0 +1,18 @@ +Index: gnulib/Makefile.am +=================================================================== +--- gnulib/Makefile.am (revision 5691) ++++ gnulib/Makefile.am (working copy) +@@ -26,6 +26,9 @@ + MAINTAINERCLEANFILES = + + AM_CPPFLAGS = ++if GCC_COMPILER +<<<<<<< HEAD:gnulib/regenerate/no-error.patch ++ AM_CFLAGS += -Wno-error +======= ++ AM_CFLAGS = -Wno-error -Wno-sign-compare +>>>>>>> upstream:gnulib/regenerate/no-error.patch ++endif + + noinst_LTLIBRARIES += libgnu.la + diff --git a/gnulib/regenerate/no-error.patch.LOCAL.7723.patch b/gnulib/regenerate/no-error.patch.LOCAL.7723.patch new file mode 100644 index 0000000..411d948 --- /dev/null +++ b/gnulib/regenerate/no-error.patch.LOCAL.7723.patch @@ -0,0 +1,14 @@ +Index: gnulib/Makefile.am +=================================================================== +--- gnulib/Makefile.am (revision 5691) ++++ gnulib/Makefile.am (working copy) +@@ -26,6 +26,9 @@ + MAINTAINERCLEANFILES = + + AM_CPPFLAGS = ++if GCC_COMPILER ++ AM_CFLAGS += -Wno-error ++endif + + noinst_LTLIBRARIES += libgnu.la + diff --git a/gnulib/regenerate/no-error.patch.REMOTE.7723.patch b/gnulib/regenerate/no-error.patch.REMOTE.7723.patch new file mode 100644 index 0000000..a12e7d2 --- /dev/null +++ b/gnulib/regenerate/no-error.patch.REMOTE.7723.patch @@ -0,0 +1,14 @@ +Index: gnulib/Makefile.am +=================================================================== +--- gnulib/Makefile.am (revision 5691) ++++ gnulib/Makefile.am (working copy) +@@ -26,6 +26,9 @@ + MAINTAINERCLEANFILES = + + AM_CPPFLAGS = ++if GCC_COMPILER ++ AM_CFLAGS = -Wno-error -Wno-sign-compare ++endif + + noinst_LTLIBRARIES += libgnu.la + diff --git a/gnulib/safe-read.c b/gnulib/safe-read.c new file mode 100644 index 0000000..b7bf1d5 --- /dev/null +++ b/gnulib/safe-read.c @@ -0,0 +1,78 @@ +/* An interface to read and write that retries after interrupts. + + Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free + Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +/* Specification. */ +#ifdef SAFE_WRITE +# include "safe-write.h" +#else +# include "safe-read.h" +#endif + +/* Get ssize_t. */ +#include +#include + +#include + +#ifdef EINTR +# define IS_EINTR(x) ((x) == EINTR) +#else +# define IS_EINTR(x) 0 +#endif + +#include + +#ifdef SAFE_WRITE +# define safe_rw safe_write +# define rw write +#else +# define safe_rw safe_read +# define rw read +# undef const +# define const /* empty */ +#endif + +/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if + interrupted. Return the actual number of bytes read(written), zero for EOF, + or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */ +size_t +safe_rw (int fd, void const *buf, size_t count) +{ + /* Work around a bug in Tru64 5.1. Attempting to read more than + INT_MAX bytes fails with errno == EINVAL. See + . + When decreasing COUNT, keep it block-aligned. */ + enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 }; + + for (;;) + { + ssize_t result = rw (fd, buf, count); + + if (0 <= result) + return result; + else if (IS_EINTR (errno)) + continue; + else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count) + count = BUGGY_READ_MAXIMUM; + else + return result; + } +} diff --git a/gnulib/safe-read.h b/gnulib/safe-read.h new file mode 100644 index 0000000..3451955 --- /dev/null +++ b/gnulib/safe-read.h @@ -0,0 +1,35 @@ +/* An interface to read() that retries after interrupts. + Copyright (C) 2002, 2006 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SAFE_READ_ERROR ((size_t) -1) + +/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted. + Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR + upon error. */ +extern size_t safe_read (int fd, void *buf, size_t count); + + +#ifdef __cplusplus +} +#endif diff --git a/gnulib/safe-write.c b/gnulib/safe-write.c new file mode 100644 index 0000000..4c375a6 --- /dev/null +++ b/gnulib/safe-write.c @@ -0,0 +1,19 @@ +/* An interface to write that retries after interrupts. + Copyright (C) 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#define SAFE_WRITE +#include "safe-read.c" diff --git a/gnulib/safe-write.h b/gnulib/safe-write.h new file mode 100644 index 0000000..c194636 --- /dev/null +++ b/gnulib/safe-write.h @@ -0,0 +1,25 @@ +/* An interface to write() that retries after interrupts. + Copyright (C) 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +#define SAFE_WRITE_ERROR ((size_t) -1) + +/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted. + Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR + upon error. */ +extern size_t safe_write (int fd, const void *buf, size_t count); diff --git a/gnulib/stdint_.h b/gnulib/stdint_.h new file mode 100644 index 0000000..121118c --- /dev/null +++ b/gnulib/stdint_.h @@ -0,0 +1,508 @@ +/* Copyright (C) 2001-2002, 2004-2007 Free Software Foundation, Inc. + Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. + This file is part of gnulib. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* + * ISO C 99 for platforms that lack it. + * + */ + +#ifndef _GL_STDINT_H + +/* Get those types that are already defined in other system include + files, so that we can "#define int8_t signed char" below without + worrying about a later system include file containing a "typedef + signed char int8_t;" that will get messed up by our macro. Our + macros should all be consistent with the system versions, except + for the "fast" types and macros, which we recommend against using + in public interfaces due to compiler differences. */ + +#if @HAVE_STDINT_H@ +# if defined __sgi && ! defined __c99 + /* Bypass IRIX's if in C89 mode, since it merely annoys users + with "This header file is to be used only for c99 mode compilations" + diagnostics. */ +# define __STDINT_H__ +# endif + /* Other systems may have an incomplete or buggy . + Include it before , since any "#include " + in would reinclude us, skipping our contents because + _GL_STDINT_H is defined. + The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#endif + +#if ! defined _GL_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H +#define _GL_STDINT_H + +/* defines some of the stdint.h types as well, on glibc, + IRIX 6.5, and OpenBSD 3.8 (via ). + AIX 5.2 isn't needed and causes troubles. + MacOS X 10.4.6 includes (which is us), but + relies on the system definitions, so include + after @NEXT_STDINT_H@. */ +#if @HAVE_SYS_TYPES_H@ && ! defined _AIX +# include +#endif + +/* Get LONG_MIN, LONG_MAX, ULONG_MAX. */ +#include + +#if @HAVE_INTTYPES_H@ + /* In OpenBSD 3.8, includes , which defines + int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. + also defines intptr_t and uintptr_t. */ +# define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H +# include +# undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H +#elif @HAVE_SYS_INTTYPES_H@ + /* Solaris 7 has the types except the *_fast*_t types, and + the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ +# include +#endif + +#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ + /* Linux libc4 >= 4.6.7 and libc5 have a that defines + int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is + included by . */ +# include +#endif + +#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS + +/* Get WCHAR_MIN, WCHAR_MAX. */ +# if ! (defined WCHAR_MIN && defined WCHAR_MAX) +# include +# endif + +#endif + +/* Minimum and maximum values for a integer type under the usual assumption. + Return an unspecified value if BITS == 0, adding a check to pacify + picky compilers. */ + +#define _STDINT_MIN(signed, bits, zero) \ + ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero)) + +#define _STDINT_MAX(signed, bits, zero) \ + ((signed) \ + ? ~ _STDINT_MIN (signed, bits, zero) \ + : ((((zero) + 1) << ((bits) ? (bits) - 1 : 0)) - 1) * 2 + 1) + +/* 7.18.1.1. Exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +#undef int8_t +#undef uint8_t +#define int8_t signed char +#define uint8_t unsigned char + +#undef int16_t +#undef uint16_t +#define int16_t short int +#define uint16_t unsigned short int + +#undef int32_t +#undef uint32_t +#define int32_t int +#define uint32_t unsigned int + +/* Do not undefine int64_t if gnulib is not being used with 64-bit + types, since otherwise it breaks platforms like Tandem/NSK. */ +#if LONG_MAX >> 31 >> 31 == 1 +# undef int64_t +# define int64_t long int +# define GL_INT64_T +#elif defined _MSC_VER +# undef int64_t +# define int64_t __int64 +# define GL_INT64_T +#elif @HAVE_LONG_LONG_INT@ +# undef int64_t +# define int64_t long long int +# define GL_INT64_T +#endif + +#if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# undef uint64_t +# define uint64_t unsigned long int +# define GL_UINT64_T +#elif defined _MSC_VER +# undef uint64_t +# define uint64_t unsigned __int64 +# define GL_UINT64_T +#elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# undef uint64_t +# define uint64_t unsigned long long int +# define GL_UINT64_T +#endif + +/* Avoid collision with Solaris 2.5.1 etc. */ +#define _UINT8_T +#define _UINT32_T +#define _UINT64_T + + +/* 7.18.1.2. Minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +#undef int_least8_t +#undef uint_least8_t +#undef int_least16_t +#undef uint_least16_t +#undef int_least32_t +#undef uint_least32_t +#undef int_least64_t +#undef uint_least64_t +#define int_least8_t int8_t +#define uint_least8_t uint8_t +#define int_least16_t int16_t +#define uint_least16_t uint16_t +#define int_least32_t int32_t +#define uint_least32_t uint32_t +#ifdef GL_INT64_T +# define int_least64_t int64_t +#endif +#ifdef GL_UINT64_T +# define uint_least64_t uint64_t +#endif + +/* 7.18.1.3. Fastest minimum-width integer types */ + +/* Note: Other substitutes may define these types differently. + It is not recommended to use these types in public header files. */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. Assume that 'long int' + is fast enough for all narrower integers. */ + +#undef int_fast8_t +#undef uint_fast8_t +#undef int_fast16_t +#undef uint_fast16_t +#undef int_fast32_t +#undef uint_fast32_t +#undef int_fast64_t +#undef uint_fast64_t +#define int_fast8_t long int +#define uint_fast8_t unsigned int_fast8_t +#define int_fast16_t long int +#define uint_fast16_t unsigned int_fast16_t +#define int_fast32_t long int +#define uint_fast32_t unsigned int_fast32_t +#ifdef GL_INT64_T +# define int_fast64_t int64_t +#endif +#ifdef GL_UINT64_T +# define uint_fast64_t uint64_t +#endif + +/* 7.18.1.4. Integer types capable of holding object pointers */ + +#undef intptr_t +#undef uintptr_t +#define intptr_t long int +#define uintptr_t unsigned long int + +/* 7.18.1.5. Greatest-width integer types */ + +/* Note: These types are compiler dependent. It may be unwise to use them in + public header files. */ + +#undef intmax_t +#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +# define intmax_t long long int +#elif defined GL_INT64_T +# define intmax_t int64_t +#else +# define intmax_t long int +#endif + +#undef uintmax_t +#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +# define uintmax_t unsigned long long int +#elif defined GL_UINT64_T +# define uintmax_t uint64_t +#else +# define uintmax_t unsigned long int +#endif + +/* 7.18.2. Limits of specified-width integer types */ + +#if ! defined __cplusplus || defined __STDC_LIMIT_MACROS + +/* 7.18.2.1. Limits of exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +#undef INT8_MIN +#undef INT8_MAX +#undef UINT8_MAX +#define INT8_MIN (~ INT8_MAX) +#define INT8_MAX 127 +#define UINT8_MAX 255 + +#undef INT16_MIN +#undef INT16_MAX +#undef UINT16_MAX +#define INT16_MIN (~ INT16_MAX) +#define INT16_MAX 32767 +#define UINT16_MAX 65535 + +#undef INT32_MIN +#undef INT32_MAX +#undef UINT32_MAX +#define INT32_MIN (~ INT32_MAX) +#define INT32_MAX 2147483647 +#define UINT32_MAX 4294967295U + +#undef INT64_MIN +#undef INT64_MAX +#ifdef GL_INT64_T +/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0 + evaluates the latter incorrectly in preprocessor expressions. */ +# define INT64_MIN (- INTMAX_C (1) << 63) +# define INT64_MAX INTMAX_C (9223372036854775807) +#endif + +#undef UINT64_MAX +#ifdef GL_UINT64_T +# define UINT64_MAX UINTMAX_C (18446744073709551615) +#endif + +/* 7.18.2.2. Limits of minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +#undef INT_LEAST8_MIN +#undef INT_LEAST8_MAX +#undef UINT_LEAST8_MAX +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#undef INT_LEAST16_MIN +#undef INT_LEAST16_MAX +#undef UINT_LEAST16_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#undef INT_LEAST32_MIN +#undef INT_LEAST32_MAX +#undef UINT_LEAST32_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#undef INT_LEAST64_MIN +#undef INT_LEAST64_MAX +#ifdef GL_INT64_T +# define INT_LEAST64_MIN INT64_MIN +# define INT_LEAST64_MAX INT64_MAX +#endif + +#undef UINT_LEAST64_MAX +#ifdef GL_UINT64_T +# define UINT_LEAST64_MAX UINT64_MAX +#endif + +/* 7.18.2.3. Limits of fastest minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. */ + +#undef INT_FAST8_MIN +#undef INT_FAST8_MAX +#undef UINT_FAST8_MAX +#define INT_FAST8_MIN LONG_MIN +#define INT_FAST8_MAX LONG_MAX +#define UINT_FAST8_MAX ULONG_MAX + +#undef INT_FAST16_MIN +#undef INT_FAST16_MAX +#undef UINT_FAST16_MAX +#define INT_FAST16_MIN LONG_MIN +#define INT_FAST16_MAX LONG_MAX +#define UINT_FAST16_MAX ULONG_MAX + +#undef INT_FAST32_MIN +#undef INT_FAST32_MAX +#undef UINT_FAST32_MAX +#define INT_FAST32_MIN LONG_MIN +#define INT_FAST32_MAX LONG_MAX +#define UINT_FAST32_MAX ULONG_MAX + +#undef INT_FAST64_MIN +#undef INT_FAST64_MAX +#ifdef GL_INT64_T +# define INT_FAST64_MIN INT64_MIN +# define INT_FAST64_MAX INT64_MAX +#endif + +#undef UINT_FAST64_MAX +#ifdef GL_UINT64_T +# define UINT_FAST64_MAX UINT64_MAX +#endif + +/* 7.18.2.4. Limits of integer types capable of holding object pointers */ + +#undef INTPTR_MIN +#undef INTPTR_MAX +#undef UINTPTR_MAX +#define INTPTR_MIN LONG_MIN +#define INTPTR_MAX LONG_MAX +#define UINTPTR_MAX ULONG_MAX + +/* 7.18.2.5. Limits of greatest-width integer types */ + +#undef INTMAX_MIN +#undef INTMAX_MAX +#ifdef INT64_MAX +# define INTMAX_MIN INT64_MIN +# define INTMAX_MAX INT64_MAX +#else +# define INTMAX_MIN INT32_MIN +# define INTMAX_MAX INT32_MAX +#endif + +#undef UINTMAX_MAX +#ifdef UINT64_MAX +# define UINTMAX_MAX UINT64_MAX +#else +# define UINTMAX_MAX UINT32_MAX +#endif + +/* 7.18.3. Limits of other integer types */ + +/* ptrdiff_t limits */ +#undef PTRDIFF_MIN +#undef PTRDIFF_MAX +#define PTRDIFF_MIN \ + _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +#define PTRDIFF_MAX \ + _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) + +/* sig_atomic_t limits */ +#undef SIG_ATOMIC_MIN +#undef SIG_ATOMIC_MAX +#define SIG_ATOMIC_MIN \ + _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ + 0@SIG_ATOMIC_T_SUFFIX@) +#define SIG_ATOMIC_MAX \ + _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ + 0@SIG_ATOMIC_T_SUFFIX@) + + +/* size_t limit */ +#undef SIZE_MAX +#define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) + +/* wchar_t limits */ +#undef WCHAR_MIN +#undef WCHAR_MAX +#define WCHAR_MIN \ + _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +#define WCHAR_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) + +/* wint_t limits */ +#undef WINT_MIN +#undef WINT_MAX +#define WINT_MIN \ + _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +#define WINT_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) + +#endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */ + +/* 7.18.4. Macros for integer constants */ + +#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS + +/* 7.18.4.1. Macros for minimum-width integer constants */ +/* According to ISO C 99 Technical Corrigendum 1 */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ + +#undef INT8_C +#undef UINT8_C +#define INT8_C(x) x +#define UINT8_C(x) x + +#undef INT16_C +#undef UINT16_C +#define INT16_C(x) x +#define UINT16_C(x) x + +#undef INT32_C +#undef UINT32_C +#define INT32_C(x) x +#define UINT32_C(x) x ## U + +#undef INT64_C +#undef UINT64_C +#if LONG_MAX >> 31 >> 31 == 1 +# define INT64_C(x) x##L +#elif defined _MSC_VER +# define INT64_C(x) x##i64 +#elif @HAVE_LONG_LONG_INT@ +# define INT64_C(x) x##LL +#endif +#if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# define UINT64_C(x) x##UL +#elif defined _MSC_VER +# define UINT64_C(x) x##ui64 +#elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# define UINT64_C(x) x##ULL +#endif + +/* 7.18.4.2. Macros for greatest-width integer constants */ + +#undef INTMAX_C +#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +# define INTMAX_C(x) x##LL +#elif defined GL_INT64_T +# define INTMAX_C(x) INT64_C(x) +#else +# define INTMAX_C(x) x##L +#endif + +#undef UINTMAX_C +#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +# define UINTMAX_C(x) x##ULL +#elif defined GL_UINT64_T +# define UINTMAX_C(x) UINT64_C(x) +#else +# define UINTMAX_C(x) x##UL +#endif + +#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */ + +#endif /* _GL_STDINT_H */ +#endif /* !defined _GL_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ diff --git a/gnulib/stdio_.h b/gnulib/stdio_.h new file mode 100644 index 0000000..76d9856 --- /dev/null +++ b/gnulib/stdio_.h @@ -0,0 +1,353 @@ +/* A GNU-like . + + Copyright (C) 2004, 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if defined __need_FILE || defined __need___FILE +/* Special invocation convention inside glibc header files. */ + +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _GL_STDIO_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#ifndef _GL_STDIO_H +#define _GL_STDIO_H + +#include +#include + +#if (@GNULIB_FSEEKO@ && @REPLACE_FSEEKO@) \ + || (@GNULIB_FTELLO@ && @REPLACE_FTELLO@) \ + || (@GNULIB_GETDELIM@ && !@HAVE_DECL_GETDELIM@) \ + || (@GNULIB_GETLINE@ && (!@HAVE_DECL_GETLINE@ || @REPLACE_GETLINE@)) +/* Get off_t and ssize_t. */ +# include +#endif + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ +# define __attribute__(Spec) /* empty */ +# endif +/* The __-protected variants of `format' and `printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) +# define __format__ format +# define __printf__ printf +# endif +#endif + + +/* The definition of GL_LINK_WARNING is copied here. */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if @GNULIB_FPRINTF_POSIX@ +# if @REPLACE_FPRINTF@ +# define fprintf rpl_fprintf +extern int fprintf (FILE *fp, const char *format, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef fprintf +# define fprintf \ + (GL_LINK_WARNING ("fprintf is not always POSIX compliant - " \ + "use gnulib module fprintf-posix for portable " \ + "POSIX compliance"), \ + fprintf) +#endif + +#if @GNULIB_VFPRINTF_POSIX@ +# if @REPLACE_VFPRINTF@ +# define vfprintf rpl_vfprintf +extern int vfprintf (FILE *fp, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 2, 0))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef vfprintf +# define vfprintf(s,f,a) \ + (GL_LINK_WARNING ("vfprintf is not always POSIX compliant - " \ + "use gnulib module vfprintf-posix for portable " \ + "POSIX compliance"), \ + vfprintf (s, f, a)) +#endif + +#if @GNULIB_PRINTF_POSIX@ +# if @REPLACE_PRINTF@ +/* Don't break __attribute__((format(printf,M,N))). */ +# define printf __printf__ +extern int printf (const char *format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef printf +# define printf \ + (GL_LINK_WARNING ("printf is not always POSIX compliant - " \ + "use gnulib module printf-posix for portable " \ + "POSIX compliance"), \ + printf) +/* Don't break __attribute__((format(printf,M,N))). */ +# define format(kind,m,n) format (__##kind##__, m, n) +# define __format__(kind,m,n) __format__ (__##kind##__, m, n) +# define ____printf____ __printf__ +# define ____scanf____ __scanf__ +# define ____strftime____ __strftime__ +# define ____strfmon____ __strfmon__ +#endif + +#if @GNULIB_VPRINTF_POSIX@ +# if @REPLACE_VPRINTF@ +# define vprintf rpl_vprintf +extern int vprintf (const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 1, 0))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef vprintf +# define vprintf(f,a) \ + (GL_LINK_WARNING ("vprintf is not always POSIX compliant - " \ + "use gnulib module vprintf-posix for portable " \ + "POSIX compliance"), \ + vprintf (f, a)) +#endif + +#if @GNULIB_SNPRINTF@ +# if @REPLACE_SNPRINTF@ +# define snprintf rpl_snprintf +# endif +# if @REPLACE_SNPRINTF@ || !@HAVE_DECL_SNPRINTF@ +extern int snprintf (char *str, size_t size, const char *format, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef snprintf +# define snprintf \ + (GL_LINK_WARNING ("snprintf is unportable - " \ + "use gnulib module snprintf for portability"), \ + snprintf) +#endif + +#if @GNULIB_VSNPRINTF@ +# if @REPLACE_VSNPRINTF@ +# define vsnprintf rpl_vsnprintf +# endif +# if @REPLACE_VSNPRINTF@ || !@HAVE_DECL_VSNPRINTF@ +extern int vsnprintf (char *str, size_t size, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 3, 0))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef vsnprintf +# define vsnprintf(b,s,f,a) \ + (GL_LINK_WARNING ("vsnprintf is unportable - " \ + "use gnulib module vsnprintf for portability"), \ + vsnprintf (b, s, f, a)) +#endif + +#if @GNULIB_SPRINTF_POSIX@ +# if @REPLACE_SPRINTF@ +# define sprintf rpl_sprintf +extern int sprintf (char *str, const char *format, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef sprintf +# define sprintf \ + (GL_LINK_WARNING ("sprintf is not always POSIX compliant - " \ + "use gnulib module sprintf-posix for portable " \ + "POSIX compliance"), \ + sprintf) +#endif + +#if @GNULIB_VSPRINTF_POSIX@ +# if @REPLACE_VSPRINTF@ +# define vsprintf rpl_vsprintf +extern int vsprintf (char *str, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 2, 0))); +# endif +#elif defined GNULIB_POSIXCHECK +# undef vsprintf +# define vsprintf(b,f,a) \ + (GL_LINK_WARNING ("vsprintf is not always POSIX compliant - " \ + "use gnulib module vsprintf-posix for portable " \ + "POSIX compliance"), \ + vsprintf (b, f, a)) +#endif + +#if @GNULIB_VASPRINTF@ +# if @REPLACE_VASPRINTF@ +# define asprintf rpl_asprintf +# define vasprintf rpl_vasprintf +# endif +# if @REPLACE_VASPRINTF@ || !@HAVE_VASPRINTF@ + /* Write formatted output to a string dynamically allocated with malloc(). + If the memory allocation succeeds, store the address of the string in + *RESULT and return the number of resulting bytes, excluding the trailing + NUL. Upon memory allocation error, or some other error, return -1. */ + extern int asprintf (char **result, const char *format, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + extern int vasprintf (char **result, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 2, 0))); +# endif +#endif + +#if @GNULIB_FSEEKO@ +# if @REPLACE_FSEEKO@ +/* Provide fseek, fseeko functions that are aware of a preceding + fflush(), and which detect pipes. */ +# define fseeko rpl_fseeko +extern int fseeko (FILE *fp, off_t offset, int whence); +# define fseek(fp, offset, whence) fseeko (fp, (off_t)(offset), whence) +# endif +#elif defined GNULIB_POSIXCHECK +# undef fseeko +# define fseeko(f,o,w) \ + (GL_LINK_WARNING ("fseeko is unportable - " \ + "use gnulib module fseeko for portability"), \ + fseeko (f, o, w)) +#endif + +#if @GNULIB_FSEEK@ && @REPLACE_FSEEK@ +extern int rpl_fseek (FILE *fp, long offset, int whence); +# undef fseek +# if defined GNULIB_POSIXCHECK +# define fseek(f,o,w) \ + (GL_LINK_WARNING ("fseek cannot handle files larger than 4 GB " \ + "on 32-bit platforms - " \ + "use fseeko function for handling of large files"), \ + rpl_fseek (f, o, w)) +# else +# define fseek rpl_fseek +# endif +#elif defined GNULIB_POSIXCHECK +# ifndef fseek +# define fseek(f,o,w) \ + (GL_LINK_WARNING ("fseek cannot handle files larger than 4 GB " \ + "on 32-bit platforms - " \ + "use fseeko function for handling of large files"), \ + fseek (f, o, w)) +# endif +#endif + +#if @GNULIB_FTELLO@ +# if @REPLACE_FTELLO@ +# define ftello rpl_ftello +extern off_t ftello (FILE *fp); +# define ftell(fp) ftello (fp) +# endif +#elif defined GNULIB_POSIXCHECK +# undef ftello +# define ftello(f) \ + (GL_LINK_WARNING ("ftello is unportable - " \ + "use gnulib module ftello for portability"), \ + ftello (f)) +#endif + +#if @GNULIB_FTELL@ && @REPLACE_FTELL@ +extern long rpl_ftell (FILE *fp); +# undef ftell +# if GNULIB_POSIXCHECK +# define ftell(f) \ + (GL_LINK_WARNING ("ftell cannot handle files larger than 4 GB " \ + "on 32-bit platforms - " \ + "use ftello function for handling of large files"), \ + rpl_ftell (f)) +# else +# define ftell rpl_ftell +# endif +#elif defined GNULIB_POSIXCHECK +# ifndef ftell +# define ftell(f) \ + (GL_LINK_WARNING ("ftell cannot handle files larger than 4 GB " \ + "on 32-bit platforms - " \ + "use ftello function for handling of large files"), \ + ftell (f)) +# endif +#endif + +#if @GNULIB_FFLUSH@ +# if @REPLACE_FFLUSH@ +# define fflush rpl_fflush + /* Flush all pending data on STREAM according to POSIX rules. Both + output and seekable input streams are supported. + Note! LOSS OF DATA can occur if fflush is applied on an input stream + that is _not_seekable_ or on an update stream that is _not_seekable_ + and in which the most recent operation was input. Seekability can + be tested with lseek(fileno(fp),0,SEEK_CUR). */ + extern int fflush (FILE *gl_stream); +# endif +#elif defined GNULIB_POSIXCHECK +# undef fflush +# define fflush(f) \ + (GL_LINK_WARNING ("fflush is not always POSIX compliant - " \ + "use gnulib module fflush for portable " \ + "POSIX compliance"), \ + fflush (f)) +#endif + +#if @GNULIB_GETDELIM@ +# if !@HAVE_DECL_GETDELIM@ + /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + extern ssize_t getdelim (char **, size_t *, int delim, FILE *); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getdelim +# define getdelim(l, s, d, f) \ + (GL_LINK_WARNING ("getdelim is unportable - " \ + "use gnulib module getdelim for portability"), \ + getdelim (l, s, d, f)) +#endif + +#if @GNULIB_GETLINE@ +# if @REPLACE_GETLINE@ +# undef getline +# define getline rpl_getline +# endif +# if !@HAVE_DECL_GETLINE@ || @REPLACE_GETLINE@ + /* Read up to (and including) a newline from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + extern ssize_t getline (char **, size_t *, FILE *); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getline +# define getline(l, s, f) \ + (GL_LINK_WARNING ("getline is unportable - " \ + "use gnulib module getline for portability"), \ + getline (l, s, f)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_STDIO_H */ +#endif /* _GL_STDIO_H */ +#endif diff --git a/gnulib/stdlib_.h b/gnulib/stdlib_.h new file mode 100644 index 0000000..a4946e6 --- /dev/null +++ b/gnulib/stdlib_.h @@ -0,0 +1,177 @@ +/* A GNU-like . + + Copyright (C) 1995, 2001-2002, 2006-2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if defined __need_malloc_and_calloc +/* Special invocation convention inside glibc header files. */ + +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _GL_STDLIB_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#ifndef _GL_STDLIB_H +#define _GL_STDLIB_H + + +/* The definition of GL_LINK_WARNING is copied here. */ + + +/* Some systems do not define EXIT_*, despite otherwise supporting C89. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +/* Tandem/NSK and other platforms that define EXIT_FAILURE as -1 interfere + with proper operation of xargs. */ +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#elif EXIT_FAILURE != 1 +# undef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if @GNULIB_MALLOC_POSIX@ +# if !@HAVE_MALLOC_POSIX@ +# undef malloc +# define malloc rpl_malloc +extern void * malloc (size_t size); +# endif +#elif defined GNULIB_POSIXCHECK +# undef malloc +# define malloc(s) \ + (GL_LINK_WARNING ("malloc is not POSIX compliant everywhere - " \ + "use gnulib module malloc-posix for portability"), \ + malloc (s)) +#endif + + +#if @GNULIB_REALLOC_POSIX@ +# if !@HAVE_REALLOC_POSIX@ +# undef realloc +# define realloc rpl_realloc +extern void * realloc (void *ptr, size_t size); +# endif +#elif defined GNULIB_POSIXCHECK +# undef realloc +# define realloc(p,s) \ + (GL_LINK_WARNING ("realloc is not POSIX compliant everywhere - " \ + "use gnulib module realloc-posix for portability"), \ + realloc (p, s)) +#endif + + +#if @GNULIB_CALLOC_POSIX@ +# if !@HAVE_CALLOC_POSIX@ +# undef calloc +# define calloc rpl_calloc +extern void * calloc (size_t nmemb, size_t size); +# endif +#elif defined GNULIB_POSIXCHECK +# undef calloc +# define calloc(n,s) \ + (GL_LINK_WARNING ("calloc is not POSIX compliant everywhere - " \ + "use gnulib module calloc-posix for portability"), \ + calloc (n, s)) +#endif + + +#if @GNULIB_GETSUBOPT@ +/* Assuming *OPTIONP is a comma separated list of elements of the form + "token" or "token=value", getsubopt parses the first of these elements. + If the first element refers to a "token" that is member of the given + NULL-terminated array of tokens: + - It replaces the comma with a NUL byte, updates *OPTIONP to point past + the first option and the comma, sets *VALUEP to the value of the + element (or NULL if it doesn't contain an "=" sign), + - It returns the index of the "token" in the given array of tokens. + Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined. + For more details see the POSIX:2001 specification. + http://www.opengroup.org/susv3xsh/getsubopt.html */ +# if !@HAVE_GETSUBOPT@ +extern int getsubopt (char **optionp, char *const *tokens, char **valuep); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getsubopt +# define getsubopt(o,t,v) \ + (GL_LINK_WARNING ("getsubopt is unportable - " \ + "use gnulib module getsubopt for portability"), \ + getsubopt (o, t, v)) +#endif + + +#if @GNULIB_MKDTEMP@ +# if !@HAVE_MKDTEMP@ +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +extern char * mkdtemp (char * /*template*/); +# endif +#elif defined GNULIB_POSIXCHECK +# undef mkdtemp +# define mkdtemp(t) \ + (GL_LINK_WARNING ("mkdtemp is unportable - " \ + "use gnulib module mkdtemp for portability"), \ + mkdtemp (t)) +#endif + + +#if @GNULIB_MKSTEMP@ +# if @REPLACE_MKSTEMP@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The file is then created, ensuring it didn't exist before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# define mkstemp rpl_mkstemp +extern int mkstemp (char * /*template*/); +# else +/* On MacOS X 10.3, only declares mkstemp. */ +# include +# endif +#elif defined GNULIB_POSIXCHECK +# undef mkstemp +# define mkstemp(t) \ + (GL_LINK_WARNING ("mkstemp is unportable - " \ + "use gnulib module mkstemp for portability"), \ + mkstemp (t)) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_STDLIB_H */ +#endif /* _GL_STDLIB_H */ +#endif diff --git a/gnulib/sys_socket_.h b/gnulib/sys_socket_.h new file mode 100644 index 0000000..c25b6ab --- /dev/null +++ b/gnulib/sys_socket_.h @@ -0,0 +1,91 @@ +/* Provide a sys/socket header file for systems lacking it (read: MinGW). + Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* This file is supposed to be used on platforms that lack + and on platforms where cannot be included standalone. + It is intended to provide definitions and prototypes needed by an + application. */ + +#ifndef _GL_SYS_SOCKET_H + +#if @HAVE_SYS_SOCKET_H@ + +/* On many platforms, assumes prior inclusion of + . */ +# include + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_SYS_SOCKET_H@ + +#endif + +#ifndef _GL_SYS_SOCKET_H +#define _GL_SYS_SOCKET_H + +#if !@HAVE_SYS_SOCKET_H@ + +/* A platform that lacks . + + Currently only MinGW is supported. See the gnulib manual regarding + Windows sockets. MinGW has the header files winsock2.h and + ws2tcpip.h that declare the sys/socket.h definitions we need. Note + that you can influence which definitions you get by setting the + WINVER symbol before including these two files. For example, + getaddrinfo is only available if _WIN32_WINNT >= 0x0501 (that + symbol is set indiriectly through WINVER). You can set this by + adding AC_DEFINE(WINVER, 0x0501) to configure.ac. Note that your + code may not run on older Windows releases then. My Windows 2000 + box was not able to run the code, for example. The situation is + slightly confusing because: + http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/getaddrinfo_2.asp + suggests that getaddrinfo should be available on all Windows + releases. */ + + +# if @HAVE_WINSOCK2_H@ +# include +# endif +# if @HAVE_WS2TCPIP_H@ +# include +# endif + +/* For shutdown(). */ +# if !defined SHUT_RD && defined SD_RECEIVE +# define SHUT_RD SD_RECEIVE +# endif +# if !defined SHUT_WR && defined SD_SEND +# define SHUT_WR SD_SEND +# endif +# if !defined SHUT_RDWR && defined SD_BOTH +# define SHUT_RDWR SD_BOTH +# endif + +# if defined _WIN32 || defined __WIN32__ +# define ENOTSOCK WSAENOTSOCK +# define EADDRINUSE WSAEADDRINUSE +# define ENETRESET WSAENETRESET +# define ECONNABORTED WSAECONNABORTED +# define ECONNRESET WSAECONNRESET +# define ENOTCONN WSAENOTCONN +# define ESHUTDOWN WSAESHUTDOWN +# endif + +#endif /* HAVE_SYS_SOCKET_H */ + +#endif /* _GL_SYS_SOCKET_H */ +#endif /* _GL_SYS_SOCKET_H */ diff --git a/gnulib/sys_stat_.h b/gnulib/sys_stat_.h new file mode 100644 index 0000000..2e411cd --- /dev/null +++ b/gnulib/sys_stat_.h @@ -0,0 +1,280 @@ +/* Provide a more complete sys/stat header file. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */ + +/* This file is supposed to be used on platforms where is + incomplete. It is intended to provide definitions and prototypes + needed by an application. Start with what the system provides. */ + +#ifndef _GL_SYS_STAT_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ + +#ifndef _GL_SYS_STAT_H +#define _GL_SYS_STAT_H + +#ifndef S_IFMT +# define S_IFMT 0170000 +#endif + +#if STAT_MACROS_BROKEN +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISLNK +# undef S_ISNAM +# undef S_ISMPB +# undef S_ISMPC +# undef S_ISNWK +# undef S_ISREG +# undef S_ISSOCK +#endif + +#ifndef S_ISBLK +# ifdef S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# else +# define S_ISBLK(m) 0 +# endif +#endif + +#ifndef S_ISCHR +# ifdef S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# else +# define S_ISCHR(m) 0 +# endif +#endif + +#ifndef S_ISDIR +# ifdef S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# else +# define S_ISDIR(m) 0 +# endif +#endif + +#ifndef S_ISDOOR /* Solaris 2.5 and up */ +# define S_ISDOOR(m) 0 +#endif + +#ifndef S_ISFIFO +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) 0 +# endif +#endif + +#ifndef S_ISLNK +# ifdef S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) 0 +# endif +#endif + +#ifndef S_ISMPB /* V7 */ +# ifdef S_IFMPB +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +# else +# define S_ISMPB(m) 0 +# define S_ISMPC(m) 0 +# endif +#endif + +#ifndef S_ISNAM /* Xenix */ +# ifdef S_IFNAM +# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) +# else +# define S_ISNAM(m) 0 +# endif +#endif + +#ifndef S_ISNWK /* HP/UX */ +# ifdef S_IFNWK +# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) +# else +# define S_ISNWK(m) 0 +# endif +#endif + +#ifndef S_ISPORT /* Solaris 10 and up */ +# define S_ISPORT(m) 0 +#endif + +#ifndef S_ISREG +# ifdef S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# else +# define S_ISREG(m) 0 +# endif +#endif + +#ifndef S_ISSOCK +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) 0 +# endif +#endif + + +#ifndef S_TYPEISMQ +# define S_TYPEISMQ(p) 0 +#endif + +#ifndef S_TYPEISTMO +# define S_TYPEISTMO(p) 0 +#endif + + +#ifndef S_TYPEISSEM +# ifdef S_INSEM +# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) +# else +# define S_TYPEISSEM(p) 0 +# endif +#endif + +#ifndef S_TYPEISSHM +# ifdef S_INSHD +# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) +# else +# define S_TYPEISSHM(p) 0 +# endif +#endif + +/* high performance ("contiguous data") */ +#ifndef S_ISCTG +# define S_ISCTG(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with data */ +#ifndef S_ISOFD +# define S_ISOFD(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with no data */ +#ifndef S_ISOFL +# define S_ISOFL(p) 0 +#endif + +/* 4.4BSD whiteout */ +#ifndef S_ISWHT +# define S_ISWHT(m) 0 +#endif + +/* If any of the following are undefined, + define them to their de facto standard values. */ +#if !S_ISUID +# define S_ISUID 04000 +#endif +#if !S_ISGID +# define S_ISGID 02000 +#endif + +/* S_ISVTX is a common extension to POSIX. */ +#ifndef S_ISVTX +# define S_ISVTX 01000 +#endif + +#if !S_IRUSR && S_IREAD +# define S_IRUSR S_IREAD +#endif +#if !S_IRUSR +# define S_IRUSR 00400 +#endif +#if !S_IRGRP +# define S_IRGRP (S_IRUSR >> 3) +#endif +#if !S_IROTH +# define S_IROTH (S_IRUSR >> 6) +#endif + +#if !S_IWUSR && S_IWRITE +# define S_IWUSR S_IWRITE +#endif +#if !S_IWUSR +# define S_IWUSR 00200 +#endif +#if !S_IWGRP +# define S_IWGRP (S_IWUSR >> 3) +#endif +#if !S_IWOTH +# define S_IWOTH (S_IWUSR >> 6) +#endif + +#if !S_IXUSR && S_IEXEC +# define S_IXUSR S_IEXEC +#endif +#if !S_IXUSR +# define S_IXUSR 00100 +#endif +#if !S_IXGRP +# define S_IXGRP (S_IXUSR >> 3) +#endif +#if !S_IXOTH +# define S_IXOTH (S_IXUSR >> 6) +#endif + +#if !S_IRWXU +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#endif +#if !S_IRWXG +# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#endif +#if !S_IRWXO +# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif + +/* S_IXUGO is a common extension to POSIX. */ +#if !S_IXUGO +# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) +#endif + +#ifndef S_IRWXUGO +# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) +#endif + +/* mingw does not support symlinks, therefore it does not have lstat. But + without links, stat does just fine. */ +#if ! @HAVE_LSTAT@ +# define lstat stat +#endif + +/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. + Additionally, it declares _mkdir (and depending on compile flags, an + alias mkdir), only in the nonstandard io.h. */ +#if ! @HAVE_DECL_MKDIR@ && @HAVE_IO_H@ +# include + +static inline int +rpl_mkdir (char const *name, mode_t mode) +{ + return _mkdir (name); +} + +# define mkdir rpl_mkdir +#endif + +#endif /* _GL_SYS_STAT_H */ +#endif /* _GL_SYS_STAT_H */ diff --git a/gnulib/sys_time_.h b/gnulib/sys_time_.h new file mode 100644 index 0000000..296d20d --- /dev/null +++ b/gnulib/sys_time_.h @@ -0,0 +1,52 @@ +/* Provide a more complete sys/time.h. + + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Paul Eggert. */ + +#if defined _GL_SYS_TIME_H + +/* Simply delegate to the system's header, without adding anything. */ +# if @HAVE_SYS_TIME_H@ +# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ +# endif + +#else + +# define _GL_SYS_TIME_H + +# if @HAVE_SYS_TIME_H@ +# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ +# else +# include +# endif + +# if ! @HAVE_STRUCT_TIMEVAL@ +struct timeval +{ + time_t tv_sec; + long int tv_usec; +}; +# endif + +# if @REPLACE_GETTIMEOFDAY@ +# undef gettimeofday +# define gettimeofday rpl_gettimeofday +int gettimeofday (struct timeval *restrict, void *restrict); +# endif + +#endif /* _GL_SYS_TIME_H */ diff --git a/gnulib/tempname.c b/gnulib/tempname.c new file mode 100644 index 0000000..e213600 --- /dev/null +++ b/gnulib/tempname.c @@ -0,0 +1,315 @@ +/* tempname.c - generate the name of a temporary file. + + Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, + Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */ + +#if !_LIBC +# include +# include "tempname.h" +#endif + +#include +#include + +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#ifndef P_tmpdir +# define P_tmpdir "/tmp" +#endif +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif +#ifndef __GT_FILE +# define __GT_FILE 0 +# define __GT_BIGFILE 1 +# define __GT_DIR 2 +# define __GT_NOCREATE 3 +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#if _LIBC +# define struct_stat64 struct stat64 +# define small_open __open +# define large_open __open64 +#else +# define struct_stat64 struct stat +# define small_open open +# define large_open open +# define __gen_tempname gen_tempname +# define __getpid getpid +# define __gettimeofday gettimeofday +# define __mkdir mkdir +# define __lxstat64(version, file, buf) lstat (file, buf) +# define __xstat64(version, file, buf) stat (file, buf) +#endif + +#if ! (HAVE___SECURE_GETENV || _LIBC) +# define __secure_getenv getenv +#endif + +#ifdef _LIBC +# include +# if HP_TIMING_AVAIL +# define RANDOM_BITS(Var) \ + if (__builtin_expect (value == UINT64_C (0), 0)) \ + { \ + /* If this is the first time this function is used initialize \ + the variable we accumulate the value in to some somewhat \ + random value. If we'd not do this programs at startup time \ + might have a reduced set of possible names, at least on slow \ + machines. */ \ + struct timeval tv; \ + __gettimeofday (&tv, NULL); \ + value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ + } \ + HP_TIMING_NOW (Var) +# endif +#endif + +/* Use the widest available unsigned type if uint64_t is not + available. The algorithm below extracts a number less than 62**6 + (approximately 2**35.725) from uint64_t, so ancient hosts where + uintmax_t is only 32 bits lose about 3.725 bits of randomness, + which is better than not having mkstemp at all. */ +#if !defined UINT64_MAX && !defined uint64_t +# define uint64_t uintmax_t +#endif + +#if _LIBC +/* Return nonzero if DIR is an existent directory. */ +static int +direxists (const char *dir) +{ + struct_stat64 buf; + return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + int try_tmpdir) +{ + const char *d; + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); + return 0; +} +#endif /* _LIBC */ + +/* These are the characters used in temporary file names. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + does not exist at the time of the call to __gen_tempname. TMPL is + overwritten with the result. + + KIND may be one of: + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + __GT_FILE: create the file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + __GT_BIGFILE: same as __GT_FILE but use open64(). + __GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +int +__gen_tempname (char *tmpl, int kind) +{ + int len; + char *XXXXXX; + static uint64_t value; + uint64_t random_time_bits; + unsigned int count; + int fd = -1; + int save_errno = errno; + struct_stat64 st; + + /* A lower bound on the number of temporary files to attempt to + generate. The maximum total number of temporary file names that + can exist for a given template is 62**6. It should never be + necessary to try all these combinations. Instead if a reasonable + number of names is tried (we define reasonable as 62**3) fail to + give the system administrator the chance to remove the problems. */ +#define ATTEMPTS_MIN (62 * 62 * 62) + + /* The number of times to attempt to generate a temporary file. To + conform to POSIX, this must be no smaller than TMP_MAX. */ +#if ATTEMPTS_MIN < TMP_MAX + unsigned int attempts = TMP_MAX; +#else + unsigned int attempts = ATTEMPTS_MIN; +#endif + + len = strlen (tmpl); + if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) + { + __set_errno (EINVAL); + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - 6]; + + /* Get some more or less random data. */ +#ifdef RANDOM_BITS + RANDOM_BITS (random_time_bits); +#else + { + struct timeval tv; + __gettimeofday (&tv, NULL); + random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; + } +#endif + value += random_time_bits ^ __getpid (); + + for (count = 0; count < attempts; value += 7777, ++count) + { + uint64_t v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + switch (kind) + { + case __GT_FILE: + fd = small_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; + + case __GT_BIGFILE: + fd = large_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; + + case __GT_DIR: + fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + break; + + case __GT_NOCREATE: + /* This case is backward from the other three. __gen_tempname + succeeds if __xstat fails because the name does not exist. + Note the continue to bypass the common logic at the bottom + of the loop. */ + if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) + { + if (errno == ENOENT) + { + __set_errno (save_errno); + return 0; + } + else + /* Give up now. */ + return -1; + } + continue; + + default: + assert (! "invalid KIND in __gen_tempname"); + } + + if (fd >= 0) + { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} diff --git a/gnulib/tempname.h b/gnulib/tempname.h new file mode 100644 index 0000000..c51fa69 --- /dev/null +++ b/gnulib/tempname.h @@ -0,0 +1,40 @@ +/* Create a temporary file or directory. + + Copyright (C) 2006 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* header written by Eric Blake */ + +/* In gnulib, always prefer large files. GT_FILE maps to + __GT_BIGFILE, not __GT_FILE, for a reason. */ +#define GT_FILE 1 +#define GT_DIR 2 +#define GT_NOCREATE 3 + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + does not exist at the time of the call to gen_tempname. TMPL is + overwritten with the result. + + KIND may be one of: + GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + GT_FILE: create a large file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +extern int gen_tempname (char *tmpl, int kind); diff --git a/gnulib/unistd_.h b/gnulib/unistd_.h new file mode 100644 index 0000000..07c4877 --- /dev/null +++ b/gnulib/unistd_.h @@ -0,0 +1,262 @@ +/* Substitute for and wrapper around . + Copyright (C) 2004-2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _GL_UNISTD_H + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_UNISTD_H@ +# @INCLUDE_NEXT@ @NEXT_UNISTD_H@ +#endif + +#ifndef _GL_UNISTD_H +#define _GL_UNISTD_H + +/* mingw doesn't define the SEEK_* macros in . */ +#if !(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET) +# include +#endif + +/* mingw fails to declare _exit in . */ +#include + +/* The definition of GL_LINK_WARNING is copied here. */ + + +/* Declare overridden functions. */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if @GNULIB_CHOWN@ +# if @REPLACE_CHOWN@ +# ifndef REPLACE_CHOWN +# define REPLACE_CHOWN 1 +# endif +# if REPLACE_CHOWN +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2001 specification + . */ +# define chown rpl_chown +extern int chown (const char *file, uid_t uid, gid_t gid); +# endif +# endif +#elif defined GNULIB_POSIXCHECK +# undef chown +# define chown(f,u,g) \ + (GL_LINK_WARNING ("chown fails to follow symlinks on some systems and " \ + "doesn't treat a uid or gid of -1 on some systems - " \ + "use gnulib module chown for portability"), \ + chown (f, u, g)) +#endif + + +#if @GNULIB_DUP2@ +# if !@HAVE_DUP2@ +/* Copy the file descriptor OLDFD into file descriptor NEWFD. Do nothing if + NEWFD = OLDFD, otherwise close NEWFD first if it is open. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2001 specification + . */ +extern int dup2 (int oldfd, int newfd); +# endif +#elif defined GNULIB_POSIXCHECK +# undef dup2 +# define dup2(o,n) \ + (GL_LINK_WARNING ("dup2 is unportable - " \ + "use gnulib module dup2 for portability"), \ + dup2 (o, n)) +#endif + + +#if @GNULIB_FCHDIR@ +# if @REPLACE_FCHDIR@ + +/* Change the process' current working directory to the directory on which + the given file descriptor is open. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2001 specification + . */ +extern int fchdir (int /*fd*/); + +# define close rpl_close +extern int close (int); +# define dup rpl_dup +extern int dup (int); +# define dup2 rpl_dup2 +extern int dup2 (int, int); + +# endif +#elif defined GNULIB_POSIXCHECK +# undef fchdir +# define fchdir(f) \ + (GL_LINK_WARNING ("fchdir is unportable - " \ + "use gnulib module fchdir for portability"), \ + fchdir (f)) +#endif + + +#if @GNULIB_FTRUNCATE@ +# if !@HAVE_FTRUNCATE@ +/* Change the size of the file to which FD is opened to become equal to LENGTH. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2001 specification + . */ +extern int ftruncate (int fd, off_t length); +# endif +#elif defined GNULIB_POSIXCHECK +# undef ftruncate +# define ftruncate(f,l) \ + (GL_LINK_WARNING ("ftruncate is unportable - " \ + "use gnulib module ftruncate for portability"), \ + ftruncate (f, l)) +#endif + + +#if @GNULIB_GETCWD@ +/* Include the headers that might declare getcwd so that they will not + cause confusion if included after this file. */ +# include +# if @REPLACE_GETCWD@ +/* Get the name of the current working directory, and put it in SIZE bytes + of BUF. + Return BUF if successful, or NULL if the directory couldn't be determined + or SIZE was too small. + See the POSIX:2001 specification + . + Additionally, the gnulib module 'getcwd' guarantees the following GNU + extension: If BUF is NULL, an array is allocated with 'malloc'; the array + is SIZE bytes long, unless SIZE == 0, in which case it is as big as + necessary. */ +# define getcwd rpl_getcwd +extern char * getcwd (char *buf, size_t size); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getcwd +# define getcwd(b,s) \ + (GL_LINK_WARNING ("getcwd is unportable - " \ + "use gnulib module getcwd for portability"), \ + getcwd (b, s)) +#endif + + +#if @GNULIB_GETLOGIN_R@ +/* Copies the user's login name to NAME. + The array pointed to by NAME has room for SIZE bytes. + + Returns 0 if successful. Upon error, an error number is returned, or -1 in + the case that the login name cannot be found but no specific error is + provided (this case is hopefully rare but is left open by the POSIX spec). + + See . + */ +# if !@HAVE_DECL_GETLOGIN_R@ +# include +extern int getlogin_r (char *name, size_t size); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getlogin_r +# define getlogin_r(n,s) \ + (GL_LINK_WARNING ("getlogin_r is unportable - " \ + "use gnulib module getlogin_r for portability"), \ + getlogin_r (n, s)) +#endif + + +#if @GNULIB_LCHOWN@ +# if @REPLACE_LCHOWN@ +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Do not follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2001 specification + . */ +# define lchown rpl_lchown +extern int lchown (char const *file, uid_t owner, gid_t group); +# endif +#elif defined GNULIB_POSIXCHECK +# undef lchown +# define lchown(f,u,g) \ + (GL_LINK_WARNING ("lchown is unportable to pre-POSIX.1-2001 " \ + "systems - use gnulib module lchown for portability"), \ + lchown (f, u, g)) +#endif + + +#if @GNULIB_LSEEK@ +# if @REPLACE_LSEEK@ +/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END. + Return the new offset if successful, otherwise -1 and errno set. + See the POSIX:2001 specification + . */ +# define lseek rpl_lseek + extern off_t lseek (int fd, off_t offset, int whence); +# endif +#elif defined GNULIB_POSIXCHECK +# undef lseek +# define lseek(f,o,w) \ + (GL_LINK_WARNING ("lseek does not fail with ESPIPE on pipes on some " \ + "systems - use gnulib module lseek for portability"), \ + lseek (f, o, w)) +#endif + + +#if @GNULIB_READLINK@ +/* Read the contents of the symbolic link FILE and place the first BUFSIZE + bytes of it into BUF. Return the number of bytes placed into BUF if + successful, otherwise -1 and errno set. + See the POSIX:2001 specification + . */ +# if !@HAVE_READLINK@ +# include +extern int readlink (const char *file, char *buf, size_t bufsize); +# endif +#elif defined GNULIB_POSIXCHECK +# undef readlink +# define readlink(f,b,s) \ + (GL_LINK_WARNING ("readlink is unportable - " \ + "use gnulib module readlink for portability"), \ + readlink (f, b, s)) +#endif + + +#if @GNULIB_SLEEP@ +/* Pause the execution of the current thread for N seconds. + Returns the number of seconds left to sleep. + See the POSIX:2001 specification + . */ +# if !@HAVE_SLEEP@ +extern unsigned int sleep (unsigned int n); +# endif +#elif defined GNULIB_POSIXCHECK +# undef sleep +# define sleep(n) \ + (GL_LINK_WARNING ("sleep is unportable - " \ + "use gnulib module sleep for portability"), \ + sleep (n)) +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _GL_UNISTD_H */ +#endif /* _GL_UNISTD_H */ diff --git a/gnulib/wchar_.h b/gnulib/wchar_.h new file mode 100644 index 0000000..924a338 --- /dev/null +++ b/gnulib/wchar_.h @@ -0,0 +1,82 @@ +/* A substitute for ISO C99 , for platforms that have issues. + + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Eric Blake. */ + +/* + * ISO C 99 for platforms that have issues. + * + * + * For now, this just ensures proper prerequisite inclusion order and + * the declaration of wcwidth(). + */ + +#ifndef _GL_WCHAR_H + +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be + included before . */ +#include +#include +#include + +/* Include the original if it exists. + Some builds of uClibc lack it. */ +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_WCHAR_H@ +# @INCLUDE_NEXT@ @NEXT_WCHAR_H@ +#endif + +#ifndef _GL_WCHAR_H +#define _GL_WCHAR_H + +/* The definition of GL_LINK_WARNING is copied here. */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Return the number of screen columns needed for WC. */ +#if @GNULIB_WCWIDTH@ +# if @REPLACE_WCWIDTH@ +# undef wcwidth +# define wcwidth rpl_wcwidth +extern int wcwidth (wchar_t); +# else +# if !defined wcwidth && !@HAVE_DECL_WCWIDTH@ +/* wcwidth exists but is not declared. */ +extern int wcwidth (int /* actually wchar_t */); +# endif +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcwidth +# define wcwidth(w) \ + (GL_LINK_WARNING ("wcwidth is unportable - " \ + "use gnulib module wcwidth for portability"), \ + wcwidth (w)) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_WCHAR_H */ +#endif /* _GL_WCHAR_H */ diff --git a/installcheck/Amanda_Changer.pl b/installcheck/Amanda_Changer.pl new file mode 100644 index 0000000..d525fd6 --- /dev/null +++ b/installcheck/Amanda_Changer.pl @@ -0,0 +1,227 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +use Test::More qw(no_plan); +use Amconfig; +use File::Path; +use strict; + +use lib "@amperldir@"; +use Amanda::Paths; +use Amanda::Device; +use Amanda::Debug; +use Amanda::Config qw( :init :getconf config_dir_relative ); +use Amanda::Changer; + +# set up debugging so debug output doesn't interfere with test results +Amanda::Debug::dbopen("installcheck"); + +my $changer_filename = "$AMANDA_TMPDIR/chg-test"; + +sub setup_changer { + my ($changer_script) = @_; + + open my $chg_test, ">", $changer_filename or die("Could not create test changer"); + + $changer_script =~ s/\$AMANDA_TMPDIR/$AMANDA_TMPDIR/g; + + print $chg_test "#! /bin/sh\n"; + print $chg_test $changer_script; + + close $chg_test; + chmod 0755, $changer_filename; +} + +# set up and load a simple config with a tpchanger +my $testconf = Amconfig->new(); +$testconf->add_param('tpchanger', "\"$changer_filename\""); +$testconf->write(); +config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF') or die("Could not load test config"); + +# some variables we'll need +my ($error, $slot, $device); + +# OK, let's get started with some simple stuff +setup_changer <<'EOC'; +case "${1}" in + -slot) + case "${2}" in + 1) echo "1 fake:1"; exit 0;; + 2) echo " slot 2 is empty"; exit 1;; + 3) echo " oh noes!"; exit 2;; + 4) echo "1"; exit 0;; # test missing 'device' portion + esac;; + -reset) echo "reset ignored";; + -eject) echo "eject ignored";; + -clean) echo "clean ignored";; + -label) + case "${2}" in + foo?bar) echo "1 ok"; exit 0;; + *) echo " bad label"; exit 1;; + esac;; + -info) echo "7 10 1 1"; exit 0;; + -search) + case "${2}" in + TAPE?01) echo "5 fakedev"; exit 0;; + *) echo " not found"; exit 2;; + esac;; +esac +EOC + +is_deeply([ Amanda::Changer::loadslot(1) ], [0, "1", "fake:1"], + "A successful loadslot() returns the right stuff"); + +($error, $slot, $device) = Amanda::Changer::loadslot(2); +is($error, "slot 2 is empty", "A loadslot() with a benign error returns the right stuff"); + +eval { Amanda::Changer::loadslot(3); }; +like($@, qr/.*oh noes!.*/, "A loadslot() with a serious error croaks"); + +is_deeply([ Amanda::Changer::loadslot(4) ], [0, "1", undef], + "a response without a device string returns undef"); + +is_deeply([ Amanda::Changer::reset() ], [ 0, "reset" ], + "reset() calls tapechanger -reset"); +is_deeply([ Amanda::Changer::eject() ], [ 0, "eject" ], + "eject() calls tapechanger -eject"); +is_deeply([ Amanda::Changer::clean() ], [ 0, "clean" ], + "clean() calls tapechanger -clean"); + +is_deeply([ Amanda::Changer::label("foo bar") ], [ 0 ], + "label('foo bar') calls tapechanger -label 'foo bar' (note spaces)"); + +is_deeply([ Amanda::Changer::query() ], [ 0, 7, 10, 1, 1 ], + "query() returns the correct values for a 4-value changer script"); + +is_deeply([ Amanda::Changer::find("TAPE 01") ], [ 0, "5", "fakedev" ], + "find on a searchable changer invokes -search"); + +eval { Amanda::Changer::find("TAPE 02") }; +ok($@, "A searchable changer croaks when the label can't be found"); + +# Now a simple changer that returns three values for -info +setup_changer <<'EOC'; +case "${1}" in + -info) echo "11 13 0"; exit 0;; +esac +EOC + +is_deeply([ Amanda::Changer::query() ], [ 0, 11, 13, 0, 0 ], + "query() returns the correct values for a 4-value changer script"); + +# set up 5 vtapes +for (my $i = 0; $i < 5; $i++) { + my $vtapedir = "$AMANDA_TMPDIR/chg-test-tapes/$i/data"; + if (-e $vtapedir) { + rmtree($vtapedir) + or die("Could not remove '$vtapedir'"); + } + mkpath($vtapedir) + or die("Could not create '$vtapedir'"); +} + +# label three of them (slot 2 is empty; slot 4 is unlabeled) +for (my $i = 0; $i < 5; $i++) { + next if $i == 2 || $i == 4; + my $dev = Amanda::Device->new("file:$AMANDA_TMPDIR/chg-test-tapes/$i") + or die("Could not open device"); + $dev->start($Amanda::Device::ACCESS_WRITE, "TAPE$i", "19780615010203") + or die("Could not write label"); + $dev->finish(); +} + +# And finally a "stateful" changer that can support "scan" and "find" +setup_changer <<'EOC'; +STATEFILE="$AMANDA_TMPDIR/chg-test-state" +SLOT=0 +[ -f "$STATEFILE" ] && . "$STATEFILE" + +case "${1}" in + -slot) + case "${2}" in + current) ;; + 0|1|2|3|4|5) SLOT="${2}";; + next|advance) SLOT=`expr $SLOT + 1`;; + prev) SLOT=`expr $SLOT - 1`;; + first) SLOT=0;; + last) SLOT=4;; + esac + + # normalize 0 <= $SLOT < 5 + while [ "$SLOT" -ge 5 ]; do SLOT=`expr $SLOT - 5`; done + while [ "$SLOT" -lt 0 ]; do SLOT=`expr $SLOT + 5`; done + + # signal an empty slot for slot 2 + if [ "$SLOT" = 2 ]; then + echo "$SLOT slot $SLOT is empty" + EXIT=1 + else + echo "$SLOT" "file:$AMANDA_TMPDIR/chg-test-tapes/$SLOT" + fi + ;; + -info) echo "$SLOT 5 1 0";; +esac + +echo SLOT=$SLOT > $STATEFILE +exit $EXIT +EOC + +($error, $slot, $device) = Amanda::Changer::loadslot(0); +if ($error) { die("Error loading slot 0: $error"); } +is_deeply([ Amanda::Changer::find("TAPE3") ], [0, "3", "file:$AMANDA_TMPDIR/chg-test-tapes/3"], + "Finds a tape after skipping an empty slot"); + +($error, $slot, $device) = Amanda::Changer::loadslot(3); +if ($error) { die("Error loading slot 3: $error"); } +is_deeply([ Amanda::Changer::find("TAPE1") ], [0, "1", "file:$AMANDA_TMPDIR/chg-test-tapes/1"], + "Finds a tape after skipping an unlabeled but filled slot"); + +my @scanresults; +sub cb { + fail("called too many times") if (!@scanresults); + my $expected = shift @scanresults; + my $descr = pop @$expected; + my $done = pop @$expected; + is_deeply([ @_ ], $expected, $descr); + return 1; +} + +# scan the whole changer +($error, $slot, $device) = Amanda::Changer::loadslot(0); +if ($error) { die("Error loading slot 0: $error"); } +@scanresults = ( + [ "0", "file:$AMANDA_TMPDIR/chg-test-tapes/0", 0, 0, "scan starts with slot 0" ], + [ "1", "file:$AMANDA_TMPDIR/chg-test-tapes/1", 0, 0, "next in slot 1" ], + [ undef, undef, "slot 2 is empty", 0, "slot 2 is empty" ], + [ "3", "file:$AMANDA_TMPDIR/chg-test-tapes/3", 0, 0, "next in slot 3" ], + [ "4", "file:$AMANDA_TMPDIR/chg-test-tapes/4", 0, 0, "next in slot 4" ], +); +Amanda::Changer::scan(\&cb); + +# make sure it stops when "done" +($error, $slot, $device) = Amanda::Changer::loadslot(0); +if ($error) { die("Error loading slot 0: $error"); } +@scanresults = ( + [ "0", "file:$AMANDA_TMPDIR/chg-test-tapes/0", 0, 1, "scan starts with slot 0" ], +); +Amanda::Changer::scan(\&cb); + +# cleanup +unlink("$AMANDA_TMPDIR/chg-test"); +unlink("$AMANDA_TMPDIR/chg-test-state"); +rmtree("$AMANDA_TMPDIR/chg-test-tapes"); diff --git a/installcheck/Amanda_Cmdline.pl b/installcheck/Amanda_Cmdline.pl new file mode 100644 index 0000000..399101a --- /dev/null +++ b/installcheck/Amanda_Cmdline.pl @@ -0,0 +1,106 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +use Test::More qw( no_plan ); + +use lib "@amperldir@"; +use Amanda::Paths; +use Amanda::Cmdline; + +# convert a dumpspec_t object to an array, for easy is_deeply() comparisons +sub ds2av { + my ($ds) = @_; + return ( + $ds->{'host'}, + $ds->{'disk'}, + $ds->{'datestamp'}, + $ds->{'level'}, + ); +} + +# test dumpspec_t objects + +is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", "di", "ds", "l")) ], + [ "h", "di", "ds", "l" ], + "dumpspec_t constructor returns a valid dumpspec"); + +is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", "di", "ds", undef)) ], + [ "h", "di", "ds", undef ], + "dumpspec_t constructor returns a valid dumpspec with only 3 args"); + +is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", "di", undef, undef)) ], + [ "h", "di", undef, undef ], + "dumpspec_t constructor returns a valid dumpspec with only 2 args"); + +is_deeply([ ds2av(Amanda::Cmdline::dumpspec_t->new("h", undef, undef, undef)) ], + [ "h", undef, undef, undef ], + "dumpspec_t constructor returns a valid dumpspec with only 1 arg"); + +# TODO: test parse_dumpspecs +my @specs; + +@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "h2", "d2"], 0); +is(@specs, 2, "parse of four elements with no flags yields 2 specs"); +is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", undef, undef ], "..first spec is correct"); +is_deeply([ ds2av($specs[1]) ], [ "h2", "d2", undef, undef ], "..second spec is correct"); + +@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "h2", "d2", "ds2" ], $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP); +is(@specs, 2, "parse of six elements with CMDLINE_PARSE_DATESTAMP yields 2 specs"); +is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", undef ], "..first spec is correct"); +is_deeply([ ds2av($specs[1]) ], [ "h2", "d2", "ds2", undef ], "..second spec is correct"); + +@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "lv1", "h2", "d2", "ds2", "lv2" ], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); +is(@specs, 2, "parse of eight elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields 2 specs"); +is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", "lv1" ], "..first spec is correct"); +is_deeply([ ds2av($specs[1]) ], [ "h2", "d2", "ds2", "lv2" ], "..second spec is correct"); + +@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1", "lv1" ], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); +is(@specs, 1, "parse of four elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); +is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", "lv1" ], "..which is correct"); + +@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1", "ds1" ], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); +is(@specs, 1, "parse of three elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); +is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", "ds1", undef ], "..which is correct"); + +@specs = Amanda::Cmdline::parse_dumpspecs(["h1", "d1" ], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); +is(@specs, 1, "parse of two elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); +is_deeply([ ds2av($specs[0]) ], [ "h1", "d1", undef, undef ], "..which is correct"); + +@specs = Amanda::Cmdline::parse_dumpspecs(["h1" ], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); +is(@specs, 1, "parse of one element with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields one spec"); +is_deeply([ ds2av($specs[0]) ], [ "h1", undef, undef, undef ], "..which is correct"); + +@specs = Amanda::Cmdline::parse_dumpspecs([], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL); +is(@specs, 0, "parse of no elements with CMDLINE_PARSE_DATESTAMP and CMDLINE_PARSE_LEVEL yields no specs"); + +@specs = Amanda::Cmdline::parse_dumpspecs([], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP | $Amanda::Cmdline::CMDLINE_PARSE_LEVEL + | $Amanda::Cmdline::CMDLINE_EMPTY_TO_WILDCARD); +is(@specs, 1, "parse of no elements with CMDLINE_EMPTY_TO_WILDCARD yields one spec"); + +# test format_dumpspec_components + +is(Amanda::Cmdline::format_dumpspec_components("h", "di", "ds", "l"), + "h di ds l", + "format_dumpspec_components works ok"); diff --git a/installcheck/Amanda_Config.pl b/installcheck/Amanda_Config.pl new file mode 100644 index 0000000..5a0bb22 --- /dev/null +++ b/installcheck/Amanda_Config.pl @@ -0,0 +1,361 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +use Test::More qw(no_plan); +use Amconfig; +use strict; + +use lib "@amperldir@"; +use Amanda::Paths; +use Amanda::Config qw( :init :getconf ); + +my $testconf; + +## +# Try starting with no configuration at all +ok(config_init(0, ''), "Initialize with no configuration"); + +## +# Parse up a basic configuration + +# invent "large" values for CONFTYPE_AM64 and CONFTYPE_SIZE +my $am64_num = '171801575472'; # 0xA000B000C000 / 1024 +my $size_t_num = '2147483647'; # 0x7fffffff + +$testconf = Amconfig->new(); +$testconf->add_param('reserve', '75'); +$testconf->add_param('autoflush', 'yes'); +$testconf->add_param('tapedev', '"/dev/foo"'); +$testconf->add_param('bumpsize', $am64_num); +$testconf->add_param('bumpmult', '1.4'); +$testconf->add_param('reserved-udp-port', '100,200'); +$testconf->add_param('device_output_buffer_size', $size_t_num); +$testconf->add_param('taperalgo', 'last'); +$testconf->add_param('device_property', '"foo" "bar"'); +$testconf->add_param('device_property', '"blue" "car"'); +$testconf->add_param('displayunit', '"m"'); +$testconf->add_param('debug_auth', '1'); +$testconf->add_tapetype('mytapetype', [ + 'comment' => '"mine"', + 'length' => '128 M', +]); +$testconf->add_dumptype('mydumptype', [ + 'comment' => '"mine"', + 'priority' => 'high', # == 2 + 'bumpsize' => $am64_num, + 'bumpmult' => 1.75, + 'starttime' => 1829, + 'holdingdisk' => 'required', + 'compress' => 'client best', + 'encrypt' => 'server', + 'strategy' => 'incronly', + 'comprate' => '0.25,0.75', + 'exclude list' => '"foo" "bar"', + 'exclude list append' => '"true" "star"', + 'exclude file' => '"foolist"', + 'include list' => '"bing" "ting"', + 'include list append' => '"string" "fling"', + 'include file optional' => '"rhyme"', +]); +$testconf->add_interface('inyoface', [ + 'comment' => '"mine"', + 'use' => '100', +]); +$testconf->add_interface('inherface', [ + 'comment' => '"empty"', +]); +$testconf->add_holdingdisk('hd1', [ + 'comment' => '"mine"', + 'directory' => '"/mnt/hd1"', + 'use' => '100M', + 'chunksize' => '1024k', +]); +$testconf->add_holdingdisk('hd2', [ + 'comment' => '"empty"', +]); +$testconf->write(); + +my $cfg_ok = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF'); +ok($cfg_ok, "Load test configuration"); + +SKIP: { + skip "error loading config", unless $cfg_ok; + + is(Amanda::Config::get_config_name(), "TESTCONF", + "config_name set"); + is(Amanda::Config::get_config_dir(), "$CONFIG_DIR/TESTCONF", + "config_dir set"); + is(Amanda::Config::get_config_filename(), + "$CONFIG_DIR/TESTCONF/amanda.conf", + "config_filename set"); +} + +SKIP: { # global parameters + skip "error loading config", unless $cfg_ok; + + is(getconf($CNF_RESERVE), 75, + "integer global confparm"); + is(getconf($CNF_BUMPSIZE), $am64_num+0, + "am64 global confparm"); + is(getconf($CNF_TAPEDEV), "/dev/foo", + "string global confparm"); + is(getconf($CNF_DEVICE_OUTPUT_BUFFER_SIZE), $size_t_num+0, + "size global confparm"); + ok(getconf($CNF_AUTOFLUSH), + "boolean global confparm"); + is(getconf($CNF_TAPERALGO), $Amanda::Config::ALGO_LAST, + "taperalgo global confparam"); + is_deeply([getconf($CNF_RESERVED_UDP_PORT)], [100,200], + "intrange global confparm"); + is(getconf($CNF_DISPLAYUNIT), "M", + "displayunit is correctly uppercased"); + is_deeply(getconf($CNF_DEVICE_PROPERTY), + { "foo" => "bar", "blue" => "car" }, + "proplist global confparm"); + + ok(getconf_seen($CNF_TAPEDEV), + "'tapedev' parm was seen"); + ok(!getconf_seen($CNF_NETUSAGE), + "'netusage' parm was not seen"); +} + +SKIP: { # derived values + skip "error loading config", unless $cfg_ok; + + is(Amanda::Config::getconf_unit_divisor(), 1024, + "correct unit divisor (from displayunit -> KB)"); + ok($Amanda::Config::debug_auth, + "debug_auth setting reflected in global variable"); + ok(!$Amanda::Config::debug_amandad, + "debug_amandad defaults to false"); +} + +SKIP: { # tapetypes + skip "error loading config", unless $cfg_ok; + my $ttyp = lookup_tapetype("mytapetype"); + ok($ttyp, "found mytapetype"); + is(tapetype_getconf($ttyp, $TAPETYPE_COMMENT), 'mine', + "tapetype comment"); + is(tapetype_getconf($ttyp, $TAPETYPE_LENGTH), 128 * 1024, + "tapetype comment"); + + ok(tapetype_seen($ttyp, $TAPETYPE_COMMENT), + "tapetype comment was seen"); + ok(!tapetype_seen($ttyp, $TAPETYPE_LBL_TEMPL), + "tapetype lbl_templ was not seen"); + + is_deeply([ sort(+getconf_list("tapetype")) ], + [ sort("mytapetype", "TEST-TAPE") ], + "getconf_list lists all tapetypes"); +} + +SKIP: { # dumptypes + skip "error loading config", unless $cfg_ok; + + my $dtyp = lookup_dumptype("mydumptype"); + ok($dtyp, "found mydumptype"); + is(dumptype_getconf($dtyp, $DUMPTYPE_COMMENT), 'mine', + "dumptype string"); + is(dumptype_getconf($dtyp, $DUMPTYPE_PRIORITY), 2, + "dumptype priority"); + is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPSIZE), $am64_num+0, + "dumptype size"); + is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPMULT), 1.75, + "dumptype real"); + is(dumptype_getconf($dtyp, $DUMPTYPE_STARTTIME), 1829, + "dumptype time"); + is(dumptype_getconf($dtyp, $DUMPTYPE_HOLDINGDISK), $HOLD_REQUIRED, + "dumptype holdingdisk"); + is(dumptype_getconf($dtyp, $DUMPTYPE_COMPRESS), $COMP_BEST, + "dumptype compress"); + is(dumptype_getconf($dtyp, $DUMPTYPE_ENCRYPT), $ENCRYPT_SERV_CUST, + "dumptype encrypt"); + is(dumptype_getconf($dtyp, $DUMPTYPE_STRATEGY), $DS_INCRONLY, + "dumptype strategy"); + is_deeply([dumptype_getconf($dtyp, $DUMPTYPE_COMPRATE)], [0.25, 0.75], + "dumptype comprate"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_INCLUDE), + { 'file' => [ 'rhyme' ], + 'list' => [ 'bing', 'ting', 'string', 'fling' ], + 'optional' => 1 }, + "dumptype include list"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE), + { 'file' => [ 'foolist' ], + 'list' => [ 'foo', 'bar', 'true', 'star' ], + 'optional' => 0 }, + "dumptype exclude list"); + + ok(dumptype_seen($dtyp, $DUMPTYPE_EXCLUDE), + "'exclude' parm was seen"); + ok(!dumptype_seen($dtyp, $DUMPTYPE_RECORD), + "'record' parm was not seen"); + + is_deeply([ sort(+getconf_list("dumptype")) ], + [ sort(qw( + mydumptype + NO-COMPRESS COMPRESS-FAST COMPRESS-BEST COMPRESS-CUST + SRVCOMPRESS BSD-AUTH KRB4-AUTH NO-RECORD NO-HOLD + NO-FULL + )) ], + "getconf_list lists all dumptypes (including defaults)"); +} + +SKIP: { # interfaces + skip "error loading config" unless $cfg_ok; + my $iface = lookup_interface("inyoface"); + ok($iface, "found inyoface"); + is(interface_name($iface), "inyoface", + "interface knows its name"); + is(interface_getconf($iface, $INTER_COMMENT), 'mine', + "interface comment"); + is(interface_getconf($iface, $INTER_MAXUSAGE), 100, + "interface maxusage"); + + $iface = lookup_interface("inherface"); + ok($iface, "found inherface"); + ok(interface_seen($iface, $INTER_COMMENT), + "seen set for parameters that appeared"); + ok(!interface_seen($iface, $INTER_MAXUSAGE), + "seen not set for parameters that did not appear"); + + is_deeply([ sort(+getconf_list("interface")) ], + [ sort('inyoface', 'inherface', 'default') ], + "getconf_list lists all interfaces (in any order)"); +} + +SKIP: { # holdingdisks + skip "error loading config" unless $cfg_ok; + my $hdisk = lookup_holdingdisk("hd1"); + ok($hdisk, "found hd1"); + is(holdingdisk_name($hdisk), "hd1", + "hd1 knows its name"); + is(holdingdisk_getconf($hdisk, $HOLDING_COMMENT), 'mine', + "holdingdisk comment"); + is(holdingdisk_getconf($hdisk, $HOLDING_DISKDIR), '/mnt/hd1', + "holdingdisk diskdir (directory)"); + is(holdingdisk_getconf($hdisk, $HOLDING_DISKSIZE), 100*1024, + "holdingdisk disksize (use)"); + is(holdingdisk_getconf($hdisk, $HOLDING_CHUNKSIZE), 1024, + "holdingdisk chunksize"); + + $hdisk = lookup_holdingdisk("hd2"); + ok($hdisk, "found hd2"); + ok(holdingdisk_seen($hdisk, $HOLDING_COMMENT), + "seen set for parameters that appeared"); + ok(!holdingdisk_seen($hdisk, $HOLDING_CHUNKSIZE), + "seen not set for parameters that did not appear"); + + # only holdingdisks have this linked-list structure + # exposed + $hdisk = getconf_holdingdisks(); + like(holdingdisk_name($hdisk), qr/hd[12]/, + "one disk is first in list of holdingdisks"); + $hdisk = holdingdisk_next($hdisk); + like(holdingdisk_name($hdisk), qr/hd[12]/, + "another is second in list of holdingdisks"); + ok(!holdingdisk_next($hdisk), + "no third holding disk"); + + is_deeply([ sort(+getconf_list("holdingdisk")) ], + [ sort('hd1', 'hd2') ], + "getconf_list lists all holdingdisks (in any order)"); +} + +## +# Test configuration dumping + +# (uses the config from the previous section) + +# fork a child and capture its stdout +my $pid = open(my $kid, "-|"); +die "Can't fork: $!" unless defined($pid); +if (!$pid) { + Amanda::Config::dump_configuration(); + exit 1; +} +my $dump = join'', <$kid>; +close $kid; + +my $fn = Amanda::Config::get_config_filename(); +like($dump, qr/AMANDA CONFIGURATION FROM FILE "$fn"/, + "config filename is included correctly"); + +like($dump, qr/DEVICE_PROPERTY\s+"foo" "bar"\n/i, + "DEVICE_PROPERTY appears in dump output"); + +like($dump, qr/AMRECOVER_CHECK_LABEL\s+(yes|no)/i, + "AMRECOVER_CHECK_LABEL has a trailing space"); + +like($dump, qr/AMRECOVER_CHECK_LABEL\s+(yes|no)/i, + "AMRECOVER_CHECK_LABEL has a trailing space"); + +like($dump, qr/EXCLUDE\s+LIST "foo" "bar" "true" "star"/i, + "EXCLUDE LIST is in the dump"); +like($dump, qr/EXCLUDE\s+FILE "foolist"/i, + "EXCLUDE FILE is in the dump"); +like($dump, qr/INCLUDE\s+LIST OPTIONAL "bing" "ting" "string" "fling"/i, + "INCLUDE LIST is in the dump"); +like($dump, qr/INCLUDE\s+FILE OPTIONAL "rhyme"/i, + "INCLUDE FILE is in the dump"); + +## +# Explore a quirk of exinclude parsing. Only the last +# exclude (or include) directive affects the 'optional' flag. +# We may want to change this, but we should do so intentionally. +# This is also tested by the 'amgetconf' installcheck. + +$testconf = Amconfig->new(); +$testconf->add_dumptype('mydumptype', [ + 'exclude list' => '"foo" "bar"', + 'exclude list optional append' => '"true" "star"', + 'exclude list append' => '"true" "star"', +]); +$testconf->write(); + +$cfg_ok = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"); +SKIP: { + skip "error loading config", unless $cfg_ok; + + my $dtyp = lookup_dumptype("mydumptype"); + ok($dtyp, "found mydumptype"); + is(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE)->{'optional'}, 0, + "'optional' has no effect when not on the last occurrence"); +} + +$testconf = Amconfig->new(); +$testconf->add_dumptype('mydumptype', [ + 'exclude file' => '"foo" "bar"', + 'exclude file optional append' => '"true" "star"', + 'exclude list append' => '"true" "star"', +]); +$testconf->write(); + +$cfg_ok = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"); +SKIP: { + skip "error loading config", unless $cfg_ok; + + my $dtyp = lookup_dumptype("mydumptype"); + ok($dtyp, "found mydumptype"); + is(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE)->{'optional'}, 0, + "'optional' has no effect when not on the last occurrence of 'file'"); +} + +# TODO: +# overwrites +# inheritance +# more init diff --git a/installcheck/Amanda_Logfile.pl b/installcheck/Amanda_Logfile.pl new file mode 100644 index 0000000..b6c6acd --- /dev/null +++ b/installcheck/Amanda_Logfile.pl @@ -0,0 +1,282 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +use Test::More qw(no_plan); +use File::Path; +use Amconfig; +use strict; + +use lib "@amperldir@"; +use Amanda::Paths; +use Amanda::Tapefile; +use Amanda::Logfile qw(:logtype_t :program_t open_logfile get_logline close_logfile); +use Amanda::Config qw( :init :getconf config_dir_relative ); + +# write a logfile and return the filename +sub write_logfile { + my ($contents) = @_; + my $filename = "$AMANDA_TMPDIR/Amanda_Logfile_test.log"; + + if (!-e $AMANDA_TMPDIR) { + mkpath($AMANDA_TMPDIR); + } + + open my $logfile, ">", $filename or die("Could not create temporary log file"); + print $logfile $contents; + close $logfile; + + return $filename; +} + +#### +## RAW LOGFILE ACCESS + +my $logfile; +my $logdata; + +## +# Test out the constant functions + +is(logtype_t_to_string($L_MARKER), "L_MARKER", "logtype_t_to_string works"); +is(program_t_to_string($P_DRIVER), "P_DRIVER", "program_t_to_string works"); + +## +# Test a simple logfile + +$logdata = <{'timestamp'}, + $res->{'hostname'}, + $res->{'diskname'}, + $res->{'level'}, + $res->{'label'}, + $res->{'filenum'}, + $res->{'status'}, + $res->{'partnum'} + ]; +} + +# set up a basic config +my $testconf = Amconfig->new(); +$testconf->add_param("tapecycle", "20"); +$testconf->write(); + +# load the config +ok(config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"), "config_init is OK"); +my $tapelist = config_dir_relative("tapelist"); + +# set up and read the tapelist +open my $tlf, ">", $tapelist or die("Could not write tapelist"); +print $tlf "20071111010002 TESTCONF004 reuse\n"; +print $tlf "20071110010002 TESTCONF003 reuse\n"; +print $tlf "20071109010002 TESTCONF002 reuse\n"; +print $tlf "20071108010001 TESTCONF001 reuse\n"; +close $tlf; +Amanda::Tapefile::read_tapelist($tapelist) == 0 or die("Could not read tapelist"); + +# set up a number of logfiles in logdir. +my $logf; +my $logdir = $testconf->{'logdir'}; + +# (an old log file that should be ignored) +open $logf, ">", "$logdir/log.20071106010002.0" or die("Could not write logfile"); +print $logf "START taper datestamp 20071107010002 label TESTCONF017 tape 1\n"; +close $logf; + +# (a logfile with two tapes) +open $logf, ">", "$logdir/log.20071106010002.0" or die("Could not write logfile"); +print $logf "START taper datestamp 20071106010002 label TESTCONF018 tape 1\n"; +print $logf "START taper datestamp 20071106010002 label TESTCONF019 tape 2\n"; +close $logf; + +open $logf, ">", "$logdir/log.20071108010001.0" or die("Could not write logfile"); +print $logf "START taper datestamp 20071108010001 label TESTCONF001 tape 1\n"; +close $logf; + +# a logfile with some detail, to run search_logfile against +open $logf, ">", "$logdir/log.20071109010002.0" or die("Could not write logfile"); +print $logf <", "$logdir/log.20071110010002.amflush" or die("Could not write logfile"); +print $logf "START taper datestamp 20071110010002 label TESTCONF003 tape 1\n"; +close $logf; + +# "old-style main log" +open $logf, ">", "$logdir/log.20071111010002" or die("Could not write logfile"); +print $logf "START taper datestamp 20071111010002 label TESTCONF004 tape 1\n"; +close $logf; + +is_deeply([ Amanda::Logfile::find_log() ], + [ "log.20071111010002", "log.20071110010002.amflush", + "log.20071109010002.0", "log.20071108010001.0" ], + "find_log returns correct logfiles in the correct order"); + +my @results; +my @results_arr; + +@results = Amanda::Logfile::search_logfile("TESTCONF002", "20071109010002", + "$logdir/log.20071109010002.0", 1); +is($#results+1, 11, "search_logfile returned 11 results"); + +# sort by filenum so we can compare each to what it should be +@results = sort { $a->{'filenum'} <=> $b->{'filenum'} } @results; + +# and convert the hashes to arrays for easy comparison +@results_arr = map { res2arr($_) } @results; + +is_deeply(\@results_arr, + [ [ '20071109010002', 'clihost', '/usr', 0, 'TESTCONF002', 1, 'OK', '1' ], + [ '20071109010002', 'clihost', '/my documents', 0, 'TESTCONF002', 2, 'OK', '1' ], + [ '20071109010002', 'thatbox', '/var', 1, 'TESTCONF002', 3, 'OK', '--' ], + [ '20071109010002', 'clihost', '/home', 0, 'TESTCONF002', 4, 'OK', '1/5' ], + [ '20071109010002', 'clihost', '/home', 0, 'TESTCONF002', 5, 'OK', '2/5' ], + [ '20071109010002', 'clihost', '/home', 0, 'TESTCONF002', 6, 'OK', '3/5' ], + [ '20071109010002', 'clihost', '/home', 0, 'TESTCONF002', 7, 'OK', '4/5' ], + [ '20071109010002', 'clihost', '/home', 0, 'TESTCONF002', 8, 'OK', '5/5' ], + [ '20071109010002', 'thatbox', '/u_lose', 2, 'TESTCONF002', 9, '"Oh no!"', '1/4' ], + [ '20071109010002', 'thatbox', '/u_lose', 2, 'TESTCONF002', 10, '"Oh no!"', '2/4' ], + [ '20071109010002', 'thatbox', '/u_lose', 2, 'TESTCONF002', 11, '"Oh no!"', '3/4' ] ], + "results are correct"); + +my @filtered; +my @filtered_arr; + +@filtered = Amanda::Logfile::dumps_match([@results], "thatbox", undef, undef, undef, 0); +is($#filtered+1, 4, "four results match 'thatbox'"); +@filtered = sort { $a->{'filenum'} <=> $b->{'filenum'} } @filtered; + +@filtered_arr = map { res2arr($_) } @filtered; + +is_deeply(\@filtered_arr, + [ [ '20071109010002', 'thatbox', '/var', 1, 'TESTCONF002', 3, 'OK', '--' ], + [ '20071109010002', 'thatbox', '/u_lose', 2, 'TESTCONF002', 9, '"Oh no!"', '1/4' ], + [ '20071109010002', 'thatbox', '/u_lose', 2, 'TESTCONF002', 10, '"Oh no!"', '2/4' ], + [ '20071109010002', 'thatbox', '/u_lose', 2, 'TESTCONF002', 11, '"Oh no!"', '3/4' ] ], + "results are correct"); + +@filtered = Amanda::Logfile::dumps_match([@results], "thatbox", "/var", undef, undef, 0); +is($#filtered+1, 1, "only one result matches 'thatbox:/var'"); + +@filtered = Amanda::Logfile::dumps_match([@results], undef, undef, "20071109010002", undef, 0); +is($#filtered+1, 11, "all 11 results match '20071109010002'"); + +@filtered = Amanda::Logfile::dumps_match([@results], undef, undef, "20071109010002", undef, 1); +is($#filtered+1, 8, "of those, 8 results are 'OK'"); + +@filtered = Amanda::Logfile::dumps_match([@results], undef, undef, undef, "2", 0); +is($#filtered+1, 3, "3 results are at level 2"); diff --git a/installcheck/Amanda_Types.pl b/installcheck/Amanda_Types.pl new file mode 100644 index 0000000..a301f80 --- /dev/null +++ b/installcheck/Amanda_Types.pl @@ -0,0 +1,31 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +use Test::More qw(no_plan); +use Amconfig; +use strict; + +use lib "@amperldir@"; +use Amanda::Types; + +# Not much to test, but we can at least exercise the constructor and destructor, +# and the SWIG getters and setters: +ok(my $df = Amanda::Types::dumpfile_t->new(), "can create a dumpfile_t"); +is($df->{'datestamp'}, '', "newly created dumpfile_t has empty datestamp"); +ok($df->{'name'} = "myhost", "can write to a string in the header"); +is($df->{'name'}, "myhost", "..and get it back"); diff --git a/installcheck/Amconfig.pm.in b/installcheck/Amconfig.pm.in new file mode 100644 index 0000000..c2b78fd --- /dev/null +++ b/installcheck/Amconfig.pm.in @@ -0,0 +1,302 @@ +# vim:ft=perl +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +package Amconfig; +use File::Path; +use Carp; + +=head1 NAME + +Amconfig - set up amanda configurations for installcheck testing + +=head1 SYNOPSIS + + use Amconfig; + + my $testconf = Amconfig->new(); + $testconf->add_param("runtapes", "5"); + $testconf->add_subsec("tapetype", "DUCKTAPE", { length => "10G", filemark => "4096k" }); + # ... + $testconf->write(); + +The resulting configuration is always named "TESTCONF". The basic +configuration contains only a few parameters that are necessary just +to run Amanda applications in the test environment. It also contains +a tapetype, C. + +Note that it's quite possible to produce an invalid configuration with this +package (and, in fact, some of the tests do just that). + +=head2 VTAPES + +This module can set up a vtape configuration, replete with the proper +vtape directories, using C. The vtapes are created under +the "TESTCONF" configuration directory, for ease of later deletion. Do +not store anything large in these vtapes! + +=head1 WARNING + +Using this module I destroy any existing configuration named +TESTDIR. I do not use this on a production machine! + +=head1 FUNCTIONS + +=over + +=item C + +Create a new configuration object + +=cut + +sub new { + my $class = shift; + + # An instance is a blessed hash containing parameters. Start with + # some defaults to make sure things run. + my $infofile = '@CONFIG_DIR@/TESTCONF/curinfo'; + my $logdir = '@CONFIG_DIR@/TESTCONF/log'; + my $indexdir = '@CONFIG_DIR@/TESTCONF/index'; + + my $self = { + 'infofile' => $infofile, + 'logdir' => $logdir, + 'indexdir' => $indexdir, + + 'vtapes' => [], + + # Global params are stored as an arrayref, so that the same declaration + # can appear multiple times + 'params' => [ + 'mailto' => '"nobody@invalidomain"', + 'dumpuser' => '"' . (getpwuid($<))[0] . '"', # current username + + # These dirs are under CONFIG_DIR just for ease of destruction. + # This is not a recommended layout! + 'infofile' => "\"$infofile\"", + 'logdir' => "\"$logdir\"", + 'indexdir' => "\"$indexdir\"", + + 'tapetype' => '"TEST-TAPE"', + ], + + # Subsections are stored as a hashref of arrayrefs, keyed by + # subsection name + + 'tapetypes' => { + 'TEST-TAPE' => [ + 'length' => '50 mbytes', + 'filemark' => '4 kbytes' + ], + }, + + 'dumptypes' => { }, + + 'interfaces' => { }, + + 'holdingdisks' => { }, + + 'dles' => [ ], + }; + bless($self, $class); + return $self; +} + +=item C + +Add the given parameter to the configuration file, overriding any +previous value. Note that strings which should be quoted in the configuration +file itself must be double-quoted here, e.g., + + $testconf->add_param('org' => '"MyOrganization"'); + +=cut + +sub add_param { + my $self = shift; + my ($param, $value) = @_; + + push @{$self->{'params'}}, $param, $value; +} + +=item C +=item C +=item C +=item C + +Add the given subsection to the configuration file, including all +values in the arrayref. The values should be specified as alternating +key/value pairs. + +=cut + +sub add_tapetype { + my $self = shift; + my ($name, $values_arrayref) = @_; + $self->{'tapetypes'}{$name} = $values_arrayref; +} + +sub add_dumptype { + my $self = shift; + my ($name, $values_arrayref) = @_; + $self->{'dumptypes'}{$name} = $values_arrayref; +} + +sub add_holdingdisk { + my $self = shift; + my ($name, $values_arrayref) = @_; + $self->{'holdingdisks'}{$name} = $values_arrayref; +} + +sub add_interface { + my $self = shift; + my ($name, $values_arrayref) = @_; + $self->{'interfaces'}{$name} = $values_arrayref; +} + +=item C + +Add a disklist entry; C<$line> is inserted verbatim into the disklist. + +=cut + +sub add_dle { + my $self = shift; + my ($line) = @_; + push @{$self->{'dles'}}, $line; +} + +=item C + +Set up to use a single vtape (no changer). This creates the proper +directory hierarchy and sets C to the relevant path. + +=cut + +sub setup_vtape { + my $self = shift; + my $tapepath = "@CONFIG_DIR@/TESTCONF/vtapes/tape1"; + push @{$self->{'vtapes'}}, $tapepath; + + $self->add_param("tapedev", "\"file:$tapepath\""); +} + +=item C + +Write out the accumulated configuration file, along with any other +files necessary to run Amanda. + +=cut + +sub write { + my $self = shift; + + my $testconf_dir = '@CONFIG_DIR@/TESTCONF'; + if (-e $testconf_dir) { + rmtree($testconf_dir) or die("Could not remove '$testconf_dir'"); + } + mkpath($testconf_dir); + + # set up curinfo dir, etc. + mkpath($self->{'infofile'}) or die("Could not create infofile directory"); + mkpath($self->{'logdir'}) or die("Could not create logdir directory"); + mkpath($self->{'indexdir'}) or die("Could not create indexdir directory"); + + # create any vtapes + for my $vtape (@{$self->{'vtapes'}}) { + mkpath("$vtape/data") or die("Could not create vtape directory '$vtape/data'"); + } + + $self->_write_tapelist("$testconf_dir/tapelist"); + $self->_write_disklist("$testconf_dir/disklist"); + $self->_write_amanda_conf("$testconf_dir/amanda.conf"); +} + +sub _write_tapelist { + my $self = shift; + my ($filename) = @_; + + # create an empty tapelist + open(my $tapelist, ">", $filename); + close($tapelist); +} + +sub _write_disklist { + my $self = shift; + my ($filename) = @_; + + # don't bother writing a disklist if there are no dle's + return unless $self->{'dles'}; + + open(my $disklist, ">", $filename); + + for my $dle_line (@{$self->{'dles'}}) { + print $disklist "$dle_line\n"; + } + + close($disklist); +} + +sub _write_amanda_conf { + my $self = shift; + my ($filename) = @_; + + open my $amanda_conf, ">", $filename + or croak("Could not open '$filename'"); + + # write key/value pairs + my @params = @{$self->{'params'}}; + while (@params) { + $param = shift @params; + $value = shift @params; + print $amanda_conf "$param $value\n"; + } + + # write out subsections + $self->_write_amanda_conf_subsection($amanda_conf, "tapetype", $self->{"tapetypes"}); + $self->_write_amanda_conf_subsection($amanda_conf, "dumptype", $self->{"dumptypes"}); + $self->_write_amanda_conf_subsection($amanda_conf, "interface", $self->{"interfaces"}); + $self->_write_amanda_conf_subsection($amanda_conf, "holdingdisk", $self->{"holdingdisks"}); + + close($amanda_conf); +} + +sub _write_amanda_conf_subsection { + my $self = shift; + my ($amanda_conf, $subsec_type, $subsec_ref) = @_; + + for my $subsec_name (keys %$subsec_ref) { + my @values = @{$subsec_ref->{$subsec_name}}; + + if ($subsec_type eq "holdingdisk") { + print $amanda_conf "\nholdingdisk $subsec_name {\n"; + } else { + print $amanda_conf "\ndefine $subsec_type $subsec_name {\n"; + } + + while (@values) { + $param = shift @values; + $value = shift @values; + print $amanda_conf "$param $value\n"; + } + print $amanda_conf "}\n"; + } +} + +1; diff --git a/installcheck/Makefile.am b/installcheck/Makefile.am new file mode 100644 index 0000000..bb3e938 --- /dev/null +++ b/installcheck/Makefile.am @@ -0,0 +1,59 @@ +# Note that this architecture assumes a full install -- not just server +# or just client. Neither is sufficiently test-able on its own. + +include $(top_srcdir)/config/automake/vars.am +include $(top_srcdir)/config/automake/scripts.am + +# Add your tests here. + +common_tests = \ + Amanda_Config \ + Amanda_Types + +server_tests = \ + Amanda_Changer \ + Amanda_Cmdline \ + Amanda_Logfile \ + amcheckdump \ + amdevcheck \ + amgetconf + +tests = $(common_tests) +if WANT_SERVER +tests += $(server_tests) +endif + +# Add any common files (that should not be run as tests) here: +test_utils = Amconfig.pm + +SCRIPTS_PERL = $(common_tests) $(server_tests) $(test_utils) + +# we don't need to syntax check the test scripts.. +CHECK_PERL = + +.PHONY: clobber_my_config_is_ok +clobber_my_config_is_ok: + @if test "$(CLOBBER_MY_CONFIG)" != "OK"; then \ + echo ""; \ + echo "'make installcheck' is a dangerous tool. It will overwrite your"; \ + echo "amanda-client.conf and amandates, and (if it"; \ + echo "triggers an as-yet undetected bug) may do other unexpected things. You are"; \ + echo "strongly encouraged"; \ + echo " - not to run installchecks on a production install"; \ + echo " - not to run installchecks as root"; \ + echo "See http://wiki.zmanda.com/index.php/Testing for instructions on setting up a"; \ + echo "test environment in which"; \ + echo "potential damage is limited by your filesystem's permissions. To actually run"; \ + echo "the installchecks, invoke make"; \ + echo "as follows:"; \ + echo " $(MAKE) CLOBBER_MY_CONFIG=OK installcheck"; \ + exit 1; \ + fi + +installcheck-local: clobber_my_config_is_ok $(SCRIPTS_PERL) + $(mkdir_p) $(AMANDA_TMPDIR) + $(PERL) -I$(srcdir) -I$(builddir) -e 'use Test::Harness qw(&runtests); runtests(@ARGV);' $(tests) + rm -rf "$(CONFIG_DIR)/TESTCONF" + rm -rf "$(CONFIG_DIR)/amanda-client.conf" + rm -rf "$(DEFAULT_AMANDATES_FILE)" + rm -rf "$(GNUTAR_LISTED_INCREMENTAL_DIR)" diff --git a/installcheck/Makefile.in b/installcheck/Makefile.in new file mode 100644 index 0000000..afbc373 --- /dev/null +++ b/installcheck/Makefile.in @@ -0,0 +1,959 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Note that this architecture assumes a full install -- not just server +# or just client. Neither is sufficiently test-able on its own. + +# vim:ft=automake +# Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License version 2.1 as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +# simple include file to pre-define variables which are then +='d by other +# scripts in this directory. + +# vim:ft=automake +# Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License version 2.1 as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +# SYNOPSIS: +# +# Automake magic to handle the various tasks of building scripts. Scripts can +# be built down to extensionless executables (e.g., foo.pl -> foo), or to +# files with the usual extension (foo-lib.sh.in -> foo.sh). +# +# Files which support it are syntax-checked when the user invokes 'make check'. +# +# All *target* filenames must be listed in SCRIPTS_SHELL, SCRIPTS_PERL, and +# SCRIPTS_AWK to support 'make check', 'make dist', and 'make distclean'. +# +# USAGE: +# +# include $(top_srcdir)/config/automake/vars.am +# include $(top_srcdir)/config/automake/scripts.am +# ... +# SCRIPTS_PERL = fooscript barscript perl-lib.pl perlmod.pm +# SCRIPTS_SHELL = shell1 shell2 sh-lib.sh +# SCRIPTS_AWK = talk balk chalk awk-lib.awk +# +# with the corresponding files in the repository: +# +# fooscript.pl barscript.pl perl-lib.pl.in perlmod.pm.in +# shell1.sh shell2.sh sh-lib.sh.in +# talk.awk balk.awk chalk.awk awk-lib.awk.in +# +# by default, all shell and perl scripts are syntax checked. If this is +# a problem (for example, perl scripts depending on Amanda extension +# modules), then assign to CHECK_{PERL,SHELL} the list of files you wish +# to be checked (which can be empty). +# +# To add extra flags to the perl checks (e.g., to add new -I flags), set +# CHECK_PERL_FLAGS. + +# Implementation note: +# +# This file uses config.status to substitute @foo@ in those scripts while +# converting them. It also adds the executable bits (a+x) to extensionless +# files. The substitution works even though the files are not listed in +# configure.in +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/automake/scripts.am \ + $(top_srcdir)/config/automake/vars.am +@WANT_SERVER_TRUE@am__append_1 = $(server_tests) +subdir = installcheck +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/config/macro-archive/ac_define_dir.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_perl_version.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_swig.m4 \ + $(top_srcdir)/config/macro-archive/ax_compare_version.m4 \ + $(top_srcdir)/config/macro-archive/docbook-dtd.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt-min.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt.m4 \ + $(top_srcdir)/config/macro-archive/xsltproc.m4 \ + $(top_srcdir)/config/amanda/amplot.m4 \ + $(top_srcdir)/config/amanda/bsd-security.m4 \ + $(top_srcdir)/config/amanda/bsdtcp-security.m4 \ + $(top_srcdir)/config/amanda/bsdudp-security.m4 \ + $(top_srcdir)/config/amanda/changer.m4 \ + $(top_srcdir)/config/amanda/components.m4 \ + $(top_srcdir)/config/amanda/compress.m4 \ + $(top_srcdir)/config/amanda/config.m4 \ + $(top_srcdir)/config/amanda/debugging.m4 \ + $(top_srcdir)/config/amanda/defaults.m4 \ + $(top_srcdir)/config/amanda/devprefix.m4 \ + $(top_srcdir)/config/amanda/dirs.m4 \ + $(top_srcdir)/config/amanda/documentation.m4 \ + $(top_srcdir)/config/amanda/dumpers.m4 \ + $(top_srcdir)/config/amanda/flags.m4 \ + $(top_srcdir)/config/amanda/flock.m4 \ + $(top_srcdir)/config/amanda/funcs.m4 \ + $(top_srcdir)/config/amanda/getfsent.m4 \ + $(top_srcdir)/config/amanda/i18n.m4 \ + $(top_srcdir)/config/amanda/ipv6.m4 \ + $(top_srcdir)/config/amanda/krb4-security.m4 \ + $(top_srcdir)/config/amanda/krb5-security.m4 \ + $(top_srcdir)/config/amanda/lfs.m4 \ + $(top_srcdir)/config/amanda/libs.m4 \ + $(top_srcdir)/config/amanda/net.m4 \ + $(top_srcdir)/config/amanda/progs.m4 \ + $(top_srcdir)/config/amanda/readdir.m4 \ + $(top_srcdir)/config/amanda/readline.m4 \ + $(top_srcdir)/config/amanda/rsh-security.m4 \ + $(top_srcdir)/config/amanda/s3-device.m4 \ + $(top_srcdir)/config/amanda/shmem.m4 \ + $(top_srcdir)/config/amanda/socklen_t_equiv.m4 \ + $(top_srcdir)/config/amanda/ssh-security.m4 \ + $(top_srcdir)/config/amanda/summary.m4 \ + $(top_srcdir)/config/amanda/swig.m4 \ + $(top_srcdir)/config/amanda/syshacks.m4 \ + $(top_srcdir)/config/amanda/tape.m4 \ + $(top_srcdir)/config/amanda/types.m4 \ + $(top_srcdir)/config/amanda/userid.m4 \ + $(top_srcdir)/config/amanda/version.m4 \ + $(top_srcdir)/config/gnulib/alloca.m4 \ + $(top_srcdir)/config/gnulib/arpa_inet_h.m4 \ + $(top_srcdir)/config/gnulib/base64.m4 \ + $(top_srcdir)/config/gnulib/eoverflow.m4 \ + $(top_srcdir)/config/gnulib/extensions.m4 \ + $(top_srcdir)/config/gnulib/float_h.m4 \ + $(top_srcdir)/config/gnulib/fsusage.m4 \ + $(top_srcdir)/config/gnulib/getaddrinfo.m4 \ + $(top_srcdir)/config/gnulib/gettimeofday.m4 \ + $(top_srcdir)/config/gnulib/gnulib-comp.m4 \ + $(top_srcdir)/config/gnulib/include_next.m4 \ + $(top_srcdir)/config/gnulib/inet_ntop.m4 \ + $(top_srcdir)/config/gnulib/intmax_t.m4 \ + $(top_srcdir)/config/gnulib/lock.m4 \ + $(top_srcdir)/config/gnulib/longlong.m4 \ + $(top_srcdir)/config/gnulib/malloc.m4 \ + $(top_srcdir)/config/gnulib/mkdtemp.m4 \ + $(top_srcdir)/config/gnulib/netinet_in_h.m4 \ + $(top_srcdir)/config/gnulib/onceonly_2_57.m4 \ + $(top_srcdir)/config/gnulib/physmem.m4 \ + $(top_srcdir)/config/gnulib/safe-read.m4 \ + $(top_srcdir)/config/gnulib/safe-write.m4 \ + $(top_srcdir)/config/gnulib/snprintf.m4 \ + $(top_srcdir)/config/gnulib/socklen.m4 \ + $(top_srcdir)/config/gnulib/sockpfaf.m4 \ + $(top_srcdir)/config/gnulib/ssize_t.m4 \ + $(top_srcdir)/config/gnulib/stdbool.m4 \ + $(top_srcdir)/config/gnulib/stdint.m4 \ + $(top_srcdir)/config/gnulib/stdio_h.m4 \ + $(top_srcdir)/config/gnulib/stdlib_h.m4 \ + $(top_srcdir)/config/gnulib/strdup.m4 \ + $(top_srcdir)/config/gnulib/string_h.m4 \ + $(top_srcdir)/config/gnulib/sys_socket_h.m4 \ + $(top_srcdir)/config/gnulib/sys_stat_h.m4 \ + $(top_srcdir)/config/gnulib/sys_time_h.m4 \ + $(top_srcdir)/config/gnulib/tempname.m4 \ + $(top_srcdir)/config/gnulib/ulonglong.m4 \ + $(top_srcdir)/config/gnulib/unistd_h.m4 \ + $(top_srcdir)/config/gnulib/vasnprintf.m4 \ + $(top_srcdir)/config/gnulib/visibility.m4 \ + $(top_srcdir)/config/gnulib/wchar.m4 \ + $(top_srcdir)/config/gettext-macros/gettext.m4 \ + $(top_srcdir)/config/gettext-macros/iconv.m4 \ + $(top_srcdir)/config/gettext-macros/inttypes_h.m4 \ + $(top_srcdir)/config/gettext-macros/lib-ld.m4 \ + $(top_srcdir)/config/gettext-macros/lib-link.m4 \ + $(top_srcdir)/config/gettext-macros/lib-prefix.m4 \ + $(top_srcdir)/config/gettext-macros/longlong.m4 \ + $(top_srcdir)/config/gettext-macros/nls.m4 \ + $(top_srcdir)/config/gettext-macros/po.m4 \ + $(top_srcdir)/config/gettext-macros/progtest.m4 \ + $(top_srcdir)/config/gettext-macros/size_max.m4 \ + $(top_srcdir)/config/gettext-macros/stdint_h.m4 \ + $(top_srcdir)/config/gettext-macros/wchar_t.m4 \ + $(top_srcdir)/config/gettext-macros/wint_t.m4 \ + $(top_srcdir)/config/gettext-macros/xsize.m4 \ + $(top_srcdir)/config/libtool.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMANDA_DBGDIR = @AMANDA_DBGDIR@ +AMANDA_DEBUG_DAYS = @AMANDA_DEBUG_DAYS@ +AMANDA_STATIC_LDFLAGS = @AMANDA_STATIC_LDFLAGS@ +AMANDA_TMPDIR = @AMANDA_TMPDIR@ +AMANDA_WARNING_CFLAGS = @AMANDA_WARNING_CFLAGS@ +AMLINT = @AMLINT@ +AMLINTFLAGS = @AMLINTFLAGS@ +AMPLOT_CAT_COMPRESS = @AMPLOT_CAT_COMPRESS@ +AMPLOT_CAT_GZIP = @AMPLOT_CAT_GZIP@ +AMPLOT_CAT_PACK = @AMPLOT_CAT_PACK@ +AMPLOT_COMPRESS = @AMPLOT_COMPRESS@ +AMTAR = @AMTAR@ +AR = @AR@ +ARPA_INET_H = @ARPA_INET_H@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH = @BASH@ +BINARY_OWNER = @BINARY_OWNER@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +CAT = @CAT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CHIO = @CHIO@ +CHS = @CHS@ +CLIENT_LOGIN = @CLIENT_LOGIN@ +CLIENT_SCRIPTS_OPT = @CLIENT_SCRIPTS_OPT@ +COMPRESS = @COMPRESS@ +CONFIG_DIR = @CONFIG_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL_CONFIG = @CURL_CONFIG@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DD = @DD@ +DEFAULT_AMANDATES_FILE = @DEFAULT_AMANDATES_FILE@ +DEFAULT_CHANGER_DEVICE = @DEFAULT_CHANGER_DEVICE@ +DEFAULT_CONFIG = @DEFAULT_CONFIG@ +DEFAULT_SERVER = @DEFAULT_SERVER@ +DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@ +DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOC_BUILD_DATE = @DOC_BUILD_DATE@ +DUMP = @DUMP@ +DUMPER_DIR = @DUMPER_DIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EOVERFLOW = @EOVERFLOW@ +EXAMPLE_TAPEDEV = @EXAMPLE_TAPEDEV@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FLOAT_H = @FLOAT_H@ +GETCONF = @GETCONF@ +GETTEXT = @GETTEXT@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNUPLOT = @GNUPLOT@ +GNUTAR = @GNUTAR@ +GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GZIP = @GZIP@ +HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_MKDIR = @HAVE_DECL_MKDIR@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_IO_H = @HAVE_IO_H@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRNDUP = @HAVE_STRNDUP@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE__BOOL = @HAVE__BOOL@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBS = @LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAILER = @MAILER@ +MAKEINFO = @MAKEINFO@ +MAXTAPEBLOCKSIZE = @MAXTAPEBLOCKSIZE@ +MCUTIL = @MCUTIL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MT = @MT@ +MTX = @MTX@ +MT_FILE_FLAG = @MT_FILE_FLAG@ +NETINET_IN_H = @NETINET_IN_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCAT = @PCAT@ +PERL = @PERL@ +PERLEXTLIBS = @PERLEXTLIBS@ +PERL_INC = @PERL_INC@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +PRINT = @PRINT@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_FCHDIR = @REPLACE_FCHDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +RESTORE = @RESTORE@ +SAMBA_CLIENT = @SAMBA_CLIENT@ +SERVICE_SUFFIX = @SERVICE_SUFFIX@ +SETUID_GROUP = @SETUID_GROUP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SNAPSHOT_STAMP = @SNAPSHOT_STAMP@ +SORT = @SORT@ +SSH = @SSH@ +STDBOOL_H = @STDBOOL_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SVN = @SVN@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYS_SOCKET_H = @SYS_SOCKET_H@ +SYS_STAT_H = @SYS_STAT_H@ +SYS_TIME_H = @SYS_TIME_H@ +USE_NLS = @USE_NLS@ +USE_VERSION_SUFFIXES = @USE_VERSION_SUFFIXES@ +VDUMP = @VDUMP@ +VERSION = @VERSION@ +VERSION_COMMENT = @VERSION_COMMENT@ +VERSION_MAJOR = @VERSION_MAJOR@ +VERSION_MINOR = @VERSION_MINOR@ +VERSION_PATCH = @VERSION_PATCH@ +VERSION_SUFFIX = @VERSION_SUFFIX@ +VRESTORE = @VRESTORE@ +VXDUMP = @VXDUMP@ +VXRESTORE = @VXRESTORE@ +WCHAR_H = @WCHAR_H@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XFSDUMP = @XFSDUMP@ +XFSRESTORE = @XFSRESTORE@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XSLREL = @XSLREL@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +amincludedir = @amincludedir@ +amlibdir = @amlibdir@ +amlibexecdir = @amlibexecdir@ +amperldir = @amperldir@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUFFIXES = +EXTRA_DIST = +BUILT_SOURCES = +MOSTLYCLEANFILES = + +# config.status leaves config.log files around +CLEANFILES = config.log + +# and we'll need to clean up our generated files for distclean +DISTCLEANFILES = $(SCRIPTS_SHELL) $(SCRIPTS_PERL) $(SCRIPTS_AWK) +MAINTAINERCLEANFILES = + +# syntax-check shell scripts on 'make check' +CHECK_SHELL = $(SCRIPTS_SHELL) + +# Add your tests here. +common_tests = \ + Amanda_Config \ + Amanda_Types + +server_tests = \ + Amanda_Changer \ + Amanda_Cmdline \ + Amanda_Logfile \ + amcheckdump \ + amdevcheck \ + amgetconf + +tests = $(common_tests) $(am__append_1) + +# Add any common files (that should not be run as tests) here: +test_utils = Amconfig.pm +SCRIPTS_PERL = $(common_tests) $(server_tests) $(test_utils) + +# we don't need to syntax check the test scripts.. +CHECK_PERL = +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/config/automake/vars.am $(top_srcdir)/config/automake/scripts.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu installcheck/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu installcheck/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: installcheck-local + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am check-local clean clean-generic \ + clean-libtool dist-hook distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installcheck-local \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am uninstall uninstall-am + + +# Perl +%: %.pl $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + chmod a+x $@ + +%.pl: %.pl.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +%.pm: %.pm.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +# Shell +%: %.sh $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + chmod a+x $@ + +%.sh: %.sh.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +# Awk +%: %.awk $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + chmod a+x $@ + +%.awk: %.awk.in $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< + +# syntax-check perl scripts on 'make check' +check-perl: $(CHECK_PERL) + @CHECK_PERL="$(CHECK_PERL)"; \ + if test -n "$(PERL)"; then \ + for perlobj in $$CHECK_PERL; do \ + $(PERL) $(CHECK_PERL_FLAGS) -c -w -T $$perlobj || exit 1; \ + done; \ + fi +check-local: check-perl +check-shell: $(CHECK_SHELL) + @CHECK_SHELL="$(CHECK_SHELL)"; \ + if test -n "$$CHECK_SHELL"; then \ + if test -n "$(BASH)"; then \ + for shobj in $$CHECK_SHELL; do \ + if $(BASH) -n $$shobj; then \ + echo "$$shobj syntax OK"; \ + else \ + echo "$$shobj syntax error"; \ + exit 1; \ + fi; \ + done; \ + else \ + echo "No 'bash' available -- cannot syntax-check shell scripts"; \ + fi; \ + fi +check-local: check-shell + +# make sure that the sources for all shell and perl scripts get included +# in the distribution +dist-scripts: + SCRIPTS_PERL="$(SCRIPTS_PERL)"; SCRIPTS_SHELL="$(SCRIPTS_SHELL)"; SCRIPTS_AWK="$(SCRIPTS_AWK)"; \ + for script in $$SCRIPTS_PERL; do \ + test -f $(srcdir)/$${script}.pl && { cp -p $(srcdir)/$${script}.pl $(distdir)/ || exit 1; } \ + done; \ + for script in $$SCRIPTS_SHELL; do \ + test -f $(srcdir)/$${script}.sh && { cp -p $(srcdir)/$${script}.sh $(distdir)/ || exit 1; } \ + done; \ + for script in $$SCRIPTS_AWK; do \ + test -f $(srcdir)/$${script}.awk && { cp -p $(srcdir)/$${script}.awk $(distdir)/ || exit 1; } \ + done; \ + for script in $$SCRIPTS_SHELL $$SCRIPTS_PERL $$SCRIPTS_AWK; do \ + test -f $(srcdir)/$${script}.in && { cp -p $(srcdir)/$${script}.in $(distdir)/ || exit 1; } \ + done; \ + true +dist-hook: dist-scripts + +.PHONY: clobber_my_config_is_ok +clobber_my_config_is_ok: + @if test "$(CLOBBER_MY_CONFIG)" != "OK"; then \ + echo ""; \ + echo "'make installcheck' is a dangerous tool. It will overwrite your"; \ + echo "amanda-client.conf and amandates, and (if it"; \ + echo "triggers an as-yet undetected bug) may do other unexpected things. You are"; \ + echo "strongly encouraged"; \ + echo " - not to run installchecks on a production install"; \ + echo " - not to run installchecks as root"; \ + echo "See http://wiki.zmanda.com/index.php/Testing for instructions on setting up a"; \ + echo "test environment in which"; \ + echo "potential damage is limited by your filesystem's permissions. To actually run"; \ + echo "the installchecks, invoke make"; \ + echo "as follows:"; \ + echo " $(MAKE) CLOBBER_MY_CONFIG=OK installcheck"; \ + exit 1; \ + fi + +installcheck-local: clobber_my_config_is_ok $(SCRIPTS_PERL) + $(mkdir_p) $(AMANDA_TMPDIR) + $(PERL) -I$(srcdir) -I$(builddir) -e 'use Test::Harness qw(&runtests); runtests(@ARGV);' $(tests) + rm -rf "$(CONFIG_DIR)/TESTCONF" + rm -rf "$(CONFIG_DIR)/amanda-client.conf" + rm -rf "$(DEFAULT_AMANDATES_FILE)" + rm -rf "$(GNUTAR_LISTED_INCREMENTAL_DIR)" +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/installcheck/amcheckdump.pl b/installcheck/amcheckdump.pl new file mode 100644 index 0000000..ff6a150 --- /dev/null +++ b/installcheck/amcheckdump.pl @@ -0,0 +1,34 @@ +use Test::More qw( no_plan ); + +use Amconfig; + +use lib "@amperldir@"; +use Amanda::Paths; + +sub amcheckdump { + my $cmd = "$sbindir/amcheckdump " . join(" ", @_) . " 2>&1"; + my $result = `$cmd`; + chomp $result; + return $result; +} + +my $testconf; + +## +# First, try amgetconf out without a config + +like(amcheckdump(), qr/\AUSAGE:/i, + "bare 'amcheckdump' gives usage message"); +like(amcheckdump("this-probably-doesnt-exist"), qr(could not open conf file)i, + "error message when configuration parameter doesn't exist"); + +## +# Now use a config with a vtape + +# this is re-created for each test +$testconf = Amconfig->new(); +$testconf->setup_vtape(); +$testconf->write(); + +like(amcheckdump("TESTCONF"), qr(could not find)i, + "'amcheckdump' on a brand-new config finds no dumps."); diff --git a/installcheck/amdevcheck.pl b/installcheck/amdevcheck.pl new file mode 100644 index 0000000..895f73a --- /dev/null +++ b/installcheck/amdevcheck.pl @@ -0,0 +1,67 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +use Test::More qw( no_plan ); + +use Amconfig; +use lib "@amperldir@"; +use Amanda::Paths; + +sub amdevcheck { + my $cmd = "$sbindir/amdevcheck " . join(" ", @_) . " 2>&1"; + my $result = `$cmd`; + chomp $result; + return $result; +} + +my $testconf; + +## +# First, try amgetconf out without a config + +like(amdevcheck(), qr(\AUsage: )i, + "bare 'amdevcheck' gives usage message"); +like(amdevcheck("this-probably-doesnt-exist"), qr(could not open conf file)i, + "error message when configuration parameter doesn't exist"); + +## +# Next, work against a basically empty config + +# this is re-created for each test +$testconf = Amconfig->new(); +$testconf->add_param("tapedev", '"/dev/null"'); +$testconf->write(); + +# test some defaults +like(amdevcheck('TESTCONF'), qr{File /dev/null is not a tape device}, + "uses tapedev by default"); + +## +# Now use a config with a vtape + +# this is re-created for each test +$testconf = Amconfig->new(); +$testconf->setup_vtape(); +$testconf->write(); + +is_deeply([ sort split "\n", amdevcheck('TESTCONF') ], + [ sort "VOLUME_UNLABELED", "VOLUME_ERROR", "DEVICE_ERROR" ], + "empty vtape described as VOLUME_UNLABELED, VOLUME_ERROR, DEVICE_ERROR"); + +like(amdevcheck('TESTCONF', "/dev/null"), qr{File /dev/null is not a tape device}, + "can override device on the command line"); diff --git a/installcheck/amgetconf.pl b/installcheck/amgetconf.pl new file mode 100644 index 0000000..31ea204 --- /dev/null +++ b/installcheck/amgetconf.pl @@ -0,0 +1,189 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +use Test::More qw(no_plan); + +use Amconfig; +use lib "@amperldir@"; +use Amanda::Paths; + +# wrapper to call amgetconf and return the results +sub amgetconf { + # open amgetconf and read from it + my $cmd = "$sbindir/amgetconf " . join(" ", @_) . " 2>&1"; + my $result = `$cmd`; + chomp $result; + return $result; +} + +# this is re-created for each test +my $testconf; + +## +# First, try amgetconf out without a config + +like(amgetconf(), qr(\AUsage: )i, + "bare 'amgetconf' gives usage message"); +like(amgetconf("this-probably-doesnt-exist"), qr(could not open conf file)i, + "error message when configuration parameter doesn't exist"); + +## +# Next, work against a basically empty config + +$testconf = Amconfig->new(); +$testconf->write(); + +# test some defaults +is(amgetconf('TESTCONF', "reserve"), "100", + "reserve defaults to 100"); +is(amgetconf('TESTCONF', "tapelist"), "tapelist", + "tapelist defaults to 'tapelist'"); +is(amgetconf('TESTCONF', "usetimestamps"), "yes", + "usetimestamps defaults to 'yes'"); + +# test a nonexistent parameter +like(amgetconf('TESTCONF', "foos_per_bar"), qr/no such parameter/, + "handles nonexistent parameters"); + +# test build parameters (just the most common) +is(amgetconf('TESTCONF', "build.bindir"), $bindir, "build.bindir is correct"); +is(amgetconf('TESTCONF', "build.sbindir"), $sbindir, "build.sbindir is correct"); +is(amgetconf('TESTCONF', "build.amlibexecdir"), $amlibexecdir, "build.amlibexecdir is correct"); +is(amgetconf('TESTCONF', "build.mandir"), $mandir, "build.mandir is correct"); +is(amgetconf('TESTCONF', "build.AMANDA_DBGDIR"), $AMANDA_DBGDIR, "build.AMANDA_DBGDIR is correct"); +is(amgetconf('TESTCONF', "build.AMANDA_TMPDIR"), $AMANDA_TMPDIR, "build.AMANDA_TMPDIR is correct"); +is(amgetconf('TESTCONF', "build.CONFIG_DIR"), $CONFIG_DIR, "build.CONFIG_DIR is correct"); + +# dbopen, dbclose +my $dbfile = amgetconf('TESTCONF', "dbopen.foo"); +like($dbfile, qr(^$AMANDA_DBGDIR/server/foo.[0-9]*.debug$), + "'amgetconf dbopen.foo' returns a proper debug filename"); +ok(-f $dbfile, + "'amgetconf dbopen.foo' creates the debug file"); +like(amgetconf('TESTCONF', "dbclose.foo"), qr/cannot parse/, + "dbclose without filename fails"); +is(amgetconf('TESTCONF', "dbclose.foo:$dbfile"), $dbfile, + "'amgetconf dbclose.foo:' returns the debug filename"); + +## +# Test an invalid config file + +$testconf = Amconfig->new(); +$testconf->add_param("foos_per_bar", "10"); +$testconf->write(); + +like(amgetconf('TESTCONF', "foos_per_bar"), qr/errors processing config file/, + "gives error on invalid configuration"); + +## +# Now let's fill in some interesting values + +$testconf = Amconfig->new(); +$testconf->add_param("reserved-udp-port", '100,200'); +$testconf->add_param("printer", '"/dev/lp"'); +$testconf->add_param("reserve", '27'); +$testconf->write(); + +is(amgetconf('TESTCONF', "reserved-udp-port"), "100,200", + "correctly returns intrange parameters from the file"); +is(amgetconf('TESTCONF', "printer"), "/dev/lp", + "correctly returns string parameters from the file"); +is(amgetconf('TESTCONF', "reserve"), "27", + "correctly returns integer parameters from the file"); +is(amgetconf('TESTCONF', "rEsErVe"), "27", + "is case-insensitive"); + +## +# device_property can appear multiple times + +$testconf = Amconfig->new(); +$testconf->add_param("device_property", '"power" "on"'); +$testconf->add_param("device_property", '"turbo" "engaged"'); +$testconf->write(); + +is_deeply([sort(+split(qr/\n/, amgetconf('TESTCONF', 'device_property')))], + [sort('"power" "on"', '"turbo" "engaged"')], + "device_property can have multiple values"); + +## +# Subsections + +$testconf = Amconfig->new(); +$testconf->add_tapetype("cassette", [ length => "32 k" ]); +$testconf->add_tapetype("reel2reel", [ length => "1 M" ]); +$testconf->add_tapetype("scotch", [ length => "500 bytes" ]); # (use a sharpie) +$testconf->add_dumptype("testdump", [ comment => '"testdump-dumptype"' ]); +$testconf->add_interface("testiface", [ use => '10' ]); +$testconf->add_holdingdisk("hd17", [ chunksize => '128' ]); +$testconf->write(); + +is_deeply([sort(+split(/\n/, amgetconf('TESTCONF', '--list', 'tapetype')))], + [sort("cassette", "reel2reel", "scotch", "TEST-TAPE")], + "--list returns correct set of tapetypes"); +is(amgetconf('TESTCONF', 'tapetype:scotch:length'), '500', + "returns tapetype parameter correctly"); + +ok(grep { $_ eq 'testdump' } split(/\n/, amgetconf('TESTCONF', '--list', 'dumptype')), + "--list returns a test dumptype among the default dumptypes"); +is(amgetconf('TESTCONF', 'dumptype:testdump:comment'), 'testdump-dumptype', + "returns dumptype parameter correctly"); + +is_deeply([sort(+split(/\n/, amgetconf('TESTCONF', '--list', 'interface')))], + [sort("testiface", "default")], + "--list returns correct set of interfaces"); +is(amgetconf('TESTCONF', 'interface:testiface:use'), '10', + "returns interface parameter correctly"); + +is_deeply([sort(+split(/\n/, amgetconf('TESTCONF', '--list', 'holdingdisk')))], + [sort("hd17")], + "--list returns correct set of holdingdisks"); +is(amgetconf('TESTCONF', 'holdingdisk:hd17:chunksize'), '128', + "returns holdingdisk parameter correctly"); + +# non-existent subsection types, names, and parameters +like(amgetconf('TESTCONF', 'NOSUCHTYPE:testiface:comment'), qr/no such parameter/, + "handles bad subsection type"); +like(amgetconf('TESTCONF', 'dumptype:NOSUCHDUMP:comment'), qr/no such parameter/, + "handles bad dumptype namek"); +like(amgetconf('TESTCONF', 'dumptype:testdump:NOSUCHPARAM'), qr/no such parameter/, + "handles bad dumptype parameter name"); + +## +# exclude lists are a bit funny, too + +$testconf = Amconfig->new(); +$testconf->add_dumptype("testdump", [ + "exclude file optional" => '"f1"', # this optional will have no effect + "exclude file append" => '"f2"', + "exclude list" => '"l1"', + "exclude list append" => '"l2"', + "include file" => '"ifo"', + "include list optional" => '"ilo"', + ]); +$testconf->write(); + +is_deeply([sort(+split(qr/\n/, amgetconf('TESTCONF', 'dumptype:testdump:exclude')))], + [sort('FILE "f1" "f2"', + 'LIST "l1" "l2"')], + "exclude files and lists displayed correctly; a non-final optional is ignored"); + +is_deeply([sort(+split(qr/\n/, amgetconf('TESTCONF', 'dumptype:testdump:include')))], + [sort('FILE OPTIONAL "ifo"', + 'LIST OPTIONAL "ilo"')], + "a final 'OPTIONAL' makes the whole include/exclude optional") + diff --git a/man/amaddclient.8 b/man/amaddclient.8 new file mode 100644 index 0000000..0857293 --- /dev/null +++ b/man/amaddclient.8 @@ -0,0 +1,212 @@ +.\" Title: amaddclient +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMADDCLIENT" "8" "08/22/2008" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amaddclient - program to add client to an existing Amanda configuration +.SH "SYNOPSIS" +.HP 12 +\fBamaddclient\fR \-\-config \fIconfig\fR || + \-\-client \fIclient\ name\fR || + \-\-diskdev \fIdirectory\ to\ backup\fR [\-\-m] [\-\-dumptype\ \fIstring\fR] [\-\-includefile\ \fIstring\fR] [\-\-includelist\ \fIstring\fR] [\-\-excludefile\ \fIstring\fR] [\-\-excludelist\ \fIstring\fR] [\-\-user\ \fIstring\fR] [\-\-auth\ \fIstring\fR] [\-\-gnutar_list_dir\ \fIstring\fR] [\-\-amandates\ \fIstring\fR] [\-\-no\-client\-update] [\-\-batch] [\-\-help] +.SH "DESCRIPTION" +.PP +After Amanda rpms are successfully installed and +\fBamserverconfig\fR +is run, +\fBamaddclient\fR +will add client to the +\fIAmanda\fR +configuration\. +\fBamaddclient\fR +create or update +\fIAmanda\fR +disklist file and create or update /var/lib/amanda/\.amandahosts file on the server\. +.PP +If \-\-no\-client\-update is not specified, +\fBamaddclient\fR +will attempt to update or create /var/lib/amanda/\.amandahost, amanda\-client\.conf and gnutar\-lists on the client\. (See +ssh\-keygen(1) +and +ssh\-add(1) +for detail\.) +.PP + +\fBamaddclient\fR +must be run by user amandabackup\. +.PP +\-\-config, \-\-client and \-\-diskdev must be specified\. +.SH "OPTIONS" +.PP +.RS 4 + +Options may be abbreviated, as long as the abbreviation is not ambiguous\. Option argument can either separated by \'=\' or a space\. +Example: \-\-conf=v253, \-\-client client8\.zmanda\.com +.RE +.PP +\fB\-\-config config\fR +.RS 4 +\fIAmanda\fR +configuration which this program will add the client to\. +.RE +.PP +\fB\-\-client client\fR +.RS 4 +The name of the client machine to add\. FQDN name recommended\. +.RE +.PP +\fB\-\-diskdev diskdev\fR +.RS 4 +Directory for this +\fIAmanda\fR +configuration to backup\. +.RE +.PP +\fB\-\-m\fR +.RS 4 +Modify existing entry in the disklist file\. +.sp +Note: if disklist file has been modified manually, this option might not work\. +.RE +.PP +\fB\-\-dumptype dumptype\fR +.RS 4 +dumptype to use\. Dumptype must be defined in /etc/amanda/template\.d/dumptypes or /etc/amanda/$config/amanda\.conf file\. Default: [user\-tar] +.RE +.PP +\fB\-\-user string\fR +.RS 4 +name of user using +\fBamrecover\fR +on the client, default is root\. +.RE +.PP +\fB\-\-auth string\fR +.RS 4 +authentication method to use when running +\fBamrecover\fR +from the client , default is bsdtcp\. +.RE +.PP +\fB\-\-gnutar_list_dir string\fR +.RS 4 +directory where gnutar keep its state file on the client\. Absolute path required\. Default is /var/lib/amanda/gnutar\-lists\. If \-\-no\-client\-update is not set, this program will attempt to create the directory on the client\. +.RE +.PP +\fB\-\-amandates string\fR +.RS 4 +file where amanda keep the date of each dumplevel on the client, default is /etc/amandates\. +.RE +.PP +\fB\-\-batch\fR +.RS 4 +Turn on batch mode when copying files to the client, default is off +.RE +.PP +\fB\-\-no\-client\-update\fR +.RS 4 +If this option is set, +\fBamaddclient\fR +will not attempt to update/create \.amandahosts, amanda\-client\.conf and gnutar\-lists file on the client\. +.RE +.PP +\fB\-\-help\fR +.RS 4 +Display usage\. +.RE +.PP +.RS 4 + +If any of the following four options are used, \fBamaddclient\fR will extend the dumptype definition to an in\-line definition in the disklist file\. See \fBamanda\fR(8) DISKLIST FILE section for detail\. +.RE +.PP +\fB\-\-includefile string\fR +.RS 4 +string is a glob expression +.RE +.PP +\fB\-\-includelist string\fR +.RS 4 +string is a file name on the client containing glob expressions\. Specify either \-\-includefile or \-\-includelist\. +.RE +.PP +\fB\-\-excludefile string\fR +.RS 4 +string is a glob expression +.RE +.PP +\fB\-\-excludelist string\fR +.RS 4 +string is a file name on the client containing glob expressions\. Specify either \-\-excludefile or \-\-excludelist\. +.RE +.SH "FILES" +.PP +\fB/var/lib/amanda/template\.d\fR +.RS 4 +Amanda configuration template files install location +.RE +.PP +\fB/var/lib/amanda\fR +.RS 4 +amandabackup home directory +.RE +.PP +\fB/var/lib/amanda/\.amandahosts\fR +.RS 4 +\fIAmanda\fR +authentication file\. +.RE +.PP +\fB/var/lib/amanda/gnutar\-lists\fR +.RS 4 +A directory which contains backup timestamp and list of files backed up\. +.RE +.PP +\fB/etc/amanda/$config\fR +.RS 4 +\fIAmanda\fR +configuration files location for $config(e\.g: DailySet1)\. +.RE +.PP +\fB/etc/amanda/template\.d\fR +.RS 4 +A directory contains dumptypes and tapetypes files used by all +\fIAmanda\fR +configurations\. +.RE +.PP +\fB/etc/amandates\fR +.RS 4 +\fIAmanda\fR +file on the client\. It keeps track of structures of previous dumps\. +.RE +.PP +\fB/tmp/amanda\fR +.RS 4 +directory contains +\fIAmanda\fR +debug log files\. +.RE +.SH "RETURN VALUE" + +On success, zero is returned\. On error, 1 is returned\. +.SH "AUTHOR" +.PP +The tool and its documentation was written by Zmanda, Inc (http://www\.zmanda\.com/)\. +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +\fBamanda.conf\fR(5), +\fBamserverconfig\fR(8) +\fBssh-keygen\fR(1) +\fBssh-add\fR(1) +\fBscp\fR(1) +: http://wiki.zmanda.com diff --git a/man/amaespipe.8.BACKUP.16324.8 b/man/amaespipe.8.BACKUP.16324.8 new file mode 100644 index 0000000..b61cac1 --- /dev/null +++ b/man/amaespipe.8.BACKUP.16324.8 @@ -0,0 +1,94 @@ +.\" Title: amaespipe +.\" Author: +<<<<<<< HEAD:man/amaespipe.8 +.\" Generator: DocBook XSL Stylesheets v1.72.0 +.\" Date: 06/06/2007 +.\" Manual: +.\" Source: +.\" +.TH "AMAESPIPE" "8" "06/06/2007" "" "" +======= +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMAESPIPE" "8" "08/22/2008" "" "" +>>>>>>> upstream:man/amaespipe.8 +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +<<<<<<< HEAD:man/amaespipe.8 +amaespipe \- wrapper program for aespipe +======= +amaespipe - wrapper program for aespipe +>>>>>>> upstream:man/amaespipe.8 +.SH "SYNOPSIS" +.HP 10 +\fBamaespipe\fR +.SH "DESCRIPTION" +.PP + +\fBamaespipe\fR +requires +\fBaespipe\fR, +\fBuuencode\fR +and +\fBgpg\fR +<<<<<<< HEAD:man/amaespipe.8 +to work. Aespipe is available from +\fI\%http://loop\-aes.sourceforge.net\fR +.PP + +\fBamaespipe\fR +will search for the aespipe program in the following directories: /usr/bin:/usr/local/bin:/sbin:/usr/sbin. +======= +to work\. Aespipe is available from +: http://loop-aes.sourceforge.net +.PP + +\fBamaespipe\fR +will search for the aespipe program in the following directories: /usr/bin:/usr/local/bin:/sbin:/usr/sbin\. +>>>>>>> upstream:man/amaespipe.8 +.PP + +\fBamaespipe\fR +is called by +\fBamcrypt\fR +for +\fIAmanda\fR +<<<<<<< HEAD:man/amaespipe.8 +data encryption. +.PP + +\fBamaespipe\fR +is based on aespipe's bzaespipe program. It calls aespipe to encrypt data using AES256 as the encryption and SHA256 as the hash function. GPG key should be stored in $AMANDA_HOME/.gnupg/am_key.gpg. +\fBamaespipe\fR +reads passphrase from file descriptor 3. During decryption, +\fBamaespipe\fR +autodects encryption type and hash function from the encrypted image. +======= +data encryption\. +.PP + +\fBamaespipe\fR +is based on aespipe\'s bzaespipe program\. It calls aespipe to encrypt data using AES256 as the encryption and SHA256 as the hash function\. GPG key should be stored in $AMANDA_HOME/\.gnupg/am_key\.gpg\. +\fBamaespipe\fR +reads passphrase from file descriptor 3\. During decryption, +\fBamaespipe\fR +autodects encryption type and hash function from the encrypted image\. +>>>>>>> upstream:man/amaespipe.8 +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +\fBamanda.conf\fR(5), +\fBaespipe\fR(1), +\fBamcrypt\fR(8), +<<<<<<< HEAD:man/amaespipe.8 +\fBgpg\fR(1) +======= +\fBgpg\fR(1), +: http://wiki.zmanda.com +>>>>>>> upstream:man/amaespipe.8 diff --git a/man/amaespipe.8.LOCAL.16324.8 b/man/amaespipe.8.LOCAL.16324.8 new file mode 100644 index 0000000..ae0d536 --- /dev/null +++ b/man/amaespipe.8.LOCAL.16324.8 @@ -0,0 +1,55 @@ +.\" Title: amaespipe +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.72.0 +.\" Date: 06/06/2007 +.\" Manual: +.\" Source: +.\" +.TH "AMAESPIPE" "8" "06/06/2007" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amaespipe \- wrapper program for aespipe +.SH "SYNOPSIS" +.HP 10 +\fBamaespipe\fR +.SH "DESCRIPTION" +.PP + +\fBamaespipe\fR +requires +\fBaespipe\fR, +\fBuuencode\fR +and +\fBgpg\fR +to work. Aespipe is available from +\fI\%http://loop\-aes.sourceforge.net\fR +.PP + +\fBamaespipe\fR +will search for the aespipe program in the following directories: /usr/bin:/usr/local/bin:/sbin:/usr/sbin. +.PP + +\fBamaespipe\fR +is called by +\fBamcrypt\fR +for +\fIAmanda\fR +data encryption. +.PP + +\fBamaespipe\fR +is based on aespipe's bzaespipe program. It calls aespipe to encrypt data using AES256 as the encryption and SHA256 as the hash function. GPG key should be stored in $AMANDA_HOME/.gnupg/am_key.gpg. +\fBamaespipe\fR +reads passphrase from file descriptor 3. During decryption, +\fBamaespipe\fR +autodects encryption type and hash function from the encrypted image. +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +\fBamanda.conf\fR(5), +\fBaespipe\fR(1), +\fBamcrypt\fR(8), +\fBgpg\fR(1) diff --git a/man/amaespipe.8.REMOTE.16324.8 b/man/amaespipe.8.REMOTE.16324.8 new file mode 100644 index 0000000..5bf7451 --- /dev/null +++ b/man/amaespipe.8.REMOTE.16324.8 @@ -0,0 +1,56 @@ +.\" Title: amaespipe +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMAESPIPE" "8" "08/22/2008" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amaespipe - wrapper program for aespipe +.SH "SYNOPSIS" +.HP 10 +\fBamaespipe\fR +.SH "DESCRIPTION" +.PP + +\fBamaespipe\fR +requires +\fBaespipe\fR, +\fBuuencode\fR +and +\fBgpg\fR +to work\. Aespipe is available from +: http://loop-aes.sourceforge.net +.PP + +\fBamaespipe\fR +will search for the aespipe program in the following directories: /usr/bin:/usr/local/bin:/sbin:/usr/sbin\. +.PP + +\fBamaespipe\fR +is called by +\fBamcrypt\fR +for +\fIAmanda\fR +data encryption\. +.PP + +\fBamaespipe\fR +is based on aespipe\'s bzaespipe program\. It calls aespipe to encrypt data using AES256 as the encryption and SHA256 as the hash function\. GPG key should be stored in $AMANDA_HOME/\.gnupg/am_key\.gpg\. +\fBamaespipe\fR +reads passphrase from file descriptor 3\. During decryption, +\fBamaespipe\fR +autodects encryption type and hash function from the encrypted image\. +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +\fBamanda.conf\fR(5), +\fBaespipe\fR(1), +\fBamcrypt\fR(8), +\fBgpg\fR(1), +: http://wiki.zmanda.com diff --git a/man/amanda.css b/man/amanda.css new file mode 100644 index 0000000..d6ee054 --- /dev/null +++ b/man/amanda.css @@ -0,0 +1,48 @@ +/* Taken from the Zmanda wiki, for at least a little bit of visual continuity */ +body { + font: small sans-serif; + background: #82B1C8 0 0 no-repeat; + color: black; +} + +div.refentry { + background: white; + margin-left: 11em; + margin-top: 2em; + padding: .6em; + padding-top: 0; + border: thin gray ridge; +} + +pre { + padding: 1em; + border: 1px dashed #2f6fab; + color: black; + background-color: #f9f9f9; + line-height: 1.1em; +} + +/* browsers override this for some reason */ +table { + font-size: small; +} + +h1, h2, h3, h4, h5, h6 { + color: black; + background: none; + font-weight: normal; + margin: 0; + padding-top: .5em; + padding-bottom: .17em; + border-bottom: 1px solid #5C706D; +} +h1 { font-size: 188%; } +h2 { font-size: 150%; } +h3, h4, h5, h6 { + border-bottom: none; + font-weight: bold; +} +h3 { font-size: 132%; } +h4 { font-size: 116%; } +h5 { font-size: 100%; } +h6 { font-size: 80%; } diff --git a/man/amcheckdump.8 b/man/amcheckdump.8 new file mode 100644 index 0000000..4371b83 --- /dev/null +++ b/man/amcheckdump.8 @@ -0,0 +1,54 @@ +.\" Title: amcheckdump +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMCHECKDUMP" "8" "08/22/2008" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amcheckdump - check the results of an Amanda dump +.SH "SYNOPSIS" +.HP 12 +\fBamcheckdump\fR \fIconfig\fR [\-\-timestamp|\-t\ \fItimestamp\fR] [\-o\ \fIconfigoption\fR]... +.SH "DESCRIPTION" +.PP +\fBAmcheckdump\fR +verifies +\fIAmanda\fR +dump images by reading them from storage volume(s) and verifying that the images can be parsed by the appropriate application (if available)\. For example, a GNUTAR image is passed to GNU Tar for parsing, and any errors (e\.g\., corrupt or missing data) are noted\. +.PP +The application runs on the most recent dump or, if +\fI\-\-timestamp\fR +is specified, on the most recent dump with that timestamp\. Note that the verification is local to the +\fIAmanda\fR +server; if the dump application is not available, or is configured differently on the server than on the client, then the verification will most likely fail\. +.PP +If a changer is available, it is used to load the required tapes\. Otherwise, the application interactively requests the tapes\. +.PP +See the "\fBCONFIGURATION OVERRIDE\fR" section in +\fBamanda\fR(8) +for information on the +\-o +option\. +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +: http://wiki.zmanda.com +.SH "EXAMPLE" +.PP +.nf +# check the most recent dump +amcheckdump MYCONFIG + +# check a specific dump from back in \'78 +amcheckdump MYCONFIG \-\-timestamp 19780615 +.fi +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +\fBhttp://wiki.zmanda.com\fR() diff --git a/man/amcryptsimple.8 b/man/amcryptsimple.8 new file mode 100644 index 0000000..cecbd1f --- /dev/null +++ b/man/amcryptsimple.8 @@ -0,0 +1,66 @@ +.\" Title: amcryptsimple +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMCRYPTSIMPLE" "8" "08/22/2008" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amcryptsimple - reference simple crypt program for Amanda symmetric data encryption +.SH "SYNOPSIS" +.HP 14 +\fBamcryptsimple\fR to be called by \fIAmanda\fR only +.SH "DESCRIPTION" +.PP + +\fBamcryptsimple\fR +calls +\fBgpg\fR +to perform symmetric data encryption on +\fIAmanda\fR +backup\. +\fBamcryptsimple\fR +will search for the gpg program in the following directories: /usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin +.PP + +\fBamcryptsimple\fR +uses one passphrase to encrypt the +\fIAmanda\fR +data and uses the same passphrase to decrypt the +\fIAmanda\fR +backup data\. +\fBamcryptsimple\fR +uses AES256 as the symmetric cipher\. +.SH "HOW TO CREATE PASSPHRASE" + + +Store the passphrase inside the home\-directory of the AMANDA\-user($amanda_user) and protect it with proper permissions: + + echo my_secret_passphrase > ~$amanda_user/\.am_passphrase + chown $amanda_user:disk ~$amanda_user/\.am_passphrase + chmod 700 ~$amanda_user/\.am_passphrase +.SH "NOTES" +.PP +Choose a good passphrase and protect it properly\. Backup data can only be restored with the passphrase\. There is no backdoor\. +.PP +If storing and securing passphrase in your environment presents challenges, +\fIAmanda\fR +provide public\-key data encryption through +\fBamgpgcrypt\fR\. Public\-key encryption uses the public key to encrypt and uses the private key to decrypt\. +.SH "AUTHOR" +.PP +The tool and its documentation was written by Zmanda, Inc (http://www\.zmanda\.com/)\. +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +\fBamanda.conf\fR(5), +\fBamcrypt\fR(8), +\fBamgpgcrypt\fR(8), +\fBamrestore\fR(8), +\fBgpg\fR(1), +: http://wiki.zmanda.com diff --git a/man/amdevcheck.8 b/man/amdevcheck.8 new file mode 100644 index 0000000..a9b403e --- /dev/null +++ b/man/amdevcheck.8 @@ -0,0 +1,69 @@ +.\" Title: amdevcheck +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMDEVCHECK" "8" "08/22/2008" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amdevcheck - Validate an Amanda device and volume. +.SH "SYNOPSIS" +.HP 11 +\fBamdevcheck\fR \fIconfig\fR [\fIdevice\ name\fR] [\-o\ \fIconfigoption\fR]... +.SH "DESCRIPTION" +.PP + +\fBAmdevcheck\fR +provides a way to check that a particular +\fIAmanda\fR +device is accessible, whether or not it contains a volume, and whether or not that volume is labeled\. Some devices can\'t distinguish between all of these cases; a missing volume and an unlabeled volume might generate the same error code, for example\. In those cases, this tool reports all possible causes of the error\. +.PP +See the +\fBamanda\fR(8) +man page for more details about +\fIAmanda\fR\. See the +\fBOUTPUT DRIVERS\fR +section of +\fIamanda(8)\fR +for more information on the +\fIAmanda\fR +output drivers\. +.SH "OPTIONS" +.PP +\fIconfig\fR +.RS 4 + +\fIAmanda\fR +configuration to use\. Note that +\fBamdevcheck\fR +ignores any tape changer configuration\. +.RE +.PP +\fI device\fR +.RS 4 + +\fIAmanda\fR +device to use\. This option overrides any tapedev configuration specified in the configuration file\. +.RE +.PP +\fB\-o\fR \fIclientconfigoption\fR +.RS 4 +See the "\fBCONFIGURATION OVERRIDE\fR" section in +\fBamanda\fR(8)\. +.RE +.SH "AUTHOR" +.PP +Ian Turner + +and others\. Authorship of this tool and its documentation was funded by Zmanda, Inc\. +.SH "SEE ALSO" +.PP + +\fBamanda\fR(8), +\fBammt\fR(8), +: http://wiki.zmanda.com diff --git a/man/amgpgcrypt.8 b/man/amgpgcrypt.8 new file mode 100644 index 0000000..ad36e69 --- /dev/null +++ b/man/amgpgcrypt.8 @@ -0,0 +1,153 @@ +.\" Title: amgpgcrypt +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMGPGCRYPT" "8" "08/22/2008" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amgpgcrypt - reference crypt program for Amanda public-key data encryption +.SH "SYNOPSIS" +.HP 11 +\fBamgpgcrypt\fR to be called by \fIAmanda\fR only +.SH "DESCRIPTION" +.PP + +\fBamgpgcrypt\fR +calls +\fBgpg\fR +to perform public\-key data encryption on +\fIAmanda\fR +backup\. +\fBamgpgcrypt\fR +will search for the gpg program in the following directories: /usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin +.PP + +\fBamgpgcrypt\fR +sets GNUPGHOME to $AMANDA_HOME/\.gnupg where gpg will look for the gpg keys\. +\fBamgpgcrypt\fR +uses the public key to encrypt the +\fIAmanda\fR +data and uses the private key to decrypt the +\fIAmanda\fR +backup data\. Thus, passphrase is only required at the time of data restore\. +.SH "KEY AND PASSPHRASE" +.PP + +\fBamgpgcrypt\fR +uses the private key to decrypt +\fIAmanda\fR +backup data\. + +It is very important to store, manage and protect the key and the passphrase +properly\. Encrypted backup data can \fBonly\fR be recovered with the correct key and +passphrase\. +.SH "HOW TO CREATE ENCRYPTION KEYS AND PASSPHRASE FOR AMGPGCRYPT" +.PP +Store the passphrase that you used in following "gpg \-\-gen\-key" command inside the home\-directory of the AMANDA\-user($amanda_user) and protect it with proper permissions: + + echo my_secret_passphrase > ~$amanda_user/\.am_passphrase + chown $amanda_user:disk ~$amanda_user/\.am_passphrase + chmod 700 ~$amanda_user/\.am_passphrase +.PP +Run "gpg \-\-gen\-key"\. Below is an example: +.nf +$ gpg \-\-gen\-key +gpg (GnuPG) 1\.2\.6; Copyright (C) 2004 Free Software Foundation, Inc\. +This program comes with ABSOLUTELY NO WARRANTY\. +This is free software, and you are welcome to redistribute it +under certain conditions\. See the file COPYING for details\. + +Please select what kind of key you want: + (1) DSA and ElGamal (default) + (2) DSA (sign only) + (4) RSA (sign only) +Your selection? 1 +DSA keypair will have 1024 bits\. +About to generate a new ELG\-E keypair\. + minimum keysize is 768 bits + default keysize is 1024 bits + highest suggested keysize is 2048 bits +What keysize do you want? (1024) +Requested keysize is 1024 bits +Please specify how long the key should be valid\. + 0 = key does not expire + (n) = key expires in n days + (n)w = key expires in n weeks + (n)m = key expires in n months + (n)y = key expires in n years +Key is valid for? (0) 6m +Key expires at Sun 06 Aug 2006 03:51:25 PM PDT +Is this correct (y/n)? y + +You need a User\-ID to identify your key; the software constructs the user id +from Real Name, Comment and Email Address in this form: + "Heinrich Heine (Der Dichter) (heinrichh@duesseldorf\.de)" + +Real name: amandabackup +Email address: +Comment: gpg keys for amandabackup +You selected this USER\-ID: + "amandabackup (gpg keys for amandabackup)" + +Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o +You need a Passphrase to protect your secret key\. + +We need to generate a lot of random bytes\. It is a good idea to perform +some other action (type on the keyboard, move the mouse, utilize the +disks) during the prime generation; this gives the random number +generator a better chance to gain enough entropy\. + +We need to generate a lot of random bytes\. It is a good idea to perform +some other action (type on the keyboard, move the mouse, utilize the +disks) during the prime generation; this gives the random number +generator a better chance to gain enough entropy\. + +public and secret key created and signed\. +key marked as ultimately trusted\. + +pub 1024D/4417A8CB 2006\-02\-07 amandabackup (gpg keys for amandabackup) + Key fingerprint = 139C 6369 44FC 7F1A 655C E5E9 7EAA 515A 4417 A8CB +sub 1024g/8C3A6A78 2006\-02\-07 [expires: 2006\-08\-06] +.fi +.SH "FILES" +.PP +\fB$AMANDA_HOME/\.gnupg/pubring\.gpg\fR +.RS 4 +The public key\. +\fBamgpgcrypt\fR +encrypt data with this public key along with the cipher algorithm\. +.RE +.PP +\fB$AMANDA_HOME/\.gnupg/secring\.gpg\fR +.RS 4 +The private/secret key\. It\'s only needed during amrecover/amrestore\. Store and protect it properly during other time\. +.RE +.PP +\fB$AMANDA_HOME/\.am_passphrase\fR +.RS 4 +The passphrase\. It\'s only needed during amrecover/amrestore\. Store and protect it properly during other time\. +.RE +.SH "BUGS" +.PP +\fIAmanda\fR +has problem with gpg mdc(modification detection code) in the binary mode\. +\fBamgpgcrypt\fR +calls gpg with mdc disabled +.SH "AUTHOR" +.PP +The tool and its documentation was written by Zmanda, Inc (http://www\.zmanda\.com/)\. +.SH "SEE ALSO" +.PP + +\fBamanda\fR(8), +\fBamanda.conf\fR(5), +\fBamcrypt\fR(8), +\fBamrestore\fR(8), +\fBgpg\fR(1), +: http://wiki.zmanda.com diff --git a/man/amserverconfig.8 b/man/amserverconfig.8 new file mode 100644 index 0000000..093899d --- /dev/null +++ b/man/amserverconfig.8 @@ -0,0 +1,181 @@ +.\" Title: amserverconfig +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.73.2 +.\" Date: 08/22/2008 +.\" Manual: +.\" Source: +.\" +.TH "AMSERVERCONFIG" "8" "08/22/2008" "" "" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +amserverconfig - program to setup initial Amanda configuration +.SH "SYNOPSIS" +.HP 15 +\fBamserverconfig\fR \fIconfig\fR [\-\-template\ \fItemplate\fR] [\-\-no\-vtape] [\-\-tapetype\ \fItapetype\fR] [\-\-tpchanger\ \fItpchanger\fR] [\-\-tapedev\ \fItapedev\fR] [\-\-changerfile\ \fIchangerfile\fR] [\-\-changerdev\ \fIchangerdev\fR] [\-\-labelstr\ \fIlabelstr\fR] [\-\-mailto\ \fImailto\fR] [\-\-dumpcycle\ \fIdumpcycle\fR] [\-\-runspercycle\ \fIrunspercycle\fR] [\-\-runtapes\ \fIruntapes\fR] [\-\-tapecycle\ \fItapecycle\fR] [\-\-help] +.SH "DESCRIPTION" +.PP +After Amanda rpms are successfully installed, +\fBamserverconfig\fR +will setup initial +\fIAmanda\fR +configuration files\. It will create /var/lib/amanda/guntar\-lists directory if one does not exist\. +\fBamserverconfig\fR +does not change existing +\fIAmanda\fR +configurations\. +\fBamserverconfig\fR +must be run by user amandabackup\. +.SH "OPTIONS" +.PP +Options may be abbreviated, as long as the abbreviation is not ambiguous\. Option argument can either separated by \'=\' or a space\. Example: \-\-templ=harddisk \-\-tapedev /dev/nst0 +.PP + +\fBamserverconfig\fR +builds a new "config" +\fIAmanda\fR +configuration\. Customize the configuration with the options below\. +.PP +\fB\-\-template template\fR +.RS 4 +build +\fIAmanda\fR +configuration with pre\-configured template files\. Currently, +\fBharddisk\fR, +\fBsingle\-tape\fR, +\fBtape\-changer\fR +and +\fBS3\fR +are the valid inputs for this option\. Pre\-configured template files can be found in /var/lib/amanda/template\.d\. This option may be combined with other options\. +.sp +If tape\-changer is chosen for this option, program mtx is required\. +\fBamserverconfig\fR +will search for mtx in the following directory: "/usr/sbin", "/usr/local/sbin", "/usr/local/bin", "/usr/bin", "/bin" and amandabackup\'s PATH\. +.sp +If harddisk is chosen and \-\-no\-vtape is not specified, +\fBamserverconfig\fR +will create and label virtual tape file://var/lib/amanda/vtapes/$config\. +.RE +.PP +\fB\-\-no\-vtape\fR +.RS 4 +Do not create virtual tapes in the harddisk template case\. +.RE +.PP +\fB\-\-tapedev tapedev\fR +.RS 4 +The path name of non\-rewinding tape device\. default [file://var/lib/amanda/vtapes/$config] +.RE +.PP +\fB\-\-tpchanger tpchanger\fR +.RS 4 +The name of the tape changer\. default [chg\-disk] +.RE +.PP +\fB\-\-changerdev changerdev\fR +.RS 4 +A tape changer configuration parameter\. default [/dev/null] +.RE +.PP +\fB\-\-changerfile changerfile\fR +.RS 4 +A tape changer configuration parameter\. default [/etc/amanda/$config/changer\.conf] +.RE +.PP +\fB\-\-labelstr labelstr\fR +.RS 4 +The tape label constraint regular expression\. default [^$config\-[0\-9][0\-9]*$] +.sp +If this option is used with \-\-template=harddisk, only alphanumeric string is supported\. +.RE +.PP +\fB\-\-tapetype tapetype\fR +.RS 4 +The type of tape drive associated with tapedev or tpchanger\. default [HARDDISK] +.RE +.PP +\fB\-\-mailto mailto\fR +.RS 4 +A space separated list of recipients for mail reports\. default [amandabackup] +.RE +.PP +\fB\-\-dumpcycle dumpcycle\fR +.RS 4 +The number of days in the backup cycle\. default [1week] +.RE +.PP +\fB\-\-runspercycle runspercycle\fR +.RS 4 +The number of days in the backup cycle\. default [5] +.RE +.PP +\fB\-\-runtapes runtapes\fR +.RS 4 +The maximum number of tapes used in a single run\. default [1] +.RE +.PP +\fB\-\-tapecycle tapecycle\fR +.RS 4 +The size of tape rotation\. default [25] +.RE +.PP +\fB\-\-help\fR +.RS 4 +Display usage\. +.RE +.SH "FILES" +.PP +\fB/var/lib/amanda/template\.d\fR +.RS 4 +Amanda configuration template files install location +.RE +.PP +\fB/var/lib/amanda\fR +.RS 4 +amandabackup home directory +.RE +.PP +\fB/var/lib/amanda/gnutar\-lists\fR +.RS 4 +A directory which contains backup timestamp and list of files backed up\. +.RE +.PP +\fB/etc/amanda/$config\fR +.RS 4 +\fIAmanda\fR +configuration files location for $config(e\.g: DailySet1)\. +.RE +.PP +\fB/etc/amanda/template\.d\fR +.RS 4 +A directory contains dumptypes and tapetypes files used by all +\fIAmanda\fR +configurations\. +.RE +.PP +\fB/etc/amandates\fR +.RS 4 +\fIAmanda\fR +file on the client\. It keeps track of structures of previous dumps\. +.RE +.PP +\fB/tmp/amanda\fR +.RS 4 +directory contains +\fIAmanda\fR +debug log files\. +.RE +.SH "RETURN VALUE" + +On success, zero is returned\. On error, 1 is returned\. +.SH "AUTHOR" +.PP +The tool and its documentation was written by Zmanda, Inc (http://www\.zmanda\.com/)\. +.SH "SEE ALSO" +.PP +\fBamanda\fR(8), +\fBamanda.conf\fR(5), +\fBamaddclient\fR(8), +: http://wiki.zmanda.com diff --git a/man/index.php b/man/index.php new file mode 100644 index 0000000..5322dd6 --- /dev/null +++ b/man/index.php @@ -0,0 +1,4 @@ + + + %global_entities; +]> + + + +amaddclient +8 + + +amaddclient +program to add client to an existing &A; configuration + + + + + amaddclient +--config +config || +--client client name || +--diskdev directory to backup +--m +--dumptype string +--includefile string +--includelist string +--excludefile string +--excludelist string +--user string +--auth string +--gnutar_list_dir string +--amandates string +--no-client-update +--batch +--help + + + +DESCRIPTION +After Amanda rpms are successfully installed and +&amserverconfig; is run, + &amaddclient; will add client to the &A; configuration. +&amaddclient; create or update &A; disklist file and create or update +/var/lib/amanda/.amandahosts file on the server. + If --no-client-update is not specified, +&amaddclient; will attempt to update or create /var/lib/amanda/.amandahost, +amanda-client.conf and gnutar-lists on +the client. +(See ssh-keygen1 and +ssh-add1 for detail.) + +&amaddclient; must be run by user amandabackup. + --config, --client and --diskdev must be specified. + + + + +Options + + +Options may be abbreviated, as long as the abbreviation is not ambiguous. Option argument can either separated by '=' or a space. +Example: --conf=v253, --client client8.zmanda.com + + + + + + +&A; configuration which this program will add the client to. + + + + + + +The name of the client machine to add. FQDN name recommended. + + + + + + +Directory for this &A; configuration to backup. + + + + + + + +Modify existing entry in the disklist file. +Note: if disklist file has been modified manually, this option might not work. + + + + + + + +dumptype to use. Dumptype must be defined in +/etc/amanda/template.d/dumptypes or /etc/amanda/$config/amanda.conf file. Default: [user-tar] + + + + + + + name of user using &amrecover; on the client, default is root. + + + + + + + authentication method to use when running &amrecover; from the client , default is bsdtcp. + + + + + + + directory where gnutar keep its state file on the client. Absolute path +required. Default is /var/lib/amanda/gnutar-lists. If --no-client-update is not +set, this program will attempt to create the directory on the client. + + + + + + + file where amanda keep the date of each dumplevel on the client, default is /etc/amandates. + + + + + + +Turn on batch mode when copying files to the client, default is off + + + + + + +If this option is set, &amaddclient; will not attempt to update/create +.amandahosts, amanda-client.conf and gnutar-lists file on the client. + + + + + + + +Display usage. + + + + +If any of the following four options are used, &amaddclient; will extend the dumptype definition to an in-line definition in the disklist file. See amanda8 DISKLIST FILE section for detail. + + + + + +string is a glob expression + + + + + + + string is a file name on the client containing glob expressions. +Specify either --includefile or --includelist. + + + + + + +string is a glob expression + + + + + + + string is a file name on the client containing glob expressions. +Specify either --excludefile or --excludelist. + + + + + + + + +Files + + + + +Amanda configuration template files install location + + + + + + +amandabackup home directory + + + + + + +&A; authentication file. + + + + + + +A directory which contains backup timestamp and list of files backed up. + + + + + + +&A; configuration files location for $config(e.g: DailySet1). + + + + + + +A directory contains dumptypes and tapetypes files used by all &A; configurations. + + + + + + + +&A; file on the client. It keeps track of structures of previous dumps. + + + + + + +directory contains &A; debug log files. + + + + + + +RETURN VALUE +On success, zero is returned. On error, 1 is returned. + + +AUTHOR + + The tool and its documentation was written by Zmanda, Inc (http://www.zmanda.com/). + + + +SEE ALSO +amanda8, +amanda.conf5, +amserverconfig8 +ssh-keygen1 +ssh-add1 +scp1 + + + + + diff --git a/man/xml-source/amcheckdump.8.xml b/man/xml-source/amcheckdump.8.xml new file mode 100644 index 0000000..e37da35 --- /dev/null +++ b/man/xml-source/amcheckdump.8.xml @@ -0,0 +1,71 @@ + + + + %global_entities; +]> + + + +amcheckdump +8 + + +amcheckdump +check the results of an &A; dump + + + + + amcheckdump + config + --timestamp|-t timestamp + -o configoption + + + +DESCRIPTION + +Amcheckdump verifies &A; dump images by +reading them from storage volume(s) and verifying that the images can be parsed +by the appropriate application (if available). For example, a GNUTAR +image is passed to GNU Tar for parsing, and any errors +(e.g., corrupt or missing data) are noted. + +The application runs on the most recent dump or, if --timestamp is specified, on the most recent dump with +that timestamp. Note that the verification is local to the &A; server; if the +dump application is not available, or is configured differently on the server +than on the client, then the verification will most likely fail. + +If a changer is available, it is used to load the required +tapes. Otherwise, the application interactively requests the tapes. + +See the "CONFIGURATION OVERRIDE" section in +amanda8 +for information on the -o option. + + SEE ALSO + amanda8, + + + + +EXAMPLE + +# check the most recent dump +amcheckdump MYCONFIG + +# check a specific dump from back in '78 +amcheckdump MYCONFIG --timestamp 19780615 + + + SEE ALSO + amanda8, + http://wiki.zmanda.com + + + diff --git a/man/xml-source/amcryptsimple.8.xml b/man/xml-source/amcryptsimple.8.xml new file mode 100644 index 0000000..29151e1 --- /dev/null +++ b/man/xml-source/amcryptsimple.8.xml @@ -0,0 +1,72 @@ + + + + %global_entities; +]> + + + +amcryptsimple +8 + + +amcryptsimple +reference simple crypt program for &A; symmetric data encryption + + + + + amcryptsimple to be called by &A; only + + + +DESCRIPTION +&amcryptsimple; +calls gpg to perform symmetric data encryption +on &A; backup. +&amcryptsimple; will search for the gpg program in the following directories: +/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin +&amcryptsimple; uses one passphrase to encrypt the &A; data +and uses the same passphrase to decrypt the &A; backup data. &amcryptsimple; uses +AES256 as the symmetric cipher. + + + +How to Create Passphrase + +Store the passphrase inside the home-directory of the AMANDA-user($amanda_user) and protect it with proper permissions: + + echo my_secret_passphrase > ~$amanda_user/.am_passphrase + chown $amanda_user:disk ~$amanda_user/.am_passphrase + chmod 700 ~$amanda_user/.am_passphrase + + +NOTES +Choose a good passphrase and protect it properly. Backup data can only be +restored with the passphrase. There is no backdoor. +If storing and securing passphrase in your environment presents challenges, +&A; provide public-key data encryption through &amgpgcrypt;. Public-key +encryption uses the public key to encrypt and uses the private key to decrypt. + + +AUTHOR + + The tool and its documentation was written by Zmanda, Inc (http://www.zmanda.com/). + + + +SEE ALSO +amanda8, +amanda.conf5, +amcrypt8, +amgpgcrypt8, +amrestore8, +gpg1, + + + + + diff --git a/man/xml-source/amdevcheck.8.xml b/man/xml-source/amdevcheck.8.xml new file mode 100644 index 0000000..d4ca82d --- /dev/null +++ b/man/xml-source/amdevcheck.8.xml @@ -0,0 +1,101 @@ + + + + %global_entities; +]> + + + + + amdevcheck + 8 + + + amdevcheck + Validate an &A; device and volume. + + + + + amdevcheck + config + + device name + + -o + configoption + + + + DESCRIPTION + + Amdevcheck provides a way to check that a + particular &A; device is accessible, whether or not it contains a volume, + and whether or not that volume is labeled. Some devices can't distinguish + between all of these cases; a missing volume and an unlabeled volume might + generate the same error code, for example. In those cases, this tool + reports all possible causes of the error. + + + See the + amanda8 + man page for more details about &A;. + See the + OUTPUT DRIVERS + section of + amanda(8) + for more information on the &A; output drivers. + + + + OPTIONS + + + config + + + &A; configuration to use. Note that amdevcheck + ignores any tape changer configuration. + + + + + + device + + + &A; device to use. This option overrides any tapedev configuration + specified in the configuration file. + + + + + + -o clientconfigoption + + See the "CONFIGURATION OVERRIDE" + section in + amanda8. + + + + + + AUTHOR + + Ian Turner ian@zmanda.com and others. Authorship of this + tool and its documentation was funded by Zmanda, Inc. + + + + SEE ALSO + + amanda8, + ammt8, + + + + diff --git a/man/xml-source/amgpgcrypt.8.xml b/man/xml-source/amgpgcrypt.8.xml new file mode 100644 index 0000000..a2db468 --- /dev/null +++ b/man/xml-source/amgpgcrypt.8.xml @@ -0,0 +1,172 @@ + + + + %global_entities; +]> + + + +amgpgcrypt +8 + + +amgpgcrypt +reference crypt program for &A; public-key data encryption + + + + + amgpgcrypt to be called by &A; only + + + +DESCRIPTION +&amgpgcrypt; +calls gpg to perform public-key data encryption +on &A; backup. +&amgpgcrypt; will search for the gpg program in the following directories: +/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin +&amgpgcrypt; sets GNUPGHOME to $AMANDA_HOME/.gnupg where gpg will look for the +gpg keys. +&amgpgcrypt; uses the public key to encrypt the &A; data +and uses the private key to decrypt the &A; backup data. Thus, passphrase is only +required at the time of data restore. + + + +Key and Passphrase +&amgpgcrypt; uses the private key to decrypt &A; backup data. +It is very important to store, manage and protect the key and the passphrase +properly. Encrypted backup data can only be recovered with the correct key and +passphrase. + + + + +How to create encryption keys and Passphrase for amgpgcrypt + +Store the passphrase that you used in following "gpg --gen-key" command inside the home-directory of the AMANDA-user($amanda_user) and protect it with proper permissions: + echo my_secret_passphrase > ~$amanda_user/.am_passphrase + chown $amanda_user:disk ~$amanda_user/.am_passphrase + chmod 700 ~$amanda_user/.am_passphrase + Run "gpg --gen-key". Below is an example: + +$ gpg --gen-key +gpg (GnuPG) 1.2.6; Copyright (C) 2004 Free Software Foundation, Inc. +This program comes with ABSOLUTELY NO WARRANTY. +This is free software, and you are welcome to redistribute it +under certain conditions. See the file COPYING for details. + +Please select what kind of key you want: + (1) DSA and ElGamal (default) + (2) DSA (sign only) + (4) RSA (sign only) +Your selection? 1 +DSA keypair will have 1024 bits. +About to generate a new ELG-E keypair. + minimum keysize is 768 bits + default keysize is 1024 bits + highest suggested keysize is 2048 bits +What keysize do you want? (1024) +Requested keysize is 1024 bits +Please specify how long the key should be valid. + 0 = key does not expire + (n) = key expires in n days + (n)w = key expires in n weeks + (n)m = key expires in n months + (n)y = key expires in n years +Key is valid for? (0) 6m +Key expires at Sun 06 Aug 2006 03:51:25 PM PDT +Is this correct (y/n)? y + +You need a User-ID to identify your key; the software constructs the user id +from Real Name, Comment and Email Address in this form: + "Heinrich Heine (Der Dichter) (heinrichh@duesseldorf.de)" + +Real name: amandabackup +Email address: +Comment: gpg keys for amandabackup +You selected this USER-ID: + "amandabackup (gpg keys for amandabackup)" + +Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o +You need a Passphrase to protect your secret key. + +We need to generate a lot of random bytes. It is a good idea to perform +some other action (type on the keyboard, move the mouse, utilize the +disks) during the prime generation; this gives the random number +generator a better chance to gain enough entropy. + +We need to generate a lot of random bytes. It is a good idea to perform +some other action (type on the keyboard, move the mouse, utilize the +disks) during the prime generation; this gives the random number +generator a better chance to gain enough entropy. + +public and secret key created and signed. +key marked as ultimately trusted. + +pub 1024D/4417A8CB 2006-02-07 amandabackup (gpg keys for amandabackup) + Key fingerprint = 139C 6369 44FC 7F1A 655C E5E9 7EAA 515A 4417 A8CB +sub 1024g/8C3A6A78 2006-02-07 [expires: 2006-08-06] + + + + + +Files + + + + +The public key. &amgpgcrypt; encrypt data with this public key along with the +cipher algorithm. + + + + + + +The private/secret key. It's only needed during amrecover/amrestore. Store +and protect it properly during other time. + + + + + + +The passphrase. It's only needed during amrecover/amrestore. Store +and protect it properly during other time. + + + + + + + + +BUGS +&A; has problem with gpg mdc(modification detection code) in the binary +mode. &amgpgcrypt; calls gpg with mdc disabled + + +AUTHOR + + The tool and its documentation was written by Zmanda, Inc (http://www.zmanda.com/). + + + +SEE ALSO + + amanda8, + amanda.conf5, + amcrypt8, + amrestore8, + gpg1, + + + + + diff --git a/man/xml-source/amserverconfig.8.xml b/man/xml-source/amserverconfig.8.xml new file mode 100644 index 0000000..22a4f44 --- /dev/null +++ b/man/xml-source/amserverconfig.8.xml @@ -0,0 +1,251 @@ + + + + %global_entities; +]> + + + +amserverconfig +8 + + +amserverconfig +program to setup initial &A; configuration + + + + + amserverconfig +config +--template template +--no-vtape +--tapetype tapetype +--tpchanger tpchanger +--tapedev tapedev +--changerfile changerfile +--changerdev changerdev +--labelstr labelstr +--mailto mailto +--dumpcycle dumpcycle +--runspercycle runspercycle +--runtapes runtapes +--tapecycle tapecycle +--help + + + +DESCRIPTION +After Amanda rpms are successfully installed, + &amserverconfig; will setup initial &A; configuration files. +It will create /var/lib/amanda/guntar-lists directory if one does + not exist. +&amserverconfig; does not change existing &A; configurations. +&amserverconfig; must be run by user amandabackup. + + + + +Options +Options may be abbreviated, as long as the abbreviation is not ambiguous. Option argument can either separated by '=' or a space. +Example: --templ=harddisk --tapedev /dev/nst0 + +&amserverconfig; builds a new "config" &A; configuration. Customize the configuration with the options below. + + + + + +build &A; configuration with pre-configured template files. Currently, + harddisk, single-tape, tape-changer and S3 + are the valid inputs for this option. Pre-configured template files can be found in + /var/lib/amanda/template.d. This option may be combined with other options. + +If tape-changer is chosen for this option, program mtx is required. &amserverconfig; will +search for mtx in the following directory: "/usr/sbin", "/usr/local/sbin", +"/usr/local/bin", "/usr/bin", "/bin" and amandabackup's PATH. + + +If harddisk is chosen and --no-vtape is not specified, &amserverconfig; will create and label virtual tape +file://var/lib/amanda/vtapes/$config. + + + + + + + +Do not create virtual tapes in the harddisk template case. + + + + + + + +The path name of non-rewinding tape device. +default [file://var/lib/amanda/vtapes/$config] + + + + + + +The name of the tape changer. default [chg-disk] + + + + + + +A tape changer configuration parameter. default [/dev/null] + + + + + + +A tape changer configuration parameter. default [/etc/amanda/$config/changer.conf] + + + + + + +The tape label constraint regular expression. default [^$config-[0-9][0-9]*$] +If this option is used with --template=harddisk, only alphanumeric string +is supported. + + + + + + +The type of tape drive associated with tapedev or tpchanger. default [HARDDISK] + + + + + + + A space separated list of recipients for mail reports. default [amandabackup] + + + + + + +The number of days in the backup cycle. default [1week] + + + + + + +The number of days in the backup cycle. default [5] + + + + + + +The maximum number of tapes used in a single run. default [1] + + + + + + +The size of tape rotation. default [25] + + + + + + + +Display usage. + + + + + + +Files + + + + +Amanda configuration template files install location + + + + + + +amandabackup home directory + + + + + + +A directory which contains backup timestamp and list of files backed up. + + + + + + +&A; configuration files location for $config(e.g: DailySet1). + + + + + + +A directory contains dumptypes and tapetypes files used by all &A; configurations. + + + + + + +&A; file on the client. It keeps track of structures of previous dumps. + + + + + + +directory contains &A; debug log files. + + + + + + +RETURN VALUE +On success, zero is returned. On error, 1 is returned. + + +AUTHOR + + The tool and its documentation was written by Zmanda, Inc (http://www.zmanda.com/). + + + + +SEE ALSO +amanda8, +amanda.conf5, +amaddclient8, + + + + + diff --git a/man/xslt/html.xsl.in b/man/xslt/html.xsl.in new file mode 100644 index 0000000..03ae385 --- /dev/null +++ b/man/xslt/html.xsl.in @@ -0,0 +1,31 @@ + + + + + + + + + + + + + +text/css + + + + + + + + + ..html + + + + + + diff --git a/man/xslt/man.xsl.in b/man/xslt/man.xsl.in new file mode 100644 index 0000000..2453bc0 --- /dev/null +++ b/man/xslt/man.xsl.in @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + : + + + + + + + + + + + .nf + + .fi + + + + + + + + + + + + + + + + + + + + + + + + + + .SS " + + " + + + + + diff --git a/packaging/Makefile.am b/packaging/Makefile.am new file mode 100644 index 0000000..db33d59 --- /dev/null +++ b/packaging/Makefile.am @@ -0,0 +1,8 @@ +EXTRA_DIST = \ + deb \ + rpm \ + Makefile.am \ + README + +dist-hook: + rm -rf `find ${distdir} -name .svn` diff --git a/packaging/Makefile.in b/packaging/Makefile.in new file mode 100644 index 0000000..1952026 --- /dev/null +++ b/packaging/Makefile.in @@ -0,0 +1,734 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = packaging +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/config/macro-archive/ac_define_dir.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_perl_version.m4 \ + $(top_srcdir)/config/macro-archive/ac_prog_swig.m4 \ + $(top_srcdir)/config/macro-archive/ax_compare_version.m4 \ + $(top_srcdir)/config/macro-archive/docbook-dtd.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt-min.m4 \ + $(top_srcdir)/config/macro-archive/docbook-xslt.m4 \ + $(top_srcdir)/config/macro-archive/xsltproc.m4 \ + $(top_srcdir)/config/amanda/amplot.m4 \ + $(top_srcdir)/config/amanda/bsd-security.m4 \ + $(top_srcdir)/config/amanda/bsdtcp-security.m4 \ + $(top_srcdir)/config/amanda/bsdudp-security.m4 \ + $(top_srcdir)/config/amanda/changer.m4 \ + $(top_srcdir)/config/amanda/components.m4 \ + $(top_srcdir)/config/amanda/compress.m4 \ + $(top_srcdir)/config/amanda/config.m4 \ + $(top_srcdir)/config/amanda/debugging.m4 \ + $(top_srcdir)/config/amanda/defaults.m4 \ + $(top_srcdir)/config/amanda/devprefix.m4 \ + $(top_srcdir)/config/amanda/dirs.m4 \ + $(top_srcdir)/config/amanda/documentation.m4 \ + $(top_srcdir)/config/amanda/dumpers.m4 \ + $(top_srcdir)/config/amanda/flags.m4 \ + $(top_srcdir)/config/amanda/flock.m4 \ + $(top_srcdir)/config/amanda/funcs.m4 \ + $(top_srcdir)/config/amanda/getfsent.m4 \ + $(top_srcdir)/config/amanda/i18n.m4 \ + $(top_srcdir)/config/amanda/ipv6.m4 \ + $(top_srcdir)/config/amanda/krb4-security.m4 \ + $(top_srcdir)/config/amanda/krb5-security.m4 \ + $(top_srcdir)/config/amanda/lfs.m4 \ + $(top_srcdir)/config/amanda/libs.m4 \ + $(top_srcdir)/config/amanda/net.m4 \ + $(top_srcdir)/config/amanda/progs.m4 \ + $(top_srcdir)/config/amanda/readdir.m4 \ + $(top_srcdir)/config/amanda/readline.m4 \ + $(top_srcdir)/config/amanda/rsh-security.m4 \ + $(top_srcdir)/config/amanda/s3-device.m4 \ + $(top_srcdir)/config/amanda/shmem.m4 \ + $(top_srcdir)/config/amanda/socklen_t_equiv.m4 \ + $(top_srcdir)/config/amanda/ssh-security.m4 \ + $(top_srcdir)/config/amanda/summary.m4 \ + $(top_srcdir)/config/amanda/swig.m4 \ + $(top_srcdir)/config/amanda/syshacks.m4 \ + $(top_srcdir)/config/amanda/tape.m4 \ + $(top_srcdir)/config/amanda/types.m4 \ + $(top_srcdir)/config/amanda/userid.m4 \ + $(top_srcdir)/config/amanda/version.m4 \ + $(top_srcdir)/config/gnulib/alloca.m4 \ + $(top_srcdir)/config/gnulib/arpa_inet_h.m4 \ + $(top_srcdir)/config/gnulib/base64.m4 \ + $(top_srcdir)/config/gnulib/eoverflow.m4 \ + $(top_srcdir)/config/gnulib/extensions.m4 \ + $(top_srcdir)/config/gnulib/float_h.m4 \ + $(top_srcdir)/config/gnulib/fsusage.m4 \ + $(top_srcdir)/config/gnulib/getaddrinfo.m4 \ + $(top_srcdir)/config/gnulib/gettimeofday.m4 \ + $(top_srcdir)/config/gnulib/gnulib-comp.m4 \ + $(top_srcdir)/config/gnulib/include_next.m4 \ + $(top_srcdir)/config/gnulib/inet_ntop.m4 \ + $(top_srcdir)/config/gnulib/intmax_t.m4 \ + $(top_srcdir)/config/gnulib/lock.m4 \ + $(top_srcdir)/config/gnulib/longlong.m4 \ + $(top_srcdir)/config/gnulib/malloc.m4 \ + $(top_srcdir)/config/gnulib/mkdtemp.m4 \ + $(top_srcdir)/config/gnulib/netinet_in_h.m4 \ + $(top_srcdir)/config/gnulib/onceonly_2_57.m4 \ + $(top_srcdir)/config/gnulib/physmem.m4 \ + $(top_srcdir)/config/gnulib/safe-read.m4 \ + $(top_srcdir)/config/gnulib/safe-write.m4 \ + $(top_srcdir)/config/gnulib/snprintf.m4 \ + $(top_srcdir)/config/gnulib/socklen.m4 \ + $(top_srcdir)/config/gnulib/sockpfaf.m4 \ + $(top_srcdir)/config/gnulib/ssize_t.m4 \ + $(top_srcdir)/config/gnulib/stdbool.m4 \ + $(top_srcdir)/config/gnulib/stdint.m4 \ + $(top_srcdir)/config/gnulib/stdio_h.m4 \ + $(top_srcdir)/config/gnulib/stdlib_h.m4 \ + $(top_srcdir)/config/gnulib/strdup.m4 \ + $(top_srcdir)/config/gnulib/string_h.m4 \ + $(top_srcdir)/config/gnulib/sys_socket_h.m4 \ + $(top_srcdir)/config/gnulib/sys_stat_h.m4 \ + $(top_srcdir)/config/gnulib/sys_time_h.m4 \ + $(top_srcdir)/config/gnulib/tempname.m4 \ + $(top_srcdir)/config/gnulib/ulonglong.m4 \ + $(top_srcdir)/config/gnulib/unistd_h.m4 \ + $(top_srcdir)/config/gnulib/vasnprintf.m4 \ + $(top_srcdir)/config/gnulib/visibility.m4 \ + $(top_srcdir)/config/gnulib/wchar.m4 \ + $(top_srcdir)/config/gettext-macros/gettext.m4 \ + $(top_srcdir)/config/gettext-macros/iconv.m4 \ + $(top_srcdir)/config/gettext-macros/inttypes_h.m4 \ + $(top_srcdir)/config/gettext-macros/lib-ld.m4 \ + $(top_srcdir)/config/gettext-macros/lib-link.m4 \ + $(top_srcdir)/config/gettext-macros/lib-prefix.m4 \ + $(top_srcdir)/config/gettext-macros/longlong.m4 \ + $(top_srcdir)/config/gettext-macros/nls.m4 \ + $(top_srcdir)/config/gettext-macros/po.m4 \ + $(top_srcdir)/config/gettext-macros/progtest.m4 \ + $(top_srcdir)/config/gettext-macros/size_max.m4 \ + $(top_srcdir)/config/gettext-macros/stdint_h.m4 \ + $(top_srcdir)/config/gettext-macros/wchar_t.m4 \ + $(top_srcdir)/config/gettext-macros/wint_t.m4 \ + $(top_srcdir)/config/gettext-macros/xsize.m4 \ + $(top_srcdir)/config/libtool.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMANDA_DBGDIR = @AMANDA_DBGDIR@ +AMANDA_DEBUG_DAYS = @AMANDA_DEBUG_DAYS@ +AMANDA_STATIC_LDFLAGS = @AMANDA_STATIC_LDFLAGS@ +AMANDA_TMPDIR = @AMANDA_TMPDIR@ +AMANDA_WARNING_CFLAGS = @AMANDA_WARNING_CFLAGS@ +AMLINT = @AMLINT@ +AMLINTFLAGS = @AMLINTFLAGS@ +AMPLOT_CAT_COMPRESS = @AMPLOT_CAT_COMPRESS@ +AMPLOT_CAT_GZIP = @AMPLOT_CAT_GZIP@ +AMPLOT_CAT_PACK = @AMPLOT_CAT_PACK@ +AMPLOT_COMPRESS = @AMPLOT_COMPRESS@ +AMTAR = @AMTAR@ +AR = @AR@ +ARPA_INET_H = @ARPA_INET_H@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASH = @BASH@ +BINARY_OWNER = @BINARY_OWNER@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +CAT = @CAT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CHIO = @CHIO@ +CHS = @CHS@ +CLIENT_LOGIN = @CLIENT_LOGIN@ +CLIENT_SCRIPTS_OPT = @CLIENT_SCRIPTS_OPT@ +COMPRESS = @COMPRESS@ +CONFIG_DIR = @CONFIG_DIR@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL_CONFIG = @CURL_CONFIG@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DD = @DD@ +DEFAULT_AMANDATES_FILE = @DEFAULT_AMANDATES_FILE@ +DEFAULT_CHANGER_DEVICE = @DEFAULT_CHANGER_DEVICE@ +DEFAULT_CONFIG = @DEFAULT_CONFIG@ +DEFAULT_SERVER = @DEFAULT_SERVER@ +DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@ +DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOC_BUILD_DATE = @DOC_BUILD_DATE@ +DUMP = @DUMP@ +DUMPER_DIR = @DUMPER_DIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EOVERFLOW = @EOVERFLOW@ +EXAMPLE_TAPEDEV = @EXAMPLE_TAPEDEV@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FLOAT_H = @FLOAT_H@ +GETCONF = @GETCONF@ +GETTEXT = @GETTEXT@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNUPLOT = @GNUPLOT@ +GNUTAR = @GNUTAR@ +GNUTAR_LISTED_INCREMENTAL_DIR = @GNUTAR_LISTED_INCREMENTAL_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GZIP = @GZIP@ +HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_MKDIR = @HAVE_DECL_MKDIR@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_IO_H = @HAVE_IO_H@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRNDUP = @HAVE_STRNDUP@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE__BOOL = @HAVE__BOOL@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBS = @LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAILER = @MAILER@ +MAKEINFO = @MAKEINFO@ +MAXTAPEBLOCKSIZE = @MAXTAPEBLOCKSIZE@ +MCUTIL = @MCUTIL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MT = @MT@ +MTX = @MTX@ +MT_FILE_FLAG = @MT_FILE_FLAG@ +NETINET_IN_H = @NETINET_IN_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCAT = @PCAT@ +PERL = @PERL@ +PERLEXTLIBS = @PERLEXTLIBS@ +PERL_INC = @PERL_INC@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +PRINT = @PRINT@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_FCHDIR = @REPLACE_FCHDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +RESTORE = @RESTORE@ +SAMBA_CLIENT = @SAMBA_CLIENT@ +SERVICE_SUFFIX = @SERVICE_SUFFIX@ +SETUID_GROUP = @SETUID_GROUP@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SNAPSHOT_STAMP = @SNAPSHOT_STAMP@ +SORT = @SORT@ +SSH = @SSH@ +STDBOOL_H = @STDBOOL_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SVN = @SVN@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYS_SOCKET_H = @SYS_SOCKET_H@ +SYS_STAT_H = @SYS_STAT_H@ +SYS_TIME_H = @SYS_TIME_H@ +USE_NLS = @USE_NLS@ +USE_VERSION_SUFFIXES = @USE_VERSION_SUFFIXES@ +VDUMP = @VDUMP@ +VERSION = @VERSION@ +VERSION_COMMENT = @VERSION_COMMENT@ +VERSION_MAJOR = @VERSION_MAJOR@ +VERSION_MINOR = @VERSION_MINOR@ +VERSION_PATCH = @VERSION_PATCH@ +VERSION_SUFFIX = @VERSION_SUFFIX@ +VRESTORE = @VRESTORE@ +VXDUMP = @VXDUMP@ +VXRESTORE = @VXRESTORE@ +WCHAR_H = @WCHAR_H@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XFSDUMP = @XFSDUMP@ +XFSRESTORE = @XFSRESTORE@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XSLREL = @XSLREL@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +amincludedir = @amincludedir@ +amlibdir = @amlibdir@ +amlibexecdir = @amlibexecdir@ +amperldir = @amperldir@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + deb \ + rpm \ + Makefile.am \ + README + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu packaging/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu packaging/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + dist-hook distclean distclean-generic distclean-libtool \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am + + +dist-hook: + rm -rf `find ${distdir} -name .svn` +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/packaging/README b/packaging/README new file mode 100644 index 0000000..ea5689b --- /dev/null +++ b/packaging/README @@ -0,0 +1,25 @@ +This directory contains scripts and data files necessary to build various binary +(or source) installation packages. These are the currently functional packages: + -Macintosh OS X >=10.4 .pkg files + -RPMs for various OSes that use them. TODO: Wiki page with a full + list of RPM using distros and versions the .spec supports. + -Solaris .pkg files for 9,10 +Coming soon: + -ebuilds for Gentoo + -.deb Debian style packages for various OSes that use them. + -.msi packages for Windows XP and Server 2003 + +The Directory layout is as follows: +packaging/ + common/ # Common files which can be shared by all packages such + # License.txt, README, or Copyrights. So far, empty :-) + deb/ # Debian + macosx-pkg/ # Macintosh OSX + msi/ # MicroSoft Installer for Windows + rpm/ # RPM + sun-pkg/ # Solaris .pkg + +Each subdirectory (except common) has a shell script named buildpkg. This script will +actually build the package with Zmanda's defaults for you. + +See http://wiki.zmanda.com/index.php/Installation for more information. diff --git a/packaging/deb/amanda-backup-client.README.Debian b/packaging/deb/amanda-backup-client.README.Debian new file mode 100644 index 0000000..5a73992 --- /dev/null +++ b/packaging/deb/amanda-backup-client.README.Debian @@ -0,0 +1,2 @@ +Amanda Forums are located at: http://forums.zmanda.com/ +Amanda Documentation is available at: http://wiki.zmanda.com/ diff --git a/packaging/deb/amanda-backup-client.dirs b/packaging/deb/amanda-backup-client.dirs new file mode 100644 index 0000000..35eb344 --- /dev/null +++ b/packaging/deb/amanda-backup-client.dirs @@ -0,0 +1,11 @@ +etc/amanda +usr/lib/amanda +usr/libexec/amanda +usr/share/lintian/overrides +usr/share/man/man5 +usr/share/man/man8 +var/amanda +var/lib/amanda +var/lib/amanda/gnutar-lists +var/lib/amanda/example +var/log/amanda diff --git a/packaging/deb/amanda-backup-client.install b/packaging/deb/amanda-backup-client.install new file mode 100644 index 0000000..3e572ef --- /dev/null +++ b/packaging/deb/amanda-backup-client.install @@ -0,0 +1,19 @@ +usr/lib/amanda/* +usr/lib/amanda/application/* +usr/libexec/amanda/* +usr/libexec/amanda/application/* +usr/sbin/amaespipe +usr/sbin/amcryp* +usr/sbin/amgpgcrypt +usr/sbin/amoldrecover +usr/sbin/amrecover +usr/share/man/man5/amanda.conf.5 +usr/share/man/man5/amanda-client.conf.5 +usr/share/man/man8/amanda.8 +usr/share/man/man8/amcheckdump.8 +usr/share/man/man8/amrecover.8 +var/lib/amanda/* +var/lib/amanda/gnutar-lists/* +var/lib/amanda/example/xinetd.amandaclient +var/lib/amanda/example/amanda-client.conf +var/log/amanda/* diff --git a/packaging/deb/amanda-backup-client.lintian b/packaging/deb/amanda-backup-client.lintian new file mode 100644 index 0000000..b7069a4 --- /dev/null +++ b/packaging/deb/amanda-backup-client.lintian @@ -0,0 +1,20 @@ +amanda-backup-client: binary-or-shlib-defines-rpath usr/lib/amanda/* +amanda-backup-client: binary-or-shlib-defines-rpath usr/libexec/amanda/* +amanda-backup-client: binary-or-shlib-defines-rpath amoldrecover amrecover +amanda-backup-client: binary-without-manpage amaespipe +amanda-backup-client: binary-without-manpage amcryp* +amanda-backup-client: binary-without-manpage amgpgcrypt +amanda-backup-client: binary-without-manpage amoldrecover +amanda-backup-client: file-in-unusual-dir usr/libexec/amanda/* +amanda-backup-client: manpage-has-bad-whatis-entry +amanda-backup-client: non-standard-dir-in-usr usr/libexec +amanda-backup-client: non-standard-dir-in-var var/log/amanda +amanda-backup-client: non-standard-dir-in-var var/amanda +amanda-backup-client: non-standard-dir-perm var/lib/amanda/gnutar-lists +amanda-backup-client: non-standard-dir-perm var/log/amanda +amanda-backup-client: package-name-doesnt-match-sonames +amanda-backup-client: setuid-binary usr/libexec/amanda/calcsize +amanda-backup-client: setuid-binary usr/libexec/amanda/killgrp +amanda-backup-client: setuid-binary usr/libexec/amanda/planner +amanda-backup-client: setuid-binary usr/libexec/amanda/rundump +amanda-backup-client: setuid-binary usr/libexec/amanda/runtar diff --git a/packaging/deb/amanda-backup-client.postinst b/packaging/deb/amanda-backup-client.postinst new file mode 100755 index 0000000..c91894e --- /dev/null +++ b/packaging/deb/amanda-backup-client.postinst @@ -0,0 +1,104 @@ +#!/bin/sh + +SYSCONFDIR="/etc" +LOCALSTATEDIR="/var" +LOGDIR="${LOCALSTATEDIR}/log/amanda/" +AMHOMEDIR="${LOCALSTATEDIR}/lib/amanda" +amanda_user=amandabackup +amanda_group=disk +xinetd_reload="restart" + + +# Installing xinetd config and make it active. +if [ -e /etc/xinetd.d ] && [ -d /etc/xinetd.d ] ; then + if [ ! -f /etc/xinetd.d/amandaclient ] ; then + cp ${AMHOMEDIR}/example/xinetd.amandaclient /etc/xinetd.d/amandaclient || exit 1 + echo -n "`date +'%b %e %Y %T'`: Reloading xinetd configuration..." + if [ "${xinetd_reload}" = "reload" ] ; then + /usr/sbin/invoke-rc.d xinetd ${xinetd_reload} # don't exit yet... + if [ $? -ne 0 ] ; then + echo -n "reload failed. Attempting restart..." + /usr/sbin/invoke-rc.d xinetd restart || exit 1 + fi + else + /usr/sbin/invoke-rc.d xinetd ${xinetd_reload} || exit 1 + fi + fi +fi + +echo "`date +'%b %e %Y %T'`: Installing '${LOCALSTATEDIR}/amanda/amandates'." +if [ ! -f ${LOCALSTATEDIR}/amanda/amandates ] ; then + touch ${LOCALSTATEDIR}/amanda/amandates || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '${LOCALSTATEDIR}/amanda/amandates'." +chown ${amanda_user}:${amanda_group} ${LOCALSTATEDIR}/amanda/amandates || exit 1 +chmod 0640 ${LOCALSTATEDIR}/amanda/amandates || exit 1 +if [ -x /sbin/restorecon ] ; then + /sbin/restorecon ${LOCALSTATEDIR}/amanda/amandates || exit 1 +fi + +# Install .amandahosts to client +echo "`date +'%b %e %Y %T'`: Checking '${AMHOMEDIR}/.amandahosts' file." +if [ ! -f ${AMHOMEDIR}/.amandahosts ] ; then + touch ${AMHOMEDIR}/.amandahosts || exit 1 +fi +for host in localhost localhost.localdomain ; do + if [ -z "`grep \"^${host}[[:blank:]]\+${amanda_user}[[:blank:]]\+amdump\" ${AMHOMEDIR}/.amandahosts`" ] ; then + echo "${host} ${amanda_user} amdump" >> "${AMHOMEDIR}/.amandahosts" || exit 1 + fi +done +chown ${amanda_user}:${amanda_group} ${AMHOMEDIR}/.amandahosts || exit 1 +chmod 0600 ${AMHOMEDIR}/.amandahosts || exit 1 + +# Install amanda client configuration file +echo "`date +'%b %e %Y %T'`: Checking '${SYSCONFDIR}/amanda/amanda-client.conf' file." +if [ ! -f ${SYSCONFDIR}/amanda/amanda-client.conf ] ; then + cp ${AMHOMEDIR}/example/amanda-client.conf ${SYSCONFDIR}/amanda/amanda-client.conf || exit 1 +fi +chown ${amanda_user}:${amanda_group} ${SYSCONFDIR}/amanda/amanda-client.conf || exit 1 +chmod 0600 ${SYSCONFDIR}/amanda/amanda-client.conf || exit 1 + +# Install .gnupg directory +echo "`date +'%b %e %Y %T'`: Installing '${AMHOMEDIR}/.gnupg'." +if [ ! -d ${AMHOMEDIR}/.gnupg ] ; then + echo "`date +'%b %e %Y %T'`: '${AMHOMEDIR}/.gnupg' will be created." + mkdir ${AMHOMEDIR}/.gnupg || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '${AMHOMEDIR}/.gnupg'." +chown ${amanda_user}:${amanda_group} ${AMHOMEDIR}/.gnupg || exit 1 +chmod 700 ${AMHOMEDIR}/.gnupg || exit 1 + +# SSH RSA key generation on client for amrecover +KEYDIR="${AMHOMEDIR}/.ssh" +KEYFILE="id_rsa_amrecover" +COMMENT="root@client" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.save'." + mv ${KEYDIR} ${KEYDIR}.save || exit 1 + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." + mkdir ${KEYDIR} || exit 1 +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Setting permissions for '${KEYDIR}' and '${KEYDIR}/${KEYFILE}*'" +chown ${amanda_user}:${amanda_group} ${KEYDIR} || exit 1 +chmod 0750 ${KEYDIR} || exit 1 +chmod 0600 ${KEYDIR}/${KEYFILE}* || exit 1 + +# environment variables (~amandabackup/.profile) +echo "`date +'%b %e %Y %T'`: Checking for '${AMHOMEDIR}/.profile' and ensuring correct environment." +if [ ! -f ${AMHOMEDIR}/.profile ] ; then + touch ${AMHOMEDIR}/.profile || exit 1 +fi +if [ -z "`grep PATH ${AMHOMEDIR}/.profile | grep '/usr/sbin'`" ] ; then + echo "export PATH=\"\$PATH:/usr/sbin/\"" >> "${AMHOMEDIR}/.profile" || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '${AMHOMEDIR}/.profile'" +chown ${amanda_user}:${amanda_group} ${AMHOMEDIR}/.profile || exit 1 +chmod 0640 ${AMHOMEDIR}/.profile || exit 1 + +echo "`date +'%b %e %Y %T'`: === Amanda backup client installation complete. ===" diff --git a/packaging/deb/amanda-backup-client.postrm b/packaging/deb/amanda-backup-client.postrm new file mode 100755 index 0000000..e69de29 diff --git a/packaging/deb/amanda-backup-client.substvars b/packaging/deb/amanda-backup-client.substvars new file mode 100644 index 0000000..751fe57 --- /dev/null +++ b/packaging/deb/amanda-backup-client.substvars @@ -0,0 +1 @@ +shlibs:Depends=amanda-backup-server, libc6 (>= 2.3.2.ds1-21), libncurses5 (>= 5.4-1), libreadline5 diff --git a/packaging/deb/amanda-backup-server.README.Debian b/packaging/deb/amanda-backup-server.README.Debian new file mode 100644 index 0000000..3149356 --- /dev/null +++ b/packaging/deb/amanda-backup-server.README.Debian @@ -0,0 +1,2 @@ +Amanda Forums are located at: http://forums.zmanda.com/ +Amanda Documentation is available at: http://wiki.zmanda.com/ diff --git a/packaging/deb/amanda-backup-server.dirs b/packaging/deb/amanda-backup-server.dirs new file mode 100644 index 0000000..084741f --- /dev/null +++ b/packaging/deb/amanda-backup-server.dirs @@ -0,0 +1,9 @@ +etc/amanda +usr/share/lintian/overrides +usr/share/man/man5 +usr/share/man/man8 +var/amanda +var/lib/amanda +var/lib/amanda/gnutar-lists +var/lib/amanda/example/label-templates +var/log/amanda diff --git a/packaging/deb/amanda-backup-server.install b/packaging/deb/amanda-backup-server.install new file mode 100644 index 0000000..42e429d --- /dev/null +++ b/packaging/deb/amanda-backup-server.install @@ -0,0 +1,12 @@ +usr/lib/amanda/* +usr/lib/amanda/application/* +usr/libexec/amanda/* +usr/libexec/amanda/application/* +usr/sbin/* +usr/share/man/man5/* +usr/share/man/man8/* +var/lib/amanda/* +var/lib/amanda/gnutar-lists/* +var/lib/amanda/example/* +var/lib/amanda/example/label-templates/* +var/log/amanda/* diff --git a/packaging/deb/amanda-backup-server.lintian b/packaging/deb/amanda-backup-server.lintian new file mode 100644 index 0000000..a6d62ac --- /dev/null +++ b/packaging/deb/amanda-backup-server.lintian @@ -0,0 +1,16 @@ +amanda-backup-server: binary-or-shlib-defines-rpath usr/lib/amanda/* +amanda-backup-server: binary-or-shlib-defines-rpath usr/libexec/amanda/* +amanda-backup-server: binary-or-shlib-defines-rpath usr/sbin/am* +amanda-backup-server: binary-without-manpage amoldrecover +amanda-backup-server: manpage-has-bad-whatis-entry +amanda-backup-server: file-in-unusual-dir usr/libexec/amanda/* +amanda-backup-server: non-standard-dir-in-usr usr/libexec +amanda-backup-server: non-standard-dir-perm var/lib/amanda/gnutar-lists +amanda-backup-server: non-standard-dir-perm var/log/amanda +amanda-backup-server: package-name-doesnt-match-sonames +amanda-backup-server: setuid-binary usr/libexec/amanda/calcsize +amanda-backup-server: setuid-binary usr/libexec/amanda/dumper +amanda-backup-server: setuid-binary usr/libexec/amanda/killgrp +amanda-backup-server: setuid-binary usr/libexec/amanda/planner +amanda-backup-server: setuid-binary usr/libexec/amanda/rundump +amanda-backup-server: setuid-binary usr/libexec/amanda/runtar diff --git a/packaging/deb/amanda-backup-server.postinst b/packaging/deb/amanda-backup-server.postinst new file mode 100755 index 0000000..260db60 --- /dev/null +++ b/packaging/deb/amanda-backup-server.postinst @@ -0,0 +1,132 @@ +#!/bin/sh +# Debian recommends this. Script exits on simple command failure. +# set -e +LOGDIR="/var/log/amanda/" +SYSCONFDIR="/etc" +LOCALSTATEDIR="/var" +AMHOMEDIR="${LOCALSTATEDIR}/lib/amanda" +AMTMP="/tmp/amanda" +amanda_user=amandabackup +amanda_group=disk +xinetd_reload="restart" + +if [ -d /etc/xinetd.d ] ; then + if [ ! -f /etc/xinetd.d/amandaserver ] ; then + cp ${AMHOMEDIR}/example/xinetd.amandaserver /etc/xinetd.d/amandaserver || exit 1 + chmod 0644 /etc/xinetd.d/amandaserver || exit 1 + if [ -f /etc/xinetd.d/amandaclient ] ; then + rm /etc/xinetd.d/amandaclient || exit 1 + fi + echo -n "`date +'%b %e %Y %T'`: Reloading xinetd configuration..." + if [ "${xinetd_reload}" = "reload" ] ; then + /usr/sbin/invoke-rc.d xinetd ${xinetd_reload} # don't exit yet! + if [ $? -ne 0 ] ; then + echo -n "reload failed. Attempting restart..." + /usr/sbin/invoke-rc.d xinetd restart || exit 1 + fi + else + /usr/sbin/invoke-rc.d xinetd ${xinetd_reload} || exit 1 + fi + fi +fi + +echo "`date +'%b %e %Y %T'`: Installing '${LOCALSTATEDIR}/amanda/amandates'." +if [ ! -f ${LOCALSTATEDIR}/amanda/amandates ] ; then + touch ${LOCALSTATEDIR}/amanda/amandates || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '${LOCALSTATEDIR}/amanda/amandates'." +chown ${amanda_user}:${amanda_group} ${LOCALSTATEDIR}/amanda/amandates || exit 1 +chmod 0640 ${LOCALSTATEDIR}/amanda/amandates || exit 1 +if [ -x /sbin/restorecon ] ; then + /sbin/restorecon ${LOCALSTATEDIR}/amanda/amandates || exit 1 +fi + +# Check for existence of and permissions on ${AMTMP} +if [ ! -d ${AMTMP} ]; then + mkdir ${AMTMP} || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '${AMTMP}'." +chown ${amanda_user}:${amanda_group} ${AMTMP} || exit 1 +chmod 0640 ${AMTMP} || exit 1 + +# Install .gnupg directory +echo "`date +'%b %e %Y %T'`: Installing '${AMHOMEDIR}/.gnupg'." +if [ ! -d ${AMHOMEDIR}/.gnupg ] ; then + echo "`date +'%b %e %Y %T'`: '${AMHOMEDIR}/.gnupg' will be created." + mkdir ${AMHOMEDIR}/.gnupg || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '${AMHOMEDIR}/.gnupg'." +chown ${amanda_user}:${amanda_group} ${AMHOMEDIR}/.gnupg || exit 1 +chmod 700 ${AMHOMEDIR}/.gnupg || exit 1 + +# Install .amandahosts to server +echo "`date +'%b %e %Y %T'`: Checking '${AMHOMEDIR}/.amandahosts' file." +if [ ! -f ${AMHOMEDIR}/.amandahosts ] ; then + touch ${AMHOMEDIR}/.amandahosts || exit 1 +fi +for host in localhost localhost.localdomain ; do + if [ -z "`grep \"^${host}[[:blank:]]\+root[[:blank:]]\+amindexd[[:blank:]]\+amidxtaped\" ${AMHOMEDIR}/.amandahosts`" ] ; then + echo "${host} root amindexd amidxtaped" >>${AMHOMEDIR}/.amandahosts || exit 1 + fi + if [ -z "`grep \"^${host}[[:blank:]]\+${amanda_user}[[:blank:]]\+amdump\" ${AMHOMEDIR}/.amandahosts`" ] ; then + echo "${host} ${amanda_user} amdump" >>${AMHOMEDIR}/.amandahosts || exit 1 + fi +done +chown ${amanda_user}:${amanda_group} ${AMHOMEDIR}/.amandahosts || exit 1 +chmod 0600 ${AMHOMEDIR}/.amandahosts || exit 1 + +# SSH RSA key generation for amdump +KEYDIR="${AMHOMEDIR}/.ssh" +KEYFILE="id_rsa_amdump" +COMMENT="${amanda_user}@server" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.save'." + mv ${KEYDIR} ${KEYDIR}.save || exit 1 + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." + mkdir ${KEYDIR} || exit 1 +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '${KEYDIR}' and '${KEYDIR}/${KEYFILE}*'" +chown ${amanda_user}:${amanda_group} ${KEYDIR} ${KEYDIR}/${KEYFILE}* || exit 1 +chmod 0750 ${KEYDIR} || exit 1 +chmod 0600 ${KEYDIR}/${KEYFILE}* || exit 1 + +# SSH RSA key generation on client for amrecover +KEYDIR="${AMHOMEDIR}/.ssh" +KEYFILE="id_rsa_amrecover" +COMMENT="root@client" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.save'." + mv ${KEYDIR} ${KEYDIR}.save || exit 1 + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." + mkdir ${KEYDIR} || exit 1 +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Setting permissions for '${KEYDIR}'" +chown ${amanda_user}:${amanda_group} ${KEYDIR} || exit 1 +chmod 0750 ${KEYDIR} || exit 1 +chmod 0600 ${KEYDIR}/${KEYFILE}* || exit 1 + +# environment variables (~amandabackup/.profile) +echo "`date +'%b %e %Y %T'`: Checking for '${AMHOMEDIR}/.profile' and ensuring correct environment." +if [ ! -f ${AMHOMEDIR}/.profile ] ; then + touch ${AMHOMEDIR}/.profile || exit 1 +fi +if [ -z "`grep PATH ${AMHOMEDIR}/.profile | grep '/usr/sbin'`" ] ; then + echo "export PATH=\"\$PATH:/usr/sbin/\"" >> "${AMHOMEDIR}/.profile" || exit 1 +fi +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '${AMHOMEDIR}/.profile'" +chown ${amanda_user}:${amanda_group} ${AMHOMEDIR}/.profile || exit 1 +chmod 0640 ${AMHOMEDIR}/.profile || exit 1 + +echo "`date +'%b %e %Y %T'`: === Amanda backup server installation complete. ===" diff --git a/packaging/deb/amanda-backup-server.postrm b/packaging/deb/amanda-backup-server.postrm new file mode 100755 index 0000000..e69de29 diff --git a/packaging/deb/amanda-backup-server.substvars b/packaging/deb/amanda-backup-server.substvars new file mode 100644 index 0000000..c27ee0c --- /dev/null +++ b/packaging/deb/amanda-backup-server.substvars @@ -0,0 +1 @@ +shlibs:Depends=libc6 (>= 2.3.2.ds1-21), libncurses5 (>= 5.4-1), libreadline5 diff --git a/packaging/deb/buildpkg b/packaging/deb/buildpkg new file mode 100755 index 0000000..4cee2d6 --- /dev/null +++ b/packaging/deb/buildpkg @@ -0,0 +1,128 @@ +#! /bin/bash +set -x +#### Configure variables. Feel free to change these, but be careful! +SRCDIR=$(pwd) +# You can pass your own temp directory as an environment variable. +if [ -z $TMPDIR ] +then + TMPDIR="/tmp/buildpkg.deb" +fi +# This prefix is prepended to all directories during "make install" +FAKEROOT="${TMPDIR}/froot" +# Configure and Compilation directory. +BUILDDIR="${TMPDIR}/build" +# Config variables to mirror those in RPM .spec file +amanda_user=amandabackup +amanda_group=admin +udpportrange="700,740" +tcpportrange="11000,11040" +low_tcpportrange="700,710" +PREFIX="/usr" +EPREFIX="${PREFIX}" +BINDIR="${EPREFIX}/bin" +SBINDIR="${EPREFIX}/sbin" +LIBEXECDIR="${EPREFIX}/lib/amanda" +DATADIR="${PREFIX}/share" +SYSCONFDIR="/etc" +LOCALSTATEDIR="/var" +AMANDAHOMEDIR="${LOCALSTATEDIR}/lib/amanda" +LIBDIR="${EPREFIX}/lib" +INCLUDEDIR="${PREFIX}/include" +INFODIR="${PREFIX}/info" +MANDIR="${DATADIR}/man" +LOGDIR="${LOCALSTATEDIR}/log/amanda" + +#### CHECKS + +if [ ! -f common-src/amanda.h ] +then + echo "'buildpkg' must be run from the root of an otherwise unused amanda source directory." >&2 + exit 1 +fi + +if [ ! -f configure ] +then + echo "The source directory has not been autogen'd -- please download a source distribution tarball or run ./autogen." + echo "You will need autoconf, automake, and libtool to run autogen (but not to compile from a distribution tarball)." + exit 1 +fi + +if [ -z $AMVER ] +then + AMVER=amanda-2.6.0p2 +fi + +if [ -z $AMTARBALL ] +then + AMTARBALL=$AMVER.tar.gz +fi + +#### Build functions + +do_build() { + + echo "Running configure" + ./configure --quiet \ + --prefix=${PREFIX} \ + --bindir=${BINDIR} \ + --sbindir=${SBINDIR} \ + --mandir=${MANDIR} \ + --libexecdir=${LIBEXECDIR} \ + --sysconfdir=${SYSCONFDIR} \ + --localstatedir=${LOCALSTATEDIR} \ + --with-star=/bin/star \ + --with-gnutar=/bin/tar \ + --with-gnutar-listdir=${AMANDAHOMEDIR}/gnutar-lists \ + --with-index-server=localhost \ + --with-tape-server=localhost \ + --with-user=${amanda_user} \ + --with-group=${amanda_group} \ + --with-owner=${amanda_user} \ + --with-fqdn \ + --with-bsd-security \ + --with-bsdtcp-security \ + --with-bsdudp-security \ + --with-amandahosts \ + --with-smbclient=/usr/bin/smbclient \ + --with-ssh-security \ + --with-udpportrange=${udpportrange} \ + --with-tcpportrange=${tcpportrange} \ + --with-low-tcpportrange=${low_tcpportrange} \ + --with-debugging=${LOGDIR} \ + --disable-installperms \ + --enable-s3-device \ + --with-assertions \ + || exit 1 + +} + +do_resources() { + # Setup directories and files as dpkg-buildpkg expects. + if [ -d debian ]; then + rm -rf debian + fi + cp -Rf packaging/deb debian + if [ -d $AMVER ]; then + rm -rf $AMVER + fi + mkdir $AMVER + cp -Rfp * $AMVER +} + +do_package() { + + echo "Building package" + cd $AMVER + # Create unsigned packages + dpkg-buildpackage -rfakeroot -uc -us +} + + +do_all() { + do_build $1 + do_resources $1 + do_package $1 +} + +do_resources +do_package diff --git a/packaging/deb/changelog b/packaging/deb/changelog new file mode 100644 index 0000000..63eabb3 --- /dev/null +++ b/packaging/deb/changelog @@ -0,0 +1,9 @@ +amanda (2.6.0p1-1) unstable; urgency=low + + * Initial debian release: This package is based on Bdale Garbee's work as + the official debian maintainer for amanda. + * Found by Daniel_p: Fixed typos in preinst and postrm. Added permission + check for /tmp/amanda. Fixed rules to append default perl site_lib to + .install file so that perl modules are installed. + + -- Zmanda Mon, 10 Mar 2008 1:00:09 -0600 diff --git a/packaging/deb/compat b/packaging/deb/compat new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/packaging/deb/compat @@ -0,0 +1 @@ +4 diff --git a/packaging/deb/control b/packaging/deb/control new file mode 100644 index 0000000..c74248d --- /dev/null +++ b/packaging/deb/control @@ -0,0 +1,37 @@ +Source: amanda +Section: utils +Priority: optional +Maintainer: Zmanda Inc +Build-Depends: debhelper, dump, fakeroot, flex, gnuplot, libtool, mailx, mtx, perl (>=5.6.0), smbclient, + libcurl-dev, libncurses5-dev, libreadline5-dev | libreadline-dev, libssl-dev +Standards-Version: 3.6.1 + +Package: amanda-backup-server +Architecture: any +Depends: xinetd, perl (>=5.6.0), mailx, gnuplot, tar (>=1.15), libcurl3 (>=7.10.0), libglib2.0-0 (>=2.2.0), libssl | libssl0.9.8 +Suggests: amanda-backup-client (= ${Source-Version}) +Description: Amanda Network Backup and Archiving software + . + Amanda is the leading Open-Source Backup and Archiving software. + . + This package contains the Amanda server. The amanda-backup_server package + should be installed on the Amanda server, i.e. the machine attached to backup + media (such as a tape drive or disk drives) where backups will be written. The + amanda-backup_server package includes Amanda client. + . + Amanda Forums are located at: http://forums.zmanda.com/ + Amanda Documentation is available at: http://wiki.zmanda.com/ + +Package: amanda-backup-client +Architecture: any +Depends: xinetd, perl (>=5.6.0), grep, libcurl3 (>=7.10.0), libglib2.0-0 (>=2.2.0), libssl | libssl0.9.8 +Conflicts: amanda-backup-server (>=${Source-Version}) +Description: Amanda Network Backup and Archiving software + . + Amanda is the leading Open-Source Backup and Archiving software. + . + This package contains the Amanda client. The amanda-backup_client package + needs to be installed on every system that is being backed up. + . + Amanda Forums are located at: http://forums.zmanda.com/ + Amanda Documentation is available at: http://wiki.zmanda.com/ diff --git a/packaging/deb/copyright b/packaging/deb/copyright new file mode 100644 index 0000000..51bf3d5 --- /dev/null +++ b/packaging/deb/copyright @@ -0,0 +1,26 @@ + +Builder: Zmanda +Amanda copyright: http://wiki.zmanda.com/index.php/Amanda_Copyright + +/* + * Amanda, The Advanced Maryland Automatic Network Disk Archiver + * Copyright (c) 1991, 1996 University of Maryland at College Park + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/packaging/deb/debian-binary b/packaging/deb/debian-binary new file mode 100644 index 0000000..6ec12fe --- /dev/null +++ b/packaging/deb/debian-binary @@ -0,0 +1 @@ +version: 2.0 diff --git a/packaging/deb/docs b/packaging/deb/docs new file mode 100644 index 0000000..6f83607 --- /dev/null +++ b/packaging/deb/docs @@ -0,0 +1,3 @@ +AUTHORS +NEWS +README diff --git a/packaging/deb/postrm b/packaging/deb/postrm new file mode 100755 index 0000000..e972af6 --- /dev/null +++ b/packaging/deb/postrm @@ -0,0 +1,39 @@ +#!/bin/sh -e +case "$1" in + purge) + if [ -d /etc/amanda ]; then + # remove /etc amanda if there are no files left + rmdir /etc/amanda 2> /dev/null || true + fi + if [ -d /var/log/amanda ]; then + rm -rf /var/log/amanda + fi + if [ -d /var/lib/amanda/gnutar-lists ]; then + rm -rf /var/lib/amanda/gnutar-lists + fi + if [ -d /var/lib/amanda ]; then + rm -rf /var/lib/amanda + fi + if which deluser >/dev/null 2>&1 ; then + for group in disk; do + # only call deluser when amandabackup is in $group + if getent group "$group" | + awk -F: '{ print $4 }' | + awk -F, '{ for (i=1; i <= NF; i++ ) print $i }' | + grep '^amandabackup$' > /dev/null; then + deluser "amandabackup $group" || true + fi + done + fi + ;; + remove|upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "unknown argument --> $1" >&2 + exit 0 + ;; +esac diff --git a/packaging/deb/preinst b/packaging/deb/preinst new file mode 100755 index 0000000..645a662 --- /dev/null +++ b/packaging/deb/preinst @@ -0,0 +1,127 @@ +#!/bin/sh + +amanda_user=amandabackup +amanda_group=disk + +TMPFILE=`mktemp /tmp/deb-amanda.XXXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to mktemp!" 1>&2 + exit 1 +fi +LOGDIR="/var/log/amanda" +INSTALL_LOG="${LOGDIR}/install.log" +INSTALL_ERR="${LOGDIR}/install.err" + +echo "`date +'%b %e %Y %T'`: Preparing to install Amanda" >${TMPFILE} + +# Check for the '${amanda_user}' user +echo "`date +'%b %e %Y %T'`: Checking for ${amanda_user} user..." >>${TMPFILE} +if [ "`id -u ${amanda_user} >/dev/null 2>&1 && echo 0 || echo 1`" != "0" ] ; then + useradd -c "Amanda" -g ${amanda_group} -d /var/lib/amanda -s /bin/sh ${amanda_user} + # Lock the ${amanda_user} account until admin sets password + passwd -l ${amanda_user} >>/dev/null + PASSWD_EXIT=$? + if [ ${PASSWD_EXIT} -eq 0 ] ; then + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The ${amanda_user} user account has been successfully created." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Furthermore, the account has been automatically locked for you" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: for security purposes. Once a password for the '${amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: account has been set, the user can be unlocked by issuing" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the following command as root.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: # passwd -u ${amanda_user}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: If this is not a new installation of Amanda and you have" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: pre-existing Amanda configurations in /etc/amanda" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: you should ensure that 'dumpuser' is set to '${amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: in those configurations. Additionally, you should ensure" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: that /var/lib/amanda/.amandahosts on your client systems" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: is properly configured to allow connections for the user" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: '${amanda_user}'." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 + else + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! The '${amanda_user}' user account for this system has been !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! created, however the user has no password set. For !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! security purposes this account is normally locked !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! after creation. Unfortunately, when locking this !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! account an error occurred. To ensure the security !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! of your system you should set a password for the !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user account '${amanda_user}' immediately! To set such a !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! password, please issue the following command.: !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! # passwd ${amanda_user}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + PASSWD_OK=1 + fi +else + # log information about '${amanda_user}' user parameters + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The Amanda backup software is configured to operate as the" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user '${amanda_user}'. This user exists on your system and has not" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: been modified. To ensure that Amanda functions properly," >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: please see that the following parameters are set for that" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: SHELL: /bin/sh" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: HOME: /var/lib/amanda" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Default group: ${amanda_group}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Verifying ${amanda_user} user parameters :" >>${TMPFILE} + + + if [ "`id -gn ${amanda_user}`" != "${amanda_group}" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user '${amanda_user}' is not part of the ${amanda_group} group, !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! please make sure it is corrected before start using amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified group name of user '${amanda_user}'" >>${TMPFILE} + fi + + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 +fi +if [ -d /var/lib/amanda ] ; then + echo -n "`date +'%b %e %Y %T'`: Checking ownership of '/var/lib/amanda'... " >>${TMPFILE} + if [ "`ls -dl /var/lib/amanda | awk '//{split($_,x); print x[3]}'`" = "${amanda_user}" ] && \ + [ "`ls -dl /var/lib/amanda | awk '//{split($_,x); print x[4]}'`" = "${amanda_group}" ] ; then + echo "correct." >>${TMPFILE} + VARLIB_OK=0 + else + echo "incorrect!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Please ensure that the directory '/var/lib/amanda' is owned by" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the user '${amanda_user}' and group '${amanda_group}'." >>${TMPFILE} + VARLIB_OK=1 + fi +else + VARLIB_OK=0 +fi +echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} +if [ ! -e ${LOGDIR} ] ; then + # create log directory + mkdir -m 0750 ${LOGDIR} >>${TMPFILE} 2>&1 + chown ${amanda_user}:${amanda_group} ${LOGDIR} >>${TMPFILE} 2>&1 +fi + +if [ ${PASSWD_OK} -eq 1 ] || [ ${VARLIB_OK} -eq 1 ] ; then + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} + echo "Please review '${INSTALL_ERR}' to correct errors which have prevented the Amanda installation." >&2 + echo "Amanda installation log can be found in '${INSTALL_LOG}' and errors (if any) in '${INSTALL_ERR}'." + exit 1 +else + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi + +echo "`date +'%b %e %Y %T'`: === Amanda installation started. ===" >${TMPFILE} + +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} +if [ -f "${TMPFILE}" ]; then + rm -f "${TMPFILE}" +fi + diff --git a/packaging/deb/rules b/packaging/deb/rules new file mode 100755 index 0000000..bae37a0 --- /dev/null +++ b/packaging/deb/rules @@ -0,0 +1,201 @@ +#!/usr/bin/make -f +# debian/rules for amanda using debhelper. GNU copyright 2008 by Dan Locks, +# based on work by Bdale Garbee. +# requires automake 1.2d (from experimental tree) + +# Warning - do *not* use -j on an SMP machine, or the build gets +# confused... some sort of race condition in the makefiles? + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 +AMVER=2.6.0p2 + +# These are variables that the user can override. They get used in various +# places during configure, build, and install. +PREFIX=/usr +BINDIR=$(PREFIX)/bin +LIBDIR=$(PREFIX)/lib +AMLIBDIR=$(LIBDIR)/amanda +LIBEXECDIR=$(PREFIX)/libexec +AMLIBEXECDIR=$(LIBEXECDIR)/amanda +MANDIR=$(PREFIX)/share/man +DOCDIR=$(PREFIX)/share/doc +SYSCONFDIR=/etc +LOCALSTATEDIR=/var +AMHOMEDIR=$(LOCALSTATEDIR)/lib/amanda +LOGDIR=$(LOCALSTATEDIR)/log/amanda +# Extract the perl site_lib directory. This is used to install amanda's perl +# libs. If configure finds a different install or you specify a different path using +# --with-amperldir= make sure you change this variable as well. +PERLSITELIB=$(shell perl -V:installsitelib|sed -e"s:installsitelib='/::;s:'\;::") +AMANDAUSER=amandabackup +AMANDAGROUP=disk +WITHOUT_SERVER="False" +WITHOUT_CLIENT="False" + +r=$(shell pwd)/debian/amanda-common +server=$(shell pwd)/debian/amanda-backup-server +client=$(shell pwd)/debian/amanda-backup-client + +log=$(shell pwd)/debian/dpkg.log + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + +build: build-stamp +build-stamp: /sbin/dump /usr/bin/smbclient + dh_testdir + ./configure \ + MAKEFLAGS="-j1 " \ + CFLAGS="-DIGNORE_TAR_ERRORS " \ + MAILER=/usr/bin/mail \ + --quiet \ + --host=$(DEB_HOST_GNU_TYPE) \ + --build=$(DEB_BUILD_GNU_TYPE) \ + --prefix=$(PREFIX) \ + --bindir=$(BINDIR) \ + --mandir=$(MANDIR) \ + --libexecdir=$(LIBEXECDIR) \ + --enable-shared \ + --sysconfdir=$(SYSCONFDIR) \ + --localstatedir=$(LOCALSTATEDIR)\ + --with-gnutar-listdir=$(AMHOMEDIR)/gnutar-lists \ + --with-index-server=localhost \ + --with-tape-server=localhost \ + --with-user=$(AMANDAUSER) \ + --with-group=$(AMANDAGROUP) \ + --with-fqdn \ + --with-bsd-security \ + --with-bsdtcp-security \ + --with-bsdudp-security \ + --with-amandahosts \ + --with-smbclient=$(BINDIR)/smbclient \ + --with-debugging=$(LOGDIR) \ + --with-tcpportrange=11000,11040 \ + --with-udpportrange=700,740 \ + --with-low-udpportrange=700,710 \ + --with-ssh-security \ + --with-assertions \ + --enable-s3-device \ + --disable-installperms + touch missing + # There's probably a better way to do this. Preinst and postrm are the + # same for client and server, but we leave room for differences by just + # appending here. + cat $(shell pwd)/debian/preinst >> $(shell pwd)/debian/amanda-backup-client.preinst + cat $(shell pwd)/debian/preinst >> $(shell pwd)/debian/amanda-backup-server.preinst + cat $(shell pwd)/debian/postrm >> $(shell pwd)/debian/amanda-backup-client.postrm + cat $(shell pwd)/debian/postrm >> $(shell pwd)/debian/amanda-backup-server.postrm + make + touch build-stamp + +clean: + dh_testdir >> $(log) 2>&1 + dh_testroot >> $(log) 2>&1 + -make clean + -make distclean + -rm -f build-stamp missing config/config.h common-src/genversion + -find . -type d -name .deps -exec rm -rf {} \; + -test -r /usr/share/misc/config.sub && \ + cp -f /usr/share/misc/config.sub config/config.sub + -test -r /usr/share/misc/config.guess && \ + cp -f /usr/share/misc/config.guess config/config.guess + dh_clean >> $(log) 2>&1 + +# Build architecture-dependent files here. +binary-arch: build + echo "---->dh_testdir: " >> $(log) + dh_testdir >> $(log) 2>&1 + echo "---->dh_testroot: " >> $(log) + dh_testroot >> $(log) 2>&1 + echo "---->dh_clean: " >> $(log) + dh_clean -k >> $(log) 2>&1 + echo "---->dh_installdirs: " >> $(log) + dh_installdirs -v >> $(log) 2>&1 + make install DESTDIR=$(r) + echo "---->dh_installdocs: " >> $(log) + dh_installdocs -v >> $(log) 2>&1 + install -d $(r)/$(DOCDIR)/amanda-common/examples + cp -a example/* $(r)/$(DOCDIR)/amanda-common/examples + cp ChangeLog $(r)/$(DOCDIR)/amanda-common/changelog + echo "---->dh_installmenu: " >> $(log) + dh_installmenu -v >> $(log) 2>&1 + echo "---->dh_installcron: " >> $(log) + dh_installcron >> $(log) 2>&1 + echo "---->dh_installchangelogs: " >> $(log) + dh_installchangelogs -v >> $(log) 2>&1 + echo "---->dh_installdebconf: " >> $(log) + dh_installdebconf -v >> $(log) 2>&1 + # Here's how we get the perl modules installed into sitelib + echo $(PERLSITELIB)/* >> debian/amanda-backup-server.install + echo "---->dh_install -v --fail-missing: " >> $(log) + dh_install -v --sourcedir=debian/amanda-common >> $(log) 2>&1 + echo "---->dh_strip: " >> $(log) + dh_strip >> $(log) 2>&1 + echo "---->dh_compress: " >> $(log) + dh_compress >> $(log) 2>&1 + echo "---->dh_fixperms: " >> $(log) + dh_fixperms -v >> $(log) 2>&1 + # fix perms manually + chown -R $(AMANDAUSER):$(AMANDAGROUP) debian/*/var/lib/* + #chmod -R u=rwX,g=rwX,o-rwx debian/*/var/lib/* + chown -R $(AMANDAUSER):$(AMANDAGROUP) $(client)/$(LOGDIR) $(server)/$(LOGDIR) + #chmod -R u=rwX,g=rwX,o-rwx $(server)/$(LOGDIR) + chown -R $(AMANDAUSER):$(AMANDAGROUP) $(client)/$(SYSCONFDIR)/amanda $(server)/$(SYSCONFDIR)/amanda + #chmod -R u=rwX,g=rwX,o-rwx $(server)/$(SYSCONFDIR)/amanda + chown -R $(AMANDAUSER):$(AMANDAGROUP) $(client)/$(AMHOMEDIR)/gnutar-lists $(server)/$(AMHOMEDIR)/gnutar-lists + chmod -R u=rwX,g=rwX,o-rwx $(client)/$(AMHOMEDIR)/gnutar-lists $(server)/$(AMHOMEDIR)/gnutar-lists + # .. setuid + chown root:disk \ + $(client)/$(AMLIBEXECDIR)/killpgrp \ + $(client)/$(AMLIBEXECDIR)/rundump \ + $(client)/$(AMLIBEXECDIR)/runtar \ + $(client)/$(AMLIBEXECDIR)/calcsize \ + $(server)/$(AMLIBEXECDIR)/killpgrp \ + $(server)/$(AMLIBEXECDIR)/rundump \ + $(server)/$(AMLIBEXECDIR)/runtar \ + $(server)/$(AMLIBEXECDIR)/calcsize \ + $(server)/$(AMLIBEXECDIR)/dumper \ + $(server)/$(AMLIBEXECDIR)/planner \ + $(server)/usr/sbin/amcheck + chmod u=srwx,g=rx,o=r \ + $(client)$(AMLIBEXECDIR)/killpgrp \ + $(client)$(AMLIBEXECDIR)/rundump \ + $(client)$(AMLIBEXECDIR)/runtar \ + $(client)$(AMLIBEXECDIR)/calcsize \ + $(server)$(AMLIBEXECDIR)/killpgrp \ + $(server)$(AMLIBEXECDIR)/rundump \ + $(server)$(AMLIBEXECDIR)/runtar \ + $(server)$(AMLIBEXECDIR)/calcsize \ + $(server)$(AMLIBEXECDIR)/dumper \ + $(server)$(AMLIBEXECDIR)/planner \ + $(server)/usr/sbin/amcheck + echo "Amanda version $(AMVER)" > $(server)/$(AMHOMEDIR)/amanda-release + echo "Amanda version $(AMVER)" > $(client)/$(AMHOMEDIR)/amanda-release + install -o root -g root -m 0644 debian/amanda-backup-client.lintian \ + $(client)/usr/share/lintian/overrides/amanda-backup-client + #install -o root -g root -m 0644 debian/amanda-common.lintian \ + # $(r)/usr/share/lintian/overrides/amanda-common + install -o root -g root -m 0644 debian/amanda-backup-server.lintian \ + $(server)/usr/share/lintian/overrides/amanda-backup-server + dh_makeshlibs >> $(log) 2>&1 + dh_installdeb >> $(log) 2>&1 + dh_perl >> $(log) 2>&1 + dh_shlibdeps -l"debian/$(r)/usr/lib:debian/$(client)/usr/lib:debian/$(server)/usr/lib" >> $(log) 2>&1 + # strip out the non-versioned amanda-common references, we need + # the versioned ones in the control file and dupes are ugly... + sed -e 's/amanda-common, //' < debian/amanda-backup-server.substvars > debian/blah + mv debian/blah debian/amanda-backup-server.substvars + sed -e 's/amanda-common, //' < debian/amanda-backup-client.substvars > debian/blah + mv debian/blah debian/amanda-backup-client.substvars + dh_gencontrol >> $(log) 2>&1 + dh_md5sums >> $(log) 2>&1 + dh_builddeb >> $(log) 2>&1 + +source diff: + @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false + +binary: binary-arch +.PHONY: build clean binary-arch binary diff --git a/packaging/deb/watch b/packaging/deb/watch new file mode 100644 index 0000000..d1101ce --- /dev/null +++ b/packaging/deb/watch @@ -0,0 +1,2 @@ +# Compulsory line, this is a version 2 file +version=2 diff --git a/packaging/rpm/amanda.spec b/packaging/rpm/amanda.spec new file mode 100644 index 0000000..64deb84 --- /dev/null +++ b/packaging/rpm/amanda.spec @@ -0,0 +1,1794 @@ +# +# Copyright (C) 2005 Zmanda Incorporated. +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com +# + + +%define build_srpm 0 +%{?srpm_only: %define build_srpm 1} + +# Pkg-config sometimes needs its own path set, and we need to allow users to +# override our guess during detection. This macro takes care of that. +# If no --define PKG_CONFIG_PATH was passed and env var $PKG_CONFIG_PATH is +# set then use the env var. +%{!?PKG_CONFIG_PATH: %{expand:%(echo ${PKG_CONFIG_PATH:+"%%define PKG_CONFIG_PATH $PKG_CONFIG_PATH"})}} + +%{?PKG_CONFIG_PATH:%{echo:PKG_CONFIG_PATH = %{PKG_CONFIG_PATH}}} + +# Define which Distribution we are building: +# Try to detect the distribution we are building: +%if %{_vendor} == redhat + # Fedora symlinks /etc/fedora-release to /etc/redhat-release for at least + # fc3-8. So RHEL and Fedora look at the same file. Different versions have + # different numbers of spaces; hence the use if $3 vs. $4.. + %if %(awk '$1 == "Fedora" && $4 ~ /3.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist fedora + %define disttag fc + %define distver 3 + %endif + %if %(awk '$1 == "Fedora" && $4 ~ /4.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist fedora + %define disttag fc + %define distver 4 + %endif + %if %(awk '$1 == "Fedora" && $4 ~ /5.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist fedora + %define disttag fc + %define distver 5 + %endif + %if %(awk '$1 == "Fedora" && $4 ~ /6.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist fedora + %define disttag fc + %define distver 6 + %endif + %if %(awk '$1 == "Fedora" && $3 ~ /7.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist fedora + %define disttag fc + %define distver 7 + %endif + %if %(awk '$1 == "Fedora" && $3 ~ /8.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist fedora + %define disttag fc + %define distver 8 + # TODO: generalize this so that any platform can cross compile + %if %{_host_cpu} == x86_64 && %{_target_cpu} == i686 + # Do nothing if PKG_CONFIG_PATH was set by the user above. + %{!?PKG_CONFIG_PATH: %define PKG_CONFIG_PATH /usr/lib/pkgconfig} + %endif + %endif + %if %(awk '$1 == "Red" && $7 ~ /3.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist redhat + %define disttag rhel + %define distver 3 + %define tarver 1.14 + %endif + %if %(awk '$1 == "Red" && $7 ~ /4.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist redhat + %define disttag rhel + %define distver 4 + %define tarver 1.14 + %endif + %if %(awk '$1 == "Red" && $7 ~ /5.*/ { exit 1; }' /etc/redhat-release; echo $?) + %define dist redhat + %define disttag rhel + %define distver 5 + %endif +%endif +# Detect Suse variants. Suse gives us some nice macros in their rpms +%if %{_vendor} == "suse" + %if %{suse_version} == 910 + %define dist SuSE + %define disttag sles + %define distver 9 + %endif + %if %{suse_version} == 1010 + %define dist SuSE + %define disttag sles + %define distver 10 + %endif + %if %{suse_version} == 1000 + %define dist SuSE + %define disttag suse + %define distver 10 + %endif +%endif + +# Set options per distribution +%if %{dist} == redhat || %{dist} == fedora + %define rpm_group Applications/Archiving + %define xinetd_reload restart +%endif +%if %{dist} == SuSE + %define rpm_group Productivity/Archiving/Backup + %define xinetd_reload restart +%endif + +# Set minimum tar version if it wasn't set in the per-distro section +%{!?tarver: %define tarver 1.15} + +%define packer %(%{__id_u} -n) + +# --- Definitions --- + +# Define amanda_version if it is not already defined. +%{!?amanda_version: %define amanda_version 2.6.0p2} +%{!?amanda_release: %define amanda_release 1} +%define amanda_version_info "Amanda Community Edition - version %{amanda_version}" +%define amanda_user amandabackup +%define amanda_group disk +%define udpportrange "700,740" +%define tcpportrange "11000,11040" +%define low_tcpportrange "700,710" + +Summary: The Amanda Backup and Archiving System +Name: amanda +Version: %{amanda_version} +%define rpm_release %{amanda_release}.%{disttag}%{distver} +%if %{build_srpm} +%define rpm_release %{amanda_release} +%endif +Release: %{rpm_release} +Source: %{name}-%{version}.tar.gz +License: http://wiki.zmanda.com/index.php/Amanda_Copyright +Vendor: Zmanda, Inc. +Packager: www.zmanda.com +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%{packer}-buildroot +Group: %{rpm_group} +# TODO - Need required versions for these: +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: binutils +BuildRequires: bison +BuildRequires: flex +BuildRequires: gcc +BuildRequires: glibc >= 2.2.0 +BuildRequires: readline +BuildRequires: curl >= 7.10.0 +Requires: /bin/awk +Requires: /bin/date +Requires: /usr/bin/id +Requires: /sbin/ldconfig +Requires: /bin/sh +Requires: /usr/sbin/useradd +Requires: /usr/sbin/usermod +Requires: fileutils +Requires: grep +Requires: gnuplot +Requires: libc.so.6 +Requires: libm.so.6 +Requires: libnsl.so.1 +Requires: curl >= 7.10.0 +Requires: xinetd +Requires: perl >= 5.6.0 +Requires: tar >= %{tarver} +%if %{dist} == redhat || %{dist}== fedora +Requires: libtermcap.so.2 +Requires: initscripts +%endif +Provides: amanda-backup_client = %{amanda_version}, amanda-backup_server = %{amanda_version} + +%package backup_client +Summary: The Amanda Backup and Archiving Client +Group: %{rpm_group} +Requires: /bin/awk +Requires: fileutils +Requires: grep +%if %{dist} == redhat || %{dist}== fedora +Requires: libtermcap.so.2 +Requires: initscripts +%endif +Requires: xinetd +Requires: libc.so.6 +Requires: libm.so.6 +Requires: libnsl.so.1 +Requires: perl >= 5.6.0 +Requires: tar >= 1.15 +Provides: amanda-backup_client = %{amanda_version} +Provides: libamclient-%{version}.so = %{amanda_version} +Provides: libamanda-%{version}.so = %{amanda_version} +Conflicts: amanda-backup_server + +%package backup_server +Summary: The Amanda Backup and Archiving Server +Group: %{rpm_group} +Requires: /bin/awk +Requires: fileutils +Requires: grep +Requires: libc.so.6 +Requires: libm.so.6 +Requires: libnsl.so.1 +%if %{dist} == redhat || %{dist}== fedora +Requires: libtermcap.so.2 +Requires: initscripts +%endif +Requires: xinetd +Requires: perl >= 5.6.0 +Requires: tar >= 1.15 +Provides: amanda-backup_server = %{amanda_version} +Provides: libamclient-%{version}.so = %{amanda_version} +Provides: libamanda-%{version}.so = %{amanda_version} +Provides: libamserver-%{version}.so = %{amanda_version} +Provides: librestore-%{version}.so = %{amanda_version} +Provides: libamtape-%{version}.so = %{amanda_version} +Provides: libamdevice-%{version}.so = %{amanda_version} + +# --- Package descriptions --- + +%description +Amanda is the leading Open-Source Backup and Archiving software. + +The amanda-backup_server package should be installed on the Amanda server, i.e. +the machine attached to backup media (such as a tape drive or disk +drives) where backups will be written. The amanda-backup_server package +includes Amanda client. The amanda-backup_client package needs +to be installed on every system that is being backed up. + +Amanda Forums is located at: http://forums.zmanda.com/ +Amanda Documentation is available at: http://wiki.zmanda.com/ + + + +%description backup_server +Amanda is the leading Open-Source Backup and Archiving software. + +This package contains the Amanda server. The amanda-backup_server package +should be installed on the Amanda server, i.e. the machine attached +to backup media (such as a tape drive or disk drives) where backups +will be written. The amanda-backup_server package includes Amanda client. + +Amanda Forums is located at: http://forums.zmanda.com/ +Amanda Documentation is available at: http://wiki.zmanda.com/ + + + +%description backup_client +Amanda is the leading Open-Source Backup and Archiving software. + +This package contains the Amanda client. The amanda-backup_client package +needs to be installed on every system that is being backed up. + +Amanda Forums is located at: http://forums.zmanda.com/ +Amanda Documentation is available at: http://wiki.zmanda.com/ + +# --- Directory setup --- + +# Configure directories: +%define PREFIX /usr +%define EPREFIX %{PREFIX} +%define BINDIR %{EPREFIX}/bin +%define SBINDIR %{EPREFIX}/sbin +%define LIBEXECDIR %{EPREFIX}/libexec +%define AMLIBEXECDIR %{LIBEXECDIR}/amanda +%define DATADIR %{PREFIX}/share +%define SYSCONFDIR /etc +%define LOCALSTATEDIR /var +%define AMANDAHOMEDIR %{LOCALSTATEDIR}/lib/amanda +%ifarch x86_64 +%define LIBDIR %{EPREFIX}/lib64 +%else +%define LIBDIR %{EPREFIX}/lib +%endif +%define AMLIBDIR %{LIBDIR}/amanda +%define INCLUDEDIR %{PREFIX}/include +%define MANDIR %{DATADIR}/man +%define LOGDIR /var/log/amanda +%define PERLSITELIB %(eval "`perl -V:installsitelib`"; echo $installsitelib) + +# Installation directories: +%define ROOT_SBINDIR %{buildroot}/%{SBINDIR} +%define ROOT_LIBEXECDIR %{buildroot}/%{LIBEXECDIR} +%define ROOT_DATADIR %{buildroot}/%{DATADIR} +%define ROOT_LOCALSTATEDIR %{buildroot}/%{LOCALSTATEDIR} +%define ROOT_SYSCONFDIR %{buildroot}/%{SYSCONFDIR} +%define ROOT_AMANDAHOMEDIR %{buildroot}/%{AMANDAHOMEDIR} +%define ROOT_LIBDIR %{buildroot}/%{LIBDIR} +%define ROOT_MANDIR %{buildroot}/%{MANDIR} +%define ROOT_LOGDIR %{buildroot}/%{LOGDIR} + +# --- Unpack --- + +%prep +%setup -q +# --- Configure and compile --- + +%build +%define config_user %{amanda_user} +%define config_group %{amanda_group} + +%if %{disttag} == rhel && %{distver} == 3 +./configure \ + CFLAGS="%{optflags} -g" CXXFLAGS="%{optflags}" \ + --quiet \ + --prefix=%{PREFIX} \ + --sysconfdir=%{SYSCONFDIR} \ + --sharedstatedir=%{LOCALSTATEDIR} \ + --localstatedir=%{LOCALSTATEDIR} \ + --libdir=%{LIBDIR} \ + --includedir=%{INCLUDEDIR} \ + --with-gnuplot=/usr/bin/gnuplot \ + --with-gnutar=/bin/tar \ + --with-gnutar-listdir=%{AMANDAHOMEDIR}/gnutar-lists \ + --with-index-server=localhost \ + --with-tape-server=localhost \ + --with-user=%{config_user} \ + --with-group=%{config_group} \ + --with-owner=%{packer} \ + --with-fqdn \ + --with-bsd-security \ + --with-bsdtcp-security \ + --with-bsdudp-security \ + --with-ssh-security \ + --with-udpportrange=%{udpportrange} \ + --with-tcpportrange=%{tcpportrange} \ + --with-low-tcpportrange=%{low_tcpportrange} \ + --with-debugging=%{LOGDIR} \ + --with-assertions \ + --disable-installperms \ + --without-ipv6 +%else +# This confusing macro results in PKG_CONFIG_PATH=some/path if some/path +# was set on the command line, or by the platform detection bits. +./configure \ + %{?PKG_CONFIG_PATH: PKG_CONFIG_PATH=%PKG_CONFIG_PATH} \ + CFLAGS="%{optflags} -g" CXXFLAGS="%{optflags}" \ + --quiet \ + --prefix=%{PREFIX} \ + --sysconfdir=%{SYSCONFDIR} \ + --sharedstatedir=%{LOCALSTATEDIR} \ + --localstatedir=%{LOCALSTATEDIR} \ + --libdir=%{LIBDIR} \ + --includedir=%{INCLUDEDIR} \ + --with-star=/usr/bin/star \ + --with-gnuplot=/usr/bin/gnuplot \ + --with-gnutar=/bin/tar \ + --with-gnutar-listdir=%{AMANDAHOMEDIR}/gnutar-lists \ + --with-index-server=localhost \ + --with-tape-server=localhost \ + --with-user=%{config_user} \ + --with-group=%{config_group} \ + --with-owner=%{packer} \ + --with-fqdn \ + --with-bsd-security \ + --with-bsdtcp-security \ + --with-bsdudp-security \ + --with-ssh-security \ + --with-udpportrange=%{udpportrange} \ + --with-tcpportrange=%{tcpportrange} \ + --with-low-tcpportrange=%{low_tcpportrange} \ + --with-debugging=%{LOGDIR} \ + --with-assertions \ + --disable-installperms +%endif + +make + +# --- Install to buildroot --- + +%install +if [ "%{buildroot}" != "/" ]; then + if [ -d "%{buildroot}" ] ; then + rm -rf %{buildroot} + fi +else + echo "BuildRoot was somehow set to / !" + exit -1 +fi + +make -j1 DESTDIR=%{buildroot} install + +rm -rf %{ROOT_DATADIR}/amanda +rm -f %{ROOT_AMANDAHOMEDIR}/example/inetd.conf.amandaclient +mkdir %{buildroot}/{etc,var/log} +mkdir %{ROOT_LOCALSTATEDIR}/amanda +mkdir %{ROOT_SYSCONFDIR}/amanda +mkdir %{ROOT_AMANDAHOMEDIR}/gnutar-lists +mkdir %{ROOT_LOGDIR} + +echo "%{amanda_version_info}" >%{ROOT_AMANDAHOMEDIR}/amanda-release + +# --- Clean up buildroot --- + +%clean +if [ "%{buildroot}" != "/" ]; then + if [ -d "%{buildroot}" ] ; then + rm -rf %{buildroot} + fi +else + echo "BuildRoot was somehow set to / !" + exit -1 +fi + +# --- Pre/post (un)installation scripts --- + +%pre +TMPFILE=`mktemp /tmp/rpm-amanda.XXXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to mktemp!" 1>&2 + exit 1 +fi +LOGDIR="%{LOGDIR}" +INSTALL_LOG="${LOGDIR}/install.log" +INSTALL_ERR="${LOGDIR}/install.err" + +echo "`date +'%b %e %Y %T'`: Preparing to install: %{amanda_version_info}" >${TMPFILE} + +# Check for the 'amanda' user +echo "`date +'%b %e %Y %T'`: Checking for '%{amanda_user}' user..." >>${TMPFILE} +if [ "`id -u %{amanda_user} > /dev/null 2>&1 && echo 0 || echo 1`" != "0" ] ; then + useradd -c "Amanda" -M -g %{amanda_group} -d %{AMANDAHOMEDIR} -s /bin/sh %{amanda_user} + if [ %{dist} = "SuSE" ]; then + PASSWD_EXIT=$? + else + # Lock the amanda account until admin sets password + passwd -l %{amanda_user} >>/dev/null + PASSWD_EXIT=$? + fi + if [ ${PASSWD_EXIT} -eq 0 ] ; then + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The '%{amanda_user}; user account has been successfully created." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Furthermore, the account has been automatically locked for you" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: for security purposes. Once a password for the '%{amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: account has been set, the user can be unlocked by issuing" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the following command as root.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: # passwd -u %{amanda_user}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: If this is not a new installation of Amanda and you have" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: pre-existing Amanda configurations in %{SYSCONFDIR}/amanda" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: you should ensure that 'dumpuser' is set to '%{amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: in those configurations. Additionally, you should ensure" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: that %{AMANDAHOMEDIR}/.amandahosts on your client systems" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: is properly configured to allow connections for the user" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: '%{amanda_user}'." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 + else + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! The '%{amanda_user}' user account for this system has been !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! created, however the user has no password set. For !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! security purposes this account is normally locked !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! after creation. Unfortunately, when locking this !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! account an error occurred. To ensure the security !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! of your system you should set a password for the !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user account '%{amanda_user}' immediately! To set such a !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! password, please issue the following command.: !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! # passwd %{amanda_user} !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + PASSWD_OK=1 + fi +else + # log information about 'amanda' user parameters + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The Amanda backup software is configured to operate as the" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user '%{amanda_user}'. This user exists on your system and has not" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: been modified. To ensure that Amanda functions properly," >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: please see that the following parameters are set for that" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: SHELL: /bin/sh" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: HOME: %{AMANDAHOMEDIR}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Default group: %{amanda_group}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Verifying %{amanda_user} parameters :" >>${TMPFILE} + + if [ "`id -gn %{amanda_user}`" != "disk" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' is not part of the disk group,Pl !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! make sure it is corrected before start using amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified group name of user 'amandabackup'" >>${TMPFILE} + fi + + if [ "`grep ^%{amanda_user} /etc/passwd|cut -d: -f7`" != "/bin/sh" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' default shell should be set to !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! /bin/sh, pl correct before start using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified Default shell for user 'amandabackup'" >>${TMPFILE} + fi + + if [ "`grep ^%{amanda_user} /etc/passwd|cut -d: -f6`" != "%{AMANDAHOMEDIR}" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' home directory should be set to !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! %{AMANDAHOMEDIR} Pl correct before using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified Default home directory for user amandabackup" >>${TMPFILE} + fi + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 +fi +if [ -d %{AMANDAHOMEDIR} ] ; then + echo -n "`date +'%b %e %Y %T'`: Checking ownership of '%{AMANDAHOMEDIR}'... " >>${TMPFILE} + if [ "`ls -dl %{AMANDAHOMEDIR} | awk '//{split($_,x); print x[3]}'`" = "%{amanda_user}" ] && \ + [ "`ls -dl %{AMANDAHOMEDIR} | awk '//{split($_,x); print x[4]}'`" = "%{amanda_group}" ] ; then + echo "correct." >>${TMPFILE} + VARLIB_OK=0 + else + echo "incorrect!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Please ensure that the directory '%{AMANDAHOMEDIR}' is owned by" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the user '%{amanda_user}' and group '%{amanda_group}'." >>${TMPFILE} + VARLIB_OK=1 + fi +else + VARLIB_OK=0 +fi +echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} +if [ ! -e ${LOGDIR} ] ; then + # create log directory + mkdir -m 0750 ${LOGDIR} >>${TMPFILE} 2>&1 + chown %{amanda_user}:%{amanda_group} ${LOGDIR} >>${TMPFILE} 2>&1 +elif [ ! -d ${LOGDIR} ] ; then + mv ${LOGDIR} ${LOGDIR}.rpmsave >>${TMPFILE} 2>&1 + mkdir -m 0750 ${LOGDIR} >>${TMPFILE} 2>&1 + chown %{amanda_user}:%{amanda_group} ${LOGDIR} >>${TMPFILE} 2>&1 + mv ${LOGDIR}.rpmsave ${LOGDIR}/ >>${TMPFILE} 2>&1 +fi + +if [ ${PASSWD_OK} -eq 1 ] || [ ${VARLIB_OK} -eq 1 ] ; then + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} + echo "Please review '${INSTALL_ERR}' to correct errors which have prevented the Amanda installaton." >&2 + echo "Amanda installation log can be found in '${INSTALL_LOG}' and errors (if any) in '${INSTALL_ERR}'." + exit 1 +else + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi + +echo "`date +'%b %e %Y %T'`: === Amanda installation started. ===" >${TMPFILE} + +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} +if [ -f "${TMPFILE}" ]; then + rm -f "${TMPFILE}" +fi + +%post +TMPFILE=`mktemp /tmp/rpm-amanda.XXXXXXXXXXX +if [ $? -ne 0 ]; then + echo "Unable to mktemp!" 1>&2 + exit 1 +fi +LOGDIR="%{LOGDIR}" +INSTALL_LOG="${LOGDIR}/install.log" +INSTALL_ERR="${LOGDIR}/install.err" + +echo -n "`date +'%b %e %Y %T'`: Updating library cache..." >${TMPFILE} +/sbin/ldconfig >>${TMPFILE} 2>&1 +echo "done." >>${TMPFILE} +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +if [ -e /etc/xinetd.d ] && [ -d /etc/xinetd.d ] ; then + if [ ! -f /etc/xinetd.d/amandaserver ] ; then + cp %{AMANDAHOMEDIR}/example/xinetd.amandaserver /etc/xinetd.d/amandaserver + chmod 0644 /etc/xinetd.d/amandaserver >>${TMPFILE} 2>&1 + if [ -f /etc/xinetd.d/amandaclient ] ; then + rm /etc/xinetd.d/amandaclient + fi + echo -n "`date +'%b %e %Y %T'`: Reloading xinetd configuration..." >${TMPFILE} + if [ "%{xinetd_reload}" == "reload" ] ; then + /etc/init.d/xinetd %{xinetd_reload} >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -ne 0 ] ; then + echo -n "reload failed. Attempting restart..." >>${TMPFILE} + /etc/init.d/xinetd restart >>${TMPFILE} 2>&1 + ret_val=$? + fi + else + /etc/init.d/xinetd %{xinetd_reload} >>${TMPFILE} 2>&1 + ret_val=$? + fi + if [ ${ret_val} -eq 0 ] ; then + echo "success." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + else + echo "failed. Please check your system logs." >>${TMPFILE} + cat ${TMPFILE} 1>&2 + cat ${TMPFILE} >>${INSTALL_ERR} + fi + fi +fi + +echo "`date +'%b %e %Y %T'`: Installing '%{LOCALSTATEDIR}/amanda/amandates'." >${TMPFILE} +ret_val=0 +if [ ! -f %{LOCALSTATEDIR}/amanda/amandates ] ; then + touch %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: The file '%{LOCALSTATEDIR}/amanda/amandates' has been created." >>${TMPFILE} + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '%{LOCALSTATEDIR}/amanda/amandates'." >>${TMPFILE} + chown %{amanda_user}:%{amanda_group} %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + chmod 0640 %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + if [ -x /sbin/restorecon ] ; then + /sbin/restorecon %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: '%{LOCALSTATEDIR}/amanda/amandates' Installation successful." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +else + echo "`date +'%b %e %Y %T'`: '%{LOCALSTATEDIR}/amanda/amandates' Installation failed." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} +fi + + +# Install .gnupg directory +echo "`date +'%b %e %Y %T'`: Installing '%{AMANDAHOMEDIR}/.gnupg'." >${TMPFILE} +ret_val=0 +if [ ! -d %{AMANDAHOMEDIR}/.gnupg ] ; then + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' will be created." >>${TMPFILE} + mkdir %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: The directory '%{AMANDAHOMEDIR}/.gnupg' created successfully." >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: The directory '%{AMANDAHOMEDIR}/.gnupg' creation failed." >>${TMPFILE} + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '%{AMANDAHOMEDIR}/.gnupg'." >>${TMPFILE} + chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + chmod 700 %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' Installation successful." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +else + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' Installation failed." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} +fi + +# Install .amandahosts +echo "`date +'%b %e %Y %T'`: Checking '%{AMANDAHOMEDIR}/.amandahosts' file." >${TMPFILE} +if [ ! -f %{AMANDAHOMEDIR}/.amandahosts ] ; then + touch %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +fi +for host in localhost localhost.localdomain ; do + if [ -z "`grep \"^${host}[[:blank:]]\+root[[:blank:]]\+amindexd[[:blank:]]\+amidxtaped\" %{AMANDAHOMEDIR}/.amandahosts`" ] ; then + echo "${host} root amindexd amidxtaped" >>%{AMANDAHOMEDIR}/.amandahosts + fi + if [ -z "`grep \"^${host}[[:blank:]]\+%{amanda_user}[[:blank:]]\+amdump\" %{AMANDAHOMEDIR}/.amandahosts`" ] ; then + echo "${host} %{amanda_user} amdump" >>%{AMANDAHOMEDIR}/.amandahosts + fi +done +chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +chmod 0600 %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# SSH RSA key generation for amdump +KEYDIR="%{AMANDAHOMEDIR}/.ssh" +KEYFILE="id_rsa_amdump" +COMMENT="%{amanda_user}@server" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.rpmsave'." >${TMPFILE} + mv ${KEYDIR} ${KEYDIR}.rpmsave + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." >${TMPFILE} + mkdir ${KEYDIR} >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" >${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '${KEYDIR}' and '${KEYDIR}/${KEYFILE}*'" >${TMPFILE} +chown %{amanda_user}:%{amanda_group} ${KEYDIR} ${KEYDIR}/${KEYFILE}* >>${TMPFILE} 2>&1 +chmod 0750 ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0600 ${KEYDIR}/${KEYFILE}* >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# SSH RSA key generation on client for amrecover +KEYDIR="%{AMANDAHOMEDIR}/.ssh" +KEYFILE="id_rsa_amrecover" +COMMENT="root@client" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.rpmsave'." >${TMPFILE} + mv ${KEYDIR} ${KEYDIR}.rpmsave >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." >${TMPFILE} + mkdir ${KEYDIR} >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" >${TMPFILE} + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +echo "`date +'%b %e %Y %T'`: Setting permissions for '${KEYDIR}'" >${TMPFILE} +chown %{amanda_user}:%{amanda_group} ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0750 ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0600 ${KEYDIR}/${KEYFILE}* >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# environment variables (~amandabackup/.profile) +echo "`date +'%b %e %Y %T'`: Checking for '%{AMANDAHOMEDIR}/.profile' and ensuring correct environment." >${TMPFILE} +if [ ! -f %{AMANDAHOMEDIR}/.profile ] ; then + touch %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +fi +if [ -z "`grep PATH %{AMANDAHOMEDIR}/.profile | grep '%{SBINDIR}'`" ] ; then + echo "export PATH=\"\$PATH:%{SBINDIR}\"" >>%{AMANDAHOMEDIR}/.profile 2>>${TMPFILE} +fi +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '%{AMANDAHOMEDIR}/.profile'" >>${TMPFILE} +chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +chmod 0640 %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +echo "`date +'%b %e %Y %T'`: Sending anonymous distribution and version information to Zmanda" >> ${INSTALL_LOG} +if [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -o /dev/null -O - --timeout=5 http://www.zmanda.com/amanda-tips.php\?version=%{amanda_version}\&os=%{disttag}%{distver}\&type=server +fi + +echo "`date +'%b %e %Y %T'`: === Amanda installation complete. ===" >${TMPFILE} + +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} +if [ -f "${TMPFILE}" ]; then + rm -f "${TMPFILE}" +fi + +echo "Amanda installation log can be found in '${INSTALL_LOG}' and errors (if any) in '${INSTALL_ERR}'." +%postun +/sbin/ldconfig +%pre backup_server +TMPFILE=`mktemp /tmp/rpm-amanda.XXXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to mktemp!" 1>&2 + exit 1 +fi + +LOGDIR="%{LOGDIR}" +INSTALL_LOG="${LOGDIR}/install.log" +INSTALL_ERR="${LOGDIR}/install.err" + +echo "`date +'%b %e %Y %T'`: Preparing to install: %{amanda_version_info}" >${TMPFILE} + +# Check for the 'amanda' user +echo "`date +'%b %e %Y %T'`: Checking for '%{amanda_user}' user..." >>${TMPFILE} +if [ "`id -u %{amanda_user} > /dev/null 2>&1 && echo 0 || echo 1`" != "0" ] ; then + useradd -c "Amanda" -M -g %{amanda_group} -d %{AMANDAHOMEDIR} -s /bin/sh %{amanda_user} + if [ %{dist} = "SuSE" ]; then + PASSWD_EXIT=$? + else + # Lock the amanda account until admin sets password + passwd -l %{amanda_user} >>/dev/null + PASSWD_EXIT=$? + fi + if [ ${PASSWD_EXIT} -eq 0 ] ; then + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The '%{amanda_user}; user account has been successfully created." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Furthermore, the account has been automatically locked for you" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: for security purposes. Once a password for the '%{amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: account has been set, the user can be unlocked by issuing" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the following command as root.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: # passwd -u %{amanda_user}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: If this is not a new installation of Amanda and you have" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: pre-existing Amanda configurations in %{SYSCONFDIR}/amanda" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: you should ensure that 'dumpuser' is set to '%{amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: in those configurations. Additionally, you should ensure" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: that %{AMANDAHOMEDIR}/.amandahosts on your client systems" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: is properly configured to allow connections for the user" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: '%{amanda_user}'." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 + else + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! The '%{amanda_user}' user account for this system has been !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! created, however the user has no password set. For !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! security purposes this account is normally locked !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! after creation. Unfortunately, when locking this !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! account an error occurred. To ensure the security !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! of your system you should set a password for the !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user account '%{amanda_user}' immediately! To set such a !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! password, please issue the following command.: !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! # passwd %{amanda_user} !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + PASSWD_OK=1 + fi +else + # log information about 'amanda' user parameters + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The Amanda backup software is configured to operate as the" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user '%{amanda_user}'. This user exists on your system and has not" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: been modified. To ensure that Amanda functions properly," >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: please see that the following parameters are set for that" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: SHELL: /bin/sh" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: HOME: %{AMANDAHOMEDIR}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Default group: %{amanda_group}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Verifying %{amanda_user} parameters :" >>${TMPFILE} + + if [ "`id -gn %{amanda_user}`" != "disk" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' is not part of the disk group,Pl !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! make sure it is corrected before start using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified group name of user 'amandabackup'" >>${TMPFILE} + fi + + if [ "`grep ^%{amanda_user} /etc/passwd|cut -d: -f7`" != "/bin/sh" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' default shell should be set to !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! /bin/sh, pl correct before start using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified Default shell for user 'amandabackup'" >>${TMPFILE} + fi + + if [ "`grep ^%{amanda_user} /etc/passwd|cut -d: -f6`" != "%{AMANDAHOMEDIR}" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' home directory should be set to !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! %{AMANDAHOMEDIR} Pl correct before using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified Default home directory for user amandabackup" >>${TMPFILE} + fi + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 +fi +if [ -d %{AMANDAHOMEDIR} ] ; then + echo -n "`date +'%b %e %Y %T'`: Checking ownership of '%{AMANDAHOMEDIR}'... " >>${TMPFILE} + if [ "`ls -dl %{AMANDAHOMEDIR} | awk '//{split($_,x); print x[3]}'`" = "%{amanda_user}" ] && \ + [ "`ls -dl %{AMANDAHOMEDIR} | awk '//{split($_,x); print x[4]}'`" = "%{amanda_group}" ] ; then + echo "correct." >>${TMPFILE} + VARLIB_OK=0 + else + echo "incorrect!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Please ensure that the directory '%{AMANDAHOMEDIR}' is owned by" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the user '%{amanda_user}' and group '%{amanda_group}'." >>${TMPFILE} + VARLIB_OK=1 + fi +else + VARLIB_OK=0 +fi +echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + +if [ ! -e ${LOGDIR} ] ; then + # create log directory + mkdir -m 0750 ${LOGDIR} >>${TMPFILE} 2>&1 + chown %{amanda_user}:%{amanda_group} ${LOGDIR} >>${TMPFILE} 2>&1 +elif [ ! -d ${LOGDIR} ] ; then + mv ${LOGDIR} ${LOGDIR}.rpmsave >>${TMPFILE} 2>&1 + mkdir -m 0750 ${LOGDIR} >>${TMPFILE} 2>&1 + chown %{amanda_user}:%{amanda_group} ${LOGDIR} >>${TMPFILE} 2>&1 + mv ${LOGDIR}.rpmsave ${LOGDIR}/ >>${TMPFILE} 2>&1 +fi +if [ ${PASSWD_OK} -eq 1 ] || [ ${VARLIB_OK} -eq 1 ] ; then + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} + echo "Please review '${INSTALL_ERR}' to correct errors which have prevented the Amanda installaton." >&2 + echo "Amanda installation log can be found in '${INSTALL_LOG}' and errors (if any) in '${INSTALL_ERR}'." + exit 1 +else + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi + +echo "`date +'%b %e %Y %T'`: === Amanda backup server installation started. ===" >${TMPFILE} + +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} +if [ -f "${TMPFILE}" ]; then + rm -f "${TMPFILE}" +fi +%post backup_server +TMPFILE=`mktemp /tmp/rpm-amanda.XXXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to mktemp!" 1>&2 + exit 1 +fi +LOGDIR="%{LOGDIR}" +INSTALL_LOG="${LOGDIR}/install.log" +INSTALL_ERR="${LOGDIR}/install.err" + +echo -n "`date +'%b %e %Y %T'`: Updating system library cache..." >${TMPFILE} +/sbin/ldconfig +echo "done." >>${TMPFILE} +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +if [ -e /etc/xinetd.d ] && [ -d /etc/xinetd.d ] ; then + if [ ! -f /etc/xinetd.d/amandaserver ] ; then + cp %{AMANDAHOMEDIR}/example/xinetd.amandaserver /etc/xinetd.d/amandaserver + chmod 0644 /etc/xinetd.d/amandaserver >>${TMPFILE} 2>&1 + if [ -f /etc/xinetd.d/amandaclient ] ; then + rm /etc/xinetd.d/amandaclient + fi + + echo -n "`date +'%b %e %Y %T'`: Reloading xinetd configuration..." >${TMPFILE} + if [ "%{xinetd_reload}" == "reload" ] ; then + /etc/init.d/xinetd %{xinetd_reload} >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -ne 0 ] ; then + echo -n "reload failed. Attempting restart..." >>${TMPFILE} + /etc/init.d/xinetd restart >>${TMPFILE} 2>&1 + ret_val=$? + fi + else + /etc/init.d/xinetd %{xinetd_reload} >>${TMPFILE} 2>&1 + ret_val=$? + fi + if [ ${ret_val} -eq 0 ] ; then + echo "success." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + else + echo "failed. Please check your system logs." >>${TMPFILE} + cat ${TMPFILE} 1>&2 + cat ${TMPFILE} >>${INSTALL_ERR} + fi + fi +fi + +echo "`date +'%b %e %Y %T'`: Installing '%{LOCALSTATEDIR}/amanda/amandates'." >${TMPFILE} +ret_val=0 +if [ ! -f %{LOCALSTATEDIR}/amanda/amandates ] ; then + touch %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: The file '%{LOCALSTATEDIR}/amanda/amandates' has been created." >>${TMPFILE} + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '%{LOCALSTATEDIR}/amanda/amandates'." >>${TMPFILE} + chown %{amanda_user}:%{amanda_group} %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + chmod 0640 %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: '%{LOCALSTATEDIR}/amanda/amandates' Installation successful." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +else + echo "`date +'%b %e %Y %T'`: '%{LOCALSTATEDIR}/amanda/amandates' Installation failed." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} +fi + +# Install .amandahosts to server +echo "`date +'%b %e %Y %T'`: Checking '%{AMANDAHOMEDIR}/.amandahosts' file." >${TMPFILE} +if [ ! -f %{AMANDAHOMEDIR}/.amandahosts ] ; then + touch %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +fi +for host in localhost localhost.localdomain ; do + if [ -z "`grep \"^${host}[[:blank:]]\+root[[:blank:]]\+amindexd[[:blank:]]\+amidxtaped\" %{AMANDAHOMEDIR}/.amandahosts`" ] ; then + echo "${host} root amindexd amidxtaped" >>%{AMANDAHOMEDIR}/.amandahosts + fi + if [ -z "`grep \"^${host}[[:blank:]]\+%{amanda_user}[[:blank:]]\+amdump\" %{AMANDAHOMEDIR}/.amandahosts`" ] ; then + echo "${host} %{amanda_user} amdump" >>%{AMANDAHOMEDIR}/.amandahosts + fi +done +chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +chmod 0600 %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# Install amanda client configuration file +echo "`date +'%b %e %Y %T'`: Checking '%{SYSCONFDIR}/amanda/amanda-client.conf' file." >${TMPFILE} +if [ ! -f %{SYSCONFDIR}/amanda/amanda-client.conf ] ; then + cp %{AMANDAHOMEDIR}/example/amanda-client.conf %{SYSCONFDIR}/amanda/amanda-client.conf >>${TMPFILE} 2>&1 +fi +chown %{amanda_user}:%{amanda_group} %{SYSCONFDIR}/amanda/amanda-client.conf >>${TMPFILE} 2>&1 +chmod 0600 %{SYSCONFDIR}/amanda/amanda-client.conf >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# install am_passphrase file to server +echo "`date +'%b %e %Y %T'`: Checking '%{AMANDAHOMEDIR}/.am_passphrase' file." >${TMPFILE} +if [ ! -f %{AMANDAHOMEDIR}/.am_passphrase ] ; then + echo "`date +'%b %e %Y %T'`: Create '%{AMANDAHOMEDIR}/.am_passphrase' file." >${TMPFILE} + touch %{AMANDAHOMEDIR}/.am_passphrase >>${TMPFILE} 2>&1 + phrase=`echo "amandabackup" | md5sum | awk '{print $1}'` + echo ${phrase} >>%{AMANDAHOMEDIR}/.am_passphrase + + chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.am_passphrase >>${TMPFILE} 2>&1 + chmod 0700 %{AMANDAHOMEDIR}/.am_passphrase >>${TMPFILE} 2>&1 +fi +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# Install .gnupg directory +echo "`date +'%b %e %Y %T'`: Installing '%{AMANDAHOMEDIR}/.gnupg'." >${TMPFILE} +ret_val=0 +if [ ! -d %{AMANDAHOMEDIR}/.gnupg ] ; then + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' will be created." >>${TMPFILE} + mkdir %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: The directory '%{AMANDAHOMEDIR}/.gnupg' created successfully." >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: The directory '%{AMANDAHOMEDIR}/.gnupg' creation failed." >>${TMPFILE} + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '%{AMANDAHOMEDIR}/.gnupg'." >>${TMPFILE} + chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + chmod 700 %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' Installation successful." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +else + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' Installation failed." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} +fi + +# SSH RSA key generation on server for amdump +KEYDIR="%{AMANDAHOMEDIR}/.ssh" +KEYFILE="id_rsa_amdump" +COMMENT="%{amanda_user}@server" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.rpmsave'." >${TMPFILE} + mv ${KEYDIR} ${KEYDIR}.rpmsave >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." >${TMPFILE} + mkdir ${KEYDIR} >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" >${TMPFILE} + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '${KEYDIR}' and '${KEYDIR}/${KEYFILE}*'" >${TMPFILE} +chown %{amanda_user}:%{amanda_group} ${KEYDIR} ${KEYDIR}/${KEYFILE}* >>${TMPFILE} 2>&1 +chmod 0750 ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0600 ${KEYDIR}/${KEYFILE}* >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# SSH RSA key generation on client for amrecover +KEYDIR="%{AMANDAHOMEDIR}/.ssh" +KEYFILE="id_rsa_amrecover" +COMMENT="root@client" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.rpmsave'." >${TMPFILE} + mv ${KEYDIR} ${KEYDIR}.rpmsave >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." >${TMPFILE} + mkdir ${KEYDIR} >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" >${TMPFILE} + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '${KEYDIR}'" >${TMPFILE} +chown %{amanda_user}:%{amanda_group} ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0750 ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0600 ${KEYDIR}/${KEYFILE}* >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# environment variables (~amandabackup/.profile) +echo "`date +'%b %e %Y %T'`: Checking for '%{AMANDAHOMEDIR}/.profile' and ensuring correct environment." >${TMPFILE} +if [ ! -f %{AMANDAHOMEDIR}/.profile ] ; then + touch %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +fi +if [ -z "`grep PATH %{AMANDAHOMEDIR}/.profile | grep '%{SBINDIR}'`" ] ; then + echo "export PATH=\"\$PATH:%{SBINDIR}\"" >>%{AMANDAHOMEDIR}/.profile 2>>${TMPFILE} +fi +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '%{AMANDAHOMEDIR}/.profile'" >${TMPFILE} +chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +chmod 0640 %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +echo "`date +'%b %e %Y %T'`: Sending anonymous distribution and version information to Zmanda" >> ${INSTALL_LOG} +if [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -o /dev/null -O - --timeout=5 http://www.zmanda.com/amanda-tips.php\?version=%{amanda_version}\&os=%{disttag}%{distver}\&type=server +fi + +echo "`date +'%b %e %Y %T'`: === Amanda backup server installation complete. ===" >${TMPFILE} + +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +if [ -f "${TMPFILE}" ]; then + rm -f "${TMPFILE}" >>${TMPFILE} 2>&1 +fi + +echo "Amanda installation log can be found in '${INSTALL_LOG}' and errors (if any) in '${INSTALL_ERR}'." +%postun backup_server +/sbin/ldconfig +%pre backup_client +TMPFILE=`mktemp /tmp/rpm-amanda.XXXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to mktemp!" 1>&2 + exit 1 +fi +LOGDIR="%{LOGDIR}" +INSTALL_LOG="${LOGDIR}/install.log" +INSTALL_ERR="${LOGDIR}/install.err" + +echo "`date +'%b %e %Y %T'`: Preparing to install: %{amanda_version_info}" >${TMPFILE} + +# Check for the 'amanda' user +echo "`date +'%b %e %Y %T'`: Checking for '%{amanda_user}' user..." >>${TMPFILE} +if [ "`id -u %{amanda_user} > /dev/null 2>&1 && echo 0 || echo 1`" != "0" ] ; then + useradd -c "Amanda" -M -g %{amanda_group} -d %{AMANDAHOMEDIR} -s /bin/sh %{amanda_user} >>${TMPFILE} 2>&1 + if [ %{dist} = "SuSE" ]; then + PASSWD_EXIT=$? + else + # Lock the amanda account until admin sets password + passwd -l %{amanda_user} >>/dev/null + PASSWD_EXIT=$? + fi + if [ ${PASSWD_EXIT} -eq 0 ] ; then + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The '%{amanda_user}; user account has been successfully created." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Furthermore, the account has been automatically locked for you" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: for security purposes. Once a password for the '%{amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: account has been set, the user can be unlocked by issuing" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the following command as root.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: # passwd -u %{amanda_user}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: If this is not a new installation of Amanda and you have" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: pre-existing Amanda configurations in %{SYSCONFDIR}/amanda" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: you should ensure that 'dumpuser' is set to '%{amanda_user}'" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: in those configurations. Additionally, you should ensure" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: that %{AMANDAHOMEDIR}/.amandahosts on your client systems" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: is properly configured to allow connections for the user" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: '%{amanda_user}'." >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 + else + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! The '%{amanda_user}' user account for this system has been !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! created, however the user has no password set. For !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! security purposes this account is normally locked !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! after creation. Unfortunately, when locking this !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! account an error occurred. To ensure the security !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! of your system you should set a password for the !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user account '%{amanda_user}' immediately! To set such a !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! password, please issue the following command.: !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! # passwd %{amanda_user} !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + PASSWD_OK=1 + fi +else + # log information about 'amanda' user parameters + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: The Amanda backup software is configured to operate as the" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user '%{amanda_user}'. This user exists on your system and has not" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: been modified. To ensure that Amanda functions properly," >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: please see that the following parameters are set for that" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: user.:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: SHELL: /bin/sh" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: HOME: %{AMANDAHOMEDIR}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Default group: %{amanda_group}" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Verifying %{amanda_user} parameters :" >>${TMPFILE} + + if [ "`id -gn %{amanda_user}`" != "disk" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' is not part of the disk group,Pl !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! make sure it is corrected before start using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified group name of user 'amandabackup'" >>${TMPFILE} + fi + + if [ "`grep ^%{amanda_user} /etc/passwd|cut -d: -f7`" != "/bin/sh" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' default shell should be set to !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! /bin/sh, pl correct before start using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified Default shell for user 'amandabackup'" >>${TMPFILE} + fi + + if [ "`grep ^%{amanda_user} /etc/passwd|cut -d: -f6`" != "%{AMANDAHOMEDIR}" ] ; then + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! user 'amandabackup' home directory should be set to !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! %{AMANDAHOMEDIR} Pl correct before using Amanda !!!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: !!! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! !!!" >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: Verified Default home directory for user amandabackup" >>${TMPFILE} + fi + echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + PASSWD_OK=0 +fi +if [ -d %{AMANDAHOMEDIR} ] ; then + echo -n "`date +'%b %e %Y %T'`: Checking ownership of '%{AMANDAHOMEDIR}'... " >>${TMPFILE} + if [ "`ls -dl %{AMANDAHOMEDIR} | awk '//{split($_,x); print x[3]}'`" = "%{amanda_user}" ] && \ + [ "`ls -dl %{AMANDAHOMEDIR} | awk '//{split($_,x); print x[4]}'`" = "%{amanda_group}" ] ; then + echo "correct." >>${TMPFILE} + VARLIB_OK=0 + else + echo "incorrect!" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: Please ensure that the directory '%{AMANDAHOMEDIR}' is owned by" >>${TMPFILE} + echo "`date +'%b %e %Y %T'`: the user '%{amanda_user}' and group '%{amanda_group}'." >>${TMPFILE} + VARLIB_OK=1 + fi +else + VARLIB_OK=0 +fi +echo "`date +'%b %e %Y %T'`:" >>${TMPFILE} + +if [ ! -e ${LOGDIR} ] ; then + # create log directory + mkdir -m 0750 ${LOGDIR} >>${TMPFILE} 2>&1 + chown %{amanda_user}:%{amanda_group} ${LOGDIR} >>${TMPFILE} 2>&1 +elif [ ! -d ${LOGDIR} ] ; then + mv ${LOGDIR} ${LOGDIR}.rpmsave >>${TMPFILE} 2>&1 + mkdir -m 0750 ${LOGDIR} >>${TMPFILE} 2>&1 + chown %{amanda_user}:%{amanda_group} ${LOGDIR} >>${TMPFILE} 2>&1 + mv ${LOGDIR}.rpmsave ${LOGDIR}/ >>${TMPFILE} 2>&1 +fi +if [ ${PASSWD_OK} -eq 1 ] || [ ${VARLIB_OK} -eq 1 ] ; then + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} + echo "Please review '${INSTALL_ERR}' to correct errors which have prevented the Amanda installaton." >&2 + echo "Amanda installation log can be found in '${INSTALL_LOG}' and errors (if any) in '${INSTALL_ERR}'." + exit 1 +else + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi + +echo "`date +'%b %e %Y %T'`: === Amanda backup client installation started. ===" >${TMPFILE} + +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +if [ -f "${TMPFILE}" ]; then + rm -f "${TMPFILE}" +fi + +%post backup_client +TMPFILE=`mktemp /tmp/rpm-amanda.XXXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to mktemp!" 1>&2 + exit 1 +fi +LOGDIR="%{LOGDIR}" +INSTALL_LOG="${LOGDIR}/install.log" +INSTALL_ERR="${LOGDIR}/install.err" + +echo -n "`date +'%b %e %Y %T'`: Updating system library cache..." >${TMPFILE} +/sbin/ldconfig +echo "done." >>${TMPFILE} +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +if [ -e /etc/xinetd.d ] && [ -d /etc/xinetd.d ] ; then + if [ ! -f /etc/xinetd.d/amandaclient ] ; then + cp %{AMANDAHOMEDIR}/example/xinetd.amandaclient /etc/xinetd.d/amandaclient + + echo -n "`date +'%b %e %Y %T'`: Reloading xinetd configuration..." >${TMPFILE} + if [ "%{xinetd_reload}" == "reload" ] ; then + /etc/init.d/xinetd %{xinetd_reload} >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -ne 0 ] ; then + echo -n "reload failed. Attempting restart..." >>${TMPFILE} + /etc/init.d/xinetd restart >>${TMPFILE} 2>&1 + ret_val=$? + fi + else + /etc/init.d/xinetd %{xinetd_reload} >>${TMPFILE} 2>&1 + ret_val=$? + fi + if [ ${ret_val} -eq 0 ] ; then + echo "success." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + else + echo "failed. Please check your system logs." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + fi + fi +fi + +echo "`date +'%b %e %Y %T'`: Installing '%{LOCALSTATEDIR}/amanda/amandates'." >${TMPFILE} +ret_val=0 +if [ ! -f %{LOCALSTATEDIR}/amanda/amandates ] ; then + touch %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: The file '%{LOCALSTATEDIR}/amanda/amandates' has been created." >>${TMPFILE} + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '%{LOCALSTATEDIR}/amanda/amandates'." >>${TMPFILE} + chown %{amanda_user}:%{amanda_group} %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 + chmod 0640 %{LOCALSTATEDIR}/amanda/amandates >>${TMPFILE} 2>&1 +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: '%{LOCALSTATEDIR}/amanda/amandates' Installation successful." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +else + echo "`date +'%b %e %Y %T'`: '%{LOCALSTATEDIR}/amanda/amandates' Installation failed." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} +fi + +# Install .amandahosts to client +echo "`date +'%b %e %Y %T'`: Checking '%{AMANDAHOMEDIR}/.amandahosts' file." >${TMPFILE} +if [ ! -f %{AMANDAHOMEDIR}/.amandahosts ] ; then + touch %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +fi +for host in localhost localhost.localdomain ; do + if [ -z "`grep \"^${host}[[:blank:]]\+\" %{AMANDAHOMEDIR}/.amandahosts | grep \"[[:blank:]]\+%{amanda_user}[[:blank:]]\+amdump\"`" ] ; then + echo "${host} %{amanda_user} amdump" >>%{AMANDAHOMEDIR}/.amandahosts + fi +done +chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +chmod 0600 %{AMANDAHOMEDIR}/.amandahosts >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# Install amanda client configuration file +echo "`date +'%b %e %Y %T'`: Checking '%{SYSCONFDIR}/amanda/amanda-client.conf' file." >${TMPFILE} +if [ ! -f %{SYSCONFDIR}/amanda/amanda-client.conf ] ; then + cp %{AMANDAHOMEDIR}/example/amanda-client.conf %{SYSCONFDIR}/amanda/amanda-client.conf >>${TMPFILE} 2>&1 +fi +chown %{amanda_user}:%{amanda_group} %{SYSCONFDIR}/amanda/amanda-client.conf >>${TMPFILE} 2>&1 +chmod 0600 %{SYSCONFDIR}/amanda/amanda-client.conf >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# Install .gnupg directory +echo "`date +'%b %e %Y %T'`: Installing '%{AMANDAHOMEDIR}/.gnupg'." >${TMPFILE} +ret_val=0 +if [ ! -d %{AMANDAHOMEDIR}/.gnupg ] ; then + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' will be created." >>${TMPFILE} + mkdir %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: The directory '%{AMANDAHOMEDIR}/.gnupg' created successfully." >>${TMPFILE} + else + echo "`date +'%b %e %Y %T'`: The directory '%{AMANDAHOMEDIR}/.gnupg' creation failed." >>${TMPFILE} + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: Ensuring correct permissions for '%{AMANDAHOMEDIR}/.gnupg'." >>${TMPFILE} + chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + if [ ${ret_val} -eq 0 ]; then + chmod 700 %{AMANDAHOMEDIR}/.gnupg >>${TMPFILE} 2>&1 + ret_val=$? + fi +fi +if [ ${ret_val} -eq 0 ]; then + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' Installation successful." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +else + echo "`date +'%b %e %Y %T'`: '%{AMANDAHOMEDIR}/.gnupg' Installation failed." >>${TMPFILE} + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_ERR} +fi + +# SSH RSA key generation on client for amrecover +KEYDIR="%{AMANDAHOMEDIR}/.ssh" +KEYFILE="id_rsa_amrecover" +COMMENT="root@client" +if [ ! -d ${KEYDIR} ] ; then + if [ -f ${KEYDIR} ] ; then + echo "`date +'%b %e %Y %T'`: Directory '${KEYDIR}' exists as a file. Renaming to '${KEYDIR}.rpmsave'." >${TMPFILE} + mv ${KEYDIR} ${KEYDIR}.rpmsave >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} + fi + echo "`date +'%b %e %Y %T'`: Creating directory '${KEYDIR}'." >${TMPFILE} + mkdir ${KEYDIR} >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +if [ ! -f ${KEYDIR}/${KEYFILE} ] ; then + echo "`date +'%b %e %Y %T'`: Creating ssh RSA key in '${KEYDIR}/${KEYFILE}'" >${TMPFILE} + ssh-keygen -q -C $COMMENT -t rsa -f ${KEYDIR}/${KEYFILE} -N '' >>${TMPFILE} 2>&1 + cat ${TMPFILE} + cat ${TMPFILE} >>${INSTALL_LOG} +fi +echo "`date +'%b %e %Y %T'`: Setting permissions for '${KEYDIR}' and '${KEYDIR}/${KEYFILE}*'" >${TMPFILE} +chown %{amanda_user}:%{amanda_group} ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0750 ${KEYDIR} >>${TMPFILE} 2>&1 +chmod 0600 ${KEYDIR}/${KEYFILE}* >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +# environment variables (~amandabackup/.profile) +echo "`date +'%b %e %Y %T'`: Checking for '%{AMANDAHOMEDIR}/.profile' and ensuring correct environment." >${TMPFILE} +if [ ! -f %{AMANDAHOMEDIR}/.profile ] ; then + touch %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +fi +if [ -z "`grep PATH %{AMANDAHOMEDIR}/.profile | grep '%{SBINDIR}'`" ] ; then + echo "export PATH=\"\$PATH:%{SBINDIR}\"" >>%{AMANDAHOMEDIR}/.profile 2>>${TMPFILE} +fi +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} +echo "`date +'%b %e %Y %T'`: Setting ownership and permissions for '%{AMANDAHOMEDIR}/.profile'" >${TMPFILE} +chown %{amanda_user}:%{amanda_group} %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +chmod 0640 %{AMANDAHOMEDIR}/.profile >>${TMPFILE} 2>&1 +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +echo "`date +'%b %e %Y %T'`: Sending anonymous distribution and version information to Zmanda" >> ${INSTALL_LOG} +if [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -o /dev/null -O - --timeout=5 http://www.zmanda.com/amanda-tips.php\?version=%{amanda_version}\&os=%{disttag}%{distver}\&type=client +fi + +echo "`date +'%b %e %Y %T'`: === Amanda backup client installation complete. ===" >>${TMPFILE} +cat ${TMPFILE} +cat ${TMPFILE} >>${INSTALL_LOG} + +if [ -f "${TMPFILE}" ]; then + rm -f "${TMPFILE}" +fi + +echo "Amanda installation log can be found in '${INSTALL_LOG}' and errors (if any) in '${INSTALL_ERR}'." +%postun backup_client +/sbin/ldconfig + +# --- Files to install --- +# Notes: Do not use wildcards on directories not wholly owned by amanda. An +# uninstall of the software will attempt to delete whatever matches here. +%files backup_client +%defattr(0755,%{amanda_user},%{amanda_group}) +%{SYSCONFDIR}/amanda +%{AMANDAHOMEDIR} +%{AMLIBEXECDIR} +%{AMLIBDIR} +%{AMLIBEXECDIR}/amanda-sh-lib.sh +%{LOCALSTATEDIR}/amanda +%defattr(4750,root,disk) +%{AMLIBEXECDIR}/calcsize +%{AMLIBEXECDIR}/killpgrp +%{AMLIBEXECDIR}/rundump +%{AMLIBEXECDIR}/runtar +%defattr(0750,%{amanda_user},%{amanda_group}) +%{LOGDIR} +%{SBINDIR}/amaespipe +%{SBINDIR}/amcryp* +%{SBINDIR}/amgpgcrypt +%{SBINDIR}/amoldrecover +%{SBINDIR}/amrecover +%defattr(0644,%{amanda_user},%{amanda_group}) +%docdir %{MANDIR} +%{MANDIR}/man5/amanda.conf.5.gz +%{MANDIR}/man5/amanda-client.conf.5.gz +%{MANDIR}/man8/amanda.8.gz +%{MANDIR}/man8/amcheckdump.8.gz +%{MANDIR}/man8/amrecover.8.gz +%{AMLIBEXECDIR}/amcat.awk +%{AMANDAHOMEDIR}/amanda-release +%{AMANDAHOMEDIR}/example/xinetd.amandaclient +%{AMANDAHOMEDIR}/example/amanda-client.conf + +%files backup_server +%defattr(0755,%{amanda_user},%{amanda_group}) +%{SYSCONFDIR}/amanda +%{AMLIBEXECDIR} +%{AMLIBDIR} +%{PERLSITELIB}/Amanda +%{PERLSITELIB}/auto/Amanda +%{AMANDAHOMEDIR} +%{LOCALSTATEDIR}/amanda +%{SBINDIR}/amaddclient +%{SBINDIR}/amadmin +%{SBINDIR}/amcheckdb +%{SBINDIR}/amcheckdump +%{SBINDIR}/amcleanup +%{SBINDIR}/amdd +%{SBINDIR}/amdevcheck +%{SBINDIR}/amdump +%{SBINDIR}/amfetchdump +%{SBINDIR}/amflush +%{SBINDIR}/amgetconf +%{SBINDIR}/amlabel +%{SBINDIR}/ammt +%{SBINDIR}/amoverview +%{SBINDIR}/amplot +%{SBINDIR}/amreport +%{SBINDIR}/amrestore +%{SBINDIR}/amrmtape +%{SBINDIR}/amserverconfig +%{SBINDIR}/amstatus +%{SBINDIR}/amtape +%{SBINDIR}/amtapetype +%{SBINDIR}/amtoc +%{SBINDIR}/amverify +%{SBINDIR}/amverifyrun +%{AMLIBEXECDIR}/amanda-sh-lib.sh +%defattr(4750,root,disk) +%{AMLIBEXECDIR}/calcsize +%{AMLIBEXECDIR}/killpgrp +%{AMLIBEXECDIR}/rundump +%{AMLIBEXECDIR}/runtar +%{AMLIBEXECDIR}/dumper +%{AMLIBEXECDIR}/planner +%{SBINDIR}/amcheck +%defattr(0750,%{amanda_user},%{amanda_group}) +%{LOGDIR} +%{SBINDIR}/amaespipe +%{SBINDIR}/amcrypt +%{SBINDIR}/amcrypt-ossl +%{SBINDIR}/amcrypt-ossl-asym +%{SBINDIR}/amcryptsimple +%{SBINDIR}/amgpgcrypt +%{SBINDIR}/amoldrecover +%{SBINDIR}/amrecover +%defattr(0644,%{amanda_user},%{amanda_group}) +%{AMLIBEXECDIR}/amcat.awk +%{AMLIBEXECDIR}/amplot.awk +%{AMLIBEXECDIR}/amplot.g +%{AMLIBEXECDIR}/amplot.gp +%docdir %{MANDIR} +%{MANDIR}/man5/amanda.conf.5.gz +%{MANDIR}/man5/amanda-client.conf.5.gz +%{MANDIR}/man8/amaddclient.8.gz +%{MANDIR}/man8/amadmin.8.gz +%{MANDIR}/man8/amanda.8.gz +%{MANDIR}/man8/amcheck.8.gz +%{MANDIR}/man8/amcheckdb.8.gz +%{MANDIR}/man8/amcheckdump.8.gz +%{MANDIR}/man8/amcleanup.8.gz +%{MANDIR}/man8/amdd.8.gz +%{MANDIR}/man8/amdump.8.gz +%{MANDIR}/man8/amfetchdump.8.gz +%{MANDIR}/man8/amflush.8.gz +%{MANDIR}/man8/amgetconf.8.gz +%{MANDIR}/man8/amlabel.8.gz +%{MANDIR}/man8/ammt.8.gz +%{MANDIR}/man8/amoverview.8.gz +%{MANDIR}/man8/amplot.8.gz +%{MANDIR}/man8/amrecover.8.gz +%{MANDIR}/man8/amreport.8.gz +%{MANDIR}/man8/amrestore.8.gz +%{MANDIR}/man8/amrmtape.8.gz +%{MANDIR}/man8/amserverconfig.8.gz +%{MANDIR}/man8/amstatus.8.gz +%{MANDIR}/man8/amtape.8.gz +%{MANDIR}/man8/amtapetype.8.gz +%{MANDIR}/man8/amtoc.8.gz +%{MANDIR}/man8/amverify.8.gz +%{MANDIR}/man8/amverifyrun.8.gz +%{MANDIR}/man8/amcrypt.8.gz +%{MANDIR}/man8/amcrypt-ossl.8.gz +%{MANDIR}/man8/amcrypt-ossl-asym.8.gz +%{MANDIR}/man8/amcryptsimple.8.gz +%{MANDIR}/man8/amgpgcrypt.8.gz +%{MANDIR}/man8/amaespipe.8.gz +%{MANDIR}/man8/amdevcheck.8.gz +%{AMANDAHOMEDIR}/amanda-release +%{AMANDAHOMEDIR}/example/amanda-client.conf +%{AMANDAHOMEDIR}/example/xinetd.amandaserver + +# --- ChangeLog + +%changelog +* Fri May 02 2008 Dan Locks +- Changed instances of ${ to %%{ where applicable +* Tue Mar 11 2008 Dan Locks +- fixed many rpmlint complaints +- added --quiet to configure statements +- moved PERLSITELIB to definitions section +* Wed Feb 13 2008 Dan Locks +- added an environment check for PKG_CONFIG_PATH +- added PKG_CONFIG_PATH conditional to handle cross comp on FC8 (environment + var is used if provided) +* Fri Feb 01 2008 Dan Locks +- Removed amplot executable and manpages from client installation +- Added amcheckdump.8 manpage +- Fixed %%{LOCALSTATEDIR}/amanda dir creation. +* Wed Jan 23 2008 Dan Locks +- Change %%{SYSCONFDIR}/amanda/amandates to %%{LOCALSTATEDIR}/amanda/amandates, + and added %%{LOCALSTATEDIR}/amanda to the files lists. +* Mon Jan 14 2008 Dan Locks +- Updates for perlified amanda, file location moves, gpg setup. +* Tue Nov 13 2007 Paddy Sreenivasan +- Added SYSCONFDIR to client rpm +- Set xinetd and amanda-client.conf configuration files as part of postinstall +* Thu Nov 8 2007 Dan Locks +- Added Linux distribution detection +* Wed Nov 7 2007 Paddy Sreenivasan +- Added amserverconfig, amaddclient, amgpgcrypt, amcryptsimple and libamdevice. +- Added amanda configuration template files +* Fri Sep 21 2007 Paddy Sreenivasan +- Remove libamserver, libamtape from client rpm +* Wed Sep 19 2007 Paddy Sreenivasan +- Added Fedora 7 +* Tue Jun 26 2007 Kevin Till +- set debug log to /var/log/amanda +* Fri Jan 12 2007 Paddy Sreenivasan +- Added label templates +* Thu Dec 07 2006 Paddy Sreenivasan +- Application API changes +* Fri Jun 16 2006 Kevin Till +- make install will install necessary example files. + No need to "cp" +* Wed Jun 07 2006 Paddy Sreenivasan - +- Added amoldrecover and amanda-client.conf man page. +* Thu Jun 01 2006 Kevin Till - +- Added amcrypt-ossl, amcrypt-ossl-asym by Ben Slusky. +* Thu May 18 2006 Paddy Sreenivasan - +- Added SLES10, RHEL3 build options. +* Tue May 09 2006 Chris Lee - +- Added amanda-release file to amandabackup home directory. +- Installation message logging cleanup. +* Thu Apr 27 2006 Paddy Sreenivasan - +- Removed dependency on tar version. +- Moved log directory creation after backup user creation. +* Wed Apr 19 2006 Chris Lee - +- Added informative message to note the location of pre- and post- +- install script logs files. +* Mon Apr 17 2006 Chris Lee - +- Reworked installation message logging and reporting. +* Fri Apr 14 2006 Chris Lee - +- Changed behavior for creating required localhost entries in the +- amandahosts file to check for these entries even when the file +- already exists. +* Wed Apr 12 2006 Chris Lee - +- Removed pre-install check for "disk" group. This group should exist +- by default on almost all modern distributions. +* Tue Apr 11 2006 Chris Lee - +- Added amandahosts entry for "localhost" without domain. +* Fri Apr 07 2006 Chris Lee - +- Changed default entries in .amandahosts to use "localdomain" instead +- of "localnet". +- Updated amanda_version and release. +* Mon Apr 03 2006 Chris Lee - +- Added example amanda.conf to files. +* Thu Mar 16 2006 Chris Lee - +- Corrected an issue with pre-install scripts wrt bug #218. +- Corrected an issue with post-install scripts and added testing .profile +- in amandabackup's home directory for setting environment variables wrt +- bug #220. +* Mon Mar 13 2006 Chris Lee - +- Corrected a syntactical error with setting ownership of amandates file +- wrt bug #216. +* Wed Mar 08 2006 Chris Lee - +- Added pre-install scripts to verify proper ownership of +- amandabackup home directory. +* Thu Feb 2 2006 Paddy Sreenivasan - +- Require xinetd. Require termcap and initscripts for Fedora and Redhat. +* Mon Jan 09 2006 Chris Lee - +- Pre/post install scripts updated: +- o Resolved an issue where an empty amandates file was installed +- even if the file already existed on the system. +- o If .amandahosts does not exist a default is now created. +- The Amanda user account has been changed to 'amandabackup' for +- additional security. +* Tue Jan 03 2006 Paddy Sreenivasan - +- Removed amandates from files list. +* Thu Dec 29 2005 Chris Lee - +- Corrected dependency for awk to "/bin/awk". +* Thu Dec 29 2005 Kevin Till - +- add man pages for amcrypt and amaespipe +* Thu Dec 29 2005 Chris Lee - +- Updated dependancy info to depend on tar >= 1.15. +- Included dependancies from top-level package in backup_client and +- backup_server packages. +- Reorganized files lists for readability (alphabetically). +- Updated backup_client files list to include some missing files per +- bug #129. +- Updated pre- and post-install to handle potential issue when +- /var/log/amanda exists and is a file rather than a directory. +- Corrected permissions for /var/log/amanda in pre-install scripts +- per bug #78 and 13 December change. +* Thu Dec 22 2005 Paddy Sreenivasan - +- Added amaespipe and amcrypt +- Added sles9 build definitions +* Tue Dec 13 2005 Chris Lee - +- Changed permissions for /var/log/amanda, removing set group id bit. +- Added /etc/amandates to backup_client package. +* Thu Dec 08 2005 Chris Lee - +- Corrected an issue with detection of existing 'amanda' user account. +- Corrected ownership of setuid executables per Bug #66. +- Moved the gnutar and noop files to the backup_client package (where +- they sould be). +- Removed amqde from files list. +- Added logging features to pre- and post-install scripts. +* Wed Dec 07 2005 Chris Lee - +- Changed a number of directory and file permissions from amanda:root +- to amanda:disk in response to Bug #57. +* Fri Dec 02 2005 Chris Lee - +- Corrected SYSCONFDIR path definition. Closes Bug #58. +* Mon Nov 28 2005 Chris Lee - +- Really fixed user creation preinstall scripts. +* Wed Nov 23 2005 Paddy Sreenivasan - +- Updated package description. +- Changed Group for packages. +* Tue Nov 22 2005 Chris Lee - +- Corrected dependancy packaging issue with amanda libraries. +- Fixed creation of amanda user on systems which it does not exist. +- Corrected Group definition for SuSE. +- Updated descriptions to include amanda-libs package. +- Updated release number to 2. +* Tue Nov 08 2005 Chris Lee - +- Permissions changes: now using user=amanda, group=disk +* Sun Oct 30 2005 Chris Lee - +- Parameters to configure options --with-user and --with-group changed +- such that when test_build is set to '1' the username of the user who +- runs rpmbuild is used for both values. If test_build is set to '0' +- then root is used for both values. +- The release field was also changed to automatically reflect the +- distribution and distribution release version for which the RPM was +- built. +* Tue Oct 18 2005 Chris Lee - +- Initial RPM SPEC file created. + diff --git a/packaging/rpm/buildpkg b/packaging/rpm/buildpkg new file mode 100755 index 0000000..6361d14 --- /dev/null +++ b/packaging/rpm/buildpkg @@ -0,0 +1,52 @@ +#!/bin/bash +# Buildpkg script for producing RPM packages. Does not require root access. + +# This is useful for debugging +set -x +# Buildbot exports some useful env variables. +# Check for $AMVER. I couldn't come up with a good way to detect it. +if [ -z $AMVER ]; then + AMVER=amanda-2.6.0p2 +fi +# Check for AMTARBALL variable. +if [ -z $AMTARBALL ]; then + AMTARBALL=$AMVER.tar.gz +fi + +# Check for AMTARBALL file, if it's not there, create it. +if [ ! -f ${AMTARBALL} ]; then + mkdir ${AMVER} + cp -Rfp * ${AMVER}/ + tar -cf ${AMTARBALL} -z ${AMVER} + rm -rf ${AMVER} +fi + +# Check for the packaging dirs. +if [ -z $AMPKGDIR ]; then + AMPKGDIR=${PWD} +fi +if [ ! -d ${AMPKGDIR} ]; then + mkdir ${AMPKGDIR} +fi +cd ${AMPKGDIR} + +if [ -d rpm ]; then + rm -rf rpm +fi +mkdir rpm +mkdir rpm/SOURCES +mkdir rpm/SRPMS +mkdir rpm/SPECS +mkdir rpm/BUILD +mkdir rpm/RPMS + +# Make a copy of the tarball with the name that rpmbuild expects +cp ${AMTARBALL} rpm/SOURCES/${AMVER}.tar.gz +cp packaging/rpm/amanda.spec rpm/SPECS/amanda.spec +# Rpmbuild requires absolute paths. annoying. If you need to change the +# default value of some rpm.spec variable, just pass extra --define options. +# this is useful for changing %amanda_release or %amanda_version +rpmbuild -ba --define "_topdir ${AMPKGDIR}/rpm" \ + ${AMPKGDIR}/rpm/SPECS/amanda.spec +cp rpm/RPMS/*/*.rpm . || exit 1 +cp rpm/SRPMS/*.rpm . || exit 1 diff --git a/perl/Amanda/Changer.pm b/perl/Amanda/Changer.pm new file mode 100644 index 0000000..bfad1bf --- /dev/null +++ b/perl/Amanda/Changer.pm @@ -0,0 +1,349 @@ +# Copyright (c) 2006 Zmanda Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 +# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + +package Amanda::Changer; + +use Carp; +use POSIX (); +use Exporter; +@ISA = qw( Exporter ); + +@EXPORT_OK = qw( + reset clean eject label + query loadslot find scan +); + +use Amanda::Paths; +use Amanda::Util; +use Amanda::Device qw( :constants ); +use Amanda::Config qw( :getconf ); + +=head1 NAME + +Amanda::Changer -- interface to changer scripts + +=head1 SYNOPSIS + + use Amanda::Changer; + + my ($error, $slot) = Amanda::Changer::reset(); + + my ($nslots, $curslot, $backwards, $searchable) = Amanda::Changer::query(); + + my ($tpslot, $tpdevice) = Amanda::Changer::find("TAPE018"); + + sub slot_callback { + my ($slot, $device, $error) = @_; + if (!$error) print "Slot $slot: $device\n"; + return 0; + } + Amanda::Changer::scan(\&slot_callback); + +=head1 API STATUS + +Stable + +=head1 FUNCTIONS + +All of these functions return an array of values, beginning with +C<$error>, and containing any other results appropriate to the +operation. + +The functions C in the event of a serious error (problems +running the changer script, or an exit status of 2 or higher). +"Benign" errors, corresponding to an exit status of 1 or a slot named +"", result in the return of a single-element array containing +the error message. Error-handling for calls can be written + +C<$error> and C<$slot>. The first is false unless a "benign" +error, such as a positioning error, has occurred, in which case it +contains the message from the changer script, and the other results +are undefined. C<$slot> is the first word returned from the changer +script, and is usually a number, but occasionally a string such as +"". + +=over + +=item reset + + my ($error, $slot) = reset(); + +Resets the tape changer, if supported, by calling + + $tpchanger -reset + +=item clean + + my ($error, $slot) = clean(); + +Triggers a cleaning cycle, if supported, by calling + + $tpchanger -clean + +=item eject + + my ($error, $slot) = eject(); + +Ejects the tape in the current slot, if supported, by calling + + $tpchanger -eject + +=item label + + my ($error) = label($label); + +Inform the changer that the tape in the current slot is labeled C<$label>. Calls + + $tpchanger -label $label + +=item query + + my ($error, $slot, $nslots, $backwards, $searchable) = query(); + +Query the changer to determine the current slot (C<$slot>), the +number of slots (C<$nslots>), whether it can move backward through tapes +(C<$backwards>), and whether it is searchable (that is, has a barcode +reader; C<$searchable>). A changer which cannot move backward through +tapes is also known as a gravity feeder. + +This function runs + + $tpchanger -info + +=item loadslot + + my ($error, $slot, $device) = loadslot($desired_slot); + +Load the tape in the given slot, returning its slot and device. +C<$desired_slot> can be a numeric slot number or one of the symbolic +names defined by the changer API, e.g., "next", "current", or "first". + + $tpchanger -slot $slot + +=item find + + my ($error, $tpslot, $tpdevice) = Amanda::Changer::find($label); + +Search the changer for a tape with the given label, returning with +C<$tpslot = ""> if the given label is not found. + +If the changer is searchable, this function calls + + $tpchanger -search $label + +Otherwise it scans all slots in order, beginning with the current slot, +until it finds one with a label equal to C<$label> or exhausts all +slots. Note that it is considered a fatal error if the label is not +found. + +=item scan + + my ($error) = Amanda::Changer::scan(\&slot_callback); + +Call C for all slots, beginning with the current slot, +until C returns a nonzero value or all slots are +exhausted. C gets three arguments: a slot number, a +device name for that slot, and a boolean value which is true if the +changer successfully loaded the slot. + +=back + +=cut + +sub reset { + my ($error, $slot, $rest) = run_tpchanger("-reset"); + return ($error) if $error; + + return (0, $slot); +} + +sub clean { + my ($error, $slot, $rest) = run_tpchanger("-clean"); + return ($error) if $error; + + return (0, $slot); +} + +sub eject { + my ($error, $slot, $rest) = run_tpchanger("-eject"); + return ($error) if $error; + + return (0, $slot); +} + +sub label { + my ($label) = @_; + + my ($error, $slot, $rest) = run_tpchanger("-label", $label); + return ($error) if $error; + + return (0); +} + +sub query { + my ($error, $slot, $rest) = run_tpchanger("-info"); + return ($error) if $error; + + # old, unsearchable changers don't return the third result, so it's optional in the regex + $rest =~ /(\d+) (\d+) ?(\d+)?/ or croak("Malformed response from changer -seek: $rest"); + + # return array: error, nslots, curslot, backwards, searchable + return (0, $slot, $1, $2, $3?1:0); +} + +sub loadslot { + my ($desired_slot) = @_; + + my ($error, $slot, $rest) = run_tpchanger("-slot", $desired_slot); + return ($error) if $error; + + return (0, $slot, $rest); +} + +sub find { + my ($label) = @_; + + my ($error, $curslot, $nslots, $backwards, $searchable) = query(); + return ($error) if $error; + + if ($searchable) { + # search using the barcode reader, etc. + my ($error, $slot, $rest) = run_tpchanger("-search", $label); + return ($error) if $error; + return ($error, $slot, $rest); + } else { + # search manually, starting with "current" + my $slotstr = "current"; + for (my $checked = 0; $checked < $nslots; $checked++) { + my ($error, $slot, $rest) = run_tpchanger("-slot", $slotstr); + $slotstr = "next"; + + # ignore "benign" errors + next if $error; + + my $device = Amanda::Device->new($rest); + next if (!$device); + next if ($device->read_label() != $READ_LABEL_STATUS_SUCESS); + + # we found it! + if ($device->{'volume_label'} eq $label) { + return (0, $slot, $rest); + } + } + + croak("Label $label not found in any slot"); + } +} + +sub scan { + my ($slot_callback) = @_; + + my ($error, $curslot, $nslots, $backwards, $searchable) = query(); + return ($error) if $error; + + my $slotstr = "current"; + my $done = 0; + for (my $checked = 0; $checked < $nslots; $checked++) { + my ($error, $slot, $rest) = run_tpchanger("-slot", $slotstr); + $slotstr = "next"; + + if ($error) { + $done = $slot_callback->(undef, undef, $error); + } else { + $done = $slot_callback->($slot, $rest, 0); + } + + last if $done; + } + + return (0); +} + +# Internal-use function to actually invoke a changer script and parse +# its output. If the script's exit status is neither 0 nor 1, or if an error +# occurs running the script, then run_tpchanger croaks with the error message. +# +# @params @args: command-line arguments to follow the name of the changer +# @returns: array ($error, $slot, $rest), where $error is an error message if +# a benign error occurred, or 0 if no error occurred +sub run_tpchanger { + my @args = @_; + + # get the tape changer and extend it to a full path + my $tapechanger = getconf($CNF_TPCHANGER); + if ($tapechanger !~ qr(^/)) { + $tapechanger = "$amlibexecdir/$tapechanger"; + } + + my $pid = open(my $child, "-|"); + if (!defined($pid)) { + croak("Can't fork to run changer script: $!"); + } + + if (!$pid) { + # child + + # cd into the config dir, if one exists + # TODO: construct a "fake" config dir including any "-o" overrides + my $config_dir = Amanda::Config::get_config_dir(); + if ($config_dir) { + if (!chdir($config_dir)) { + print " Could not chdir to '$config_dir'\n"; + exit(2); + } + } + + %ENV = Amanda::Util::safe_env(); + + exec { $tapechanger } $tapechanger, @args or + print " Could not exec $tapechanger: $!\n"; + exit 2; + } + + # parent + my @child_output = <$child>; + + # close the child and get its exit status + my $child_exit = 0; + if (!close($child)) { + if ($!) { + croak("Error running changer script: $!"); + } else { + $child_exit = $?; + } + } + + # parse the response + croak("Malformed output from changer script -- no output") + if (@child_output < 1); + croak("Malformed output from changer script -- too many lines") + if (@child_output > 1); + croak("Malformed output from changer script: '$child_output[0]'") + if ($child_output[0] !~ /\s*([^\s]+)\s+(.+)?/); + my ($slot, $rest) = ($1, $2); + + if ($child_exit == 0) { + return (0, $slot, $rest); + } elsif (POSIX::WIFEXITED($child_exit) && POSIX::WEXITSTATUS($child_exit) == 1) { + return ($rest); # non-fatal error + } else { + croak("Fatal error from changer script: $rest"); + } +} + +1; diff --git a/perl/Amanda/Cmdline.c b/perl/Amanda/Cmdline.c new file mode 100644 index 0000000..d23c52a --- /dev/null +++ b/perl/Amanda/Cmdline.c @@ -0,0 +1,2478 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.33 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIGPERL +#define SWIG_CASTRANK_MODE +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + + +/* ----------------------------------------------------------------------------- + * swigrun.swg + * + * This file contains generic CAPI SWIG runtime support for pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +/* This should only be incremented when either the layout of swig_type_info changes, + or for whatever reason, the runtime changes incompatibly */ +#define SWIG_RUNTIME_VERSION "3" + +/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ +#ifdef SWIG_TYPE_TABLE +# define SWIG_QUOTE_STRING(x) #x +# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) +# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) +#else +# define SWIG_TYPE_TABLE_NAME +#endif + +/* + You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for + creating a static or dynamic library from the swig runtime code. + In 99.9% of the cases, swig just needs to declare them as 'static'. + + But only do this if is strictly necessary, ie, if you have problems + with your compiler or so. +*/ + +#ifndef SWIGRUNTIME +# define SWIGRUNTIME SWIGINTERN +#endif + +#ifndef SWIGRUNTIMEINLINE +# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE +#endif + +/* Generic buffer size */ +#ifndef SWIG_BUFFER_SIZE +# define SWIG_BUFFER_SIZE 1024 +#endif + +/* Flags for pointer conversions */ +#define SWIG_POINTER_DISOWN 0x1 + +/* Flags for new pointer objects */ +#define SWIG_POINTER_OWN 0x1 + + +/* + Flags/methods for returning states. + + The swig conversion methods, as ConvertPtr, return and integer + that tells if the conversion was successful or not. And if not, + an error code can be returned (see swigerrors.swg for the codes). + + Use the following macros/flags to set or process the returning + states. + + In old swig versions, you usually write code as: + + if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { + // success code + } else { + //fail code + } + + Now you can be more explicit as: + + int res = SWIG_ConvertPtr(obj,vptr,ty.flags); + if (SWIG_IsOK(res)) { + // success code + } else { + // fail code + } + + that seems to be the same, but now you can also do + + Type *ptr; + int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); + if (SWIG_IsOK(res)) { + // success code + if (SWIG_IsNewObj(res) { + ... + delete *ptr; + } else { + ... + } + } else { + // fail code + } + + I.e., now SWIG_ConvertPtr can return new objects and you can + identify the case and take care of the deallocation. Of course that + requires also to SWIG_ConvertPtr to return new result values, as + + int SWIG_ConvertPtr(obj, ptr,...) { + if () { + if () { + *ptr = ; + return SWIG_NEWOBJ; + } else { + *ptr = ; + return SWIG_OLDOBJ; + } + } else { + return SWIG_BADOBJ; + } + } + + Of course, returning the plain '0(success)/-1(fail)' still works, but you can be + more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the + swig errors code. + + Finally, if the SWIG_CASTRANK_MODE is enabled, the result code + allows to return the 'cast rank', for example, if you have this + + int food(double) + int fooi(int); + + and you call + + food(1) // cast rank '1' (1 -> 1.0) + fooi(1) // cast rank '0' + + just use the SWIG_AddCast()/SWIG_CheckState() + + + */ +#define SWIG_OK (0) +#define SWIG_ERROR (-1) +#define SWIG_IsOK(r) (r >= 0) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) + +/* The CastRankLimit says how many bits are used for the cast rank */ +#define SWIG_CASTRANKLIMIT (1 << 8) +/* The NewMask denotes the object was created (using new/malloc) */ +#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) +/* The TmpMask is for in/out typemaps that use temporal objects */ +#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) +/* Simple returning values */ +#define SWIG_BADOBJ (SWIG_ERROR) +#define SWIG_OLDOBJ (SWIG_OK) +#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) +#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) +/* Check, add and del mask methods */ +#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) +#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) +#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) +#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) +#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) +#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) + + +/* Cast-Rank Mode */ +#if defined(SWIG_CASTRANK_MODE) +# ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +# endif +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# define SWIG_MAXCASTRANK (2) +# endif +# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) +# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) +SWIGINTERNINLINE int SWIG_AddCast(int r) { + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +} +SWIGINTERNINLINE int SWIG_CheckState(int r) { + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +} +#else /* no cast-rank mode */ +# define SWIG_AddCast +# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) +#endif + + + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +/* Structure to store inforomation on one type */ +typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ +} swig_type_info; + +/* Structure to store a type and conversion function used for casting */ +typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ +} swig_cast_info; + +/* Structure used to store module information + * Each module generates one structure like this, and the runtime collects + * all of these structures and stores them in a circularly linked list.*/ +typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ +} swig_module_info; + +/* + Compare two type names skipping the space characters, therefore + "char*" == "char *" and "Class" == "Class", etc. + + Return 0 when the two name types are equivalent, as in + strncmp, but skipping ' '. +*/ +SWIGRUNTIME int +SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) ++f1; + while ((*f2 == ' ') && (f2 != l2)) ++f2; + if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + } + return (int)((l1 - f1) - (l2 - f2)); +} + +/* + Check type equivalence in a name list like ||... + Return 0 if not equal, 1 if equal +*/ +SWIGRUNTIME int +SWIG_TypeEquiv(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + +/* + Check type equivalence in a name list like ||... + Return 0 if equal, -1 if nb < tb, 1 if nb > tb +*/ +SWIGRUNTIME int +SWIG_TypeCompare(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + + +/* think of this as a c++ template<> or a scheme macro */ +#define SWIG_TypeCheck_Template(comparison, ty) \ + if (ty) { \ + swig_cast_info *iter = ty->cast; \ + while (iter) { \ + if (comparison) { \ + if (iter == ty->cast) return iter; \ + /* Move iter to the top of the linked list */ \ + iter->prev->next = iter->next; \ + if (iter->next) \ + iter->next->prev = iter->prev; \ + iter->next = ty->cast; \ + iter->prev = 0; \ + if (ty->cast) ty->cast->prev = iter; \ + ty->cast = iter; \ + return iter; \ + } \ + iter = iter->next; \ + } \ + } \ + return 0 + +/* + Check the typename +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheck(const char *c, swig_type_info *ty) { + SWIG_TypeCheck_Template(strcmp(iter->type->name, c) == 0, ty); +} + +/* Same as previous function, except strcmp is replaced with a pointer comparison */ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *into) { + SWIG_TypeCheck_Template(iter->type == from, into); +} + +/* + Cast a pointer up an inheritance hierarchy +*/ +SWIGRUNTIMEINLINE void * +SWIG_TypeCast(swig_cast_info *ty, void *ptr) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr); +} + +/* + Dynamic pointer casting. Down an inheritance hierarchy +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* + Return the name associated with this type +*/ +SWIGRUNTIMEINLINE const char * +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* + Return the pretty name associated with this type, + that is an unmangled type name in a form presentable to the user. +*/ +SWIGRUNTIME const char * +SWIG_TypePrettyName(const swig_type_info *type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') last_name = s+1; + return last_name; + } + else + return type->name; +} + +/* + Set the clientdata field for a type +*/ +SWIGRUNTIME void +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } + } + cast = cast->next; + } +} +SWIGRUNTIME void +SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; +} + +/* + Search for a swig_type_info structure only by mangled name + Search is a O(log #types) + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_MangledTypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + swig_module_info *iter = start; + do { + if (iter->size) { + register size_t l = 0; + register size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + register size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + register int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; +} + +/* + Search for a swig_type_info structure for either a mangled name or a human readable name. + It first searches the mangled names of the types, which is a O(log #types) + If a type is not found it then searches the human readable names, which is O(#types). + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + register size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; +} + +/* + Pack binary data into a string +*/ +SWIGRUNTIME char * +SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + register const unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* + Unpack binary data from a string +*/ +SWIGRUNTIME const char * +SWIG_UnpackData(const char *c, void *ptr, size_t sz) { + register unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register char d = *(c++); + register unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = ((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = ((d - ('a'-10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (d - ('a'-10)); + else + return (char *) 0; + *u = uu; + } + return c; +} + +/* + Pack 'void *' into a string buffer. +*/ +SWIGRUNTIME char * +SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { + char *r = buff; + if ((2*sizeof(void *) + 2) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; + strcpy(r,name); + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sizeof(void *)); +} + +SWIGRUNTIME char * +SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2*sz + 2 + lname) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + if (lname) { + strncpy(r,name,lname+1); + } else { + *r = 0; + } + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + memset(ptr,0,sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sz); +} + +#ifdef __cplusplus +} +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + +#ifdef __cplusplus +/* Needed on some windows machines---since MS plays funny games with the header files under C++ */ +#include +#include +extern "C" { +#endif +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +/* Add in functionality missing in older versions of Perl. Much of this is based on Devel-PPPort on cpan. */ + +/* Add PERL_REVISION, PERL_VERSION, PERL_SUBVERSION if missing */ +#ifndef PERL_REVISION +# if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION)) +# define PERL_PATCHLEVEL_H_IMPLICIT +# include +# endif +# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) +# include +# endif +# ifndef PERL_REVISION +# define PERL_REVISION (5) +# define PERL_VERSION PATCHLEVEL +# define PERL_SUBVERSION SUBVERSION +# endif +#endif + +#if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE) +#define PerlIO_exportFILE(fh,fl) (FILE*)(fh) +#endif + +#ifndef SvIOK_UV +# define SvIOK_UV(sv) (SvIOK(sv) && (SvUVX(sv) == SvIVX(sv))) +#endif + +#ifndef SvUOK +# define SvUOK(sv) SvIOK_UV(sv) +#endif + +#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))) +# define PL_sv_undef sv_undef +# define PL_na na +# define PL_errgv errgv +# define PL_sv_no sv_no +# define PL_sv_yes sv_yes +# define PL_markstack_ptr markstack_ptr +#endif + +#ifndef IVSIZE +# ifdef LONGSIZE +# define IVSIZE LONGSIZE +# else +# define IVSIZE 4 /* A bold guess, but the best we can make. */ +# endif +#endif + +#ifndef INT2PTR +# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) +# define PTRV UV +# define INT2PTR(any,d) (any)(d) +# else +# if PTRSIZE == LONGSIZE +# define PTRV unsigned long +# else +# define PTRV unsigned +# endif +# define INT2PTR(any,d) (any)(PTRV)(d) +# endif + +# define NUM2PTR(any,d) (any)(PTRV)(d) +# define PTR2IV(p) INT2PTR(IV,p) +# define PTR2UV(p) INT2PTR(UV,p) +# define PTR2NV(p) NUM2PTR(NV,p) + +# if PTRSIZE == LONGSIZE +# define PTR2ul(p) (unsigned long)(p) +# else +# define PTR2ul(p) INT2PTR(unsigned long,p) +# endif +#endif /* !INT2PTR */ + +#ifndef SvPV_nolen +# define SvPV_nolen(x) SvPV(x,PL_na) +#endif + +#ifndef get_sv +# define get_sv perl_get_sv +#endif + +#ifndef ERRSV +# define ERRSV get_sv("@",FALSE) +#endif + +#ifndef pTHX_ +#define pTHX_ +#endif + +#include +#ifdef __cplusplus +} +#endif + +/* ----------------------------------------------------------------------------- + * error manipulation + * ----------------------------------------------------------------------------- */ + +SWIGINTERN const char* +SWIG_Perl_ErrorType(int code) { + const char* type = 0; + switch(code) { + case SWIG_MemoryError: + type = "MemoryError"; + break; + case SWIG_IOError: + type = "IOError"; + break; + case SWIG_RuntimeError: + type = "RuntimeError"; + break; + case SWIG_IndexError: + type = "IndexError"; + break; + case SWIG_TypeError: + type = "TypeError"; + break; + case SWIG_DivisionByZero: + type = "ZeroDivisionError"; + break; + case SWIG_OverflowError: + type = "OverflowError"; + break; + case SWIG_SyntaxError: + type = "SyntaxError"; + break; + case SWIG_ValueError: + type = "ValueError"; + break; + case SWIG_SystemError: + type = "SystemError"; + break; + case SWIG_AttributeError: + type = "AttributeError"; + break; + default: + type = "RuntimeError"; + } + return type; +} + + + + +/* ----------------------------------------------------------------------------- + * perlrun.swg + * + * This file contains the runtime support for Perl modules + * and includes code for managing global variables and pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +#ifdef PERL_OBJECT +#define SWIG_PERL_OBJECT_DECL CPerlObj *SWIGUNUSEDPARM(pPerl), +#define SWIG_PERL_OBJECT_CALL pPerl, +#else +#define SWIG_PERL_OBJECT_DECL +#define SWIG_PERL_OBJECT_CALL +#endif + +/* Common SWIG API */ + +/* for raw pointers */ +#define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags) +#define SWIG_NewPointerObj(p, type, flags) SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags) + +/* for raw packed data */ +#define SWIG_ConvertPacked(obj, p, s, type) SWIG_Perl_ConvertPacked(SWIG_PERL_OBJECT_CALL obj, p, s, type) +#define SWIG_NewPackedObj(p, s, type) SWIG_Perl_NewPackedObj(SWIG_PERL_OBJECT_CALL p, s, type) + +/* for class or struct pointers */ +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) + +/* for C or C++ function pointers */ +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_ConvertPtr(obj, pptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NewPointerObj(ptr, type, 0) + +/* for C++ member pointers, ie, member methods */ +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_NewPackedObj(ptr, sz, type) + + +/* Runtime API */ + +#define SWIG_GetModule(clientdata) SWIG_Perl_GetModule() +#define SWIG_SetModule(clientdata, pointer) SWIG_Perl_SetModule(pointer) + + +/* Error manipulation */ + +#define SWIG_ErrorType(code) SWIG_Perl_ErrorType(code) +#define SWIG_Error(code, msg) sv_setpvf(GvSV(PL_errgv),"%s %s\n", SWIG_ErrorType(code), msg) +#define SWIG_fail goto fail + +/* Perl-specific SWIG API */ + +#define SWIG_MakePtr(sv, ptr, type, flags) SWIG_Perl_MakePtr(SWIG_PERL_OBJECT_CALL sv, ptr, type, flags) +#define SWIG_MakePackedObj(sv, p, s, type) SWIG_Perl_MakePackedObj(SWIG_PERL_OBJECT_CALL sv, p, s, type) +#define SWIG_SetError(str) SWIG_Error(SWIG_RuntimeError, str) + + +#define SWIG_PERL_DECL_ARGS_1(arg1) (SWIG_PERL_OBJECT_DECL arg1) +#define SWIG_PERL_CALL_ARGS_1(arg1) (SWIG_PERL_OBJECT_CALL arg1) +#define SWIG_PERL_DECL_ARGS_2(arg1, arg2) (SWIG_PERL_OBJECT_DECL arg1, arg2) +#define SWIG_PERL_CALL_ARGS_2(arg1, arg2) (SWIG_PERL_OBJECT_CALL arg1, arg2) + +/* ----------------------------------------------------------------------------- + * pointers/data manipulation + * ----------------------------------------------------------------------------- */ + +/* For backward compatibility only */ +#define SWIG_POINTER_EXCEPTION 0 + +#ifdef __cplusplus +extern "C" { +#endif + +#define SWIG_OWNER SWIG_POINTER_OWN +#define SWIG_SHADOW SWIG_OWNER << 1 + +#define SWIG_MAYBE_PERL_OBJECT SWIG_PERL_OBJECT_DECL + +/* SWIG Perl macros */ + +/* Macro to declare an XS function */ +#ifndef XSPROTO +# define XSPROTO(name) void name(pTHX_ CV* cv) +#endif + +/* Macro to call an XS function */ +#ifdef PERL_OBJECT +# define SWIG_CALLXS(_name) _name(cv,pPerl) +#else +# ifndef MULTIPLICITY +# define SWIG_CALLXS(_name) _name(cv) +# else +# define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) +# endif +#endif + +#ifdef PERL_OBJECT +#define MAGIC_PPERL CPerlObj *pPerl = (CPerlObj *) this; + +#ifdef __cplusplus +extern "C" { +#endif +typedef int (CPerlObj::*SwigMagicFunc)(SV *, MAGIC *); +#ifdef __cplusplus +} +#endif + +#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b) +#define SWIGCLASS_STATIC + +#else /* PERL_OBJECT */ + +#define MAGIC_PPERL +#define SWIGCLASS_STATIC static SWIGUNUSED + +#ifndef MULTIPLICITY +#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b) + +#ifdef __cplusplus +extern "C" { +#endif +typedef int (*SwigMagicFunc)(SV *, MAGIC *); +#ifdef __cplusplus +} +#endif + +#else /* MULTIPLICITY */ + +#define SWIG_MAGIC(a,b) (struct interpreter *interp, SV *a, MAGIC *b) + +#ifdef __cplusplus +extern "C" { +#endif +typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *); +#ifdef __cplusplus +} +#endif + +#endif /* MULTIPLICITY */ +#endif /* PERL_OBJECT */ + +/* Workaround for bug in perl 5.6.x croak and earlier */ +#if (PERL_VERSION < 8) +# ifdef PERL_OBJECT +# define SWIG_croak_null() SWIG_Perl_croak_null(pPerl) +static void SWIG_Perl_croak_null(CPerlObj *pPerl) +# else +static void SWIG_croak_null() +# endif +{ + SV *err=ERRSV; +# if (PERL_VERSION < 6) + croak("%_", err); +# else + if (SvOK(err) && !SvROK(err)) croak("%_", err); + croak(Nullch); +# endif +} +#else +# define SWIG_croak_null() croak(Nullch) +#endif + + +/* + Define how strict is the cast between strings and integers/doubles + when overloading between these types occurs. + + The default is making it as strict as possible by using SWIG_AddCast + when needed. + + You can use -DSWIG_PERL_NO_STRICT_STR2NUM at compilation time to + disable the SWIG_AddCast, making the casting between string and + numbers less strict. + + In the end, we try to solve the overloading between strings and + numerical types in the more natural way, but if you can avoid it, + well, avoid it using %rename, for example. +*/ +#ifndef SWIG_PERL_NO_STRICT_STR2NUM +# ifndef SWIG_PERL_STRICT_STR2NUM +# define SWIG_PERL_STRICT_STR2NUM +# endif +#endif +#ifdef SWIG_PERL_STRICT_STR2NUM +/* string takes precedence */ +#define SWIG_Str2NumCast(x) SWIG_AddCast(x) +#else +/* number takes precedence */ +#define SWIG_Str2NumCast(x) x +#endif + + + +#include + +SWIGRUNTIME const char * +SWIG_Perl_TypeProxyName(const swig_type_info *type) { + if (!type) return NULL; + if (type->clientdata != NULL) { + return (const char*) type->clientdata; + } + else { + return type->name; + } +} + +SWIGRUNTIME swig_cast_info * +SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) { + SWIG_TypeCheck_Template(( (!iter->type->clientdata && (strcmp((char*)iter->type->name, c) == 0)) + || (iter->type->clientdata && (strcmp((char*)iter->type->clientdata, c) == 0))), ty); +} + + +/* Function for getting a pointer value */ + +SWIGRUNTIME int +SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) { + swig_cast_info *tc; + void *voidptr = (void *)0; + SV *tsv = 0; + /* If magical, apply more magic */ + if (SvGMAGICAL(sv)) + mg_get(sv); + + /* Check to see if this is an object */ + if (sv_isobject(sv)) { + IV tmp = 0; + tsv = (SV*) SvRV(sv); + if ((SvTYPE(tsv) == SVt_PVHV)) { + MAGIC *mg; + if (SvMAGICAL(tsv)) { + mg = mg_find(tsv,'P'); + if (mg) { + sv = mg->mg_obj; + if (sv_isobject(sv)) { + tsv = (SV*)SvRV(sv); + tmp = SvIV(tsv); + } + } + } else { + return SWIG_ERROR; + } + } else { + tmp = SvIV(tsv); + } + voidptr = INT2PTR(void *,tmp); + } else if (! SvOK(sv)) { /* Check for undef */ + *(ptr) = (void *) 0; + return SWIG_OK; + } else if (SvTYPE(sv) == SVt_RV) { /* Check for NULL pointer */ + if (!SvROK(sv)) { + *(ptr) = (void *) 0; + return SWIG_OK; + } else { + return SWIG_ERROR; + } + } else { /* Don't know what it is */ + return SWIG_ERROR; + } + if (_t) { + /* Now see if the types match */ + char *_c = HvNAME(SvSTASH(SvRV(sv))); + tc = SWIG_TypeProxyCheck(_c,_t); + if (!tc) { + return SWIG_ERROR; + } + *ptr = SWIG_TypeCast(tc,voidptr); + } else { + *ptr = voidptr; + } + + /* + * DISOWN implementation: we need a perl guru to check this one. + */ + if (tsv && (flags & SWIG_POINTER_DISOWN)) { + /* + * almost copy paste code from below SWIG_POINTER_OWN setting + */ + SV *obj = sv; + HV *stash = SvSTASH(SvRV(obj)); + GV *gv = *(GV**) hv_fetch(stash, "OWNER", 5, TRUE); + if (isGV(gv)) { + HV *hv = GvHVn(gv); + /* + * To set ownership (see below), a newSViv(1) entry is added. + * Hence, to remove ownership, we delete the entry. + */ + if (hv_exists_ent(hv, obj, 0)) { + hv_delete_ent(hv, obj, 0, 0); + } + } + } + return SWIG_OK; +} + +SWIGRUNTIME void +SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) { + if (ptr && (flags & SWIG_SHADOW)) { + SV *self; + SV *obj=newSV(0); + HV *hash=newHV(); + HV *stash; + sv_setref_pv(obj, (char *) SWIG_Perl_TypeProxyName(t), ptr); + stash=SvSTASH(SvRV(obj)); + if (flags & SWIG_POINTER_OWN) { + HV *hv; + GV *gv=*(GV**)hv_fetch(stash, "OWNER", 5, TRUE); + if (!isGV(gv)) + gv_init(gv, stash, "OWNER", 5, FALSE); + hv=GvHVn(gv); + hv_store_ent(hv, obj, newSViv(1), 0); + } + sv_magic((SV *)hash, (SV *)obj, 'P', Nullch, 0); + SvREFCNT_dec(obj); + self=newRV_noinc((SV *)hash); + sv_setsv(sv, self); + SvREFCNT_dec((SV *)self); + sv_bless(sv, stash); + } + else { + sv_setref_pv(sv, (char *) SWIG_Perl_TypeProxyName(t), ptr); + } +} + +SWIGRUNTIMEINLINE SV * +SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) { + SV *result = sv_newmortal(); + SWIG_MakePtr(result, ptr, t, flags); + return result; +} + +SWIGRUNTIME void +SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) { + char result[1024]; + char *r = result; + if ((2*sz + 1 + strlen(SWIG_Perl_TypeProxyName(type))) > 1000) return; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + strcpy(r,SWIG_Perl_TypeProxyName(type)); + sv_setpv(sv, result); +} + +SWIGRUNTIME SV * +SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info *type) { + SV *result = sv_newmortal(); + SWIG_Perl_MakePackedObj(result, ptr, sz, type); + return result; +} + +/* Convert a packed value value */ +SWIGRUNTIME int +SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) { + swig_cast_info *tc; + const char *c = 0; + + if ((!obj) || (!SvOK(obj))) return SWIG_ERROR; + c = SvPV_nolen(obj); + /* Pointer values must start with leading underscore */ + if (*c != '_') return SWIG_ERROR; + c++; + c = SWIG_UnpackData(c,ptr,sz); + if (ty) { + tc = SWIG_TypeCheck(c,ty); + if (!tc) return SWIG_ERROR; + } + return SWIG_OK; +} + + +/* Macros for low-level exception handling */ +#define SWIG_croak(x) { SWIG_Error(SWIG_RuntimeError, x); SWIG_fail; } + + +typedef XSPROTO(SwigPerlWrapper); +typedef SwigPerlWrapper *SwigPerlWrapperPtr; + +/* Structure for command table */ +typedef struct { + const char *name; + SwigPerlWrapperPtr wrapper; +} swig_command_info; + +/* Information for constant table */ + +#define SWIG_INT 1 +#define SWIG_FLOAT 2 +#define SWIG_STRING 3 +#define SWIG_POINTER 4 +#define SWIG_BINARY 5 + +/* Constant information structure */ +typedef struct swig_constant_info { + int type; + const char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_constant_info; + + +/* Structure for variable table */ +typedef struct { + const char *name; + SwigMagicFunc set; + SwigMagicFunc get; + swig_type_info **type; +} swig_variable_info; + +/* Magic variable code */ +#ifndef PERL_OBJECT +#define swig_create_magic(s,a,b,c) _swig_create_magic(s,a,b,c) + #ifndef MULTIPLICITY + SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) + #else + SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) + #endif +#else +# define swig_create_magic(s,a,b,c) _swig_create_magic(pPerl,s,a,b,c) +SWIGRUNTIME void _swig_create_magic(CPerlObj *pPerl, SV *sv, const char *name, int (CPerlObj::*set)(SV *, MAGIC *), int (CPerlObj::*get)(SV *, MAGIC *)) +#endif +{ + MAGIC *mg; + sv_magic(sv,sv,'U',(char *) name,strlen(name)); + mg = mg_find(sv,'U'); + mg->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL)); + mg->mg_virtual->svt_get = (SwigMagicFunc) get; + mg->mg_virtual->svt_set = (SwigMagicFunc) set; + mg->mg_virtual->svt_len = 0; + mg->mg_virtual->svt_clear = 0; + mg->mg_virtual->svt_free = 0; +} + + +SWIGRUNTIME swig_module_info * +SWIG_Perl_GetModule(void) { + static void *type_pointer = (void *)0; + SV *pointer; + + /* first check if pointer already created */ + if (!type_pointer) { + pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, FALSE); + if (pointer && SvOK(pointer)) { + type_pointer = INT2PTR(swig_type_info **, SvIV(pointer)); + } + } + + return (swig_module_info *) type_pointer; +} + +SWIGRUNTIME void +SWIG_Perl_SetModule(swig_module_info *module) { + SV *pointer; + + /* create a new pointer */ + pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TRUE); + sv_setiv(pointer, PTR2IV(module)); +} + +#ifdef __cplusplus +} +#endif + +/* Workaround perl5 global namespace pollution. Note that undefining library + * functions like fopen will not solve the problem on all platforms as fopen + * might be a macro on Windows but not necessarily on other operating systems. */ +#ifdef do_open + #undef do_open +#endif +#ifdef do_close + #undef do_close +#endif +#ifdef scalar + #undef scalar +#endif +#ifdef list + #undef list +#endif +#ifdef apply + #undef apply +#endif +#ifdef convert + #undef convert +#endif +#ifdef Error + #undef Error +#endif +#ifdef form + #undef form +#endif +#ifdef vform + #undef vform +#endif +#ifdef LABEL + #undef LABEL +#endif +#ifdef METHOD + #undef METHOD +#endif +#ifdef Move + #undef Move +#endif +#ifdef yylex + #undef yylex +#endif +#ifdef yyparse + #undef yyparse +#endif +#ifdef yyerror + #undef yyerror +#endif +#ifdef invert + #undef invert +#endif +#ifdef ref + #undef ref +#endif +#ifdef read + #undef read +#endif +#ifdef write + #undef write +#endif +#ifdef eof + #undef eof +#endif +#ifdef bool + #undef bool +#endif +#ifdef close + #undef close +#endif +#ifdef rewind + #undef rewind +#endif +#ifdef free + #undef free +#endif +#ifdef malloc + #undef malloc +#endif +#ifdef calloc + #undef calloc +#endif +#ifdef Stat + #undef Stat +#endif +#ifdef check + #undef check +#endif +#ifdef seekdir + #undef seekdir +#endif +#ifdef open + #undef open +#endif + + + +#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) + +#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else + + + + #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_GSList swig_types[0] +#define SWIGTYPE_p_char swig_types[1] +#define SWIGTYPE_p_double swig_types[2] +#define SWIGTYPE_p_dumpspec_t swig_types[3] +#define SWIGTYPE_p_float swig_types[4] +#define SWIGTYPE_p_int swig_types[5] +#define SWIGTYPE_p_p_char swig_types[6] +#define SWIGTYPE_p_unsigned_char swig_types[7] +static swig_type_info *swig_types[9]; +static swig_module_info swig_module = {swig_types, 8, 0, 0, 0, 0}; +#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) +#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) + +/* -------- TYPES TABLE (END) -------- */ + +#define SWIG_init boot_Amanda__Cmdline + +#define SWIG_name "Amanda::Cmdlinec::boot_Amanda__Cmdline" +#define SWIG_prefix "Amanda::Cmdlinec::" + +#define SWIGVERSION 0x010333 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +#ifdef __cplusplus +extern "C" +#endif +#ifndef PERL_OBJECT +#ifndef MULTIPLICITY +SWIGEXPORT void SWIG_init (CV* cv); +#else +SWIGEXPORT void SWIG_init (pTHXo_ CV* cv); +#endif +#else +SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *); +#endif + + +#include "amglue.h" + + +#include "amglue.h" + + +#include "amglue.h" + + +#include "cmdline.h" + + +typedef GSList amglue_dumpspec_list; + + +#include +#include "cmdline.h" + + +SWIGINTERNINLINE SV * +SWIG_FromCharPtrAndSize(const char* carray, size_t size) +{ + SV *obj = sv_newmortal(); + if (carray) { + sv_setpvn(obj, carray, size); + } else { + sv_setsv(obj, &PL_sv_undef); + } + return obj; +} + + +SWIGINTERNINLINE SV * +SWIG_FromCharPtr(const char *cptr) +{ + return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); +} + + +SWIGINTERN swig_type_info* +SWIG_pchar_descriptor(void) +{ + static int init = 0; + static swig_type_info* info = 0; + if (!init) { + info = SWIG_TypeQuery("_p_char"); + init = 1; + } + return info; +} + + +SWIGINTERN int +SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc) +{ + if (SvPOK(obj)) { + STRLEN len = 0; + char *cstr = SvPV(obj, len); + size_t size = len + 1; + if (cptr) { + if (alloc) { + if (*alloc == SWIG_NEWOBJ) { + *cptr = (char *)memcpy((char *)malloc((size)*sizeof(char)), cstr, sizeof(char)*(size)); + } else { + *cptr = cstr; + *alloc = SWIG_OLDOBJ; + } + } + } + if (psize) *psize = size; + return SWIG_OK; + } else { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + if (pchar_descriptor) { + char* vptr = 0; + if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) { + if (cptr) *cptr = vptr; + if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0; + if (alloc) *alloc = SWIG_OLDOBJ; + return SWIG_OK; + } + } + } + return SWIG_TypeError; +} + + + + +SWIGINTERN dumpspec_t *new_dumpspec_t(char *host,char *disk,char *datestamp,char *level){ + return dumpspec_new(host, disk, datestamp, level); + } +SWIGINTERN void delete_dumpspec_t(dumpspec_t *self){ + dumpspec_free(self); + } +SWIGINTERN char *dumpspec_t_format(dumpspec_t *self){ + return cmdline_format_dumpspec(self); + } + +SWIGINTERNINLINE SV * +SWIG_From_long SWIG_PERL_DECL_ARGS_1(long value) +{ + SV *obj = sv_newmortal(); + sv_setiv(obj, (IV) value); + return obj; +} + + +SWIGINTERNINLINE SV * +SWIG_From_int SWIG_PERL_DECL_ARGS_1(int value) +{ + return SWIG_From_long SWIG_PERL_CALL_ARGS_1(value); +} + + +#include +#if !defined(SWIG_NO_LLONG_MAX) +# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) +# define LLONG_MAX __LONG_LONG_MAX__ +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +# endif +#endif + + +SWIGINTERN int +SWIG_AsVal_double SWIG_PERL_DECL_ARGS_2(SV *obj, double *val) +{ + if (SvNIOK(obj)) { + if (val) *val = SvNV(obj); + return SWIG_OK; + } else if (SvIOK(obj)) { + if (val) *val = (double) SvIV(obj); + return SWIG_AddCast(SWIG_OK); + } else { + const char *nptr = SvPV_nolen(obj); + if (nptr) { + char *endptr; + double v = strtod(nptr, &endptr); + if (errno == ERANGE) { + errno = 0; + return SWIG_OverflowError; + } else { + if (*endptr == '\0') { + if (val) *val = v; + return SWIG_Str2NumCast(SWIG_OK); + } + } + } + } + return SWIG_TypeError; +} + + +#include + + +#include + + +SWIGINTERNINLINE int +SWIG_CanCastAsInteger(double *d, double min, double max) { + double x = *d; + if ((min <= x && x <= max)) { + double fx = floor(x); + double cx = ceil(x); + double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ + if ((errno == EDOM) || (errno == ERANGE)) { + errno = 0; + } else { + double summ, reps, diff; + if (rd < x) { + diff = x - rd; + } else if (rd > x) { + diff = rd - x; + } else { + return 1; + } + summ = rd + x; + reps = diff/summ; + if (reps < 8*DBL_EPSILON) { + *d = rd; + return 1; + } + } + } + return 0; +} + + +SWIGINTERN int +SWIG_AsVal_long SWIG_PERL_DECL_ARGS_2(SV *obj, long* val) +{ + if (SvIOK(obj)) { + if (val) *val = SvIV(obj); + return SWIG_OK; + } else { + int dispatch = 0; + const char *nptr = SvPV_nolen(obj); + if (nptr) { + char *endptr; + long v; + errno = 0; + v = strtol(nptr, &endptr,0); + if (errno == ERANGE) { + errno = 0; + return SWIG_OverflowError; + } else { + if (*endptr == '\0') { + if (val) *val = v; + return SWIG_Str2NumCast(SWIG_OK); + } + } + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; + } + } + } + return SWIG_TypeError; +} + + +SWIGINTERN int +SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val) +{ + long v; + int res = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(obj, &v); + if (SWIG_IsOK(res)) { + if ((v < INT_MIN || v > INT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (int)(v); + } + } + return res; +} + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PERL_OBJECT +#define MAGIC_CLASS _wrap_Amanda::Cmdline_var:: +class _wrap_Amanda::Cmdline_var : public CPerlObj { +public: +#else +#define MAGIC_CLASS +#endif +SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + croak("Value is read-only."); + return 0; +} + + +#ifdef PERL_OBJECT +}; +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif +XS(_wrap_dumpspec_t_host_get) { + { + dumpspec_t *arg1 = (dumpspec_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: dumpspec_t_host_get(self);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumpspec_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumpspec_t_host_get" "', argument " "1"" of type '" "dumpspec_t *""'"); + } + arg1 = (dumpspec_t *)(argp1); + result = (char *) ((arg1)->host); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_dumpspec_t_disk_get) { + { + dumpspec_t *arg1 = (dumpspec_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: dumpspec_t_disk_get(self);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumpspec_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumpspec_t_disk_get" "', argument " "1"" of type '" "dumpspec_t *""'"); + } + arg1 = (dumpspec_t *)(argp1); + result = (char *) ((arg1)->disk); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_dumpspec_t_datestamp_get) { + { + dumpspec_t *arg1 = (dumpspec_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: dumpspec_t_datestamp_get(self);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumpspec_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumpspec_t_datestamp_get" "', argument " "1"" of type '" "dumpspec_t *""'"); + } + arg1 = (dumpspec_t *)(argp1); + result = (char *) ((arg1)->datestamp); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_dumpspec_t_level_get) { + { + dumpspec_t *arg1 = (dumpspec_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: dumpspec_t_level_get(self);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumpspec_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumpspec_t_level_get" "', argument " "1"" of type '" "dumpspec_t *""'"); + } + arg1 = (dumpspec_t *)(argp1); + result = (char *) ((arg1)->level); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_new_dumpspec_t) { + { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + dumpspec_t *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + int res4 ; + char *buf4 = 0 ; + int alloc4 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 4) || (items > 4)) { + SWIG_croak("Usage: new_dumpspec_t(host,disk,datestamp,level);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_dumpspec_t" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_dumpspec_t" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "new_dumpspec_t" "', argument " "3"" of type '" "char *""'"); + } + arg3 = (char *)(buf3); + res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "new_dumpspec_t" "', argument " "4"" of type '" "char *""'"); + } + arg4 = (char *)(buf4); + result = (dumpspec_t *)new_dumpspec_t(arg1,arg2,arg3,arg4); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_dumpspec_t, SWIG_OWNER | SWIG_SHADOW); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + if (alloc4 == SWIG_NEWOBJ) free((char*)buf4); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + if (alloc4 == SWIG_NEWOBJ) free((char*)buf4); + SWIG_croak_null(); + } +} + + +XS(_wrap_delete_dumpspec_t) { + { + dumpspec_t *arg1 = (dumpspec_t *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: delete_dumpspec_t(self);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumpspec_t, SWIG_POINTER_DISOWN | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_dumpspec_t" "', argument " "1"" of type '" "dumpspec_t *""'"); + } + arg1 = (dumpspec_t *)(argp1); + delete_dumpspec_t(arg1); + + + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_dumpspec_t_format) { + { + dumpspec_t *arg1 = (dumpspec_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: dumpspec_t_format(self);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumpspec_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumpspec_t_format" "', argument " "1"" of type '" "dumpspec_t *""'"); + } + arg1 = (dumpspec_t *)(argp1); + result = (char *)dumpspec_t_format(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + free((char*)result); + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_format_dumpspec_components) { + { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + char *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + int res4 ; + char *buf4 = 0 ; + int alloc4 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 4) || (items > 4)) { + SWIG_croak("Usage: format_dumpspec_components(host,disk,datestamp,level);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "format_dumpspec_components" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "format_dumpspec_components" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "format_dumpspec_components" "', argument " "3"" of type '" "char *""'"); + } + arg3 = (char *)(buf3); + res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "format_dumpspec_components" "', argument " "4"" of type '" "char *""'"); + } + arg4 = (char *)(buf4); + result = (char *)cmdline_format_dumpspec_components(arg1,arg2,arg3,arg4); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + if (alloc4 == SWIG_NEWOBJ) free((char*)buf4); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + if (alloc4 == SWIG_NEWOBJ) free((char*)buf4); + SWIG_croak_null(); + } +} + + +XS(_wrap_parse_dumpspecs) { + { + int arg1 ; + char **arg2 = (char **) 0 ; + int arg3 ; + amglue_dumpspec_list *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: parse_dumpspecs(argc,argv,flags);"); + } + { + AV *av; + int i; + + if (!SvROK(ST(0)) || SvTYPE(SvRV(ST(0))) != SVt_PVAV) { + SWIG_exception(SWIG_TypeError, "Expected an arrayref"); + } + av = (AV *)SvRV(ST(0)); + + arg1 = av_len(av)+1; /* av_len(av) is like $#av */ + arg2 = malloc(sizeof(char *) * arg1); + for (i = 0; i < arg1; i++) { + SV **elt = av_fetch(av, i, 0); + if (!elt || !SvPOK(*elt)) { + SWIG_exception(SWIG_TypeError, "Non-string in arrayref"); + } + arg2[i] = SvPV_nolen(*elt); /* TODO: handle unicode here */ + } + } + { + if (sizeof(signed int) == 1) { + arg3 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg3 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg3 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg3 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (amglue_dumpspec_list *)cmdline_parse_dumpspecs(arg1,arg2,arg3); + { + if (result) { + GSList *iter; + EXTEND(SP, g_slist_length(result)); /* make room for return values */ + + iter = result; + while (iter) { + /* Let SWIG take ownership of the object; we'll free the GSList momentarily */ + ST(argvi) = SWIG_NewPointerObj(iter->data, SWIGTYPE_p_dumpspec_t, SWIG_OWNER | SWIG_SHADOW); + argvi++; + iter = iter->next; + } + + /* Now free the GSList, but *not* its contents (which are now "owned" by SWIG) */ + g_slist_free(result); + } + } + { + free(arg2); + } + + XSRETURN(argvi); + fail: + { + free(arg2); + } + + SWIG_croak_null(); + } +} + + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_GSList = {"_p_GSList", "amglue_dumpspec_list *|GSList *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_char = {"_p_char", "gchar *|char *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_double = {"_p_double", "double *|gdouble *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_dumpspec_t = {"_p_dumpspec_t", "struct dumpspec_t *|dumpspec_t *", 0, 0, (void*)"Amanda::Cmdline::dumpspec_t", 0}; +static swig_type_info _swigt__p_float = {"_p_float", "float *|gfloat *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_int = {"_p_int", "int *|gboolean *|cmdline_parse_dumpspecs_flags *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "guchar *|unsigned char *", 0, 0, (void*)0, 0}; + +static swig_type_info *swig_type_initial[] = { + &_swigt__p_GSList, + &_swigt__p_char, + &_swigt__p_double, + &_swigt__p_dumpspec_t, + &_swigt__p_float, + &_swigt__p_int, + &_swigt__p_p_char, + &_swigt__p_unsigned_char, +}; + +static swig_cast_info _swigc__p_GSList[] = { {&_swigt__p_GSList, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_double[] = { {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_dumpspec_t[] = { {&_swigt__p_dumpspec_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_float[] = { {&_swigt__p_float, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_p_char[] = { {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; + +static swig_cast_info *swig_cast_initial[] = { + _swigc__p_GSList, + _swigc__p_char, + _swigc__p_double, + _swigc__p_dumpspec_t, + _swigc__p_float, + _swigc__p_int, + _swigc__p_p_char, + _swigc__p_unsigned_char, +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +static swig_constant_info swig_constants[] = { +{0,0,0,0,0,0} +}; +#ifdef __cplusplus +} +#endif +static swig_variable_info swig_variables[] = { +{0,0,0,0} +}; +static swig_command_info swig_commands[] = { +{"Amanda::Cmdlinec::dumpspec_t_host_get", _wrap_dumpspec_t_host_get}, +{"Amanda::Cmdlinec::dumpspec_t_disk_get", _wrap_dumpspec_t_disk_get}, +{"Amanda::Cmdlinec::dumpspec_t_datestamp_get", _wrap_dumpspec_t_datestamp_get}, +{"Amanda::Cmdlinec::dumpspec_t_level_get", _wrap_dumpspec_t_level_get}, +{"Amanda::Cmdlinec::new_dumpspec_t", _wrap_new_dumpspec_t}, +{"Amanda::Cmdlinec::delete_dumpspec_t", _wrap_delete_dumpspec_t}, +{"Amanda::Cmdlinec::dumpspec_t_format", _wrap_dumpspec_t_format}, +{"Amanda::Cmdlinec::format_dumpspec_components", _wrap_format_dumpspec_components}, +{"Amanda::Cmdlinec::parse_dumpspecs", _wrap_parse_dumpspecs}, +{0,0} +}; +/* ----------------------------------------------------------------------------- + * Type initialization: + * This problem is tough by the requirement that no dynamic + * memory is used. Also, since swig_type_info structures store pointers to + * swig_cast_info structures and swig_cast_info structures store pointers back + * to swig_type_info structures, we need some lookup code at initialization. + * The idea is that swig generates all the structures that are needed. + * The runtime then collects these partially filled structures. + * The SWIG_InitializeModule function takes these initial arrays out of + * swig_module, and does all the lookup, filling in the swig_module.types + * array with the correct data and linking the correct swig_cast_info + * structures together. + * + * The generated swig_type_info structures are assigned staticly to an initial + * array. We just loop through that array, and handle each type individually. + * First we lookup if this type has been already loaded, and if so, use the + * loaded structure instead of the generated one. Then we have to fill in the + * cast linked list. The cast data is initially stored in something like a + * two-dimensional array. Each row corresponds to a type (there are the same + * number of rows as there are in the swig_type_initial array). Each entry in + * a column is one of the swig_cast_info structures for that type. + * The cast_initial array is actually an array of arrays, because each row has + * a variable number of columns. So to actually build the cast linked list, + * we find the array of casts associated with the type, and loop through it + * adding the casts to the list. The one last trick we need to do is making + * sure the type pointer in the swig_cast_info struct is correct. + * + * First off, we lookup the cast->type name to see if it is already loaded. + * There are three cases to handle: + * 1) If the cast->type has already been loaded AND the type we are adding + * casting info to has not been loaded (it is in this module), THEN we + * replace the cast->type pointer with the type pointer that has already + * been loaded. + * 2) If BOTH types (the one we are adding casting info to, and the + * cast->type) are loaded, THEN the cast info has already been loaded by + * the previous module so we just ignore it. + * 3) Finally, if cast->type has not already been loaded, then we add that + * swig_cast_info to the linked list (because the cast->type) pointer will + * be correct. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* c-mode */ +#endif +#endif + +#if 0 +#define SWIGRUNTIME_DEBUG +#endif + + +SWIGRUNTIME void +SWIG_InitializeModule(void *clientdata) { + size_t i; + swig_module_info *module_head, *iter; + int found; + + clientdata = clientdata; + + /* check to see if the circular list has been setup, if not, set it up */ + if (swig_module.next==0) { + /* Initialize the swig_module */ + swig_module.type_initial = swig_type_initial; + swig_module.cast_initial = swig_cast_initial; + swig_module.next = &swig_module; + } + + /* Try and load any already created modules */ + module_head = SWIG_GetModule(clientdata); + if (!module_head) { + /* This is the first module loaded for this interpreter */ + /* so set the swig module into the interpreter */ + SWIG_SetModule(clientdata, &swig_module); + module_head = &swig_module; + } else { + /* the interpreter has loaded a SWIG module, but has it loaded this one? */ + found=0; + iter=module_head; + do { + if (iter==&swig_module) { + found=1; + break; + } + iter=iter->next; + } while (iter!= module_head); + + /* if the is found in the list, then all is done and we may leave */ + if (found) return; + /* otherwise we must add out module into the list */ + swig_module.next = module_head->next; + module_head->next = &swig_module; + } + + /* Now work on filling in swig_module.types */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: size %d\n", swig_module.size); +#endif + for (i = 0; i < swig_module.size; ++i) { + swig_type_info *type = 0; + swig_type_info *ret; + swig_cast_info *cast; + +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); +#endif + + /* if there is another module already loaded */ + if (swig_module.next != &swig_module) { + type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + } + if (type) { + /* Overwrite clientdata field */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found type %s\n", type->name); +#endif + if (swig_module.type_initial[i]->clientdata) { + type->clientdata = swig_module.type_initial[i]->clientdata; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); +#endif + } + } else { + type = swig_module.type_initial[i]; + } + + /* Insert casting types */ + cast = swig_module.cast_initial[i]; + while (cast->type) { + /* Don't need to add information already in the list */ + ret = 0; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); +#endif + if (swig_module.next != &swig_module) { + ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); +#ifdef SWIGRUNTIME_DEBUG + if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); +#endif + } + if (ret) { + if (type == swig_module.type_initial[i]) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: skip old type %s\n", ret->name); +#endif + cast->type = ret; + ret = 0; + } else { + /* Check for casting already in the list */ + swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); +#ifdef SWIGRUNTIME_DEBUG + if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); +#endif + if (!ocast) ret = 0; + } + } + + if (!ret) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); +#endif + if (type->cast) { + type->cast->prev = cast; + cast->next = type->cast; + } + type->cast = cast; + } + cast++; + } + /* Set entry in modules->types array equal to the type */ + swig_module.types[i] = type; + } + swig_module.types[i] = 0; + +#ifdef SWIGRUNTIME_DEBUG + printf("**** SWIG_InitializeModule: Cast List ******\n"); + for (i = 0; i < swig_module.size; ++i) { + int j = 0; + swig_cast_info *cast = swig_module.cast_initial[i]; + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + while (cast->type) { + printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); + cast++; + ++j; + } + printf("---- Total casts: %d\n",j); + } + printf("**** SWIG_InitializeModule: Cast List ******\n"); +#endif +} + +/* This function will propagate the clientdata field of type to +* any new swig_type_info structures that have been added into the list +* of equivalent types. It is like calling +* SWIG_TypeClientData(type, clientdata) a second time. +*/ +SWIGRUNTIME void +SWIG_PropagateClientData(void) { + size_t i; + swig_cast_info *equiv; + static int init_run = 0; + + if (init_run) return; + init_run = 1; + + for (i = 0; i < swig_module.size; i++) { + if (swig_module.types[i]->clientdata) { + equiv = swig_module.types[i]->cast; + while (equiv) { + if (!equiv->converter) { + if (equiv->type && !equiv->type->clientdata) + SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + } + equiv = equiv->next; + } + } + } +} + +#ifdef __cplusplus +#if 0 +{ + /* c-mode */ +#endif +} +#endif + + + +#ifdef __cplusplus +extern "C" +#endif + +XS(SWIG_init) { + dXSARGS; + int i; + + SWIG_InitializeModule(0); + + /* Install commands */ + for (i = 0; swig_commands[i].name; i++) { + newXS((char*) swig_commands[i].name,swig_commands[i].wrapper, (char*)__FILE__); + } + + /* Install variables */ + for (i = 0; swig_variables[i].name; i++) { + SV *sv; + sv = get_sv((char*) swig_variables[i].name, TRUE | 0x2); + if (swig_variables[i].type) { + SWIG_MakePtr(sv,(void *)1, *swig_variables[i].type,0); + } else { + sv_setiv(sv,(IV) 0); + } + swig_create_magic(sv, (char *) swig_variables[i].name, swig_variables[i].set, swig_variables[i].get); + } + + /* Install constant */ + for (i = 0; swig_constants[i].type; i++) { + SV *sv; + sv = get_sv((char*)swig_constants[i].name, TRUE | 0x2); + switch(swig_constants[i].type) { + case SWIG_INT: + sv_setiv(sv, (IV) swig_constants[i].lvalue); + break; + case SWIG_FLOAT: + sv_setnv(sv, (double) swig_constants[i].dvalue); + break; + case SWIG_STRING: + sv_setpv(sv, (char *) swig_constants[i].pvalue); + break; + case SWIG_POINTER: + SWIG_MakePtr(sv, swig_constants[i].pvalue, *(swig_constants[i].ptype),0); + break; + case SWIG_BINARY: + SWIG_MakePackedObj(sv, swig_constants[i].pvalue, swig_constants[i].lvalue, *(swig_constants[i].ptype)); + break; + default: + break; + } + SvREADONLY_on(sv); + } + + SWIG_TypeClientData(SWIGTYPE_p_dumpspec_t, (void*) "Amanda::Cmdline::dumpspec_t"); + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CMDLINE_PARSE_DATESTAMP", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CMDLINE_PARSE_DATESTAMP))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CMDLINE_PARSE_LEVEL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CMDLINE_PARSE_LEVEL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CMDLINE_EMPTY_TO_WILDCARD", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CMDLINE_EMPTY_TO_WILDCARD))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + ST(0) = &PL_sv_yes; + XSRETURN(1); +} + diff --git a/perl/Amanda/Cmdline.pm b/perl/Amanda/Cmdline.pm new file mode 100644 index 0000000..fa99ed1 --- /dev/null +++ b/perl/Amanda/Cmdline.pm @@ -0,0 +1,220 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 1.3.33 +# +# Don't modify this file, modify the SWIG interface instead. + +package Amanda::Cmdline; +require Exporter; +require DynaLoader; +@ISA = qw(Exporter DynaLoader); +package Amanda::Cmdlinec; +bootstrap Amanda::Cmdline; +package Amanda::Cmdline; +@EXPORT = qw( ); + +# ---------- BASE METHODS ------------- + +package Amanda::Cmdline; + +sub TIEHASH { + my ($classname,$obj) = @_; + return bless $obj, $classname; +} + +sub CLEAR { } + +sub FIRSTKEY { } + +sub NEXTKEY { } + +sub FETCH { + my ($self,$field) = @_; + my $member_func = "swig_${field}_get"; + $self->$member_func(); +} + +sub STORE { + my ($self,$field,$newval) = @_; + my $member_func = "swig_${field}_set"; + $self->$member_func($newval); +} + +sub this { + my $ptr = shift; + return tied(%$ptr); +} + + +# ------- FUNCTION WRAPPERS -------- + +package Amanda::Cmdline; + +*format_dumpspec_components = *Amanda::Cmdlinec::format_dumpspec_components; +*parse_dumpspecs = *Amanda::Cmdlinec::parse_dumpspecs; + +############# Class : Amanda::Cmdline::dumpspec_t ############## + +package Amanda::Cmdline::dumpspec_t; +use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS); +@ISA = qw( Amanda::Cmdline ); +%OWNER = (); +%ITERATORS = (); +*swig_host_get = *Amanda::Cmdlinec::dumpspec_t_host_get; +*swig_host_set = *Amanda::Cmdlinec::dumpspec_t_host_set; +*swig_disk_get = *Amanda::Cmdlinec::dumpspec_t_disk_get; +*swig_disk_set = *Amanda::Cmdlinec::dumpspec_t_disk_set; +*swig_datestamp_get = *Amanda::Cmdlinec::dumpspec_t_datestamp_get; +*swig_datestamp_set = *Amanda::Cmdlinec::dumpspec_t_datestamp_set; +*swig_level_get = *Amanda::Cmdlinec::dumpspec_t_level_get; +*swig_level_set = *Amanda::Cmdlinec::dumpspec_t_level_set; +sub new { + my $pkg = shift; + my $self = Amanda::Cmdlinec::new_dumpspec_t(@_); + bless $self, $pkg if defined($self); +} + +sub DESTROY { + return unless $_[0]->isa('HASH'); + my $self = tied(%{$_[0]}); + return unless defined $self; + delete $ITERATORS{$self}; + if (exists $OWNER{$self}) { + Amanda::Cmdlinec::delete_dumpspec_t($self); + delete $OWNER{$self}; + } +} + +*format = *Amanda::Cmdlinec::dumpspec_t_format; +sub DISOWN { + my $self = shift; + my $ptr = tied(%$self); + delete $OWNER{$ptr}; +} + +sub ACQUIRE { + my $self = shift; + my $ptr = tied(%$self); + $OWNER{$ptr} = 1; +} + + +# ------- VARIABLE STUBS -------- + +package Amanda::Cmdline; + +*CMDLINE_PARSE_DATESTAMP = *Amanda::Cmdlinec::CMDLINE_PARSE_DATESTAMP; +*CMDLINE_PARSE_LEVEL = *Amanda::Cmdlinec::CMDLINE_PARSE_LEVEL; +*CMDLINE_EMPTY_TO_WILDCARD = *Amanda::Cmdlinec::CMDLINE_EMPTY_TO_WILDCARD; + +@EXPORT_OK = (); +%EXPORT_TAGS = (); + +=head1 NAME + +Amanda::Cmdline - utilities for handling command lines + +=head1 SYNOPSIS + + use Amanda::Cmdline; + + my $spec = Amanda::Cmdline::dumpspec_t->new($host, $disk, $datestamp, $level); + print "host: $spec->{'host'}; disk: $spec->{'disk'}\n"; + + my @specs = Amanda::Cmdline::parse_dumpspecs(["host", "disk", "date"], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP); + +=head1 API STATUS + +Will change. + +=head1 Amanda::Cmdline::dumpspec_t Objects + +=head2 Instance Variables + +=over + +=item C<$host> + +=item C<$disk> + +=item C<$datestamp> + +=item C<$level> + +=back + +=head2 Methods + +=over + +=item C + +Format the dumpspec as a string. + +=back + +=head1 Functions + +=over + +=item C + +This function returns a string representing the formatted form of the given dumpspec. This formatting +is the same as performed by C, but does not need a C. + +=item C + +This function parses C<@cmdline> into a list of C objects, +according to C<$flags>, which is a logical combination of zero or +more of C<$CMDLINE_PARSE_DATESTAMP> to recognize datestamps and +C<$CMDLINE_PARSE_LEVEL> to recognize levels. + +=back + +=head1 SEE ALSO + +L handles C<-o> options itself, through C. + +=cut + +push @EXPORT_OK, qw(cmdline_parse_dumpspecs_flags_to_strings); +push @{$EXPORT_TAGS{"cmdline_parse_dumpspecs_flags"}}, qw(cmdline_parse_dumpspecs_flags_to_strings); + +my %_cmdline_parse_dumpspecs_flags_VALUES; +#Convert a flag value to a list of names for flags that are set. +sub cmdline_parse_dumpspecs_flags_to_strings { + my ($flags) = @_; + my @result = (); + + for my $k (keys %_cmdline_parse_dumpspecs_flags_VALUES) { + my $v = $_cmdline_parse_dumpspecs_flags_VALUES{$k}; + + #is this a matching flag? + if (($v == 0 && $flags == 0) || ($v != 0 && ($flags & $v) == $v)) { + push @result, $k; + } + } + +#by default, just return the number as a 1-element list + if (!@result) { + return ($flags); + } + + return @result; +} + +push @EXPORT_OK, qw($CMDLINE_PARSE_DATESTAMP); +push @{$EXPORT_TAGS{"cmdline_parse_dumpspecs_flags"}}, qw($CMDLINE_PARSE_DATESTAMP); + +$_cmdline_parse_dumpspecs_flags_VALUES{"CMDLINE_PARSE_DATESTAMP"} = $CMDLINE_PARSE_DATESTAMP; + +push @EXPORT_OK, qw($CMDLINE_PARSE_LEVEL); +push @{$EXPORT_TAGS{"cmdline_parse_dumpspecs_flags"}}, qw($CMDLINE_PARSE_LEVEL); + +$_cmdline_parse_dumpspecs_flags_VALUES{"CMDLINE_PARSE_LEVEL"} = $CMDLINE_PARSE_LEVEL; + +push @EXPORT_OK, qw($CMDLINE_EMPTY_TO_WILDCARD); +push @{$EXPORT_TAGS{"cmdline_parse_dumpspecs_flags"}}, qw($CMDLINE_EMPTY_TO_WILDCARD); + +$_cmdline_parse_dumpspecs_flags_VALUES{"CMDLINE_EMPTY_TO_WILDCARD"} = $CMDLINE_EMPTY_TO_WILDCARD; +1; diff --git a/perl/Amanda/Cmdline.swg b/perl/Amanda/Cmdline.swg new file mode 100644 index 0000000..953edab --- /dev/null +++ b/perl/Amanda/Cmdline.swg @@ -0,0 +1,171 @@ +/* + * Copyright (c) Zmanda, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + */ + +%module "Amanda::Cmdline" +%include "amglue/amglue.swg" +%include "exception.i" +%include "amglue/dumpspecs.swg" + +%{ +#include +#include "cmdline.h" +%} + +%perlcode %{ +=head1 NAME + +Amanda::Cmdline - utilities for handling command lines + +=head1 SYNOPSIS + + use Amanda::Cmdline; + + my $spec = Amanda::Cmdline::dumpspec_t->new($host, $disk, $datestamp, $level); + print "host: $spec->{'host'}; disk: $spec->{'disk'}\n"; + + my @specs = Amanda::Cmdline::parse_dumpspecs(["host", "disk", "date"], + $Amanda::Cmdline::CMDLINE_PARSE_DATESTAMP); + +=head1 API STATUS + +Will change. + +=head1 Amanda::Cmdline::dumpspec_t Objects + +=head2 Instance Variables + +=over + +=item C<$host> + +=item C<$disk> + +=item C<$datestamp> + +=item C<$level> + +=back + +=head2 Methods + +=over + +=item C + +Format the dumpspec as a string. + +=back + +=head1 Functions + +=over + +=item C + +This function returns a string representing the formatted form of the given dumpspec. This formatting +is the same as performed by C, but does not need a C. + +=item C + +This function parses C<@cmdline> into a list of C objects, +according to C<$flags>, which is a logical combination of zero or +more of C<$CMDLINE_PARSE_DATESTAMP> to recognize datestamps and +C<$CMDLINE_PARSE_LEVEL> to recognize levels. + +=back + +=head1 SEE ALSO + +L handles C<-o> options itself, through C. + +=cut +%} + +/* Add a few methods to make this type act like a class */ +typedef struct dumpspec_t { + %immutable; + char *host; + char *disk; + char *datestamp; + char *level; + %mutable; + + %extend { + /* constructor */ + dumpspec_t(char *host, char *disk, char *datestamp, char *level) { + return dumpspec_new(host, disk, datestamp, level); + } + + ~dumpspec_t() { + dumpspec_free(self); + } + + %newobject format; + char *format() { + return cmdline_format_dumpspec(self); + } + } +} dumpspec_t; + +%rename(format_dumpspec_components) cmdline_format_dumpspec_components; +char *cmdline_format_dumpspec_components(char *host, char *disk, char *datestamp, char *level); + +/* Typemap to convert a perl list of strings to the strv that + * cmdline_parse_dumpspecs expects. + */ +%typemap(in, numinputs=1) (int argc, char **argv) { + AV *av; + int i; + + if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV) { + SWIG_exception(SWIG_TypeError, "Expected an arrayref"); + } + av = (AV *)SvRV($input); + + $1 = av_len(av)+1; /* av_len(av) is like $#av */ + $2 = malloc(sizeof(char *) * $1); + for (i = 0; i < $1; i++) { + SV **elt = av_fetch(av, i, 0); + if (!elt || !SvPOK(*elt)) { + SWIG_exception(SWIG_TypeError, "Non-string in arrayref"); + } + $2[i] = SvPV_nolen(*elt); /* TODO: handle unicode here */ + } +} + +/* Free the space allocated by the previous typemap */ +%typemap(freearg) (int argc, char **argv) { + free($2); +} + +amglue_add_flag_tag_fns(cmdline_parse_dumpspecs_flags); +amglue_add_constant(CMDLINE_PARSE_DATESTAMP, cmdline_parse_dumpspecs_flags); +amglue_add_constant(CMDLINE_PARSE_LEVEL, cmdline_parse_dumpspecs_flags); +amglue_add_constant(CMDLINE_EMPTY_TO_WILDCARD, cmdline_parse_dumpspecs_flags); + +%rename(parse_dumpspecs) cmdline_parse_dumpspecs; +amglue_dumpspec_list *cmdline_parse_dumpspecs(int argc, char **argv, int flags); + +/* TODO: + * convert AV back to GSList as input, convert resulting GSList into an AV of strings + * on output + */ +/* amglue_dumpspec_list * cmdline_match_holding(amglue_dumpspec_list *dumpspec_list); */ + diff --git a/perl/Amanda/Config.c b/perl/Amanda/Config.c new file mode 100644 index 0000000..dfd13c5 --- /dev/null +++ b/perl/Amanda/Config.c @@ -0,0 +1,5280 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.33 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIGPERL +#define SWIG_CASTRANK_MODE +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + + +/* ----------------------------------------------------------------------------- + * swigrun.swg + * + * This file contains generic CAPI SWIG runtime support for pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +/* This should only be incremented when either the layout of swig_type_info changes, + or for whatever reason, the runtime changes incompatibly */ +#define SWIG_RUNTIME_VERSION "3" + +/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ +#ifdef SWIG_TYPE_TABLE +# define SWIG_QUOTE_STRING(x) #x +# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) +# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) +#else +# define SWIG_TYPE_TABLE_NAME +#endif + +/* + You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for + creating a static or dynamic library from the swig runtime code. + In 99.9% of the cases, swig just needs to declare them as 'static'. + + But only do this if is strictly necessary, ie, if you have problems + with your compiler or so. +*/ + +#ifndef SWIGRUNTIME +# define SWIGRUNTIME SWIGINTERN +#endif + +#ifndef SWIGRUNTIMEINLINE +# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE +#endif + +/* Generic buffer size */ +#ifndef SWIG_BUFFER_SIZE +# define SWIG_BUFFER_SIZE 1024 +#endif + +/* Flags for pointer conversions */ +#define SWIG_POINTER_DISOWN 0x1 + +/* Flags for new pointer objects */ +#define SWIG_POINTER_OWN 0x1 + + +/* + Flags/methods for returning states. + + The swig conversion methods, as ConvertPtr, return and integer + that tells if the conversion was successful or not. And if not, + an error code can be returned (see swigerrors.swg for the codes). + + Use the following macros/flags to set or process the returning + states. + + In old swig versions, you usually write code as: + + if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { + // success code + } else { + //fail code + } + + Now you can be more explicit as: + + int res = SWIG_ConvertPtr(obj,vptr,ty.flags); + if (SWIG_IsOK(res)) { + // success code + } else { + // fail code + } + + that seems to be the same, but now you can also do + + Type *ptr; + int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); + if (SWIG_IsOK(res)) { + // success code + if (SWIG_IsNewObj(res) { + ... + delete *ptr; + } else { + ... + } + } else { + // fail code + } + + I.e., now SWIG_ConvertPtr can return new objects and you can + identify the case and take care of the deallocation. Of course that + requires also to SWIG_ConvertPtr to return new result values, as + + int SWIG_ConvertPtr(obj, ptr,...) { + if () { + if () { + *ptr = ; + return SWIG_NEWOBJ; + } else { + *ptr = ; + return SWIG_OLDOBJ; + } + } else { + return SWIG_BADOBJ; + } + } + + Of course, returning the plain '0(success)/-1(fail)' still works, but you can be + more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the + swig errors code. + + Finally, if the SWIG_CASTRANK_MODE is enabled, the result code + allows to return the 'cast rank', for example, if you have this + + int food(double) + int fooi(int); + + and you call + + food(1) // cast rank '1' (1 -> 1.0) + fooi(1) // cast rank '0' + + just use the SWIG_AddCast()/SWIG_CheckState() + + + */ +#define SWIG_OK (0) +#define SWIG_ERROR (-1) +#define SWIG_IsOK(r) (r >= 0) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) + +/* The CastRankLimit says how many bits are used for the cast rank */ +#define SWIG_CASTRANKLIMIT (1 << 8) +/* The NewMask denotes the object was created (using new/malloc) */ +#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) +/* The TmpMask is for in/out typemaps that use temporal objects */ +#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) +/* Simple returning values */ +#define SWIG_BADOBJ (SWIG_ERROR) +#define SWIG_OLDOBJ (SWIG_OK) +#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) +#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) +/* Check, add and del mask methods */ +#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) +#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) +#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) +#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) +#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) +#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) + + +/* Cast-Rank Mode */ +#if defined(SWIG_CASTRANK_MODE) +# ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +# endif +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# define SWIG_MAXCASTRANK (2) +# endif +# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) +# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) +SWIGINTERNINLINE int SWIG_AddCast(int r) { + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +} +SWIGINTERNINLINE int SWIG_CheckState(int r) { + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +} +#else /* no cast-rank mode */ +# define SWIG_AddCast +# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) +#endif + + + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +/* Structure to store inforomation on one type */ +typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ +} swig_type_info; + +/* Structure to store a type and conversion function used for casting */ +typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ +} swig_cast_info; + +/* Structure used to store module information + * Each module generates one structure like this, and the runtime collects + * all of these structures and stores them in a circularly linked list.*/ +typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ +} swig_module_info; + +/* + Compare two type names skipping the space characters, therefore + "char*" == "char *" and "Class" == "Class", etc. + + Return 0 when the two name types are equivalent, as in + strncmp, but skipping ' '. +*/ +SWIGRUNTIME int +SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) ++f1; + while ((*f2 == ' ') && (f2 != l2)) ++f2; + if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + } + return (int)((l1 - f1) - (l2 - f2)); +} + +/* + Check type equivalence in a name list like ||... + Return 0 if not equal, 1 if equal +*/ +SWIGRUNTIME int +SWIG_TypeEquiv(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + +/* + Check type equivalence in a name list like ||... + Return 0 if equal, -1 if nb < tb, 1 if nb > tb +*/ +SWIGRUNTIME int +SWIG_TypeCompare(const char *nb, const char *tb) { + int equiv = 0; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) ++ne; + } + return equiv; +} + + +/* think of this as a c++ template<> or a scheme macro */ +#define SWIG_TypeCheck_Template(comparison, ty) \ + if (ty) { \ + swig_cast_info *iter = ty->cast; \ + while (iter) { \ + if (comparison) { \ + if (iter == ty->cast) return iter; \ + /* Move iter to the top of the linked list */ \ + iter->prev->next = iter->next; \ + if (iter->next) \ + iter->next->prev = iter->prev; \ + iter->next = ty->cast; \ + iter->prev = 0; \ + if (ty->cast) ty->cast->prev = iter; \ + ty->cast = iter; \ + return iter; \ + } \ + iter = iter->next; \ + } \ + } \ + return 0 + +/* + Check the typename +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheck(const char *c, swig_type_info *ty) { + SWIG_TypeCheck_Template(strcmp(iter->type->name, c) == 0, ty); +} + +/* Same as previous function, except strcmp is replaced with a pointer comparison */ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *into) { + SWIG_TypeCheck_Template(iter->type == from, into); +} + +/* + Cast a pointer up an inheritance hierarchy +*/ +SWIGRUNTIMEINLINE void * +SWIG_TypeCast(swig_cast_info *ty, void *ptr) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr); +} + +/* + Dynamic pointer casting. Down an inheritance hierarchy +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* + Return the name associated with this type +*/ +SWIGRUNTIMEINLINE const char * +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* + Return the pretty name associated with this type, + that is an unmangled type name in a form presentable to the user. +*/ +SWIGRUNTIME const char * +SWIG_TypePrettyName(const swig_type_info *type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') last_name = s+1; + return last_name; + } + else + return type->name; +} + +/* + Set the clientdata field for a type +*/ +SWIGRUNTIME void +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } + } + cast = cast->next; + } +} +SWIGRUNTIME void +SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; +} + +/* + Search for a swig_type_info structure only by mangled name + Search is a O(log #types) + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_MangledTypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + swig_module_info *iter = start; + do { + if (iter->size) { + register size_t l = 0; + register size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + register size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + register int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; +} + +/* + Search for a swig_type_info structure for either a mangled name or a human readable name. + It first searches the mangled names of the types, which is a O(log #types) + If a type is not found it then searches the human readable names, which is O(#types). + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + register size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; +} + +/* + Pack binary data into a string +*/ +SWIGRUNTIME char * +SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + register const unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* + Unpack binary data from a string +*/ +SWIGRUNTIME const char * +SWIG_UnpackData(const char *c, void *ptr, size_t sz) { + register unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register char d = *(c++); + register unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = ((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = ((d - ('a'-10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (d - ('a'-10)); + else + return (char *) 0; + *u = uu; + } + return c; +} + +/* + Pack 'void *' into a string buffer. +*/ +SWIGRUNTIME char * +SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { + char *r = buff; + if ((2*sizeof(void *) + 2) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; + strcpy(r,name); + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sizeof(void *)); +} + +SWIGRUNTIME char * +SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2*sz + 2 + lname) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + if (lname) { + strncpy(r,name,lname+1); + } else { + *r = 0; + } + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + memset(ptr,0,sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sz); +} + +#ifdef __cplusplus +} +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + +#ifdef __cplusplus +/* Needed on some windows machines---since MS plays funny games with the header files under C++ */ +#include +#include +extern "C" { +#endif +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +/* Add in functionality missing in older versions of Perl. Much of this is based on Devel-PPPort on cpan. */ + +/* Add PERL_REVISION, PERL_VERSION, PERL_SUBVERSION if missing */ +#ifndef PERL_REVISION +# if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION)) +# define PERL_PATCHLEVEL_H_IMPLICIT +# include +# endif +# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) +# include +# endif +# ifndef PERL_REVISION +# define PERL_REVISION (5) +# define PERL_VERSION PATCHLEVEL +# define PERL_SUBVERSION SUBVERSION +# endif +#endif + +#if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE) +#define PerlIO_exportFILE(fh,fl) (FILE*)(fh) +#endif + +#ifndef SvIOK_UV +# define SvIOK_UV(sv) (SvIOK(sv) && (SvUVX(sv) == SvIVX(sv))) +#endif + +#ifndef SvUOK +# define SvUOK(sv) SvIOK_UV(sv) +#endif + +#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))) +# define PL_sv_undef sv_undef +# define PL_na na +# define PL_errgv errgv +# define PL_sv_no sv_no +# define PL_sv_yes sv_yes +# define PL_markstack_ptr markstack_ptr +#endif + +#ifndef IVSIZE +# ifdef LONGSIZE +# define IVSIZE LONGSIZE +# else +# define IVSIZE 4 /* A bold guess, but the best we can make. */ +# endif +#endif + +#ifndef INT2PTR +# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) +# define PTRV UV +# define INT2PTR(any,d) (any)(d) +# else +# if PTRSIZE == LONGSIZE +# define PTRV unsigned long +# else +# define PTRV unsigned +# endif +# define INT2PTR(any,d) (any)(PTRV)(d) +# endif + +# define NUM2PTR(any,d) (any)(PTRV)(d) +# define PTR2IV(p) INT2PTR(IV,p) +# define PTR2UV(p) INT2PTR(UV,p) +# define PTR2NV(p) NUM2PTR(NV,p) + +# if PTRSIZE == LONGSIZE +# define PTR2ul(p) (unsigned long)(p) +# else +# define PTR2ul(p) INT2PTR(unsigned long,p) +# endif +#endif /* !INT2PTR */ + +#ifndef SvPV_nolen +# define SvPV_nolen(x) SvPV(x,PL_na) +#endif + +#ifndef get_sv +# define get_sv perl_get_sv +#endif + +#ifndef ERRSV +# define ERRSV get_sv("@",FALSE) +#endif + +#ifndef pTHX_ +#define pTHX_ +#endif + +#include +#ifdef __cplusplus +} +#endif + +/* ----------------------------------------------------------------------------- + * error manipulation + * ----------------------------------------------------------------------------- */ + +SWIGINTERN const char* +SWIG_Perl_ErrorType(int code) { + const char* type = 0; + switch(code) { + case SWIG_MemoryError: + type = "MemoryError"; + break; + case SWIG_IOError: + type = "IOError"; + break; + case SWIG_RuntimeError: + type = "RuntimeError"; + break; + case SWIG_IndexError: + type = "IndexError"; + break; + case SWIG_TypeError: + type = "TypeError"; + break; + case SWIG_DivisionByZero: + type = "ZeroDivisionError"; + break; + case SWIG_OverflowError: + type = "OverflowError"; + break; + case SWIG_SyntaxError: + type = "SyntaxError"; + break; + case SWIG_ValueError: + type = "ValueError"; + break; + case SWIG_SystemError: + type = "SystemError"; + break; + case SWIG_AttributeError: + type = "AttributeError"; + break; + default: + type = "RuntimeError"; + } + return type; +} + + + + +/* ----------------------------------------------------------------------------- + * perlrun.swg + * + * This file contains the runtime support for Perl modules + * and includes code for managing global variables and pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +#ifdef PERL_OBJECT +#define SWIG_PERL_OBJECT_DECL CPerlObj *SWIGUNUSEDPARM(pPerl), +#define SWIG_PERL_OBJECT_CALL pPerl, +#else +#define SWIG_PERL_OBJECT_DECL +#define SWIG_PERL_OBJECT_CALL +#endif + +/* Common SWIG API */ + +/* for raw pointers */ +#define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags) +#define SWIG_NewPointerObj(p, type, flags) SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags) + +/* for raw packed data */ +#define SWIG_ConvertPacked(obj, p, s, type) SWIG_Perl_ConvertPacked(SWIG_PERL_OBJECT_CALL obj, p, s, type) +#define SWIG_NewPackedObj(p, s, type) SWIG_Perl_NewPackedObj(SWIG_PERL_OBJECT_CALL p, s, type) + +/* for class or struct pointers */ +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) + +/* for C or C++ function pointers */ +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_ConvertPtr(obj, pptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NewPointerObj(ptr, type, 0) + +/* for C++ member pointers, ie, member methods */ +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_NewPackedObj(ptr, sz, type) + + +/* Runtime API */ + +#define SWIG_GetModule(clientdata) SWIG_Perl_GetModule() +#define SWIG_SetModule(clientdata, pointer) SWIG_Perl_SetModule(pointer) + + +/* Error manipulation */ + +#define SWIG_ErrorType(code) SWIG_Perl_ErrorType(code) +#define SWIG_Error(code, msg) sv_setpvf(GvSV(PL_errgv),"%s %s\n", SWIG_ErrorType(code), msg) +#define SWIG_fail goto fail + +/* Perl-specific SWIG API */ + +#define SWIG_MakePtr(sv, ptr, type, flags) SWIG_Perl_MakePtr(SWIG_PERL_OBJECT_CALL sv, ptr, type, flags) +#define SWIG_MakePackedObj(sv, p, s, type) SWIG_Perl_MakePackedObj(SWIG_PERL_OBJECT_CALL sv, p, s, type) +#define SWIG_SetError(str) SWIG_Error(SWIG_RuntimeError, str) + + +#define SWIG_PERL_DECL_ARGS_1(arg1) (SWIG_PERL_OBJECT_DECL arg1) +#define SWIG_PERL_CALL_ARGS_1(arg1) (SWIG_PERL_OBJECT_CALL arg1) +#define SWIG_PERL_DECL_ARGS_2(arg1, arg2) (SWIG_PERL_OBJECT_DECL arg1, arg2) +#define SWIG_PERL_CALL_ARGS_2(arg1, arg2) (SWIG_PERL_OBJECT_CALL arg1, arg2) + +/* ----------------------------------------------------------------------------- + * pointers/data manipulation + * ----------------------------------------------------------------------------- */ + +/* For backward compatibility only */ +#define SWIG_POINTER_EXCEPTION 0 + +#ifdef __cplusplus +extern "C" { +#endif + +#define SWIG_OWNER SWIG_POINTER_OWN +#define SWIG_SHADOW SWIG_OWNER << 1 + +#define SWIG_MAYBE_PERL_OBJECT SWIG_PERL_OBJECT_DECL + +/* SWIG Perl macros */ + +/* Macro to declare an XS function */ +#ifndef XSPROTO +# define XSPROTO(name) void name(pTHX_ CV* cv) +#endif + +/* Macro to call an XS function */ +#ifdef PERL_OBJECT +# define SWIG_CALLXS(_name) _name(cv,pPerl) +#else +# ifndef MULTIPLICITY +# define SWIG_CALLXS(_name) _name(cv) +# else +# define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) +# endif +#endif + +#ifdef PERL_OBJECT +#define MAGIC_PPERL CPerlObj *pPerl = (CPerlObj *) this; + +#ifdef __cplusplus +extern "C" { +#endif +typedef int (CPerlObj::*SwigMagicFunc)(SV *, MAGIC *); +#ifdef __cplusplus +} +#endif + +#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b) +#define SWIGCLASS_STATIC + +#else /* PERL_OBJECT */ + +#define MAGIC_PPERL +#define SWIGCLASS_STATIC static SWIGUNUSED + +#ifndef MULTIPLICITY +#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b) + +#ifdef __cplusplus +extern "C" { +#endif +typedef int (*SwigMagicFunc)(SV *, MAGIC *); +#ifdef __cplusplus +} +#endif + +#else /* MULTIPLICITY */ + +#define SWIG_MAGIC(a,b) (struct interpreter *interp, SV *a, MAGIC *b) + +#ifdef __cplusplus +extern "C" { +#endif +typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *); +#ifdef __cplusplus +} +#endif + +#endif /* MULTIPLICITY */ +#endif /* PERL_OBJECT */ + +/* Workaround for bug in perl 5.6.x croak and earlier */ +#if (PERL_VERSION < 8) +# ifdef PERL_OBJECT +# define SWIG_croak_null() SWIG_Perl_croak_null(pPerl) +static void SWIG_Perl_croak_null(CPerlObj *pPerl) +# else +static void SWIG_croak_null() +# endif +{ + SV *err=ERRSV; +# if (PERL_VERSION < 6) + croak("%_", err); +# else + if (SvOK(err) && !SvROK(err)) croak("%_", err); + croak(Nullch); +# endif +} +#else +# define SWIG_croak_null() croak(Nullch) +#endif + + +/* + Define how strict is the cast between strings and integers/doubles + when overloading between these types occurs. + + The default is making it as strict as possible by using SWIG_AddCast + when needed. + + You can use -DSWIG_PERL_NO_STRICT_STR2NUM at compilation time to + disable the SWIG_AddCast, making the casting between string and + numbers less strict. + + In the end, we try to solve the overloading between strings and + numerical types in the more natural way, but if you can avoid it, + well, avoid it using %rename, for example. +*/ +#ifndef SWIG_PERL_NO_STRICT_STR2NUM +# ifndef SWIG_PERL_STRICT_STR2NUM +# define SWIG_PERL_STRICT_STR2NUM +# endif +#endif +#ifdef SWIG_PERL_STRICT_STR2NUM +/* string takes precedence */ +#define SWIG_Str2NumCast(x) SWIG_AddCast(x) +#else +/* number takes precedence */ +#define SWIG_Str2NumCast(x) x +#endif + + + +#include + +SWIGRUNTIME const char * +SWIG_Perl_TypeProxyName(const swig_type_info *type) { + if (!type) return NULL; + if (type->clientdata != NULL) { + return (const char*) type->clientdata; + } + else { + return type->name; + } +} + +SWIGRUNTIME swig_cast_info * +SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) { + SWIG_TypeCheck_Template(( (!iter->type->clientdata && (strcmp((char*)iter->type->name, c) == 0)) + || (iter->type->clientdata && (strcmp((char*)iter->type->clientdata, c) == 0))), ty); +} + + +/* Function for getting a pointer value */ + +SWIGRUNTIME int +SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) { + swig_cast_info *tc; + void *voidptr = (void *)0; + SV *tsv = 0; + /* If magical, apply more magic */ + if (SvGMAGICAL(sv)) + mg_get(sv); + + /* Check to see if this is an object */ + if (sv_isobject(sv)) { + IV tmp = 0; + tsv = (SV*) SvRV(sv); + if ((SvTYPE(tsv) == SVt_PVHV)) { + MAGIC *mg; + if (SvMAGICAL(tsv)) { + mg = mg_find(tsv,'P'); + if (mg) { + sv = mg->mg_obj; + if (sv_isobject(sv)) { + tsv = (SV*)SvRV(sv); + tmp = SvIV(tsv); + } + } + } else { + return SWIG_ERROR; + } + } else { + tmp = SvIV(tsv); + } + voidptr = INT2PTR(void *,tmp); + } else if (! SvOK(sv)) { /* Check for undef */ + *(ptr) = (void *) 0; + return SWIG_OK; + } else if (SvTYPE(sv) == SVt_RV) { /* Check for NULL pointer */ + if (!SvROK(sv)) { + *(ptr) = (void *) 0; + return SWIG_OK; + } else { + return SWIG_ERROR; + } + } else { /* Don't know what it is */ + return SWIG_ERROR; + } + if (_t) { + /* Now see if the types match */ + char *_c = HvNAME(SvSTASH(SvRV(sv))); + tc = SWIG_TypeProxyCheck(_c,_t); + if (!tc) { + return SWIG_ERROR; + } + *ptr = SWIG_TypeCast(tc,voidptr); + } else { + *ptr = voidptr; + } + + /* + * DISOWN implementation: we need a perl guru to check this one. + */ + if (tsv && (flags & SWIG_POINTER_DISOWN)) { + /* + * almost copy paste code from below SWIG_POINTER_OWN setting + */ + SV *obj = sv; + HV *stash = SvSTASH(SvRV(obj)); + GV *gv = *(GV**) hv_fetch(stash, "OWNER", 5, TRUE); + if (isGV(gv)) { + HV *hv = GvHVn(gv); + /* + * To set ownership (see below), a newSViv(1) entry is added. + * Hence, to remove ownership, we delete the entry. + */ + if (hv_exists_ent(hv, obj, 0)) { + hv_delete_ent(hv, obj, 0, 0); + } + } + } + return SWIG_OK; +} + +SWIGRUNTIME void +SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) { + if (ptr && (flags & SWIG_SHADOW)) { + SV *self; + SV *obj=newSV(0); + HV *hash=newHV(); + HV *stash; + sv_setref_pv(obj, (char *) SWIG_Perl_TypeProxyName(t), ptr); + stash=SvSTASH(SvRV(obj)); + if (flags & SWIG_POINTER_OWN) { + HV *hv; + GV *gv=*(GV**)hv_fetch(stash, "OWNER", 5, TRUE); + if (!isGV(gv)) + gv_init(gv, stash, "OWNER", 5, FALSE); + hv=GvHVn(gv); + hv_store_ent(hv, obj, newSViv(1), 0); + } + sv_magic((SV *)hash, (SV *)obj, 'P', Nullch, 0); + SvREFCNT_dec(obj); + self=newRV_noinc((SV *)hash); + sv_setsv(sv, self); + SvREFCNT_dec((SV *)self); + sv_bless(sv, stash); + } + else { + sv_setref_pv(sv, (char *) SWIG_Perl_TypeProxyName(t), ptr); + } +} + +SWIGRUNTIMEINLINE SV * +SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) { + SV *result = sv_newmortal(); + SWIG_MakePtr(result, ptr, t, flags); + return result; +} + +SWIGRUNTIME void +SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) { + char result[1024]; + char *r = result; + if ((2*sz + 1 + strlen(SWIG_Perl_TypeProxyName(type))) > 1000) return; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + strcpy(r,SWIG_Perl_TypeProxyName(type)); + sv_setpv(sv, result); +} + +SWIGRUNTIME SV * +SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info *type) { + SV *result = sv_newmortal(); + SWIG_Perl_MakePackedObj(result, ptr, sz, type); + return result; +} + +/* Convert a packed value value */ +SWIGRUNTIME int +SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) { + swig_cast_info *tc; + const char *c = 0; + + if ((!obj) || (!SvOK(obj))) return SWIG_ERROR; + c = SvPV_nolen(obj); + /* Pointer values must start with leading underscore */ + if (*c != '_') return SWIG_ERROR; + c++; + c = SWIG_UnpackData(c,ptr,sz); + if (ty) { + tc = SWIG_TypeCheck(c,ty); + if (!tc) return SWIG_ERROR; + } + return SWIG_OK; +} + + +/* Macros for low-level exception handling */ +#define SWIG_croak(x) { SWIG_Error(SWIG_RuntimeError, x); SWIG_fail; } + + +typedef XSPROTO(SwigPerlWrapper); +typedef SwigPerlWrapper *SwigPerlWrapperPtr; + +/* Structure for command table */ +typedef struct { + const char *name; + SwigPerlWrapperPtr wrapper; +} swig_command_info; + +/* Information for constant table */ + +#define SWIG_INT 1 +#define SWIG_FLOAT 2 +#define SWIG_STRING 3 +#define SWIG_POINTER 4 +#define SWIG_BINARY 5 + +/* Constant information structure */ +typedef struct swig_constant_info { + int type; + const char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_constant_info; + + +/* Structure for variable table */ +typedef struct { + const char *name; + SwigMagicFunc set; + SwigMagicFunc get; + swig_type_info **type; +} swig_variable_info; + +/* Magic variable code */ +#ifndef PERL_OBJECT +#define swig_create_magic(s,a,b,c) _swig_create_magic(s,a,b,c) + #ifndef MULTIPLICITY + SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) + #else + SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) + #endif +#else +# define swig_create_magic(s,a,b,c) _swig_create_magic(pPerl,s,a,b,c) +SWIGRUNTIME void _swig_create_magic(CPerlObj *pPerl, SV *sv, const char *name, int (CPerlObj::*set)(SV *, MAGIC *), int (CPerlObj::*get)(SV *, MAGIC *)) +#endif +{ + MAGIC *mg; + sv_magic(sv,sv,'U',(char *) name,strlen(name)); + mg = mg_find(sv,'U'); + mg->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL)); + mg->mg_virtual->svt_get = (SwigMagicFunc) get; + mg->mg_virtual->svt_set = (SwigMagicFunc) set; + mg->mg_virtual->svt_len = 0; + mg->mg_virtual->svt_clear = 0; + mg->mg_virtual->svt_free = 0; +} + + +SWIGRUNTIME swig_module_info * +SWIG_Perl_GetModule(void) { + static void *type_pointer = (void *)0; + SV *pointer; + + /* first check if pointer already created */ + if (!type_pointer) { + pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, FALSE); + if (pointer && SvOK(pointer)) { + type_pointer = INT2PTR(swig_type_info **, SvIV(pointer)); + } + } + + return (swig_module_info *) type_pointer; +} + +SWIGRUNTIME void +SWIG_Perl_SetModule(swig_module_info *module) { + SV *pointer; + + /* create a new pointer */ + pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TRUE); + sv_setiv(pointer, PTR2IV(module)); +} + +#ifdef __cplusplus +} +#endif + +/* Workaround perl5 global namespace pollution. Note that undefining library + * functions like fopen will not solve the problem on all platforms as fopen + * might be a macro on Windows but not necessarily on other operating systems. */ +#ifdef do_open + #undef do_open +#endif +#ifdef do_close + #undef do_close +#endif +#ifdef scalar + #undef scalar +#endif +#ifdef list + #undef list +#endif +#ifdef apply + #undef apply +#endif +#ifdef convert + #undef convert +#endif +#ifdef Error + #undef Error +#endif +#ifdef form + #undef form +#endif +#ifdef vform + #undef vform +#endif +#ifdef LABEL + #undef LABEL +#endif +#ifdef METHOD + #undef METHOD +#endif +#ifdef Move + #undef Move +#endif +#ifdef yylex + #undef yylex +#endif +#ifdef yyparse + #undef yyparse +#endif +#ifdef yyerror + #undef yyerror +#endif +#ifdef invert + #undef invert +#endif +#ifdef ref + #undef ref +#endif +#ifdef read + #undef read +#endif +#ifdef write + #undef write +#endif +#ifdef eof + #undef eof +#endif +#ifdef bool + #undef bool +#endif +#ifdef close + #undef close +#endif +#ifdef rewind + #undef rewind +#endif +#ifdef free + #undef free +#endif +#ifdef malloc + #undef malloc +#endif +#ifdef calloc + #undef calloc +#endif +#ifdef Stat + #undef Stat +#endif +#ifdef check + #undef check +#endif +#ifdef seekdir + #undef seekdir +#endif +#ifdef open + #undef open +#endif + + + +#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) + +#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else + + + + #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_char swig_types[0] +#define SWIGTYPE_p_config_overwrites_t swig_types[1] +#define SWIGTYPE_p_double swig_types[2] +#define SWIGTYPE_p_dumptype_t swig_types[3] +#define SWIGTYPE_p_float swig_types[4] +#define SWIGTYPE_p_holdingdisk_t swig_types[5] +#define SWIGTYPE_p_int swig_types[6] +#define SWIGTYPE_p_interface_t swig_types[7] +#define SWIGTYPE_p_p_char swig_types[8] +#define SWIGTYPE_p_tapetype_t swig_types[9] +#define SWIGTYPE_p_unsigned_char swig_types[10] +static swig_type_info *swig_types[12]; +static swig_module_info swig_module = {swig_types, 11, 0, 0, 0, 0}; +#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) +#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) + +/* -------- TYPES TABLE (END) -------- */ + +#define SWIG_init boot_Amanda__Config + +#define SWIG_name "Amanda::Configc::boot_Amanda__Config" +#define SWIG_prefix "Amanda::Configc::" + +#define SWIGVERSION 0x010333 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +#ifdef __cplusplus +extern "C" +#endif +#ifndef PERL_OBJECT +#ifndef MULTIPLICITY +SWIGEXPORT void SWIG_init (CV* cv); +#else +SWIGEXPORT void SWIG_init (pTHXo_ CV* cv); +#endif +#else +SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *); +#endif + + +#include "amglue.h" + + +#include "amglue.h" + + +#include "amglue.h" + + +#include "conffile.h" + + +SWIGINTERNINLINE SV * +SWIG_From_long SWIG_PERL_DECL_ARGS_1(long value) +{ + SV *obj = sv_newmortal(); + sv_setiv(obj, (IV) value); + return obj; +} + + +SWIGINTERNINLINE SV * +SWIG_From_int SWIG_PERL_DECL_ARGS_1(int value) +{ + return SWIG_From_long SWIG_PERL_CALL_ARGS_1(value); +} + + +#include +#if !defined(SWIG_NO_LLONG_MAX) +# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) +# define LLONG_MAX __LONG_LONG_MAX__ +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +# endif +#endif + + +SWIGINTERN int +SWIG_AsVal_double SWIG_PERL_DECL_ARGS_2(SV *obj, double *val) +{ + if (SvNIOK(obj)) { + if (val) *val = SvNV(obj); + return SWIG_OK; + } else if (SvIOK(obj)) { + if (val) *val = (double) SvIV(obj); + return SWIG_AddCast(SWIG_OK); + } else { + const char *nptr = SvPV_nolen(obj); + if (nptr) { + char *endptr; + double v = strtod(nptr, &endptr); + if (errno == ERANGE) { + errno = 0; + return SWIG_OverflowError; + } else { + if (*endptr == '\0') { + if (val) *val = v; + return SWIG_Str2NumCast(SWIG_OK); + } + } + } + } + return SWIG_TypeError; +} + + +#include + + +#include + + +SWIGINTERNINLINE int +SWIG_CanCastAsInteger(double *d, double min, double max) { + double x = *d; + if ((min <= x && x <= max)) { + double fx = floor(x); + double cx = ceil(x); + double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ + if ((errno == EDOM) || (errno == ERANGE)) { + errno = 0; + } else { + double summ, reps, diff; + if (rd < x) { + diff = x - rd; + } else if (rd > x) { + diff = rd - x; + } else { + return 1; + } + summ = rd + x; + reps = diff/summ; + if (reps < 8*DBL_EPSILON) { + *d = rd; + return 1; + } + } + } + return 0; +} + + +SWIGINTERN int +SWIG_AsVal_long SWIG_PERL_DECL_ARGS_2(SV *obj, long* val) +{ + if (SvIOK(obj)) { + if (val) *val = SvIV(obj); + return SWIG_OK; + } else { + int dispatch = 0; + const char *nptr = SvPV_nolen(obj); + if (nptr) { + char *endptr; + long v; + errno = 0; + v = strtol(nptr, &endptr,0); + if (errno == ERANGE) { + errno = 0; + return SWIG_OverflowError; + } else { + if (*endptr == '\0') { + if (val) *val = v; + return SWIG_Str2NumCast(SWIG_OK); + } + } + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; + } + } + } + return SWIG_TypeError; +} + + +SWIGINTERN int +SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val) +{ + long v; + int res = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(obj, &v); + if (SWIG_IsOK(res)) { + if ((v < INT_MIN || v > INT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (int)(v); + } + } + return res; +} + + +SWIGINTERN swig_type_info* +SWIG_pchar_descriptor(void) +{ + static int init = 0; + static swig_type_info* info = 0; + if (!init) { + info = SWIG_TypeQuery("_p_char"); + init = 1; + } + return info; +} + + +SWIGINTERN int +SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc) +{ + if (SvPOK(obj)) { + STRLEN len = 0; + char *cstr = SvPV(obj, len); + size_t size = len + 1; + if (cptr) { + if (alloc) { + if (*alloc == SWIG_NEWOBJ) { + *cptr = (char *)memcpy((char *)malloc((size)*sizeof(char)), cstr, sizeof(char)*(size)); + } else { + *cptr = cstr; + *alloc = SWIG_OLDOBJ; + } + } + } + if (psize) *psize = size; + return SWIG_OK; + } else { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + if (pchar_descriptor) { + char* vptr = 0; + if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) { + if (cptr) *cptr = vptr; + if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0; + if (alloc) *alloc = SWIG_OLDOBJ; + return SWIG_OK; + } + } + } + return SWIG_TypeError; +} + + + + + +SWIGINTERNINLINE SV * +SWIG_FromCharPtrAndSize(const char* carray, size_t size) +{ + SV *obj = sv_newmortal(); + if (carray) { + sv_setpvn(obj, carray, size); + } else { + sv_setsv(obj, &PL_sv_undef); + } + return obj; +} + + +SWIGINTERNINLINE SV * +SWIG_FromCharPtr(const char *cptr) +{ + return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); +} + + + char *get_config_name(void) { return config_name; } + char *get_config_dir(void) { return config_dir; } + char *get_config_filename(void) { return config_filename; } + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PERL_OBJECT +#define MAGIC_CLASS _wrap_Amanda::Config_var:: +class _wrap_Amanda::Config_var : public CPerlObj { +public: +#else +#define MAGIC_CLASS +#endif +SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + croak("Value is read-only."); + return 0; +} +SWIGCLASS_STATIC int _wrap_debug_amandad_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_amandad""' of type '""int""'"); + } + debug_amandad = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_amandad_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_amandad))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_amidxtaped_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_amidxtaped""' of type '""int""'"); + } + debug_amidxtaped = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_amidxtaped_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_amidxtaped))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_amindexd_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_amindexd""' of type '""int""'"); + } + debug_amindexd = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_amindexd_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_amindexd))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_amrecover_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_amrecover""' of type '""int""'"); + } + debug_amrecover = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_amrecover_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_amrecover))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_auth_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_auth""' of type '""int""'"); + } + debug_auth = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_auth_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_auth))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_event_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_event""' of type '""int""'"); + } + debug_event = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_event_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_event))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_holding_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_holding""' of type '""int""'"); + } + debug_holding = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_holding_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_holding))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_protocol_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_protocol""' of type '""int""'"); + } + debug_protocol = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_protocol_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_protocol))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_planner_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_planner""' of type '""int""'"); + } + debug_planner = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_planner_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_planner))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_driver_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_driver""' of type '""int""'"); + } + debug_driver = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_driver_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_driver))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_dumper_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_dumper""' of type '""int""'"); + } + debug_dumper = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_dumper_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_dumper))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_chunker_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_chunker""' of type '""int""'"); + } + debug_chunker = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_chunker_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_chunker))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_taper_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_taper""' of type '""int""'"); + } + debug_taper = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_taper_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_taper))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_selfcheck_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_selfcheck""' of type '""int""'"); + } + debug_selfcheck = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_selfcheck_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_selfcheck))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_sendsize_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_sendsize""' of type '""int""'"); + } + debug_sendsize = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_sendsize_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_sendsize))) ; + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_sendbackup_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + { + int val; + int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(sv, &val); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ArgError(res), "in variable '""debug_sendbackup""' of type '""int""'"); + } + debug_sendbackup = (int)(val); + } +fail: + return 1; +} + + +SWIGCLASS_STATIC int _wrap_debug_sendbackup_get(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) { + MAGIC_PPERL + sv_setsv(sv,SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(debug_sendbackup))) ; + return 1; +} + + + + +#ifdef PERL_OBJECT +}; +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif +XS(_wrap_getconf) { + { + confparm_key arg1 ; + val_t *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: getconf(key);"); + } + { + if (sizeof(signed int) == 1) { + arg1 = amglue_SvI8(ST(0)); + } else if (sizeof(signed int) == 2) { + arg1 = amglue_SvI16(ST(0)); + } else if (sizeof(signed int) == 4) { + arg1 = amglue_SvI32(ST(0)); + } else if (sizeof(signed int) == 8) { + arg1 = amglue_SvI64(ST(0)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (val_t *)getconf(arg1); + { + switch (result->type) { + case CONFTYPE_RATE: { + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[1]); + argvi++; + break; + } + + case CONFTYPE_INTRANGE: { + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[1]); + argvi++; + break; + break; + } + + case CONFTYPE_EXINCLUDE: { + /* exincludes are represented in perl as { + * 'list' : [ 'list1', 'list2', ..], + * 'file' : [ 'file1', 'file2', ..], + * 'optional' : 1, + * } + */ + exinclude_t *ei = &val_t__exinclude(result); + AV *list_entries = (AV *)sv_2mortal((SV *)newAV()); + AV *file_entries = (AV *)sv_2mortal((SV *)newAV()); + SV *optional = sv_newmortal(); + HV *hv; + sle_t *iter; + + /* first set up each of the hash values */ + + if (ei->sl_list) { + for (iter = ei->sl_list->first; iter != NULL; iter = iter->next) { + av_push(list_entries, newSVpv(iter->name, 0)); + } + } + + if(ei->sl_file) { + for (iter = ei->sl_file->first; iter != NULL; iter = iter->next) { + av_push(file_entries, newSVpv(iter->name, 0)); + } + } + + sv_setiv(optional, ei->optional); + + /* now build the hash */ + hv = (HV *)sv_2mortal((SV *)newHV()); + + hv_store(hv, "file", 4, newRV((SV *)file_entries), 0); + hv_store(hv, "list", 4, newRV((SV *)list_entries), 0); + hv_store(hv, "optional", 8, optional, 0); + SvREFCNT_inc(optional); + + ST(argvi) = sv_2mortal(newRV((SV *)hv)); + argvi++; + break; + } + + case CONFTYPE_PROPLIST: + ST(argvi) = sv_2mortal(g_hash_table_to_hashref(val_t__proplist(result))); + argvi++; + break; + + case CONFTYPE_SIZE: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__size(result))); + argvi++; + break; + + case CONFTYPE_AM64: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__am64(result))); + argvi++; + break; + + case CONFTYPE_BOOLEAN: /* all same as INT.. */ + case CONFTYPE_COMPRESS: + case CONFTYPE_ENCRYPT: + case CONFTYPE_ESTIMATE: + case CONFTYPE_STRATEGY: + case CONFTYPE_TAPERALGO: + case CONFTYPE_PRIORITY: + case CONFTYPE_HOLDING: + case CONFTYPE_INT: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__int(result))); + argvi++; + break; + + case CONFTYPE_TIME: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__time(result))); + argvi++; + break; + + case CONFTYPE_REAL: + ST(argvi) = sv_newmortal(); + sv_setnv(ST(argvi), val_t__real(result)); + argvi++; + break; + + case CONFTYPE_IDENT: /* same as STRING */ + case CONFTYPE_STR: + ST(argvi) = sv_newmortal(); + sv_setpv(ST(argvi), val_t__str(result)); + argvi++; + break; + + /* No match yet -> not one of the "complex" types */ + default: + SWIG_exception(SWIG_TypeError, "Unknown val_t conftype"); + break; + } + } + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_getconf_seen) { + { + confparm_key arg1 ; + gboolean result; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: getconf_seen(key);"); + } + { + if (sizeof(signed int) == 1) { + arg1 = amglue_SvI8(ST(0)); + } else if (sizeof(signed int) == 2) { + arg1 = amglue_SvI16(ST(0)); + } else if (sizeof(signed int) == 4) { + arg1 = amglue_SvI32(ST(0)); + } else if (sizeof(signed int) == 8) { + arg1 = amglue_SvI64(ST(0)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (gboolean)getconf_seen(arg1); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_getconf_byname) { + { + char *arg1 = (char *) 0 ; + val_t *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: getconf_byname(key);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "getconf_byname" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (val_t *)getconf_byname(arg1); + { + switch (result->type) { + case CONFTYPE_RATE: { + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[1]); + argvi++; + break; + } + + case CONFTYPE_INTRANGE: { + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[1]); + argvi++; + break; + break; + } + + case CONFTYPE_EXINCLUDE: { + /* exincludes are represented in perl as { + * 'list' : [ 'list1', 'list2', ..], + * 'file' : [ 'file1', 'file2', ..], + * 'optional' : 1, + * } + */ + exinclude_t *ei = &val_t__exinclude(result); + AV *list_entries = (AV *)sv_2mortal((SV *)newAV()); + AV *file_entries = (AV *)sv_2mortal((SV *)newAV()); + SV *optional = sv_newmortal(); + HV *hv; + sle_t *iter; + + /* first set up each of the hash values */ + + if (ei->sl_list) { + for (iter = ei->sl_list->first; iter != NULL; iter = iter->next) { + av_push(list_entries, newSVpv(iter->name, 0)); + } + } + + if(ei->sl_file) { + for (iter = ei->sl_file->first; iter != NULL; iter = iter->next) { + av_push(file_entries, newSVpv(iter->name, 0)); + } + } + + sv_setiv(optional, ei->optional); + + /* now build the hash */ + hv = (HV *)sv_2mortal((SV *)newHV()); + + hv_store(hv, "file", 4, newRV((SV *)file_entries), 0); + hv_store(hv, "list", 4, newRV((SV *)list_entries), 0); + hv_store(hv, "optional", 8, optional, 0); + SvREFCNT_inc(optional); + + ST(argvi) = sv_2mortal(newRV((SV *)hv)); + argvi++; + break; + } + + case CONFTYPE_PROPLIST: + ST(argvi) = sv_2mortal(g_hash_table_to_hashref(val_t__proplist(result))); + argvi++; + break; + + case CONFTYPE_SIZE: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__size(result))); + argvi++; + break; + + case CONFTYPE_AM64: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__am64(result))); + argvi++; + break; + + case CONFTYPE_BOOLEAN: /* all same as INT.. */ + case CONFTYPE_COMPRESS: + case CONFTYPE_ENCRYPT: + case CONFTYPE_ESTIMATE: + case CONFTYPE_STRATEGY: + case CONFTYPE_TAPERALGO: + case CONFTYPE_PRIORITY: + case CONFTYPE_HOLDING: + case CONFTYPE_INT: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__int(result))); + argvi++; + break; + + case CONFTYPE_TIME: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__time(result))); + argvi++; + break; + + case CONFTYPE_REAL: + ST(argvi) = sv_newmortal(); + sv_setnv(ST(argvi), val_t__real(result)); + argvi++; + break; + + case CONFTYPE_IDENT: /* same as STRING */ + case CONFTYPE_STR: + ST(argvi) = sv_newmortal(); + sv_setpv(ST(argvi), val_t__str(result)); + argvi++; + break; + + /* No match yet -> not one of the "complex" types */ + default: + SWIG_exception(SWIG_TypeError, "Unknown val_t conftype"); + break; + } + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + +XS(_wrap_getconf_list) { + { + char *arg1 = (char *) 0 ; + GSList *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: getconf_list(listname);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "getconf_list" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (GSList *)getconf_list(arg1); + { + GSList *it = result; + + while (it) { + ST(argvi) = sv_2mortal(newSVpv(it->data, 0)); + argvi++; + it = it->next; + } + + g_slist_free(result); + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + +XS(_wrap_lookup_tapetype) { + { + char *arg1 = (char *) 0 ; + tapetype_t *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: lookup_tapetype(identifier);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "lookup_tapetype" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (tapetype_t *)lookup_tapetype(arg1); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_tapetype_t, 0 | 0); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + +XS(_wrap_tapetype_getconf) { + { + tapetype_t *arg1 = (tapetype_t *) 0 ; + tapetype_key arg2 ; + val_t *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: tapetype_getconf(ttyp,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_tapetype_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "tapetype_getconf" "', argument " "1"" of type '" "tapetype_t *""'"); + } + arg1 = (tapetype_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (val_t *)tapetype_getconf(arg1,arg2); + { + switch (result->type) { + case CONFTYPE_RATE: { + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[1]); + argvi++; + break; + } + + case CONFTYPE_INTRANGE: { + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[1]); + argvi++; + break; + break; + } + + case CONFTYPE_EXINCLUDE: { + /* exincludes are represented in perl as { + * 'list' : [ 'list1', 'list2', ..], + * 'file' : [ 'file1', 'file2', ..], + * 'optional' : 1, + * } + */ + exinclude_t *ei = &val_t__exinclude(result); + AV *list_entries = (AV *)sv_2mortal((SV *)newAV()); + AV *file_entries = (AV *)sv_2mortal((SV *)newAV()); + SV *optional = sv_newmortal(); + HV *hv; + sle_t *iter; + + /* first set up each of the hash values */ + + if (ei->sl_list) { + for (iter = ei->sl_list->first; iter != NULL; iter = iter->next) { + av_push(list_entries, newSVpv(iter->name, 0)); + } + } + + if(ei->sl_file) { + for (iter = ei->sl_file->first; iter != NULL; iter = iter->next) { + av_push(file_entries, newSVpv(iter->name, 0)); + } + } + + sv_setiv(optional, ei->optional); + + /* now build the hash */ + hv = (HV *)sv_2mortal((SV *)newHV()); + + hv_store(hv, "file", 4, newRV((SV *)file_entries), 0); + hv_store(hv, "list", 4, newRV((SV *)list_entries), 0); + hv_store(hv, "optional", 8, optional, 0); + SvREFCNT_inc(optional); + + ST(argvi) = sv_2mortal(newRV((SV *)hv)); + argvi++; + break; + } + + case CONFTYPE_PROPLIST: + ST(argvi) = sv_2mortal(g_hash_table_to_hashref(val_t__proplist(result))); + argvi++; + break; + + case CONFTYPE_SIZE: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__size(result))); + argvi++; + break; + + case CONFTYPE_AM64: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__am64(result))); + argvi++; + break; + + case CONFTYPE_BOOLEAN: /* all same as INT.. */ + case CONFTYPE_COMPRESS: + case CONFTYPE_ENCRYPT: + case CONFTYPE_ESTIMATE: + case CONFTYPE_STRATEGY: + case CONFTYPE_TAPERALGO: + case CONFTYPE_PRIORITY: + case CONFTYPE_HOLDING: + case CONFTYPE_INT: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__int(result))); + argvi++; + break; + + case CONFTYPE_TIME: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__time(result))); + argvi++; + break; + + case CONFTYPE_REAL: + ST(argvi) = sv_newmortal(); + sv_setnv(ST(argvi), val_t__real(result)); + argvi++; + break; + + case CONFTYPE_IDENT: /* same as STRING */ + case CONFTYPE_STR: + ST(argvi) = sv_newmortal(); + sv_setpv(ST(argvi), val_t__str(result)); + argvi++; + break; + + /* No match yet -> not one of the "complex" types */ + default: + SWIG_exception(SWIG_TypeError, "Unknown val_t conftype"); + break; + } + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_tapetype_name) { + { + tapetype_t *arg1 = (tapetype_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: tapetype_name(ttyp);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_tapetype_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "tapetype_name" "', argument " "1"" of type '" "tapetype_t *""'"); + } + arg1 = (tapetype_t *)(argp1); + result = (char *)tapetype_name(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_tapetype_seen) { + { + tapetype_t *arg1 = (tapetype_t *) 0 ; + tapetype_key arg2 ; + gboolean result; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: tapetype_seen(ttyp,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_tapetype_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "tapetype_seen" "', argument " "1"" of type '" "tapetype_t *""'"); + } + arg1 = (tapetype_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (gboolean)tapetype_seen(arg1,arg2); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_lookup_dumptype) { + { + char *arg1 = (char *) 0 ; + dumptype_t *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: lookup_dumptype(identifier);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "lookup_dumptype" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (dumptype_t *)lookup_dumptype(arg1); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_dumptype_t, 0 | 0); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + +XS(_wrap_dumptype_getconf) { + { + dumptype_t *arg1 = (dumptype_t *) 0 ; + dumptype_key arg2 ; + val_t *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: dumptype_getconf(dtyp,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumptype_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumptype_getconf" "', argument " "1"" of type '" "dumptype_t *""'"); + } + arg1 = (dumptype_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (val_t *)dumptype_getconf(arg1,arg2); + { + switch (result->type) { + case CONFTYPE_RATE: { + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[1]); + argvi++; + break; + } + + case CONFTYPE_INTRANGE: { + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[1]); + argvi++; + break; + break; + } + + case CONFTYPE_EXINCLUDE: { + /* exincludes are represented in perl as { + * 'list' : [ 'list1', 'list2', ..], + * 'file' : [ 'file1', 'file2', ..], + * 'optional' : 1, + * } + */ + exinclude_t *ei = &val_t__exinclude(result); + AV *list_entries = (AV *)sv_2mortal((SV *)newAV()); + AV *file_entries = (AV *)sv_2mortal((SV *)newAV()); + SV *optional = sv_newmortal(); + HV *hv; + sle_t *iter; + + /* first set up each of the hash values */ + + if (ei->sl_list) { + for (iter = ei->sl_list->first; iter != NULL; iter = iter->next) { + av_push(list_entries, newSVpv(iter->name, 0)); + } + } + + if(ei->sl_file) { + for (iter = ei->sl_file->first; iter != NULL; iter = iter->next) { + av_push(file_entries, newSVpv(iter->name, 0)); + } + } + + sv_setiv(optional, ei->optional); + + /* now build the hash */ + hv = (HV *)sv_2mortal((SV *)newHV()); + + hv_store(hv, "file", 4, newRV((SV *)file_entries), 0); + hv_store(hv, "list", 4, newRV((SV *)list_entries), 0); + hv_store(hv, "optional", 8, optional, 0); + SvREFCNT_inc(optional); + + ST(argvi) = sv_2mortal(newRV((SV *)hv)); + argvi++; + break; + } + + case CONFTYPE_PROPLIST: + ST(argvi) = sv_2mortal(g_hash_table_to_hashref(val_t__proplist(result))); + argvi++; + break; + + case CONFTYPE_SIZE: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__size(result))); + argvi++; + break; + + case CONFTYPE_AM64: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__am64(result))); + argvi++; + break; + + case CONFTYPE_BOOLEAN: /* all same as INT.. */ + case CONFTYPE_COMPRESS: + case CONFTYPE_ENCRYPT: + case CONFTYPE_ESTIMATE: + case CONFTYPE_STRATEGY: + case CONFTYPE_TAPERALGO: + case CONFTYPE_PRIORITY: + case CONFTYPE_HOLDING: + case CONFTYPE_INT: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__int(result))); + argvi++; + break; + + case CONFTYPE_TIME: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__time(result))); + argvi++; + break; + + case CONFTYPE_REAL: + ST(argvi) = sv_newmortal(); + sv_setnv(ST(argvi), val_t__real(result)); + argvi++; + break; + + case CONFTYPE_IDENT: /* same as STRING */ + case CONFTYPE_STR: + ST(argvi) = sv_newmortal(); + sv_setpv(ST(argvi), val_t__str(result)); + argvi++; + break; + + /* No match yet -> not one of the "complex" types */ + default: + SWIG_exception(SWIG_TypeError, "Unknown val_t conftype"); + break; + } + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_dumptype_name) { + { + dumptype_t *arg1 = (dumptype_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: dumptype_name(dtyp);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumptype_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumptype_name" "', argument " "1"" of type '" "dumptype_t *""'"); + } + arg1 = (dumptype_t *)(argp1); + result = (char *)dumptype_name(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_dumptype_seen) { + { + dumptype_t *arg1 = (dumptype_t *) 0 ; + dumptype_key arg2 ; + gboolean result; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: dumptype_seen(dtyp,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_dumptype_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dumptype_seen" "', argument " "1"" of type '" "dumptype_t *""'"); + } + arg1 = (dumptype_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (gboolean)dumptype_seen(arg1,arg2); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_lookup_interface) { + { + char *arg1 = (char *) 0 ; + interface_t *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: lookup_interface(identifier);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "lookup_interface" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (interface_t *)lookup_interface(arg1); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_interface_t, 0 | 0); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + +XS(_wrap_interface_getconf) { + { + interface_t *arg1 = (interface_t *) 0 ; + interface_key arg2 ; + val_t *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: interface_getconf(iface,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_interface_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "interface_getconf" "', argument " "1"" of type '" "interface_t *""'"); + } + arg1 = (interface_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (val_t *)interface_getconf(arg1,arg2); + { + switch (result->type) { + case CONFTYPE_RATE: { + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[1]); + argvi++; + break; + } + + case CONFTYPE_INTRANGE: { + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[1]); + argvi++; + break; + break; + } + + case CONFTYPE_EXINCLUDE: { + /* exincludes are represented in perl as { + * 'list' : [ 'list1', 'list2', ..], + * 'file' : [ 'file1', 'file2', ..], + * 'optional' : 1, + * } + */ + exinclude_t *ei = &val_t__exinclude(result); + AV *list_entries = (AV *)sv_2mortal((SV *)newAV()); + AV *file_entries = (AV *)sv_2mortal((SV *)newAV()); + SV *optional = sv_newmortal(); + HV *hv; + sle_t *iter; + + /* first set up each of the hash values */ + + if (ei->sl_list) { + for (iter = ei->sl_list->first; iter != NULL; iter = iter->next) { + av_push(list_entries, newSVpv(iter->name, 0)); + } + } + + if(ei->sl_file) { + for (iter = ei->sl_file->first; iter != NULL; iter = iter->next) { + av_push(file_entries, newSVpv(iter->name, 0)); + } + } + + sv_setiv(optional, ei->optional); + + /* now build the hash */ + hv = (HV *)sv_2mortal((SV *)newHV()); + + hv_store(hv, "file", 4, newRV((SV *)file_entries), 0); + hv_store(hv, "list", 4, newRV((SV *)list_entries), 0); + hv_store(hv, "optional", 8, optional, 0); + SvREFCNT_inc(optional); + + ST(argvi) = sv_2mortal(newRV((SV *)hv)); + argvi++; + break; + } + + case CONFTYPE_PROPLIST: + ST(argvi) = sv_2mortal(g_hash_table_to_hashref(val_t__proplist(result))); + argvi++; + break; + + case CONFTYPE_SIZE: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__size(result))); + argvi++; + break; + + case CONFTYPE_AM64: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__am64(result))); + argvi++; + break; + + case CONFTYPE_BOOLEAN: /* all same as INT.. */ + case CONFTYPE_COMPRESS: + case CONFTYPE_ENCRYPT: + case CONFTYPE_ESTIMATE: + case CONFTYPE_STRATEGY: + case CONFTYPE_TAPERALGO: + case CONFTYPE_PRIORITY: + case CONFTYPE_HOLDING: + case CONFTYPE_INT: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__int(result))); + argvi++; + break; + + case CONFTYPE_TIME: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__time(result))); + argvi++; + break; + + case CONFTYPE_REAL: + ST(argvi) = sv_newmortal(); + sv_setnv(ST(argvi), val_t__real(result)); + argvi++; + break; + + case CONFTYPE_IDENT: /* same as STRING */ + case CONFTYPE_STR: + ST(argvi) = sv_newmortal(); + sv_setpv(ST(argvi), val_t__str(result)); + argvi++; + break; + + /* No match yet -> not one of the "complex" types */ + default: + SWIG_exception(SWIG_TypeError, "Unknown val_t conftype"); + break; + } + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_interface_name) { + { + interface_t *arg1 = (interface_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: interface_name(iface);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_interface_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "interface_name" "', argument " "1"" of type '" "interface_t *""'"); + } + arg1 = (interface_t *)(argp1); + result = (char *)interface_name(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_interface_seen) { + { + interface_t *arg1 = (interface_t *) 0 ; + interface_key arg2 ; + gboolean result; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: interface_seen(iface,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_interface_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "interface_seen" "', argument " "1"" of type '" "interface_t *""'"); + } + arg1 = (interface_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (gboolean)interface_seen(arg1,arg2); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_lookup_holdingdisk) { + { + char *arg1 = (char *) 0 ; + holdingdisk_t *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: lookup_holdingdisk(identifier);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "lookup_holdingdisk" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (holdingdisk_t *)lookup_holdingdisk(arg1); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_holdingdisk_t, 0 | 0); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + +XS(_wrap_getconf_holdingdisks) { + { + holdingdisk_t *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 0) || (items > 0)) { + SWIG_croak("Usage: getconf_holdingdisks();"); + } + result = (holdingdisk_t *)getconf_holdingdisks(); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_holdingdisk_t, 0 | 0); argvi++ ; + XSRETURN(argvi); + fail: + SWIG_croak_null(); + } +} + + +XS(_wrap_holdingdisk_next) { + { + holdingdisk_t *arg1 = (holdingdisk_t *) 0 ; + holdingdisk_t *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: holdingdisk_next(hdisk);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_holdingdisk_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "holdingdisk_next" "', argument " "1"" of type '" "holdingdisk_t *""'"); + } + arg1 = (holdingdisk_t *)(argp1); + result = (holdingdisk_t *)holdingdisk_next(arg1); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_holdingdisk_t, 0 | 0); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_holdingdisk_getconf) { + { + holdingdisk_t *arg1 = (holdingdisk_t *) 0 ; + holdingdisk_key arg2 ; + val_t *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: holdingdisk_getconf(hdisk,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_holdingdisk_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "holdingdisk_getconf" "', argument " "1"" of type '" "holdingdisk_t *""'"); + } + arg1 = (holdingdisk_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (val_t *)holdingdisk_getconf(arg1,arg2); + { + switch (result->type) { + case CONFTYPE_RATE: { + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setnv(ST(argvi), val_t__rate(result)[1]); + argvi++; + break; + } + + case CONFTYPE_INTRANGE: { + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[0]); + argvi++; + + ST(argvi)= sv_newmortal(); + sv_setiv(ST(argvi), val_t__intrange(result)[1]); + argvi++; + break; + break; + } + + case CONFTYPE_EXINCLUDE: { + /* exincludes are represented in perl as { + * 'list' : [ 'list1', 'list2', ..], + * 'file' : [ 'file1', 'file2', ..], + * 'optional' : 1, + * } + */ + exinclude_t *ei = &val_t__exinclude(result); + AV *list_entries = (AV *)sv_2mortal((SV *)newAV()); + AV *file_entries = (AV *)sv_2mortal((SV *)newAV()); + SV *optional = sv_newmortal(); + HV *hv; + sle_t *iter; + + /* first set up each of the hash values */ + + if (ei->sl_list) { + for (iter = ei->sl_list->first; iter != NULL; iter = iter->next) { + av_push(list_entries, newSVpv(iter->name, 0)); + } + } + + if(ei->sl_file) { + for (iter = ei->sl_file->first; iter != NULL; iter = iter->next) { + av_push(file_entries, newSVpv(iter->name, 0)); + } + } + + sv_setiv(optional, ei->optional); + + /* now build the hash */ + hv = (HV *)sv_2mortal((SV *)newHV()); + + hv_store(hv, "file", 4, newRV((SV *)file_entries), 0); + hv_store(hv, "list", 4, newRV((SV *)list_entries), 0); + hv_store(hv, "optional", 8, optional, 0); + SvREFCNT_inc(optional); + + ST(argvi) = sv_2mortal(newRV((SV *)hv)); + argvi++; + break; + } + + case CONFTYPE_PROPLIST: + ST(argvi) = sv_2mortal(g_hash_table_to_hashref(val_t__proplist(result))); + argvi++; + break; + + case CONFTYPE_SIZE: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__size(result))); + argvi++; + break; + + case CONFTYPE_AM64: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__am64(result))); + argvi++; + break; + + case CONFTYPE_BOOLEAN: /* all same as INT.. */ + case CONFTYPE_COMPRESS: + case CONFTYPE_ENCRYPT: + case CONFTYPE_ESTIMATE: + case CONFTYPE_STRATEGY: + case CONFTYPE_TAPERALGO: + case CONFTYPE_PRIORITY: + case CONFTYPE_HOLDING: + case CONFTYPE_INT: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__int(result))); + argvi++; + break; + + case CONFTYPE_TIME: + ST(argvi) = sv_2mortal(amglue_newSVi64(val_t__time(result))); + argvi++; + break; + + case CONFTYPE_REAL: + ST(argvi) = sv_newmortal(); + sv_setnv(ST(argvi), val_t__real(result)); + argvi++; + break; + + case CONFTYPE_IDENT: /* same as STRING */ + case CONFTYPE_STR: + ST(argvi) = sv_newmortal(); + sv_setpv(ST(argvi), val_t__str(result)); + argvi++; + break; + + /* No match yet -> not one of the "complex" types */ + default: + SWIG_exception(SWIG_TypeError, "Unknown val_t conftype"); + break; + } + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_holdingdisk_name) { + { + holdingdisk_t *arg1 = (holdingdisk_t *) 0 ; + char *result = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: holdingdisk_name(hdisk);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_holdingdisk_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "holdingdisk_name" "', argument " "1"" of type '" "holdingdisk_t *""'"); + } + arg1 = (holdingdisk_t *)(argp1); + result = (char *)holdingdisk_name(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_holdingdisk_seen) { + { + holdingdisk_t *arg1 = (holdingdisk_t *) 0 ; + holdingdisk_key arg2 ; + gboolean result; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: holdingdisk_seen(hdisk,key);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_holdingdisk_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "holdingdisk_seen" "', argument " "1"" of type '" "holdingdisk_t *""'"); + } + arg1 = (holdingdisk_t *)(argp1); + { + if (sizeof(signed int) == 1) { + arg2 = amglue_SvI8(ST(1)); + } else if (sizeof(signed int) == 2) { + arg2 = amglue_SvI16(ST(1)); + } else if (sizeof(signed int) == 4) { + arg2 = amglue_SvI32(ST(1)); + } else if (sizeof(signed int) == 8) { + arg2 = amglue_SvI64(ST(1)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (gboolean)holdingdisk_seen(arg1,arg2); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + + + XSRETURN(argvi); + fail: + + + SWIG_croak_null(); + } +} + + +XS(_wrap_getconf_unit_divisor) { + { + long result; + int argvi = 0; + dXSARGS; + + if ((items < 0) || (items > 0)) { + SWIG_croak("Usage: getconf_unit_divisor();"); + } + result = (long)getconf_unit_divisor(); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + XSRETURN(argvi); + fail: + SWIG_croak_null(); + } +} + + +XS(_wrap_new_config_overwrites) { + { + int arg1 ; + config_overwrites_t *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: new_config_overwrites(size_estimate);"); + } + { + if (sizeof(signed int) == 1) { + arg1 = amglue_SvI8(ST(0)); + } else if (sizeof(signed int) == 2) { + arg1 = amglue_SvI16(ST(0)); + } else if (sizeof(signed int) == 4) { + arg1 = amglue_SvI32(ST(0)); + } else if (sizeof(signed int) == 8) { + arg1 = amglue_SvI64(ST(0)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (config_overwrites_t *)new_config_overwrites(arg1); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_config_overwrites_t, 0 | 0); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_free_config_overwrites) { + { + config_overwrites_t *arg1 = (config_overwrites_t *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: free_config_overwrites(co);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_config_overwrites_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "free_config_overwrites" "', argument " "1"" of type '" "config_overwrites_t *""'"); + } + arg1 = (config_overwrites_t *)(argp1); + free_config_overwrites(arg1); + + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_add_config_overwrite) { + { + config_overwrites_t *arg1 = (config_overwrites_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 3) || (items > 3)) { + SWIG_croak("Usage: add_config_overwrite(co,key,value);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_config_overwrites_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "add_config_overwrite" "', argument " "1"" of type '" "config_overwrites_t *""'"); + } + arg1 = (config_overwrites_t *)(argp1); + res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "add_config_overwrite" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "add_config_overwrite" "', argument " "3"" of type '" "char *""'"); + } + arg3 = (char *)(buf3); + add_config_overwrite(arg1,arg2,arg3); + + + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + XSRETURN(argvi); + fail: + + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + SWIG_croak_null(); + } +} + + +XS(_wrap_add_config_overwrite_opt) { + { + config_overwrites_t *arg1 = (config_overwrites_t *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: add_config_overwrite_opt(co,optarg);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_config_overwrites_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "add_config_overwrite_opt" "', argument " "1"" of type '" "config_overwrites_t *""'"); + } + arg1 = (config_overwrites_t *)(argp1); + res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "add_config_overwrite_opt" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + add_config_overwrite_opt(arg1,arg2); + + + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + XSRETURN(argvi); + fail: + + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + SWIG_croak_null(); + } +} + + +XS(_wrap_apply_config_overwrites) { + { + config_overwrites_t *arg1 = (config_overwrites_t *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: apply_config_overwrites(co);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_config_overwrites_t, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "apply_config_overwrites" "', argument " "1"" of type '" "config_overwrites_t *""'"); + } + arg1 = (config_overwrites_t *)(argp1); + apply_config_overwrites(arg1); + + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_config_init) { + { + config_init_flags arg1 ; + char *arg2 = (char *) 0 ; + gboolean result; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: config_init(flags,arg_config_name);"); + } + { + if (sizeof(signed int) == 1) { + arg1 = amglue_SvI8(ST(0)); + } else if (sizeof(signed int) == 2) { + arg1 = amglue_SvI16(ST(0)); + } else if (sizeof(signed int) == 4) { + arg1 = amglue_SvI32(ST(0)); + } else if (sizeof(signed int) == 8) { + arg1 = amglue_SvI64(ST(0)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "config_init" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + result = (gboolean)config_init(arg1,arg2); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + XSRETURN(argvi); + fail: + + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + SWIG_croak_null(); + } +} + + +XS(_wrap_config_uninit) { + { + int argvi = 0; + dXSARGS; + + if ((items < 0) || (items > 0)) { + SWIG_croak("Usage: config_uninit();"); + } + config_uninit(); + + XSRETURN(argvi); + fail: + SWIG_croak_null(); + } +} + + +XS(_wrap_get_config_options) { + { + int arg1 ; + char **result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: get_config_options(first);"); + } + { + if (sizeof(signed int) == 1) { + arg1 = amglue_SvI8(ST(0)); + } else if (sizeof(signed int) == 2) { + arg1 = amglue_SvI16(ST(0)); + } else if (sizeof(signed int) == 4) { + arg1 = amglue_SvI32(ST(0)); + } else if (sizeof(signed int) == 8) { + arg1 = amglue_SvI64(ST(0)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (char **)get_config_options(arg1); + ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_p_char, 0 | 0); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_get_config_name) { + { + char *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 0) || (items > 0)) { + SWIG_croak("Usage: get_config_name();"); + } + result = (char *)get_config_name(); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + XSRETURN(argvi); + fail: + SWIG_croak_null(); + } +} + + +XS(_wrap_get_config_dir) { + { + char *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 0) || (items > 0)) { + SWIG_croak("Usage: get_config_dir();"); + } + result = (char *)get_config_dir(); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + XSRETURN(argvi); + fail: + SWIG_croak_null(); + } +} + + +XS(_wrap_get_config_filename) { + { + char *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 0) || (items > 0)) { + SWIG_croak("Usage: get_config_filename();"); + } + result = (char *)get_config_filename(); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + XSRETURN(argvi); + fail: + SWIG_croak_null(); + } +} + + +XS(_wrap_dump_configuration) { + { + int argvi = 0; + dXSARGS; + + if ((items < 0) || (items > 0)) { + SWIG_croak("Usage: dump_configuration();"); + } + dump_configuration(); + + XSRETURN(argvi); + fail: + SWIG_croak_null(); + } +} + + +XS(_wrap_config_dir_relative) { + { + char *arg1 = (char *) 0 ; + char *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: config_dir_relative(filename);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "config_dir_relative" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (char *)config_dir_relative(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + +XS(_wrap_taperalgo2str) { + { + taperalgo_t arg1 ; + char *result = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: taperalgo2str(taperalgo);"); + } + { + if (sizeof(signed int) == 1) { + arg1 = amglue_SvI8(ST(0)); + } else if (sizeof(signed int) == 2) { + arg1 = amglue_SvI16(ST(0)); + } else if (sizeof(signed int) == 4) { + arg1 = amglue_SvI32(ST(0)); + } else if (sizeof(signed int) == 8) { + arg1 = amglue_SvI64(ST(0)); + } else { + g_critical("Unexpected signed int >64 bits?"); /* should be optimized out unless sizeof(signed int) > 8 */ + } + } + result = (char *)taperalgo2str(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + + XSRETURN(argvi); + fail: + + SWIG_croak_null(); + } +} + + +XS(_wrap_find_multiplier) { + { + char *arg1 = (char *) 0 ; + gint64 result; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: find_multiplier(casestr);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "find_multiplier" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = find_multiplier(arg1); + { + ST(argvi) = sv_2mortal(amglue_newSVi64(result)); + argvi++; + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + SWIG_croak_null(); + } +} + + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_char = {"_p_char", "gchar *|char *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_config_overwrites_t = {"_p_config_overwrites_t", "config_overwrites_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_double = {"_p_double", "double *|gdouble *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_dumptype_t = {"_p_dumptype_t", "dumptype_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_float = {"_p_float", "float *|gfloat *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_holdingdisk_t = {"_p_holdingdisk_t", "holdingdisk_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_int = {"_p_int", "strategy_t *|int *|comp_t *|dump_holdingdisk_t *|holdingdisk_key *|interface_key *|confparm_key *|dumptype_key *|tapetype_key *|encrypt_t *|taperalgo_t *|gboolean *|estimate_t *|config_init_flags *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_interface_t = {"_p_interface_t", "interface_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_tapetype_t = {"_p_tapetype_t", "tapetype_t *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "guchar *|unsigned char *", 0, 0, (void*)0, 0}; + +static swig_type_info *swig_type_initial[] = { + &_swigt__p_char, + &_swigt__p_config_overwrites_t, + &_swigt__p_double, + &_swigt__p_dumptype_t, + &_swigt__p_float, + &_swigt__p_holdingdisk_t, + &_swigt__p_int, + &_swigt__p_interface_t, + &_swigt__p_p_char, + &_swigt__p_tapetype_t, + &_swigt__p_unsigned_char, +}; + +static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_config_overwrites_t[] = { {&_swigt__p_config_overwrites_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_double[] = { {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_dumptype_t[] = { {&_swigt__p_dumptype_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_float[] = { {&_swigt__p_float, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_holdingdisk_t[] = { {&_swigt__p_holdingdisk_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_interface_t[] = { {&_swigt__p_interface_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_p_char[] = { {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_tapetype_t[] = { {&_swigt__p_tapetype_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; + +static swig_cast_info *swig_cast_initial[] = { + _swigc__p_char, + _swigc__p_config_overwrites_t, + _swigc__p_double, + _swigc__p_dumptype_t, + _swigc__p_float, + _swigc__p_holdingdisk_t, + _swigc__p_int, + _swigc__p_interface_t, + _swigc__p_p_char, + _swigc__p_tapetype_t, + _swigc__p_unsigned_char, +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +static swig_constant_info swig_constants[] = { +{0,0,0,0,0,0} +}; +#ifdef __cplusplus +} +#endif +static swig_variable_info swig_variables[] = { + { "Amanda::Configc::debug_amandad", MAGIC_CLASS _wrap_debug_amandad_set, MAGIC_CLASS _wrap_debug_amandad_get,0 }, + { "Amanda::Configc::debug_amidxtaped", MAGIC_CLASS _wrap_debug_amidxtaped_set, MAGIC_CLASS _wrap_debug_amidxtaped_get,0 }, + { "Amanda::Configc::debug_amindexd", MAGIC_CLASS _wrap_debug_amindexd_set, MAGIC_CLASS _wrap_debug_amindexd_get,0 }, + { "Amanda::Configc::debug_amrecover", MAGIC_CLASS _wrap_debug_amrecover_set, MAGIC_CLASS _wrap_debug_amrecover_get,0 }, + { "Amanda::Configc::debug_auth", MAGIC_CLASS _wrap_debug_auth_set, MAGIC_CLASS _wrap_debug_auth_get,0 }, + { "Amanda::Configc::debug_event", MAGIC_CLASS _wrap_debug_event_set, MAGIC_CLASS _wrap_debug_event_get,0 }, + { "Amanda::Configc::debug_holding", MAGIC_CLASS _wrap_debug_holding_set, MAGIC_CLASS _wrap_debug_holding_get,0 }, + { "Amanda::Configc::debug_protocol", MAGIC_CLASS _wrap_debug_protocol_set, MAGIC_CLASS _wrap_debug_protocol_get,0 }, + { "Amanda::Configc::debug_planner", MAGIC_CLASS _wrap_debug_planner_set, MAGIC_CLASS _wrap_debug_planner_get,0 }, + { "Amanda::Configc::debug_driver", MAGIC_CLASS _wrap_debug_driver_set, MAGIC_CLASS _wrap_debug_driver_get,0 }, + { "Amanda::Configc::debug_dumper", MAGIC_CLASS _wrap_debug_dumper_set, MAGIC_CLASS _wrap_debug_dumper_get,0 }, + { "Amanda::Configc::debug_chunker", MAGIC_CLASS _wrap_debug_chunker_set, MAGIC_CLASS _wrap_debug_chunker_get,0 }, + { "Amanda::Configc::debug_taper", MAGIC_CLASS _wrap_debug_taper_set, MAGIC_CLASS _wrap_debug_taper_get,0 }, + { "Amanda::Configc::debug_selfcheck", MAGIC_CLASS _wrap_debug_selfcheck_set, MAGIC_CLASS _wrap_debug_selfcheck_get,0 }, + { "Amanda::Configc::debug_sendsize", MAGIC_CLASS _wrap_debug_sendsize_set, MAGIC_CLASS _wrap_debug_sendsize_get,0 }, + { "Amanda::Configc::debug_sendbackup", MAGIC_CLASS _wrap_debug_sendbackup_set, MAGIC_CLASS _wrap_debug_sendbackup_get,0 }, +{0,0,0,0} +}; +static swig_command_info swig_commands[] = { +{"Amanda::Configc::getconf", _wrap_getconf}, +{"Amanda::Configc::getconf_seen", _wrap_getconf_seen}, +{"Amanda::Configc::getconf_byname", _wrap_getconf_byname}, +{"Amanda::Configc::getconf_list", _wrap_getconf_list}, +{"Amanda::Configc::lookup_tapetype", _wrap_lookup_tapetype}, +{"Amanda::Configc::tapetype_getconf", _wrap_tapetype_getconf}, +{"Amanda::Configc::tapetype_name", _wrap_tapetype_name}, +{"Amanda::Configc::tapetype_seen", _wrap_tapetype_seen}, +{"Amanda::Configc::lookup_dumptype", _wrap_lookup_dumptype}, +{"Amanda::Configc::dumptype_getconf", _wrap_dumptype_getconf}, +{"Amanda::Configc::dumptype_name", _wrap_dumptype_name}, +{"Amanda::Configc::dumptype_seen", _wrap_dumptype_seen}, +{"Amanda::Configc::lookup_interface", _wrap_lookup_interface}, +{"Amanda::Configc::interface_getconf", _wrap_interface_getconf}, +{"Amanda::Configc::interface_name", _wrap_interface_name}, +{"Amanda::Configc::interface_seen", _wrap_interface_seen}, +{"Amanda::Configc::lookup_holdingdisk", _wrap_lookup_holdingdisk}, +{"Amanda::Configc::getconf_holdingdisks", _wrap_getconf_holdingdisks}, +{"Amanda::Configc::holdingdisk_next", _wrap_holdingdisk_next}, +{"Amanda::Configc::holdingdisk_getconf", _wrap_holdingdisk_getconf}, +{"Amanda::Configc::holdingdisk_name", _wrap_holdingdisk_name}, +{"Amanda::Configc::holdingdisk_seen", _wrap_holdingdisk_seen}, +{"Amanda::Configc::getconf_unit_divisor", _wrap_getconf_unit_divisor}, +{"Amanda::Configc::new_config_overwrites", _wrap_new_config_overwrites}, +{"Amanda::Configc::free_config_overwrites", _wrap_free_config_overwrites}, +{"Amanda::Configc::add_config_overwrite", _wrap_add_config_overwrite}, +{"Amanda::Configc::add_config_overwrite_opt", _wrap_add_config_overwrite_opt}, +{"Amanda::Configc::apply_config_overwrites", _wrap_apply_config_overwrites}, +{"Amanda::Configc::config_init", _wrap_config_init}, +{"Amanda::Configc::config_uninit", _wrap_config_uninit}, +{"Amanda::Configc::get_config_options", _wrap_get_config_options}, +{"Amanda::Configc::get_config_name", _wrap_get_config_name}, +{"Amanda::Configc::get_config_dir", _wrap_get_config_dir}, +{"Amanda::Configc::get_config_filename", _wrap_get_config_filename}, +{"Amanda::Configc::dump_configuration", _wrap_dump_configuration}, +{"Amanda::Configc::config_dir_relative", _wrap_config_dir_relative}, +{"Amanda::Configc::taperalgo2str", _wrap_taperalgo2str}, +{"Amanda::Configc::find_multiplier", _wrap_find_multiplier}, +{0,0} +}; +/* ----------------------------------------------------------------------------- + * Type initialization: + * This problem is tough by the requirement that no dynamic + * memory is used. Also, since swig_type_info structures store pointers to + * swig_cast_info structures and swig_cast_info structures store pointers back + * to swig_type_info structures, we need some lookup code at initialization. + * The idea is that swig generates all the structures that are needed. + * The runtime then collects these partially filled structures. + * The SWIG_InitializeModule function takes these initial arrays out of + * swig_module, and does all the lookup, filling in the swig_module.types + * array with the correct data and linking the correct swig_cast_info + * structures together. + * + * The generated swig_type_info structures are assigned staticly to an initial + * array. We just loop through that array, and handle each type individually. + * First we lookup if this type has been already loaded, and if so, use the + * loaded structure instead of the generated one. Then we have to fill in the + * cast linked list. The cast data is initially stored in something like a + * two-dimensional array. Each row corresponds to a type (there are the same + * number of rows as there are in the swig_type_initial array). Each entry in + * a column is one of the swig_cast_info structures for that type. + * The cast_initial array is actually an array of arrays, because each row has + * a variable number of columns. So to actually build the cast linked list, + * we find the array of casts associated with the type, and loop through it + * adding the casts to the list. The one last trick we need to do is making + * sure the type pointer in the swig_cast_info struct is correct. + * + * First off, we lookup the cast->type name to see if it is already loaded. + * There are three cases to handle: + * 1) If the cast->type has already been loaded AND the type we are adding + * casting info to has not been loaded (it is in this module), THEN we + * replace the cast->type pointer with the type pointer that has already + * been loaded. + * 2) If BOTH types (the one we are adding casting info to, and the + * cast->type) are loaded, THEN the cast info has already been loaded by + * the previous module so we just ignore it. + * 3) Finally, if cast->type has not already been loaded, then we add that + * swig_cast_info to the linked list (because the cast->type) pointer will + * be correct. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* c-mode */ +#endif +#endif + +#if 0 +#define SWIGRUNTIME_DEBUG +#endif + + +SWIGRUNTIME void +SWIG_InitializeModule(void *clientdata) { + size_t i; + swig_module_info *module_head, *iter; + int found; + + clientdata = clientdata; + + /* check to see if the circular list has been setup, if not, set it up */ + if (swig_module.next==0) { + /* Initialize the swig_module */ + swig_module.type_initial = swig_type_initial; + swig_module.cast_initial = swig_cast_initial; + swig_module.next = &swig_module; + } + + /* Try and load any already created modules */ + module_head = SWIG_GetModule(clientdata); + if (!module_head) { + /* This is the first module loaded for this interpreter */ + /* so set the swig module into the interpreter */ + SWIG_SetModule(clientdata, &swig_module); + module_head = &swig_module; + } else { + /* the interpreter has loaded a SWIG module, but has it loaded this one? */ + found=0; + iter=module_head; + do { + if (iter==&swig_module) { + found=1; + break; + } + iter=iter->next; + } while (iter!= module_head); + + /* if the is found in the list, then all is done and we may leave */ + if (found) return; + /* otherwise we must add out module into the list */ + swig_module.next = module_head->next; + module_head->next = &swig_module; + } + + /* Now work on filling in swig_module.types */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: size %d\n", swig_module.size); +#endif + for (i = 0; i < swig_module.size; ++i) { + swig_type_info *type = 0; + swig_type_info *ret; + swig_cast_info *cast; + +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); +#endif + + /* if there is another module already loaded */ + if (swig_module.next != &swig_module) { + type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + } + if (type) { + /* Overwrite clientdata field */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found type %s\n", type->name); +#endif + if (swig_module.type_initial[i]->clientdata) { + type->clientdata = swig_module.type_initial[i]->clientdata; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); +#endif + } + } else { + type = swig_module.type_initial[i]; + } + + /* Insert casting types */ + cast = swig_module.cast_initial[i]; + while (cast->type) { + /* Don't need to add information already in the list */ + ret = 0; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); +#endif + if (swig_module.next != &swig_module) { + ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); +#ifdef SWIGRUNTIME_DEBUG + if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); +#endif + } + if (ret) { + if (type == swig_module.type_initial[i]) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: skip old type %s\n", ret->name); +#endif + cast->type = ret; + ret = 0; + } else { + /* Check for casting already in the list */ + swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); +#ifdef SWIGRUNTIME_DEBUG + if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); +#endif + if (!ocast) ret = 0; + } + } + + if (!ret) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); +#endif + if (type->cast) { + type->cast->prev = cast; + cast->next = type->cast; + } + type->cast = cast; + } + cast++; + } + /* Set entry in modules->types array equal to the type */ + swig_module.types[i] = type; + } + swig_module.types[i] = 0; + +#ifdef SWIGRUNTIME_DEBUG + printf("**** SWIG_InitializeModule: Cast List ******\n"); + for (i = 0; i < swig_module.size; ++i) { + int j = 0; + swig_cast_info *cast = swig_module.cast_initial[i]; + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + while (cast->type) { + printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); + cast++; + ++j; + } + printf("---- Total casts: %d\n",j); + } + printf("**** SWIG_InitializeModule: Cast List ******\n"); +#endif +} + +/* This function will propagate the clientdata field of type to +* any new swig_type_info structures that have been added into the list +* of equivalent types. It is like calling +* SWIG_TypeClientData(type, clientdata) a second time. +*/ +SWIGRUNTIME void +SWIG_PropagateClientData(void) { + size_t i; + swig_cast_info *equiv; + static int init_run = 0; + + if (init_run) return; + init_run = 1; + + for (i = 0; i < swig_module.size; i++) { + if (swig_module.types[i]->clientdata) { + equiv = swig_module.types[i]->cast; + while (equiv) { + if (!equiv->converter) { + if (equiv->type && !equiv->type->clientdata) + SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + } + equiv = equiv->next; + } + } + } +} + +#ifdef __cplusplus +#if 0 +{ + /* c-mode */ +#endif +} +#endif + + + +#ifdef __cplusplus +extern "C" +#endif + +XS(SWIG_init) { + dXSARGS; + int i; + + SWIG_InitializeModule(0); + + /* Install commands */ + for (i = 0; swig_commands[i].name; i++) { + newXS((char*) swig_commands[i].name,swig_commands[i].wrapper, (char*)__FILE__); + } + + /* Install variables */ + for (i = 0; swig_variables[i].name; i++) { + SV *sv; + sv = get_sv((char*) swig_variables[i].name, TRUE | 0x2); + if (swig_variables[i].type) { + SWIG_MakePtr(sv,(void *)1, *swig_variables[i].type,0); + } else { + sv_setiv(sv,(IV) 0); + } + swig_create_magic(sv, (char *) swig_variables[i].name, swig_variables[i].set, swig_variables[i].get); + } + + /* Install constant */ + for (i = 0; swig_constants[i].type; i++) { + SV *sv; + sv = get_sv((char*)swig_constants[i].name, TRUE | 0x2); + switch(swig_constants[i].type) { + case SWIG_INT: + sv_setiv(sv, (IV) swig_constants[i].lvalue); + break; + case SWIG_FLOAT: + sv_setnv(sv, (double) swig_constants[i].dvalue); + break; + case SWIG_STRING: + sv_setpv(sv, (char *) swig_constants[i].pvalue); + break; + case SWIG_POINTER: + SWIG_MakePtr(sv, swig_constants[i].pvalue, *(swig_constants[i].ptype),0); + break; + case SWIG_BINARY: + SWIG_MakePackedObj(sv, swig_constants[i].pvalue, swig_constants[i].lvalue, *(swig_constants[i].ptype)); + break; + default: + break; + } + SvREADONLY_on(sv); + } + + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_ORG", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_ORG))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_CONF", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_CONF))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_INDEX_SERVER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_INDEX_SERVER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPE_SERVER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPE_SERVER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_AUTH", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_AUTH))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_SSH_KEYS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_SSH_KEYS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_AMANDAD_PATH", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_AMANDAD_PATH))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_CLIENT_USERNAME", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_CLIENT_USERNAME))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_GNUTAR_LIST_DIR", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_GNUTAR_LIST_DIR))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_AMANDATES", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_AMANDATES))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_MAILTO", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_MAILTO))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DUMPUSER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DUMPUSER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPEDEV", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPEDEV))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEVICE_PROPERTY", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEVICE_PROPERTY))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_CHANGERDEV", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_CHANGERDEV))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_CHANGERFILE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_CHANGERFILE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_LABELSTR", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_LABELSTR))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPELIST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPELIST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DISKFILE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DISKFILE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_INFOFILE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_INFOFILE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_LOGDIR", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_LOGDIR))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_INDEXDIR", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_INDEXDIR))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPETYPE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPETYPE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DUMPCYCLE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DUMPCYCLE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_RUNSPERCYCLE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_RUNSPERCYCLE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPECYCLE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPECYCLE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_NETUSAGE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_NETUSAGE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_INPARALLEL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_INPARALLEL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DUMPORDER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DUMPORDER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_BUMPPERCENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_BUMPPERCENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_BUMPSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_BUMPSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_BUMPMULT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_BUMPMULT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_BUMPDAYS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_BUMPDAYS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TPCHANGER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TPCHANGER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_RUNTAPES", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_RUNTAPES))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_MAXDUMPS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_MAXDUMPS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_ETIMEOUT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_ETIMEOUT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DTIMEOUT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DTIMEOUT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_CTIMEOUT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_CTIMEOUT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPEBUFS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPEBUFS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEVICE_OUTPUT_BUFFER_SIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEVICE_OUTPUT_BUFFER_SIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_PRINTER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_PRINTER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_AUTOFLUSH", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_AUTOFLUSH))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_RESERVE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_RESERVE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_MAXDUMPSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_MAXDUMPSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_COLUMNSPEC", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_COLUMNSPEC))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_AMRECOVER_DO_FSF", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_AMRECOVER_DO_FSF))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_AMRECOVER_CHECK_LABEL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_AMRECOVER_CHECK_LABEL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_AMRECOVER_CHANGER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_AMRECOVER_CHANGER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPERALGO", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPERALGO))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_FLUSH_THRESHOLD_DUMPED", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_FLUSH_THRESHOLD_DUMPED))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_FLUSH_THRESHOLD_SCHEDULED", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_FLUSH_THRESHOLD_SCHEDULED))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_TAPERFLUSH", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_TAPERFLUSH))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DISPLAYUNIT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DISPLAYUNIT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_KRB5KEYTAB", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_KRB5KEYTAB))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_KRB5PRINCIPAL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_KRB5PRINCIPAL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_LABEL_NEW_TAPES", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_LABEL_NEW_TAPES))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_USETIMESTAMPS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_USETIMESTAMPS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_REP_TRIES", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_REP_TRIES))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_CONNECT_TRIES", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_CONNECT_TRIES))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_REQ_TRIES", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_REQ_TRIES))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_AMANDAD", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_AMANDAD))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_AMIDXTAPED", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_AMIDXTAPED))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_AMINDEXD", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_AMINDEXD))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_AMRECOVER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_AMRECOVER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_AUTH", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_AUTH))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_EVENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_EVENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_HOLDING", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_HOLDING))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_PROTOCOL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_PROTOCOL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_PLANNER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_PLANNER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_DRIVER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_DRIVER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_DUMPER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_DUMPER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_CHUNKER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_CHUNKER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_TAPER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_TAPER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_SELFCHECK", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_SELFCHECK))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_SENDSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_SENDSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_DEBUG_SENDBACKUP", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_DEBUG_SENDBACKUP))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_RESERVED_UDP_PORT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_RESERVED_UDP_PORT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_RESERVED_TCP_PORT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_RESERVED_TCP_PORT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CNF_UNRESERVED_TCP_PORT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CNF_UNRESERVED_TCP_PORT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_COMMENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_COMMENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_LBL_TEMPL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_LBL_TEMPL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_BLOCKSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_BLOCKSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_READBLOCKSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_READBLOCKSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_LENGTH", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_LENGTH))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_FILEMARK", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_FILEMARK))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_SPEED", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_SPEED))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "TAPETYPE_FILE_PAD", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(TAPETYPE_FILE_PAD))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_COMMENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_COMMENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_PROGRAM", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_PROGRAM))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SRVCOMPPROG", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SRVCOMPPROG))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_CLNTCOMPPROG", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_CLNTCOMPPROG))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SRV_ENCRYPT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SRV_ENCRYPT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_CLNT_ENCRYPT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_CLNT_ENCRYPT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_AMANDAD_PATH", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_AMANDAD_PATH))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_CLIENT_USERNAME", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_CLIENT_USERNAME))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SSH_KEYS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SSH_KEYS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SECURITY_DRIVER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SECURITY_DRIVER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_EXCLUDE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_EXCLUDE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_INCLUDE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_INCLUDE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_PRIORITY", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_PRIORITY))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_DUMPCYCLE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_DUMPCYCLE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_MAXDUMPS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_MAXDUMPS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_MAXPROMOTEDAY", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_MAXPROMOTEDAY))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_BUMPPERCENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_BUMPPERCENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_BUMPSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_BUMPSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_BUMPDAYS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_BUMPDAYS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_BUMPMULT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_BUMPMULT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_STARTTIME", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_STARTTIME))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_STRATEGY", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_STRATEGY))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_ESTIMATE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_ESTIMATE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_COMPRESS", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_COMPRESS))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_ENCRYPT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_ENCRYPT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SRV_DECRYPT_OPT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SRV_DECRYPT_OPT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_CLNT_DECRYPT_OPT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_CLNT_DECRYPT_OPT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_COMPRATE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_COMPRATE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_TAPE_SPLITSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_TAPE_SPLITSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_FALLBACK_SPLITSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_FALLBACK_SPLITSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SPLIT_DISKBUFFER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SPLIT_DISKBUFFER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_RECORD", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_RECORD))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SKIP_INCR", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SKIP_INCR))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_SKIP_FULL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_SKIP_FULL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_HOLDINGDISK", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_HOLDINGDISK))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_KENCRYPT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_KENCRYPT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_IGNORE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_IGNORE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DUMPTYPE_INDEX", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DUMPTYPE_INDEX))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "INTER_COMMENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(INTER_COMMENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "INTER_MAXUSAGE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(INTER_MAXUSAGE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "HOLDING_COMMENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(HOLDING_COMMENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "HOLDING_DISKDIR", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(HOLDING_DISKDIR))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "HOLDING_DISKSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(HOLDING_DISKSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "HOLDING_CHUNKSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(HOLDING_CHUNKSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "HOLD_NEVER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(HOLD_NEVER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "HOLD_AUTO", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(HOLD_AUTO))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "HOLD_REQUIRED", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(HOLD_REQUIRED))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "COMP_NONE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(COMP_NONE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "COMP_FAST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(COMP_FAST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "COMP_BEST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(COMP_BEST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "COMP_CUST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(COMP_CUST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "COMP_SERVER_FAST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(COMP_SERVER_FAST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "COMP_SERVER_BEST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(COMP_SERVER_BEST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "COMP_SERVER_CUST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(COMP_SERVER_CUST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ENCRYPT_NONE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ENCRYPT_NONE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ENCRYPT_CUST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ENCRYPT_CUST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ENCRYPT_SERV_CUST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ENCRYPT_SERV_CUST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_SKIP", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_SKIP))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_STANDARD", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_STANDARD))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_NOFULL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_NOFULL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_NOINC", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_NOINC))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_4", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_4))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_5", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_5))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_HANOI", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_HANOI))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "DS_INCRONLY", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(DS_INCRONLY))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ES_CLIENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ES_CLIENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ES_SERVER", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ES_SERVER))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ES_CALCSIZE", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ES_CALCSIZE))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ALGO_FIRST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ALGO_FIRST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ALGO_FIRSTFIT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ALGO_FIRSTFIT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ALGO_LARGEST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ALGO_LARGEST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ALGO_LARGESTFIT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ALGO_LARGESTFIT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ALGO_SMALLEST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ALGO_SMALLEST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "ALGO_LAST", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(ALGO_LAST))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CONFIG_INIT_EXPLICIT_NAME", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CONFIG_INIT_EXPLICIT_NAME))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CONFIG_INIT_USE_CWD", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CONFIG_INIT_USE_CWD))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CONFIG_INIT_CLIENT", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CONFIG_INIT_CLIENT))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CONFIG_INIT_OVERLAY", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CONFIG_INIT_OVERLAY))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + /*@SWIG:/usr/share/swig/1.3.33/perl5/perltypemaps.swg,64,%set_constant@*/ do { + SV *sv = get_sv((char*) SWIG_prefix "CONFIG_INIT_FATAL", TRUE | 0x2); + sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1((int)(CONFIG_INIT_FATAL))); + SvREADONLY_on(sv); + } while(0) /*@SWIG@*/; + ST(0) = &PL_sv_yes; + XSRETURN(1); +} + diff --git a/perl/Amanda/Config.pm b/perl/Amanda/Config.pm new file mode 100644 index 0000000..b254c92 --- /dev/null +++ b/perl/Amanda/Config.pm @@ -0,0 +1,1673 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 1.3.33 +# +# Don't modify this file, modify the SWIG interface instead. + +package Amanda::Config; +require Exporter; +require DynaLoader; +@ISA = qw(Exporter DynaLoader); +package Amanda::Configc; +bootstrap Amanda::Config; +package Amanda::Config; +@EXPORT = qw( ); + +# ---------- BASE METHODS ------------- + +package Amanda::Config; + +sub TIEHASH { + my ($classname,$obj) = @_; + return bless $obj, $classname; +} + +sub CLEAR { } + +sub FIRSTKEY { } + +sub NEXTKEY { } + +sub FETCH { + my ($self,$field) = @_; + my $member_func = "swig_${field}_get"; + $self->$member_func(); +} + +sub STORE { + my ($self,$field,$newval) = @_; + my $member_func = "swig_${field}_set"; + $self->$member_func($newval); +} + +sub this { + my $ptr = shift; + return tied(%$ptr); +} + + +# ------- FUNCTION WRAPPERS -------- + +package Amanda::Config; + +*getconf = *Amanda::Configc::getconf; +*getconf_seen = *Amanda::Configc::getconf_seen; +*getconf_byname = *Amanda::Configc::getconf_byname; +*getconf_list = *Amanda::Configc::getconf_list; +*lookup_tapetype = *Amanda::Configc::lookup_tapetype; +*tapetype_getconf = *Amanda::Configc::tapetype_getconf; +*tapetype_name = *Amanda::Configc::tapetype_name; +*tapetype_seen = *Amanda::Configc::tapetype_seen; +*lookup_dumptype = *Amanda::Configc::lookup_dumptype; +*dumptype_getconf = *Amanda::Configc::dumptype_getconf; +*dumptype_name = *Amanda::Configc::dumptype_name; +*dumptype_seen = *Amanda::Configc::dumptype_seen; +*lookup_interface = *Amanda::Configc::lookup_interface; +*interface_getconf = *Amanda::Configc::interface_getconf; +*interface_name = *Amanda::Configc::interface_name; +*interface_seen = *Amanda::Configc::interface_seen; +*lookup_holdingdisk = *Amanda::Configc::lookup_holdingdisk; +*getconf_holdingdisks = *Amanda::Configc::getconf_holdingdisks; +*holdingdisk_next = *Amanda::Configc::holdingdisk_next; +*holdingdisk_getconf = *Amanda::Configc::holdingdisk_getconf; +*holdingdisk_name = *Amanda::Configc::holdingdisk_name; +*holdingdisk_seen = *Amanda::Configc::holdingdisk_seen; +*getconf_unit_divisor = *Amanda::Configc::getconf_unit_divisor; +*new_config_overwrites = *Amanda::Configc::new_config_overwrites; +*free_config_overwrites = *Amanda::Configc::free_config_overwrites; +*add_config_overwrite = *Amanda::Configc::add_config_overwrite; +*add_config_overwrite_opt = *Amanda::Configc::add_config_overwrite_opt; +*apply_config_overwrites = *Amanda::Configc::apply_config_overwrites; +*config_init = *Amanda::Configc::config_init; +*config_uninit = *Amanda::Configc::config_uninit; +*get_config_options = *Amanda::Configc::get_config_options; +*get_config_name = *Amanda::Configc::get_config_name; +*get_config_dir = *Amanda::Configc::get_config_dir; +*get_config_filename = *Amanda::Configc::get_config_filename; +*dump_configuration = *Amanda::Configc::dump_configuration; +*config_dir_relative = *Amanda::Configc::config_dir_relative; +*taperalgo2str = *Amanda::Configc::taperalgo2str; +*find_multiplier = *Amanda::Configc::find_multiplier; + +# ------- VARIABLE STUBS -------- + +package Amanda::Config; + +*CNF_ORG = *Amanda::Configc::CNF_ORG; +*CNF_CONF = *Amanda::Configc::CNF_CONF; +*CNF_INDEX_SERVER = *Amanda::Configc::CNF_INDEX_SERVER; +*CNF_TAPE_SERVER = *Amanda::Configc::CNF_TAPE_SERVER; +*CNF_AUTH = *Amanda::Configc::CNF_AUTH; +*CNF_SSH_KEYS = *Amanda::Configc::CNF_SSH_KEYS; +*CNF_AMANDAD_PATH = *Amanda::Configc::CNF_AMANDAD_PATH; +*CNF_CLIENT_USERNAME = *Amanda::Configc::CNF_CLIENT_USERNAME; +*CNF_GNUTAR_LIST_DIR = *Amanda::Configc::CNF_GNUTAR_LIST_DIR; +*CNF_AMANDATES = *Amanda::Configc::CNF_AMANDATES; +*CNF_MAILTO = *Amanda::Configc::CNF_MAILTO; +*CNF_DUMPUSER = *Amanda::Configc::CNF_DUMPUSER; +*CNF_TAPEDEV = *Amanda::Configc::CNF_TAPEDEV; +*CNF_DEVICE_PROPERTY = *Amanda::Configc::CNF_DEVICE_PROPERTY; +*CNF_CHANGERDEV = *Amanda::Configc::CNF_CHANGERDEV; +*CNF_CHANGERFILE = *Amanda::Configc::CNF_CHANGERFILE; +*CNF_LABELSTR = *Amanda::Configc::CNF_LABELSTR; +*CNF_TAPELIST = *Amanda::Configc::CNF_TAPELIST; +*CNF_DISKFILE = *Amanda::Configc::CNF_DISKFILE; +*CNF_INFOFILE = *Amanda::Configc::CNF_INFOFILE; +*CNF_LOGDIR = *Amanda::Configc::CNF_LOGDIR; +*CNF_INDEXDIR = *Amanda::Configc::CNF_INDEXDIR; +*CNF_TAPETYPE = *Amanda::Configc::CNF_TAPETYPE; +*CNF_DUMPCYCLE = *Amanda::Configc::CNF_DUMPCYCLE; +*CNF_RUNSPERCYCLE = *Amanda::Configc::CNF_RUNSPERCYCLE; +*CNF_TAPECYCLE = *Amanda::Configc::CNF_TAPECYCLE; +*CNF_NETUSAGE = *Amanda::Configc::CNF_NETUSAGE; +*CNF_INPARALLEL = *Amanda::Configc::CNF_INPARALLEL; +*CNF_DUMPORDER = *Amanda::Configc::CNF_DUMPORDER; +*CNF_BUMPPERCENT = *Amanda::Configc::CNF_BUMPPERCENT; +*CNF_BUMPSIZE = *Amanda::Configc::CNF_BUMPSIZE; +*CNF_BUMPMULT = *Amanda::Configc::CNF_BUMPMULT; +*CNF_BUMPDAYS = *Amanda::Configc::CNF_BUMPDAYS; +*CNF_TPCHANGER = *Amanda::Configc::CNF_TPCHANGER; +*CNF_RUNTAPES = *Amanda::Configc::CNF_RUNTAPES; +*CNF_MAXDUMPS = *Amanda::Configc::CNF_MAXDUMPS; +*CNF_ETIMEOUT = *Amanda::Configc::CNF_ETIMEOUT; +*CNF_DTIMEOUT = *Amanda::Configc::CNF_DTIMEOUT; +*CNF_CTIMEOUT = *Amanda::Configc::CNF_CTIMEOUT; +*CNF_TAPEBUFS = *Amanda::Configc::CNF_TAPEBUFS; +*CNF_DEVICE_OUTPUT_BUFFER_SIZE = *Amanda::Configc::CNF_DEVICE_OUTPUT_BUFFER_SIZE; +*CNF_PRINTER = *Amanda::Configc::CNF_PRINTER; +*CNF_AUTOFLUSH = *Amanda::Configc::CNF_AUTOFLUSH; +*CNF_RESERVE = *Amanda::Configc::CNF_RESERVE; +*CNF_MAXDUMPSIZE = *Amanda::Configc::CNF_MAXDUMPSIZE; +*CNF_COLUMNSPEC = *Amanda::Configc::CNF_COLUMNSPEC; +*CNF_AMRECOVER_DO_FSF = *Amanda::Configc::CNF_AMRECOVER_DO_FSF; +*CNF_AMRECOVER_CHECK_LABEL = *Amanda::Configc::CNF_AMRECOVER_CHECK_LABEL; +*CNF_AMRECOVER_CHANGER = *Amanda::Configc::CNF_AMRECOVER_CHANGER; +*CNF_TAPERALGO = *Amanda::Configc::CNF_TAPERALGO; +*CNF_FLUSH_THRESHOLD_DUMPED = *Amanda::Configc::CNF_FLUSH_THRESHOLD_DUMPED; +*CNF_FLUSH_THRESHOLD_SCHEDULED = *Amanda::Configc::CNF_FLUSH_THRESHOLD_SCHEDULED; +*CNF_TAPERFLUSH = *Amanda::Configc::CNF_TAPERFLUSH; +*CNF_DISPLAYUNIT = *Amanda::Configc::CNF_DISPLAYUNIT; +*CNF_KRB5KEYTAB = *Amanda::Configc::CNF_KRB5KEYTAB; +*CNF_KRB5PRINCIPAL = *Amanda::Configc::CNF_KRB5PRINCIPAL; +*CNF_LABEL_NEW_TAPES = *Amanda::Configc::CNF_LABEL_NEW_TAPES; +*CNF_USETIMESTAMPS = *Amanda::Configc::CNF_USETIMESTAMPS; +*CNF_REP_TRIES = *Amanda::Configc::CNF_REP_TRIES; +*CNF_CONNECT_TRIES = *Amanda::Configc::CNF_CONNECT_TRIES; +*CNF_REQ_TRIES = *Amanda::Configc::CNF_REQ_TRIES; +*CNF_DEBUG_AMANDAD = *Amanda::Configc::CNF_DEBUG_AMANDAD; +*CNF_DEBUG_AMIDXTAPED = *Amanda::Configc::CNF_DEBUG_AMIDXTAPED; +*CNF_DEBUG_AMINDEXD = *Amanda::Configc::CNF_DEBUG_AMINDEXD; +*CNF_DEBUG_AMRECOVER = *Amanda::Configc::CNF_DEBUG_AMRECOVER; +*CNF_DEBUG_AUTH = *Amanda::Configc::CNF_DEBUG_AUTH; +*CNF_DEBUG_EVENT = *Amanda::Configc::CNF_DEBUG_EVENT; +*CNF_DEBUG_HOLDING = *Amanda::Configc::CNF_DEBUG_HOLDING; +*CNF_DEBUG_PROTOCOL = *Amanda::Configc::CNF_DEBUG_PROTOCOL; +*CNF_DEBUG_PLANNER = *Amanda::Configc::CNF_DEBUG_PLANNER; +*CNF_DEBUG_DRIVER = *Amanda::Configc::CNF_DEBUG_DRIVER; +*CNF_DEBUG_DUMPER = *Amanda::Configc::CNF_DEBUG_DUMPER; +*CNF_DEBUG_CHUNKER = *Amanda::Configc::CNF_DEBUG_CHUNKER; +*CNF_DEBUG_TAPER = *Amanda::Configc::CNF_DEBUG_TAPER; +*CNF_DEBUG_SELFCHECK = *Amanda::Configc::CNF_DEBUG_SELFCHECK; +*CNF_DEBUG_SENDSIZE = *Amanda::Configc::CNF_DEBUG_SENDSIZE; +*CNF_DEBUG_SENDBACKUP = *Amanda::Configc::CNF_DEBUG_SENDBACKUP; +*CNF_RESERVED_UDP_PORT = *Amanda::Configc::CNF_RESERVED_UDP_PORT; +*CNF_RESERVED_TCP_PORT = *Amanda::Configc::CNF_RESERVED_TCP_PORT; +*CNF_UNRESERVED_TCP_PORT = *Amanda::Configc::CNF_UNRESERVED_TCP_PORT; +*TAPETYPE_COMMENT = *Amanda::Configc::TAPETYPE_COMMENT; +*TAPETYPE_LBL_TEMPL = *Amanda::Configc::TAPETYPE_LBL_TEMPL; +*TAPETYPE_BLOCKSIZE = *Amanda::Configc::TAPETYPE_BLOCKSIZE; +*TAPETYPE_READBLOCKSIZE = *Amanda::Configc::TAPETYPE_READBLOCKSIZE; +*TAPETYPE_LENGTH = *Amanda::Configc::TAPETYPE_LENGTH; +*TAPETYPE_FILEMARK = *Amanda::Configc::TAPETYPE_FILEMARK; +*TAPETYPE_SPEED = *Amanda::Configc::TAPETYPE_SPEED; +*TAPETYPE_FILE_PAD = *Amanda::Configc::TAPETYPE_FILE_PAD; +*DUMPTYPE_COMMENT = *Amanda::Configc::DUMPTYPE_COMMENT; +*DUMPTYPE_PROGRAM = *Amanda::Configc::DUMPTYPE_PROGRAM; +*DUMPTYPE_SRVCOMPPROG = *Amanda::Configc::DUMPTYPE_SRVCOMPPROG; +*DUMPTYPE_CLNTCOMPPROG = *Amanda::Configc::DUMPTYPE_CLNTCOMPPROG; +*DUMPTYPE_SRV_ENCRYPT = *Amanda::Configc::DUMPTYPE_SRV_ENCRYPT; +*DUMPTYPE_CLNT_ENCRYPT = *Amanda::Configc::DUMPTYPE_CLNT_ENCRYPT; +*DUMPTYPE_AMANDAD_PATH = *Amanda::Configc::DUMPTYPE_AMANDAD_PATH; +*DUMPTYPE_CLIENT_USERNAME = *Amanda::Configc::DUMPTYPE_CLIENT_USERNAME; +*DUMPTYPE_SSH_KEYS = *Amanda::Configc::DUMPTYPE_SSH_KEYS; +*DUMPTYPE_SECURITY_DRIVER = *Amanda::Configc::DUMPTYPE_SECURITY_DRIVER; +*DUMPTYPE_EXCLUDE = *Amanda::Configc::DUMPTYPE_EXCLUDE; +*DUMPTYPE_INCLUDE = *Amanda::Configc::DUMPTYPE_INCLUDE; +*DUMPTYPE_PRIORITY = *Amanda::Configc::DUMPTYPE_PRIORITY; +*DUMPTYPE_DUMPCYCLE = *Amanda::Configc::DUMPTYPE_DUMPCYCLE; +*DUMPTYPE_MAXDUMPS = *Amanda::Configc::DUMPTYPE_MAXDUMPS; +*DUMPTYPE_MAXPROMOTEDAY = *Amanda::Configc::DUMPTYPE_MAXPROMOTEDAY; +*DUMPTYPE_BUMPPERCENT = *Amanda::Configc::DUMPTYPE_BUMPPERCENT; +*DUMPTYPE_BUMPSIZE = *Amanda::Configc::DUMPTYPE_BUMPSIZE; +*DUMPTYPE_BUMPDAYS = *Amanda::Configc::DUMPTYPE_BUMPDAYS; +*DUMPTYPE_BUMPMULT = *Amanda::Configc::DUMPTYPE_BUMPMULT; +*DUMPTYPE_STARTTIME = *Amanda::Configc::DUMPTYPE_STARTTIME; +*DUMPTYPE_STRATEGY = *Amanda::Configc::DUMPTYPE_STRATEGY; +*DUMPTYPE_ESTIMATE = *Amanda::Configc::DUMPTYPE_ESTIMATE; +*DUMPTYPE_COMPRESS = *Amanda::Configc::DUMPTYPE_COMPRESS; +*DUMPTYPE_ENCRYPT = *Amanda::Configc::DUMPTYPE_ENCRYPT; +*DUMPTYPE_SRV_DECRYPT_OPT = *Amanda::Configc::DUMPTYPE_SRV_DECRYPT_OPT; +*DUMPTYPE_CLNT_DECRYPT_OPT = *Amanda::Configc::DUMPTYPE_CLNT_DECRYPT_OPT; +*DUMPTYPE_COMPRATE = *Amanda::Configc::DUMPTYPE_COMPRATE; +*DUMPTYPE_TAPE_SPLITSIZE = *Amanda::Configc::DUMPTYPE_TAPE_SPLITSIZE; +*DUMPTYPE_FALLBACK_SPLITSIZE = *Amanda::Configc::DUMPTYPE_FALLBACK_SPLITSIZE; +*DUMPTYPE_SPLIT_DISKBUFFER = *Amanda::Configc::DUMPTYPE_SPLIT_DISKBUFFER; +*DUMPTYPE_RECORD = *Amanda::Configc::DUMPTYPE_RECORD; +*DUMPTYPE_SKIP_INCR = *Amanda::Configc::DUMPTYPE_SKIP_INCR; +*DUMPTYPE_SKIP_FULL = *Amanda::Configc::DUMPTYPE_SKIP_FULL; +*DUMPTYPE_HOLDINGDISK = *Amanda::Configc::DUMPTYPE_HOLDINGDISK; +*DUMPTYPE_KENCRYPT = *Amanda::Configc::DUMPTYPE_KENCRYPT; +*DUMPTYPE_IGNORE = *Amanda::Configc::DUMPTYPE_IGNORE; +*DUMPTYPE_INDEX = *Amanda::Configc::DUMPTYPE_INDEX; +*INTER_COMMENT = *Amanda::Configc::INTER_COMMENT; +*INTER_MAXUSAGE = *Amanda::Configc::INTER_MAXUSAGE; +*HOLDING_COMMENT = *Amanda::Configc::HOLDING_COMMENT; +*HOLDING_DISKDIR = *Amanda::Configc::HOLDING_DISKDIR; +*HOLDING_DISKSIZE = *Amanda::Configc::HOLDING_DISKSIZE; +*HOLDING_CHUNKSIZE = *Amanda::Configc::HOLDING_CHUNKSIZE; +*HOLD_NEVER = *Amanda::Configc::HOLD_NEVER; +*HOLD_AUTO = *Amanda::Configc::HOLD_AUTO; +*HOLD_REQUIRED = *Amanda::Configc::HOLD_REQUIRED; +*COMP_NONE = *Amanda::Configc::COMP_NONE; +*COMP_FAST = *Amanda::Configc::COMP_FAST; +*COMP_BEST = *Amanda::Configc::COMP_BEST; +*COMP_CUST = *Amanda::Configc::COMP_CUST; +*COMP_SERVER_FAST = *Amanda::Configc::COMP_SERVER_FAST; +*COMP_SERVER_BEST = *Amanda::Configc::COMP_SERVER_BEST; +*COMP_SERVER_CUST = *Amanda::Configc::COMP_SERVER_CUST; +*ENCRYPT_NONE = *Amanda::Configc::ENCRYPT_NONE; +*ENCRYPT_CUST = *Amanda::Configc::ENCRYPT_CUST; +*ENCRYPT_SERV_CUST = *Amanda::Configc::ENCRYPT_SERV_CUST; +*DS_SKIP = *Amanda::Configc::DS_SKIP; +*DS_STANDARD = *Amanda::Configc::DS_STANDARD; +*DS_NOFULL = *Amanda::Configc::DS_NOFULL; +*DS_NOINC = *Amanda::Configc::DS_NOINC; +*DS_4 = *Amanda::Configc::DS_4; +*DS_5 = *Amanda::Configc::DS_5; +*DS_HANOI = *Amanda::Configc::DS_HANOI; +*DS_INCRONLY = *Amanda::Configc::DS_INCRONLY; +*ES_CLIENT = *Amanda::Configc::ES_CLIENT; +*ES_SERVER = *Amanda::Configc::ES_SERVER; +*ES_CALCSIZE = *Amanda::Configc::ES_CALCSIZE; +*ALGO_FIRST = *Amanda::Configc::ALGO_FIRST; +*ALGO_FIRSTFIT = *Amanda::Configc::ALGO_FIRSTFIT; +*ALGO_LARGEST = *Amanda::Configc::ALGO_LARGEST; +*ALGO_LARGESTFIT = *Amanda::Configc::ALGO_LARGESTFIT; +*ALGO_SMALLEST = *Amanda::Configc::ALGO_SMALLEST; +*ALGO_LAST = *Amanda::Configc::ALGO_LAST; +*debug_amandad = *Amanda::Configc::debug_amandad; +*debug_amidxtaped = *Amanda::Configc::debug_amidxtaped; +*debug_amindexd = *Amanda::Configc::debug_amindexd; +*debug_amrecover = *Amanda::Configc::debug_amrecover; +*debug_auth = *Amanda::Configc::debug_auth; +*debug_event = *Amanda::Configc::debug_event; +*debug_holding = *Amanda::Configc::debug_holding; +*debug_protocol = *Amanda::Configc::debug_protocol; +*debug_planner = *Amanda::Configc::debug_planner; +*debug_driver = *Amanda::Configc::debug_driver; +*debug_dumper = *Amanda::Configc::debug_dumper; +*debug_chunker = *Amanda::Configc::debug_chunker; +*debug_taper = *Amanda::Configc::debug_taper; +*debug_selfcheck = *Amanda::Configc::debug_selfcheck; +*debug_sendsize = *Amanda::Configc::debug_sendsize; +*debug_sendbackup = *Amanda::Configc::debug_sendbackup; +*CONFIG_INIT_EXPLICIT_NAME = *Amanda::Configc::CONFIG_INIT_EXPLICIT_NAME; +*CONFIG_INIT_USE_CWD = *Amanda::Configc::CONFIG_INIT_USE_CWD; +*CONFIG_INIT_CLIENT = *Amanda::Configc::CONFIG_INIT_CLIENT; +*CONFIG_INIT_OVERLAY = *Amanda::Configc::CONFIG_INIT_OVERLAY; +*CONFIG_INIT_FATAL = *Amanda::Configc::CONFIG_INIT_FATAL; + +@EXPORT_OK = (); +%EXPORT_TAGS = (); + +=head1 NAME + +Amanda::Config - access to Amanda configuration parameters + +=head1 SYNOPSIS + + use Amanda::Config qw( :init :getconf ); + + config_init($CONFIG_INIT_EXPLICIT_NAME, $ARGV[1]) + or die("errors processing config file " . $Amanda::Config::get_config_filename()); + + print "tape device is ", getconf($CNF_TAPEDEV), "\n"; + +This API closely parallels the C API. See F for details +on the functions and constants available here. + +=head1 API STATUS + +Stable + +=head1 INITIALIZATION + +The Amanda configuration is treated as a global state for the +application. It is not possible to load two configurations +simultaneously. + +All initialization-related symbols can be imported with the tag +C<:init>. + +=head2 LOADING CONFIGURATION + +The Amanda configuration is loaded with the aptly named +C. Because of the great variety in +invocation method among Amanda applications, this function has a number +of flags that affect its behavior. These flags can be OR'd together. + +=over + +=item If C is given, then the C<$name> +parameter can contain the name of a configuration to load. + +=item If C is given, and if the current directory +contains C, then that file is loaded. + +=item If C is given, then a client configuration +is loaded. + +=item If C is given, then any existing +configuration is not reset. + +=item If C is given, then any errors are considered +fatal, and C does not return. + +=back + +See C for more detailed information on these flags and +their interactions. + +C reverses the effects of C. It is +not often used. + +Once the configuration is loaded, the configuration name +(e.g., "DailySet1"), directory (C), +and filename (C) are +available from C, C, and +C, respectively. + +=head2 CONFIG OVERWRITES + +Most Amanda applications accept the command-line option C<-o> +to "overwrite" configuration values in C. In Perl +applications, these options should be parsed with L, with +the action being a call to C. For example: + + my $config_overwrites = new_config_overwrites($#ARGV+1); + GetOptions( + # ... + 'o=s' => sub { add_config_overwrite_opt($config_overwrites, $_[1]); }, + ) or usage(); + my $cfg_ok = config_init($CONFIG_INIT_EXPLICIT_NAME | $CONFIG_INIT_USE_CWD, $config_name); + apply_config_overwrites($config_overwrites); + +C creates a new +overwrites object, using the given size as an estimate of +the number of items it will contain (C<$#ARGC/2> is a good +estimate). Individual configuration options are then added via +C (which takes a key/value +pair) or C, which parses a +string following C<-o> on the command line. + +Once the overwrites are gathered, they are applied with +C, which applies the overwrites to the +active configuration. No further operations can be performed on the +overwrites object after C has been called. + +The utility function C returns a list of +command-line arguments to represent any overwrites that were used +to generate the current configuration. (TODO: this function isn't +available yet) + +=head1 PARAMETER ACCESS + +Amanda configurations consist of "global" parameters and several +sets of "subsections" -- one set for dumptypes, one for tapetypes, +and so on. + +All of the global parameters are represented by a constant beginning +with C<$CNF_>, e.g., C<$CNF_LABELSTR>. The function C +returns the value of parameter C<$cnf>, in whatever format is +appropriate for the parameter. C returns a true +value if C<$cnf> was seen in the configuration file. If it was not +seen, then it will have its default value. + +Some parameters have enumerated types. The values for those +enumerations are available from this module with the same name as +in C. For example, C<$CNF_TAPERALGO> will yield a value +from the enumeration C, the constants for which all +begin with C<$ALGO_>. See C for the details. + +Each subsection type has the following functions: + +=over + +=item C + +which returns an opaque object +(C<$ss>) representing the subsection, or C if no subsection +with that name exists; + +=item C + +returning the name of the subsection; + +=item C + +which fetches a parameter value from C<$ss>; and + +=item C + +which returns a true value if <$cnf> was seen in the subsection. + +=back + +The subsections are: + +=over + +=item C + +with constants beginning with C<$TAPETYPE_> + +=item C + +with constants beginning with C<$DUMPTYPE_> + +=item C + +with constants beginning with C<$HOLDING_> + +=item C + +with constants beginning with C<$APPLICATION_> + +=item C