Sophie

Sophie

distrib > Mandriva > current > i586 > media > contrib-release-src > by-pkgid > 6a41704604c0e0eaefc3923641944fd5 > files > 2

amanda-2.5.1-9mdv2009.1.src.rpm

diff -urP amanda-2.4.2p2/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/amanda.conf amanda-2.4.2p2-changed/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/amanda.conf
--- amanda-2.4.2p2/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/amanda.conf	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/amanda.conf	Fri Feb 25 13:57:25 2000
@@ -0,0 +1,300 @@
+#
+# amanda.conf - sample Amanda configuration file.  
+#
+# If your configuration is called, say, "UrbanetInternalSet1", then this file
+# normally goes in /etc/amanda/UrbanetInternalSet1/amanda.conf.
+# 
+# for explanation of the parameters refer to amanda(8) and
+# /usr/doc/amanda/WHATS.NEW.gz 
+
+org "UrbanetInternalSet1"	# your organization name for reports
+mailto "amanda"		# space separated list of operators at your site
+dumpuser "amanda"	# the user to run dumps under
+#
+inparallel 4		# maximum dumpers that will run in parallel
+netusage  600		# maximum net bandwidth for Amanda, in KB per sec
+
+# a filesystem is due for a full backup once every <dumpcycle> days
+dumpcycle 1 weeks	# the number of days in the normal dump cycle
+tapecycle 15 tapes	# the number of tapes in rotation
+
+bumpsize 100 MB		# minimum savings (threshold) to bump level 1 -> 2
+bumpdays     1		# minimum days at each level
+bumpmult     4		# threshold = bumpsize * (level-1)**bumpmult
+
+etimeout 2400		# number of seconds per filesystem for estimates.
+
+runtapes     1          # max number of tapes to be used in a single run
+tpchanger "chg-scsi" # the tape-changer glue script, see TAPE.CHANGERS
+tapedev	"0"	# changer configuration 0
+changerfile "/usr/local/amanda/etc/amanda/uis/changer.conf"
+
+tapetype SONY-DDS3-125m-nolabel  # what kind of tape it is (see tapetypes below)
+labelstr "^UrbanetInternalSet[0-9][0-9]*$"	# label constraint regex: all tapes must match
+
+diskdir "/space"		# where the holding disk is
+disksize 1300 MB			# how much space can we use on it
+
+# 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.  We use /usr/adm.  Create an amanda directory
+# under there.  You need a separate infofile and logfile for each
+# configuration, so create subdirectories for each conf and put the files
+# there.  Specify the filenames below.
+
+infofile "/usr/local/amanda/var/lib/UrbanetInternalSet1/curinfo"	# database filename
+logfile  "/usr/local/amanda/var/log/UrbanetInternalSet1/log"	# log filename
+
+# where the index files live
+indexdir "/usr/local/amanda/var/lib/UrbanetInternalSet1/index"
+
+# where the append tape file is
+currenttape "/usr/local/amanda/etc/amanda/uis/current-tape-for-append"
+
+appendmode 1
+
+# 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.
+#
+# 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.
+
+define tapetype QIC-60 {
+    comment "Archive Viper"
+    length 60 mbytes
+    filemark 100 kbytes		# don't know a better value
+    speed 100 kbytes		# dito
+}
+
+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	# I don't know what this means
+    speed 1500 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"
+    length 1900 mbytes		# these numbers are not accurate
+    filemark 100 kbytes		# but you get the idea
+    speed 500 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
+}
+
+define tapetype SONY-DDS2-60m-nolabel {
+    comment "DAT tape drives"
+    length 1350 mbytes
+    filemark 500 kbytes
+    speed 300 kbytes
+}
+
+define tapetype SONY-DDS3-125m-nolabel {
+    comment "DAT tape drives"
+    length 12000 mbytes
+    filemark 500 kbytes
+    speed 1100 kbytes
+}
+
+# dumptypes
+#
+# These are referred to by the disklist file.  The dumptype specifies
+# certain "options" for dumping including:
+#	index		- keep an index of the files backed up
+#	compress-fast	- (default) compress on the client using fast algorithm
+#	compress-best	- compress using the best (and slowww) algorithm
+#	no-compress	- don't compress the dump output
+#	srvcompress	- Compress dumps on the tape host instead of client
+#			  machines.  This may be useful when a fast tape host
+#			  is backing up slow clients.
+#	record		- (default) record the dump in /etc/dumpdates
+#	no-record	- don't record the dump, for testing
+#	no-hold		- don't go to the holding disk, good for dumping
+#			  the holding disk partition itself.
+#	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.
+#	no-full		- Do a level 1 every night.  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.
+#
+# Also, the dumptype specifies the priority level, where "low", "medium" and
+# "high" are the allowed levels.  These are only really 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 dumped first.
+
+define dumptype always-full {
+    comment "Full dump of this filesystem always"
+    options no-compress
+    priority high
+    dumpcycle 0
+    maxcycle 0
+}
+
+define dumptype comp-user-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options compress-fast, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority medium
+}
+
+define dumptype comp-root-tar {
+    program "GNUTAR"
+    comment "Root partitions with compression"
+    options compress-fast, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority low
+}
+
+define dumptype user-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority high
+}
+
+define dumptype high-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority high
+}
+
+define dumptype root-tar {
+    program "GNUTAR"
+    comment "Root partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority low
+}
+
+define dumptype comp-user {
+    comment "Non-root partitions on reasonably fast machines"
+    options compress-fast
+    priority medium
+}
+
+define dumptype nocomp-user {
+    comment "Non-root partitions on slow machines"
+    options no-compress
+    priority medium
+}
+
+define dumptype holding-disk {
+    comment "The master-host holding disk itself"
+    options no-hold
+    priority medium
+}
+
+define dumptype comp-root {
+    comment "Root partitions with compression"
+    options compress-fast
+    priority low
+}
+
+define dumptype nocomp-root {
+    comment "Root partitions without compression"
+    options no-compress
+    priority low
+}
+
+define dumptype comp-high {
+    comment "very important partitions on fast machines"
+    options compress-best
+    priority high
+}
+
+define dumptype nocomp-high {
+    comment "very important partitions on slow machines"
+    options no-compress
+    priority high
+}
+
+define dumptype nocomp-test {
+    comment "test dump without compression, no /etc/dumpdates recording"
+    options no-compress, no-record
+    priority medium
+}
+
+define dumptype comp-test {
+    comment "test dump with compression, no /etc/dumpdates recording"
+    options compress-fast, no-record
+    priority medium
+}
+
+define dumptype usr-tar {
+   root-tar
+   priority medium
+   comment "/usr tar"
+}
+
+define dumptype boot-tar {
+   root-tar
+   priority medium
+   comment "/boot tar"
+}
+
+define dumptype no-home-root-tar {
+    root-tar
+    comment "/ without home root tar"
+    priority high
+    exclude list "/etc/amanda/exclude-home"
+}
+
+define dumptype user-tar-spec {
+    root-tar
+    comment "user tar with special exclusions"
+    priority high
+    exclude list "/etc/amanda/exclude-spec"
+}
+
diff -urP amanda-2.4.2p2/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/changer.conf amanda-2.4.2p2-changed/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/changer.conf
--- amanda-2.4.2p2/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/changer.conf	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/changer.conf	Fri Feb 25 13:57:26 2000
@@ -0,0 +1,21 @@
+number_configs  1
+eject           0       # Tapedrives need an eject command
+sleep           200      # Seconds to wait until the tape gets ready
+cleanmax        15     # How many times could a cleaning tape get used
+changerdev      /dev/sg2
+#
+# Next comes the data for drive 0
+#
+config          0
+drivenum        0
+dev             /dev/nst0
+scsitapedev     /dev/sg1
+startuse        0       # The slots associated with the drive 0
+enduse          6       # 
+statfile        /usr/local/amanda/var/lib/tape0-slot  # The file where the actual slot is stored
+cleancart       7       # the slot where the cleaningcartridge for drive 0 is located
+cleanfile       /usr/local/amanda/var/lib/tape0-clean # The file where the cleanings are recorded
+usagecount      /usr/local/amanda/var/lib/totaltime
+tapestatus      /usr/local/amanda/var/lib/tapestatus # here will some status infos be stored
+#labelfile      /usr/local/amanda/var/lib/labelfile # Use this if you have an barcode reader
+
diff -urP amanda-2.4.2p2/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/disklist amanda-2.4.2p2-changed/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/disklist
--- amanda-2.4.2p2/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/disklist	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/debian-2.1-2.2.13-ncr53c8xx.OLD/disklist	Fri Feb 25 13:57:26 2000
@@ -0,0 +1,11 @@
+#debian /     no-home-root-tar
+debian /home user-tar
+debian /boot boot-tar
+
+defian /usr user-tar
+defian /boot user-tar
+defian /mfs/ROOT user-tar
+defian /mfs/TEMP user-tar
+defian / no-home-root-tar # also no usr
+defian /home user-tar-spec # without schaefer/SOUNDS
+###define /home/schaefer/SOUNDS user-tar
diff -urP amanda-2.4.2p2/DILOG/conf/golid-2.0.27-aha1542.OLD/amanda.conf amanda-2.4.2p2-changed/DILOG/conf/golid-2.0.27-aha1542.OLD/amanda.conf
--- amanda-2.4.2p2/DILOG/conf/golid-2.0.27-aha1542.OLD/amanda.conf	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/golid-2.0.27-aha1542.OLD/amanda.conf	Fri Feb 25 13:58:26 2000
@@ -0,0 +1,361 @@
+#
+# amanda.conf - sample Amanda configuration file.  
+#
+# If your configuration is called, say, "DilogNewEngSet1", then this file
+# normally goes in /etc/amanda/DilogNewEngSet1/amanda.conf.
+# 
+# for explanation of the parameters refer to amanda(8) and
+# /usr/doc/amanda/WHATS.NEW.gz 
+
+org "DilogNewEngSet1"	# your organization name for reports
+mailto "amanda"		# space separated list of operators at your site
+dumpuser "amanda"	# the user to run dumps under
+#
+inparallel 4		# maximum dumpers that will run in parallel
+netusage  600 Kbps	# maximum net bandwidth for Amanda, in KB per sec
+
+# a filesystem is due for a full backup once every <dumpcycle> days
+dumpcycle 1 weeks	# the number of days in the normal dump cycle
+runspercycle 1 weeks    # the number of amdump runs in dumpcycle days
+tapecycle 6 tapes	# the number of tapes in rotation
+
+bumpsize 100 MB		# minimum savings (threshold) to bump level 1 -> 2
+bumpdays     1		# minimum days at each level
+bumpmult     4		# threshold = bumpsize * (level-1)**bumpmult
+
+etimeout 2400		# number of seconds per filesystem for estimates.
+
+runtapes     1          # max number of tapes to be used in a single run
+tpchanger "chg-scsi" # the tape-changer glue script, see TAPE.CHANGERS
+tapedev	"0"	# changer configuration 0
+changerfile "/usr/local/amanda/etc/amanda/dne/changer.conf"
+
+tapetype SONY-DDS3-125m-nolabel  # what kind of tape it is (see tapetypes below)
+labelstr "^DilogNewEngSet[0-9][0-9]*$"	# label constraint regex: all tapes must match
+
+holdingdisk hd1 {
+    comment "main holding disk"
+    directory "/scratch/amanda" # where the holding disk is
+    use -80 Mb          # how much space can we use on it
+                        # a negative value mean:
+                        #        use all space except that value
+    chunksize -1        # size of chunk if you want big dump to be
+                        # dumped on multiple files on holding disks
+                        #  N Kb/Mb/Gb split disks in chunks of size N
+                        #  0          split disks in INT_MAX/1024 Kb chunks
+                        # -1          same as -INT_MAX/1024 (see below)
+                        # -N Kb/Mb/Gb dont split, dump larger
+                        #             filesystems directly to tape
+                        #             (example: -2 Gb)
+    # chunksize 2 Gb
+    }
+holdingdisk hd2 {
+    comment "secondary holding disk"
+    directory "/spare/amanda"
+    use -80 Mb
+    chunksize -1
+    }
+
+# 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.  
+
+# 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.  We use /usr/adm.  Create an amanda directory
+# under there.  You need a separate infofile and logfile for each
+# configuration, so create subdirectories for each conf and put the files
+# there.  Specify the filenames below.
+
+infofile "/usr/local/amanda/var/lib/DilogNewEngSet1/curinfo"	# database filename
+logfile  "/usr/local/amanda/var/log/DilogNewEngSet1/log"	# log filename
+
+# where the index files live
+indexdir "/usr/local/amanda/var/lib/DilogNewEngSet1/index"
+
+# where the append tape file is
+currenttape "/usr/local/amanda/etc/amanda/dne/current-tape-for-append"
+
+appendmode 1
+
+# 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.
+#
+# 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.
+
+define tapetype QIC-60 {
+    comment "Archive Viper"
+    length 60 mbytes
+    filemark 100 kbytes		# don't know a better value
+    speed 100 kbytes		# dito
+}
+
+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	# I don't know what this means
+    speed 1500 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"
+    length 1900 mbytes		# these numbers are not accurate
+    filemark 100 kbytes		# but you get the idea
+    speed 500 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
+}
+
+define tapetype SONY-DDS2-60m-nolabel {
+    comment "DAT tape drives"
+    length 1350 mbytes
+    filemark 500 kbytes
+    speed 300 kbytes
+}
+
+define tapetype SONY-DDS3-125m-nolabel {
+    comment "DAT tape drives"
+    length 12000 mbytes
+    filemark 500 kbytes
+    speed 1100 kbytes
+}
+
+# dumptypes
+#
+# These are referred to by the disklist file.  The dumptype specifies
+# certain "options" for dumping including:
+#	index		- keep an index of the files backed up
+#	compress-fast	- (default) compress on the client using fast algorithm
+#	compress-best	- compress using the best (and slowww) algorithm
+#	no-compress	- don't compress the dump output
+#	srvcompress	- Compress dumps on the tape host instead of client
+#			  machines.  This may be useful when a fast tape host
+#			  is backing up slow clients.
+#	record		- (default) record the dump in /etc/dumpdates
+#	no-record	- don't record the dump, for testing
+#	no-hold		- don't go to the holding disk, good for dumping
+#			  the holding disk partition itself.
+#	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.
+#	no-full		- Do a level 1 every night.  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.
+#
+# Also, the dumptype specifies the priority level, where "low", "medium" and
+# "high" are the allowed levels.  These are only really 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 dumped first.
+
+define dumptype always-full {
+    comment "Full dump of this filesystem always"
+    options no-compress
+    priority high
+    dumpcycle 0
+    maxcycle 0
+}
+
+define dumptype comp-user-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options compress-fast, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority medium
+}
+
+define dumptype comp-root-tar {
+    program "GNUTAR"
+    comment "Root partitions with compression"
+    options compress-fast, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority low
+}
+
+define dumptype user-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority high
+}
+
+define dumptype high-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority high
+}
+
+define dumptype root-tar {
+    program "GNUTAR"
+    comment "Root partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority low
+}
+
+define dumptype comp-user {
+    comment "Non-root partitions on reasonably fast machines"
+    options compress-fast
+    priority medium
+}
+
+define dumptype nocomp-user {
+    comment "Non-root partitions on slow machines"
+    options no-compress
+    priority medium
+}
+
+define dumptype holding-disk {
+    comment "The master-host holding disk itself"
+    options no-hold
+    priority medium
+}
+
+define dumptype comp-root {
+    comment "Root partitions with compression"
+    options compress-fast
+    priority low
+}
+
+define dumptype nocomp-root {
+    comment "Root partitions without compression"
+    options no-compress
+    priority low
+}
+
+define dumptype comp-high {
+    comment "very important partitions on fast machines"
+    options compress-best
+    priority high
+}
+
+define dumptype nocomp-high {
+    comment "very important partitions on slow machines"
+    options no-compress
+    priority high
+}
+
+define dumptype nocomp-test {
+    comment "test dump without compression, no /etc/dumpdates recording"
+    options no-compress, no-record
+    priority medium
+}
+
+define dumptype comp-test {
+    comment "test dump with compression, no /etc/dumpdates recording"
+    options compress-fast, no-record
+    priority medium
+}
+
+define dumptype usr-tar {
+   root-tar
+   priority medium
+   comment "/usr tar"
+}
+
+define dumptype boot-tar {
+   root-tar
+   priority medium
+   comment "/boot tar"
+}
+
+define dumptype user-tar-spec {
+    root-tar
+    comment "user tar with special exclusions"
+    priority high
+    exclude list "/etc/amanda/exclude-spec"
+}
+
+define dumptype root-tar-spec {
+    root-tar
+    comment "user tar with special exclusions"
+    priority high
+    exclude list "/etc/amanda/exclude-root-spec"
+}
+
+define dumptype user-tar-spec2 {
+    root-tar
+    comment "user tar with special exclusions 2"
+    priority high
+    exclude list "/etc/amanda/exclude-spec2"
+}
+
+define dumptype user-tar-spec3 {
+    root-tar
+    comment "user tar with special exclusions 3"
+    priority high
+    exclude list "/etc/amanda/exclude-spec3"
+}
+
+define dumptype user-smb-tar {
+    root-tar
+    comment "user partitions dumped with smbtar"
+    priority medium
+    exclude list "/etc/amanda/exclude-smb-tar"
+}
+
+define dumptype user-smb-tar-no-incr {
+   user-smb-tar
+   skip-incr
+}
+
diff -urP amanda-2.4.2p2/DILOG/conf/golid-2.0.27-aha1542.OLD/changer.conf amanda-2.4.2p2-changed/DILOG/conf/golid-2.0.27-aha1542.OLD/changer.conf
--- amanda-2.4.2p2/DILOG/conf/golid-2.0.27-aha1542.OLD/changer.conf	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/golid-2.0.27-aha1542.OLD/changer.conf	Fri Feb 25 13:58:26 2000
@@ -0,0 +1,21 @@
+number_configs  1
+eject           0       # Tapedrives need an eject command
+sleep           200      # Seconds to wait until the tape gets ready
+cleanmax        15     # How many times could a cleaning tape get used
+changerdev      /dev/sg2
+#
+# Next comes the data for drive 0
+#
+config          0
+drivenum        0
+dev             /dev/nst0
+scsitapedev     /dev/sg1
+startuse        0       # The slots associated with the drive 0
+enduse          6       # 
+statfile        /usr/local/amanda/var/lib/tape0-slot  # The file where the actual slot is stored
+cleancart       7       # the slot where the cleaningcartridge for drive 0 is located
+cleanfile       /usr/local/amanda/var/lib/tape0-clean # The file where the cleanings are recorded
+usagecount      /usr/local/amanda/var/lib/totaltime
+tapestatus      /usr/local/amanda/var/lib/tapestatus # here will some status infos be stored
+#labelfile      /usr/local/amanda/var/lib/labelfile # Use this if you have an barcode reader
+
diff -urP amanda-2.4.2p2/DILOG/conf/golid-2.0.27-aha1542.OLD/disklist amanda-2.4.2p2-changed/DILOG/conf/golid-2.0.27-aha1542.OLD/disklist
--- amanda-2.4.2p2/DILOG/conf/golid-2.0.27-aha1542.OLD/disklist	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/golid-2.0.27-aha1542.OLD/disklist	Fri Feb 25 13:58:26 2000
@@ -0,0 +1,30 @@
+golid / root-tar-spec
+golid /usr user-tar
+golid /users user-tar
+golid /usr/src user-tar
+golid /scratch/world user-tar
+golid /spare user-tar-spec
+
+# Some of those are symlinks.
+sun1 / root-tar
+sun1 /d2 user-tar
+sun1 /usr user-tar
+
+pc5 / user-tar
+pc5 /usr user-tar
+pc5 /dos user-tar
+
+# SMB backups
+#golid  //paul/paul         user-smb-tar
+
+# Incremental doesn't work on those because Patrick also backups them
+# completely.
+golid   //alphie1/product   user-smb-tar-no-incr
+#golid   //alphie1/sales    user-smb-tar
+golid   //alphie1/dilog    user-smb-tar-no-incr
+#golid   //alphie1/accounts user-smb-tar
+#golid   //alphie1/karin    user-smb-tar
+
+debian / user-tar
+debian /boot user-tar
+
diff -urP amanda-2.4.2p2/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/amanda.conf amanda-2.4.2p2-changed/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/amanda.conf
--- amanda-2.4.2p2/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/amanda.conf	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/amanda.conf	Fri Mar 10 15:52:16 2000
@@ -0,0 +1,359 @@
+#
+# amanda.conf - sample Amanda configuration file.  
+#
+# If your configuration is called, say, "UrbanetInternalSet1", then this file
+# normally goes in /etc/amanda/UrbanetInternalSet1/amanda.conf.
+# 
+# for explanation of the parameters refer to amanda(8) and
+# /usr/doc/amanda/WHATS.NEW.gz 
+
+org "UrbanetInternalSet1"	# your organization name for reports
+mailto "amanda"		# space separated list of operators at your site
+dumpuser "amanda"	# the user to run dumps under
+#
+inparallel 4		# maximum dumpers that will run in parallel
+netusage  600		# maximum net bandwidth for Amanda, in KB per sec
+
+# a filesystem is due for a full backup once every <dumpcycle> days
+dumpcycle 4 weeks	# the number of days in the normal dump cycle
+runspercycle 28         # the number of amdump runs in dumpcycle days
+tapecycle 14 tapes	# the number of tapes in rotation
+
+bumpsize 100 MB		# minimum savings (threshold) to bump level 1 -> 2
+bumpdays     1		# minimum days at each level
+bumpmult     4		# threshold = bumpsize * (level-1)**bumpmult
+
+etimeout 2400		# number of seconds per filesystem for estimates.
+
+dtimeout 1800           # number of idle seconds before a dump is aborted.
+
+tapebufs 40		# Allocate 1.2 MB buffers for taper
+
+runtapes     2          # max number of tapes to be used in a single run
+tpchanger "chg-scsi" 	# the tape-changer glue script, see TAPE.CHANGERS
+tapedev	"0"		# changer configuration 0
+changerfile "/usr/local/amanda/etc/amanda/uis/changer.conf"
+
+tapetype SONY-DDS3-125m-nolabel  # what kind of tape it is (see tapetypes below)
+labelstr "^UrbanetInternalSet[0-9][0-9]*$"	# label constraint regex: all tapes must match
+
+holdingdisk hd1 {
+    comment "main holding disk"
+    directory "/amanda/space" # where the holding disk is
+    use -80 Mb          # how much space can we use on it
+                        # a negative value mean:
+                        #        use all space except that value
+    #chunksize -1        # size of chunk if you want big dump to be
+                        # dumped on multiple files on holding disks
+                        #  N Kb/Mb/Gb split disks in chunks of size N
+                        #  0          split disks in INT_MAX/1024 Kb chunks
+                        # -1          same as -INT_MAX/1024 (see below)
+                        # -N Kb/Mb/Gb dont split, dump larger
+                        #             filesystems directly to tape
+                        #             (example: -2 Gb)
+    chunksize 2 Gb
+}
+
+# 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.  
+
+# 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.  We use /usr/adm.  Create an amanda directory
+# under there.  You need a separate infofile and logfile for each
+# configuration, so create subdirectories for each conf and put the files
+# there.  Specify the filenames below.
+
+infofile "/usr/local/amanda/var/lib/UrbanetInternalSet1/curinfo"	# database filename
+logfile  "/usr/local/amanda/var/log/UrbanetInternalSet1/log"	# log filename
+
+# where the index files live
+indexdir "/usr/local/amanda/var/lib/UrbanetInternalSet1/index"
+
+# where the append tape file is
+currenttape "/usr/local/amanda/etc/amanda/uis/current-tape-for-append"
+
+appendmode 1
+
+# 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.
+#
+# 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.
+
+define tapetype QIC-60 {
+    comment "Archive Viper"
+    length 60 mbytes
+    filemark 100 kbytes		# don't know a better value
+    speed 100 kbytes		# dito
+}
+
+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	# I don't know what this means
+    speed 1500 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"
+    length 1900 mbytes		# these numbers are not accurate
+    filemark 100 kbytes		# but you get the idea
+    speed 500 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
+}
+
+define tapetype SONY-DDS2-60m-nolabel {
+    comment "DAT tape drives"
+    length 1350 mbytes
+    filemark 500 kbytes
+    speed 300 kbytes
+}
+
+define tapetype SONY-DDS3-125m-nolabel {
+    comment "DAT tape drives"
+    length 12000 mbytes
+    filemark 500 kbytes
+    speed 1100 kbytes
+}
+
+# dumptypes
+#
+# These are referred to by the disklist file.  The dumptype specifies
+# certain "options" for dumping including:
+#	index		- keep an index of the files backed up
+#	compress-fast	- (default) compress on the client using fast algorithm
+#	compress-best	- compress using the best (and slowww) algorithm
+#	no-compress	- don't compress the dump output
+#	srvcompress	- Compress dumps on the tape host instead of client
+#			  machines.  This may be useful when a fast tape host
+#			  is backing up slow clients.
+#	record		- (default) record the dump in /etc/dumpdates
+#	no-record	- don't record the dump, for testing
+#	no-hold		- don't go to the holding disk, good for dumping
+#			  the holding disk partition itself.
+#	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.
+#	no-full		- Do a level 1 every night.  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.
+#
+# Also, the dumptype specifies the priority level, where "low", "medium" and
+# "high" are the allowed levels.  These are only really 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 dumped first.
+
+define dumptype always-full {
+    comment "Full dump of this filesystem always"
+    options no-compress
+    priority high
+    dumpcycle 0
+    maxcycle 0
+}
+
+define dumptype comp-user-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options compress-fast, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority medium
+}
+
+define dumptype comp-root-tar {
+    program "GNUTAR"
+    comment "Root partitions with compression"
+    options compress-fast, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority low
+}
+
+define dumptype user-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority high
+}
+
+define dumptype high-tar {
+    program "GNUTAR"
+    comment "partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority high
+}
+
+define dumptype root-tar {
+    program "GNUTAR"
+    comment "Root partitions dumped with tar"
+    options no-compress, index, exclude-list "/etc/amanda/exclude.gtar"
+    priority low
+}
+
+define dumptype comp-user {
+    comment "Non-root partitions on reasonably fast machines"
+    options compress-fast
+    priority medium
+}
+
+define dumptype nocomp-user {
+    comment "Non-root partitions on slow machines"
+    options no-compress
+    priority medium
+}
+
+define dumptype holding-disk {
+    comment "The master-host holding disk itself"
+    options no-hold
+    priority medium
+}
+
+define dumptype comp-root {
+    comment "Root partitions with compression"
+    options compress-fast
+    priority low
+}
+
+define dumptype nocomp-root {
+    comment "Root partitions without compression"
+    options no-compress
+    priority low
+}
+
+define dumptype comp-high {
+    comment "very important partitions on fast machines"
+    options compress-best
+    priority high
+}
+
+define dumptype nocomp-high {
+    comment "very important partitions on slow machines"
+    options no-compress
+    priority high
+}
+
+define dumptype nocomp-test {
+    comment "test dump without compression, no /etc/dumpdates recording"
+    options no-compress, no-record
+    priority medium
+}
+
+define dumptype comp-test {
+    comment "test dump with compression, no /etc/dumpdates recording"
+    options compress-fast, no-record
+    priority medium
+}
+
+define dumptype usr-tar {
+   root-tar
+   priority medium
+   comment "/usr tar"
+}
+
+define dumptype boot-tar {
+   root-tar
+   priority medium
+   comment "/boot tar"
+}
+
+define dumptype user-tar-spec {
+    root-tar
+    comment "user tar with special exclusions"
+    priority high
+    exclude list "/etc/amanda/exclude-spec"
+}
+
+define dumptype root-tar-spec {
+    root-tar
+    comment "user tar with special exclusions"
+    priority high
+    exclude list "/etc/amanda/exclude-root-spec"
+}
+
+define dumptype user-tar-spec2 {
+    root-tar
+    comment "user tar with special exclusions 2"
+    priority high
+    exclude list "/etc/amanda/exclude-spec2"
+}
+
+define dumptype user-tar-spec3 {
+    root-tar
+    comment "user tar with special exclusions 3"
+    priority high
+    exclude list "/etc/amanda/exclude-spec3"
+}
+
+define dumptype user-smb-tar {
+    root-tar
+    comment "user partitions dumped with smbtar"
+    priority medium
+    exclude list "/etc/amanda/exclude-smb-tar"
+}
+
+define dumptype user-smb-tar-no-incr {
+   user-smb-tar
+   skip-incr
+}
+
diff -urP amanda-2.4.2p2/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/changer.conf amanda-2.4.2p2-changed/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/changer.conf
--- amanda-2.4.2p2/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/changer.conf	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/changer.conf	Fri Mar 10 15:49:34 2000
@@ -0,0 +1,24 @@
+number_configs  1
+eject           0       # Tapedrives need an eject command
+sleep           200      # Seconds to wait until the tape gets ready
+cleanmax        15     # How many times could a cleaning tape get used
+# Assuming a drive, a tape and a changer on the bus in that order.
+#changerdev      /dev/sg2
+changerdev      /dev/sg3
+#
+# Next comes the data for drive 0
+#
+config          0
+drivenum        0
+dev             /dev/nst0
+#scsitapedev     /dev/sg1
+scsitapedev     /dev/sg2
+startuse        0       # The slots associated with the drive 0
+enduse          6       # 
+statfile        /usr/local/amanda/var/lib/tape0-slot  # The file where the actual slot is stored
+cleancart       7       # the slot where the cleaningcartridge for drive 0 is located
+cleanfile       /usr/local/amanda/var/lib/tape0-clean # The file where the cleanings are recorded
+usagecount      /usr/local/amanda/var/lib/totaltime
+tapestatus      /usr/local/amanda/var/lib/tapestatus # here will some status infos be stored
+#labelfile      /usr/local/amanda/var/lib/labelfile # Use this if you have an barcode reader
+
diff -urP amanda-2.4.2p2/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/disklist amanda-2.4.2p2-changed/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/disklist
--- amanda-2.4.2p2/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/disklist	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/conf/urbanet-2.2.x-debian-2.1/etc/amanda/uis/disklist	Fri Mar 10 16:49:41 2000
@@ -0,0 +1,3 @@
+#debian / user-tar
+#debian /boot user-tar
+#debian /usr/local/amanda user-tar
diff -urP amanda-2.4.2p2/DILOG/crontabs/crontab.example amanda-2.4.2p2-changed/DILOG/crontabs/crontab.example
--- amanda-2.4.2p2/DILOG/crontabs/crontab.example	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/DILOG/crontabs/crontab.example	Fri Mar 10 15:30:53 2000
@@ -0,0 +1,15 @@
+# Verifies that everything is fine only on week-day. Mail if any problem.
+0 17   * * 1-5 /usr/local/amanda/sbin/amcheck -m uis
+
+# Backup
+45 0   * * *   /usr/local/amanda/sbin/amdump uis
+
+# Clean drive and display error statistics, once a week
+#    DRIVE MUST BE CLEANED EVERY 20 HOURS OF USAGE. If
+#    backuping 7 systems of 1 GB, this is 7 GB, and thus this
+#    is 2 hours/day. Every week is enough.
+05 14  * * 1   /usr/local/amanda/scripts/clean_and_check_tape.sh uis /usr/local/amanda var/lib/tapestatus
+
+# On friday, print a summary of usage. It's probably a good time to
+# move the tapes in a safe place with the printed information.
+10 12  * * 5   /usr/local/amanda/scripts/summary.sh uis
diff -urP amanda-2.4.2p2/Makefile.am amanda-2.4.2p2-changed/Makefile.am
--- amanda-2.4.2p2/Makefile.am	Tue Apr  3 21:55:19 2001
+++ amanda-2.4.2p2-changed/Makefile.am	Fri Aug  3 07:59:26 2001
@@ -8,12 +8,13 @@
 
 if WANT_CLIENT
 CLIENT_SUBDIRS = client-src
+AMRIO_SUBDIRS += remote-io-src
 endif
 if WANT_TAPE
 TAPE_SUBDIRS = tape-src
 endif
 if WANT_SERVER
-SERVER_SUBDIRS = server-src changer-src
+SERVER_SUBDIRS = server-src changer-src scripts
 endif
 if WANT_RESTORE
 RESTORE_SUBDIRS += restore-src
@@ -34,7 +35,8 @@
 	$(RESTORE_SUBDIRS) \
 	$(RECOVER_SUBDIRS) \
 	$(PLOT_SUBDIRS) \
-	man docs example
+	$(AMRIO_SUBDIRS) \
+	man docs example scripts
 
 pkgdata_DATA = \
 	COPYRIGHT			\
Only in amanda-2.4.2p2: Makefile.in
diff -urP amanda-2.4.2p2/changer-src/chg-scsi-chio.c amanda-2.4.2p2-changed/changer-src/chg-scsi-chio.c
--- amanda-2.4.2p2/changer-src/chg-scsi-chio.c	Tue Jun 13 00:57:32 2000
+++ amanda-2.4.2p2-changed/changer-src/chg-scsi-chio.c	Fri Aug  3 08:59:42 2001
@@ -639,7 +639,7 @@
 
   if(read_conffile(CONFFILE_NAME)) {
     fprintf(stderr, "%s: could not find config file \"%s\"",
-		    changer_dev, conffile);
+		    changer_dev, CONFFILE_NAME);
     exit(1);
   }
 
diff -urP amanda-2.4.2p2/changer-src/patch-aha1542 amanda-2.4.2p2-changed/changer-src/patch-aha1542
--- amanda-2.4.2p2/changer-src/patch-aha1542	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/changer-src/patch-aha1542	Mon Feb 21 13:45:49 2000
@@ -0,0 +1,105 @@
+--- chg-scsi.c	Thu Sep  9 21:53:13 1999
++++ chg-scsi.c	Mon Feb 21 13:43:02 2000
+@@ -97,6 +97,8 @@
+ extern int IEE;
+ extern int DTE;
+ 
++static int My_Tape_Ready(char *tapedev, OpenFiles_T *pTapeDev, int wait);
++
+ 
+ /*----------------------------------------------------------------------------*/
+ /* Some stuff for our own configurationfile */
+@@ -1108,7 +1110,7 @@
+       }
+ 
+     if (need_sleep)
+-      if (Tape_Ready(scsitapedevice, need_sleep) == -1)
++      if (My_Tape_Ready(tape_device, pTapeDev, need_sleep) == -1)
+         {
+           printf("tape not ready\n");
+           endstatus = 2;
+@@ -1176,7 +1178,7 @@
+     put_current_slot(changer_file, slot_offset);
+ 
+     if (need_sleep)
+-       if (Tape_Ready(scsitapedevice, need_sleep) == -1)
++       if (My_Tape_Ready(tape_device, pTapeDev, need_sleep) == -1)
+         {
+           printf("tape not ready\n");
+           endstatus = 2;
+@@ -1239,6 +1241,75 @@
+   dbclose();
+   return endstatus;
+ }
++
++static int My_Tape_Ready(char *tapedev, OpenFiles_T *pTapeDev, int wait) {
++   /* closing can be ready because of the way Linux handles tape changes,
++    * which is BTW a good way.
++    */
++  if (pTapeDev) {
++     if (pTapeDev->fd != -1) {
++        close(pTapeDev->fd); /* ignored */
++        pTapeDev->fd = open(tapedev, O_RDONLY);
++     }
++
++     if (pTapeDev->fd == -1) {
++        return -1;
++     }
++  }
++   
++  do { 
++     int f;
++
++     if (pTapeDev) {
++        if (pTapeDev->fd != -1) {
++           close(pTapeDev->fd); /* ignored */
++           pTapeDev->fd = open(tapedev, O_RDONLY);
++        }
++   
++        if (pTapeDev->fd == -1) {
++           return -1;
++        }
++     }
++
++     f = pTapeDev ? pTapeDev->fd : open(tapedev, O_RDONLY);
++
++     if (f != -1) {
++        int res = -1;
++#include <sys/mtio.h>
++        struct mtop mt;
++
++        /* BUGS
++         *    - We need that here because it internally would
++         *      sleep 30 seconds. We can't assume it and we can't
++         *      count the time portably, so ...
++         */
++
++        mt.mt_op = MTREW;
++        mt.mt_count = 1;
++
++        if (!ioctl(f, MTIOCTOP, &mt)) {
++           res = 0;
++        }
++        if (!pTapeDev) {
++           close(f);
++        }
++
++        if (res == 0) {
++           return res;
++        }
++     }
++     sleep(5);
++     if (wait > 5) {
++        wait -= 5;
++     }
++     else {
++        wait = 0;
++     }
++  } while (wait);
++
++  return -1;
++}
++
+ /*
+  * Local variables:
+  * indent-tabs-mode: nil
diff -urP amanda-2.4.2p2/client-src/sendbackup-gnutar.c amanda-2.4.2p2-changed/client-src/sendbackup-gnutar.c
--- amanda-2.4.2p2/client-src/sendbackup-gnutar.c	Thu Mar 15 03:17:36 2001
+++ amanda-2.4.2p2-changed/client-src/sendbackup-gnutar.c	Fri Aug  3 08:14:55 2001
@@ -434,7 +434,6 @@
 			     * dumps will think the file has changed. */
 			    "--atime-preserve",
 #endif
-			    "--sparse",
 			    "--ignore-failed-read",
 			    "--totals",
 			    efile ? "--exclude-from" : skip_argument,
diff -urP amanda-2.4.2p2/client-src/sendsize.c amanda-2.4.2p2-changed/client-src/sendsize.c
--- amanda-2.4.2p2/client-src/sendsize.c	Thu Mar 15 03:17:37 2001
+++ amanda-2.4.2p2-changed/client-src/sendsize.c	Fri Aug  3 08:15:04 2001
@@ -1211,7 +1211,6 @@
 	       * dumps will think the file has changed. */
 	      "--atime-preserve",
 #endif
-	      "--sparse",
 	      "--ignore-failed-read",
 	      "--totals",
 	      efile ? "--exclude-from" : skip_argument,
Only in amanda-2.4.2p2: configure
diff -urP amanda-2.4.2p2/configure.in amanda-2.4.2p2-changed/configure.in
--- amanda-2.4.2p2/configure.in	Tue Apr  3 02:44:41 2001
+++ amanda-2.4.2p2-changed/configure.in	Fri Aug  3 08:05:54 2001
@@ -255,6 +255,23 @@
     ]
 )
 
+AC_ARG_WITH(amrio,
+    [  --without-amrio    do not build amrio],
+    [
+	case "$withval" in
+	y | ye | yes)
+	    if ${NO_CLIENT_MODE-false}; then
+		AC_MSG_ERROR([*** --without-client and --with-amrio are incompatible])
+	    fi
+	    NO_AMRIO_MODE=false;;
+	n | no) NO_AMRIO_MODE=true;;
+	*)
+	    AC_MSG_ERROR([*** You must not supply an argument to --with-amrio option.])
+	  ;;
+	esac
+    ]
+)
+
 AC_ARG_WITH(index-server,
    [  --with-index-server=HOST default amanda index server [`uname -n`]],
    [
@@ -2500,6 +2517,7 @@
 AM_CONDITIONAL(WANT_RESTORE, test x"$NO_RESTORE_MODE" != x"true")
 AM_CONDITIONAL(WANT_SERVER, test x"$NO_SERVER_MODE" != x"true")
 AM_CONDITIONAL(WANT_RECOVER, test x"$NO_RECOVER_MODE" != x"true" && test x"$NO_CLIENT_MODE" != x"true")
+AM_CONDITIONAL(WANT_AMRIO, test x"$NO_AMRIO_MODE" != x"true" && test x"$NO_CLIENT_MODE" != x"true")
 AM_CONDITIONAL(WANT_TAPE, test x"$NO_SERVER_MODE" != x"true" || test x"$NO_RESTORE_MODE" != x"true")
 AM_CONDITIONAL(WANT_AMPLOT, test x"$NO_AMPLOT_MODE" != x"true")
 AM_CONDITIONAL(WANT_CHG_SCSI, test x"$NO_SCSI_CHANGER_MODE" != x"true")
@@ -2539,11 +2557,17 @@
 	man/amrmtape.8			man/amtoc.8			\
 	man/amverify.8			man/Makefile			\
 	man/amstatus.8			man/amreport.8			\
+	man/amrio.8			man/amcompare.8		        \
 	man/amgetconf.8							\
 									\
 	docs/Makefile							\
 									\
 	recover-src/Makefile						\
+                                                                        \
+	remote-io-src/Makefile						\
+	remote-io-src/amcompare                                         \
+                                                                        \
+	scripts/Makefile						\
 									\
 	restore-src/Makefile						\
 									\
diff -urP amanda-2.4.2p2/docs/AMRESTORE amanda-2.4.2p2-changed/docs/AMRESTORE
--- amanda-2.4.2p2/docs/AMRESTORE	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/docs/AMRESTORE	Fri Aug  3 11:47:16 2001
@@ -0,0 +1,58 @@
+AUTHOR
+   Marc SCHAEFER <schaefer@dilog.ch>
+
+GOAL
+   Make so that amrestore (and thus amidxtaped and amrio) can restore
+   a specified file without needing to scan the whole tape, and with
+   the support of autochangers.
+
+DESCRIPTION
+   With this patch, new arguments are implemented for amrecover:
+      -T
+      -F
+      -N
+   They set three parameters, a tape label, a file number, and a config name.
+   The new amrestore, when these flags are specified will load + skip
+   to the right tape. This will use amtape to locate the requested tape,
+   then open the tape device, rewind, verify the label, skip to the
+   right file, send output to stdio, close the tape. This is notably
+   supported by amrio, when compiled with ENABLE_SMART_AMRESTORE
+   (see source).
+
+ASSUMPTIONS
+
+LICENSE
+   This patch is (C) Distributed Logic SA, released under the same license
+   as Amanda. This patch has no warranty and is provided as is.
+
+THANKS
+   To all the Amanda authors
+
+NOTES
+   - Using amtape means we will still remain a quite small standalone
+     utility, when -[TFN] are not used.
+   - We need to reverify the label after tape open since there is
+     a window from the return of amtape to the device opening.
+
+SERIOUS-BUGS
+
+BUGS
+
+TODO
+   - finish implementation
+   - test with amrio
+
+CHANGELOG
+   15/02/2000 schaefer Started documentation. Modified manpage.
+                       Started implementation.
+   16/02/2000 schaefer Now three arguments. Finished implementation.
+   15/03/2000 schaefer Documented the new amrestore options in
+                       the manual. Fixed amidxtaped.c to
+                       use the right device also when using special
+                       options.
+
+
+
+
+
+
diff -urP amanda-2.4.2p2/docs/AMRIO amanda-2.4.2p2-changed/docs/AMRIO
--- amanda-2.4.2p2/docs/AMRIO	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/docs/AMRIO	Sat Aug  4 14:37:40 2001
@@ -0,0 +1,67 @@
+AUTHOR
+   Marc SCHAEFER <schaefer@dilog.ch>
+
+GOAL
+   Allows a remote client to pipe the specified backup to a tar --compare
+   command, for example, without intermediate files. The command also
+   locates the right tape and file (quickly), through extensions to
+   the remote tape protocol/amrestore (only compiled in if
+   ENABLE_SMART_AMRESTORE is set). This is now also supported within
+   amrecover.
+
+DESCRIPTION
+   With this patch, a new command is implemented: amrio. This command
+   allows to search for a specified tape and file, and then pipe
+   the result to any command, including tar --compare.
+
+ASSUMPTIONS
+
+LICENSE
+   This patch is (C) Distributed Logic SA, released under the same license
+   as Amanda. This patch has no warranty and is provided as is.
+
+THANKS
+   To all the Amanda authors
+
+NOTES
+
+SERIOUS-BUGS
+
+BUGS
+   - If autochanger is manual, ENABLE_SMART_AMRESTORE will not work.
+   - If extracting from file, amrecover/amrio shouldn't do the
+     magic positionning tricks (or amrestore should be more intelligent).
+     Infact, we just need to ensure amtape is not used if tape label
+     starts with /, the file being 0.
+   - amrecover is less efficient (no file seeks) than amrio.
+   - amrio runs as root and will create debug in /tmp/amanda. This might
+     cause problems for the next normal Amanda run, or if the local machine
+     is also the server (running with backup UID). The symptom is amrio
+     (called e.g. by amcompare) failing.
+     Run chown backup.backup /tmp/backup to fix the problem.
+
+TODO
+   - Add checking on the header that it's the right label, file, etc.
+   - Check that with amrestore it works also with files in different files.
+
+CHANGELOG
+   02/02/2000 schaefer Started implementation of new amrio client command
+                       which can be used already now to verify the data
+                       with tar --compare.
+   14/02/2000 schaefer Added amrio.sh script to verify a level 0 backup
+   15/02/2000 schaefer Removed unneeded debugging.
+   16/02/2000 schaefer Fixed amrio.sh to require a leading / (makes
+                       specifying of root fs easier). Now also passing
+                       configname to amrestore. Modified the option names.
+   21/02/2000 schaefer Integrated amrio to the Amanda Makefile.
+   15/03/2000 schaefer Fixed Makefile.DIS (to be used if automake is not
+                       available). Created manpage. Moved amrio.sh
+                       to DILOG/scripts/verify_full.sh. Added support
+                       configure.in.
+   16/03/2000 schaefer Fixed configure.in (tested on potato), incorporated.
+                       Manpage copying when installing.
+   10/04/2000 schaefer Replaced verify_full.sh by amcompare, using autoconf
+                       and in-text value replacements.
+   12/04/2000 schaefer If !ENABLE_SMART_RESTORE, send 6 arguments like
+                       before. Also fixed comments. Implemented
+                       smart restoring in recover-src/extract_list.c.
diff -urP amanda-2.4.2p2/docs/BUGS amanda-2.4.2p2-changed/docs/BUGS
--- amanda-2.4.2p2/docs/BUGS	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/docs/BUGS	Tue Mar 28 15:44:50 2000
@@ -0,0 +1,43 @@
+AUTHOR
+   Marc SCHAEFER <schaefer@dilog.ch>
+
+GOAL
+   Fix a few Amanda bugs.
+
+DESCRIPTION
+   With this patch, Amanda will have a few problems fixed. For the
+   list of fixed problems, look at the NOTES section. Note that
+   some Amanda bugs might be fixed by our other enhancements. The
+   known cases will be listed also in the NOTES section. This
+   is not the place for fixes for bugs introduced by our
+   patches. However, bugs fixed by other of our patches should
+   be referenced here.
+
+ASSUMPTIONS
+
+LICENSE
+   This patch is (C) Distributed Logic SA, released under the same license
+   as Amanda. This patch has no warranty and is provided as is.
+
+THANKS
+   To all the Amanda authors
+
+NOTES
+   - Fixes the server-src/amlabel.c amfree() which caused a SIGSEGV
+   - The missing of freeing of the sort array in server-src/find.c,
+     sort_find_result(), is fixed in TAPE_APPEND patch.
+
+SERIOUS-BUGS
+
+BUGS
+
+TODO
+   - document that our future amrecover positionning enhancement will fix
+     the out-of-order flush bug too.
+
+CHANGELOG
+   15/03/2000 schaefer Created this file. Implemented amlabel fix.
+   17/03/2000 schaefer Fixed changer-src/chg-scsi-chio.c, using a non
+                       declared conffile variable.
+   28/03/2000 schaefer sort_find_result() in server-src/find.c should really
+                       free the array (fixed in TAPE_APPEND).
\ No newline at end of file
diff -urP amanda-2.4.2p2/docs/DILOG_DEBIAN_CHANGES amanda-2.4.2p2-changed/docs/DILOG_DEBIAN_CHANGES
--- amanda-2.4.2p2/docs/DILOG_DEBIAN_CHANGES	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/docs/DILOG_DEBIAN_CHANGES	Thu Jun 29 09:34:26 2000
@@ -0,0 +1,71 @@
+AUTHOR
+   Marc SCHAEFER <schaefer@dilog.ch>
+
+GOAL
+   Standard configuration for DILOG on Debian
+
+DESCRIPTION
+   This file contains generic installation instructions, including
+   tricks.
+
+ASSUMPTIONS
+
+LICENSE
+   This patch is (C) Distributed Logic SA, released under the same license
+   as Amanda. This patch has no warranty and is provided as is.
+
+THANKS
+   to all the Amanda authors
+
+NOTES
+   - For 2.2.x + Tekram:
+      - modified changer-src/scsi-linux.c, undef LINUX_CHG, this fixes the
+	tape not ready issue (and maybe check cond detection)
+      - Also you have to change the NORMAL_TIMEOUT in
+	/usr/src/linux/drivers/scsi/scsi_ioctl.c from (10 * HZ) to
+        (5 * 60 * HZ).
+   - For 2.0.x + AHA1542:
+      - apply patch changer-src/patch-aha1542, do not apply the above fix.
+   - chown amanda.amanda /dev/sg[12] (tape/changer, if disk @ 0)
+   - ./configure  --prefix=/usr/local/amanda --with-user=amanda \
+        --with-group=amanda
+   - (make; su -c 'make install')
+   - permission fix (/usr/local/amanda, amanda.amanda, 750)
+   - .amandahosts on server and clients
+   - inetd services on the server:
+
+amandaidx stream tcp nowait     backup /usr/sbin/tcpd /usr/lib/amanda/amindexd
+amidxtape stream tcp nowait     backup /usr/sbin/tcpd /usr/lib/amanda/amidxtaped- on the clients
+
+   - on all the clients (possibly the server, too)
+amanda dgram udp wait backup /usr/sbin/tcpd /usr/lib/amanda/amandad
+
+   - firewall rules on those ports (3 for server, 1 for client, UDP)
+
+   - crontab:
+      0 17 * * 1-5 /usr/local/amanda/sbin/amcheck -m uis
+      45 0  * * 2-7 /usr/local/amanda/sbin/amdump uis
+      10 12 * * 5   /usr/local/amanda/scripts/summary.sh uis
+      05 14  * * * /usr/local/amanda/scripts/clean_and_check_tape.sh uis /usr/local/amanda var/lib/tapestatus
+
+   - scripts see ../scripts
+
+   - config examples see ../DILOG/conf
+
+   - Note that if you want to dump fs bigger than 2 GB on Linux,
+     you need to set chunksize to 0 in amanda.conf
+
+
+SERIOUS-BUGS
+
+BUGS
+
+TODO
+
+CHANGELOG
+   25/02/2000 schaefer Created from the old DEBIAN_CHANGES file, imported
+                       scripts and configurations.
+   20/03/2000 schaefer Moved scripts; added comments.
+   16/05/2000 schaefer Added option for list_tape.sh script to show
+                       the actual tape location as seen by mt.
+   29/06/2000 schaefer Added spec-1/2/3 and -no-tmp in dump-types.
\ No newline at end of file
diff -urP amanda-2.4.2p2/docs/SPARSE amanda-2.4.2p2-changed/docs/SPARSE
--- amanda-2.4.2p2/docs/SPARSE	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/docs/SPARSE	Wed Feb  2 13:54:09 2000
@@ -0,0 +1,33 @@
+AUTHOR
+   Marc SCHAEFER <schaefer@dilog.ch>
+
+GOAL
+   Make so that tar produces verifiable archives
+
+DESCRIPTION
+   With this patch, Amanda will not use the --sparse option to tar,
+   since it seems broken in all recent and old GNU tar releases, at
+   least on Linux, possibly on Solaris too.
+
+ASSUMPTIONS
+
+LICENSE
+   This patch is (C) Distributed Logic SA, released under the same license
+   as Amanda. This patch has no warranty and is provided as is.
+
+THANKS
+   To all the Amanda authors
+
+NOTES
+   - Removed --sparse option from sendsize and sendbackup since tar has
+     a bug.
+
+SERIOUS-BUGS
+
+BUGS
+
+TODO
+
+CHANGELOG
+   02/02/2000 schaefer Removed --sparse options in the sendsize and sendbackup
+                       files, since tar has a bug with these options.
diff -urP amanda-2.4.2p2/docs/TAPE_APPEND amanda-2.4.2p2-changed/docs/TAPE_APPEND
--- amanda-2.4.2p2/docs/TAPE_APPEND	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/docs/TAPE_APPEND	Tue May 16 10:45:01 2000
@@ -0,0 +1,166 @@
+AUTHOR
+   Marc SCHAEFER <schaefer@dilog.ch>
+
+GOAL
+   Allow Amanda to append to a previous's day tape (recurses)
+
+DESCRIPTION
+   With this patch, Amanda will from now on append to the last used
+   tape, except if it cannot be found, or if the amadmin conf newtape
+   command was used. The currenttape file path must be specified in
+   amanda.conf, and the appendmode variable should not be set to 0
+   (see examples/amanda.conf.in). The major change are:
+      - the addition of a current-tape-for-append file
+      - tape success log now done to a special tape.<LABEL> file (find no
+        longer parses all log files unless that file is not found).
+
+ASSUMPTIONS
+   - The end marker on tape needs to be removed, else common-src/fileheader.c
+     and restore-src/amrestore.c may be confused. The end marker will
+     be added at each Amanda backup end.
+
+LICENSE
+   This patch is (C) Distributed Logic SA, released under the same license
+   as Amanda. This patch has no warranty and is provided as is.
+
+THANKS
+   John R. Jackson <jrj@gandalf.cc.purdue.edu>
+      Many cleanup suggestions.
+   Jean-Louis Martineau <martinea@IRO.UMontreal.CA>
+      Discovered why amadmin conf find doesn't work, and proposed a
+      solution.
+   (and to all the Amanda authors).
+
+NOTES
+   - We change server-src/taper.c to NOT write a label nor modify tapelist
+     if can_append(tape) is TRUE. Additionnally, allows a !reusable_tape(tape)
+     to be appended to. That function seems to only be used inside taper.c
+     (by first_tape() and next_tape(), although not declared static.
+     Remember: rolling and labelling is done the first time only, not when
+     appending. It is done again when the tape is *reused* (labelled).
+     The handler for the new data structures is the child (the taper
+     writer).
+   - Implemented can_append(tape) in tapefile.c.
+     A tape can be appened if it is top of tapelist, and is in the
+     current_tape file. If a discrepancy occurs, the current_tape file is
+     removed.
+   - Defined functions current_tape_information_{create|update|erase|read}()
+     and implemented in tapefile.[ch]
+   - We keep the tape in the list as already used (this ensures the
+     best compatibility) but we have a special file curr_tape,
+     where we store
+        label of the tape            [name label]
+        file number where to add     [name written_files]
+        blocks used on tape          [name written_blocks]
+        last time of use (initial is on tape label) [name last_used]
+   - In theory there should be no other problem since e.g. when amflush
+     runs it can dump multiple-day backups.
+   - Added new command amadmin newtape to not append.
+   - Modified amcheck.c and amtape.c so that the taper scan algorithm
+     supports appending.
+   - Added new currenttape amanda.conf configuration, which allows to set
+     the name/location of the currenttape file. Defaults to
+     current-tape-for-append.
+   - Added append {yes|no}, default no to the dumptype.
+   - server-src/taper.c adds log entries to tape.<LABEL>. Relabelling the tape
+     deletes the file. 
+   - Modified server-src/find.c to use the new tape.<LABEL> log (needed
+     since previous version expected one tape per log file).
+   - Modified taper.c so that it uses a normal filemark skip command
+     but doesn't write a filemark on the first file when appending.
+     THIS NEEDS VERY GOOD TESTING (since it introduces many possibilities
+     of problems compared to our previous version). We had to do that since
+     only Linux supports a position before filemark command apparently.
+     Using EOM wouldn't work (cannot have more than one TAPEEND, see
+     ASSUMPTIONS above).
+   - Modified find.c so that it goes back to the old log parsing if a
+     tape.<LABEL> doesn't exist (with a warning). This assumes that no
+     tape was appended after it was already used with all data valid.
+     This will be the case (except if the user creates the
+     current-tape-for-append file manually).
+   - Removed the possibility to specify append mode from dumptype to
+     dumptype: it was not implemented and was not really easy (needed
+     to e.g. reorder dumps, etc). Instead, added a global appendmode
+     enable/disable toggle, and added it to documentation, which is
+     now used.
+
+SERIOUS-BUGS
+
+BUGS
+   - At this time, the planner doesn't use the current tape information,
+     and thus believes it has a full tape for the I/O. If this is fixed,
+     there is the risk that the remaining room be under-estimated if
+     the append tape cannot be found at taper time.
+   - written_blocks in current-tape-for-append file is right now,
+     but percentage computation wasn't updated. However size of
+     written data is right.
+   - The tape.<LABEL> file is never deleted except if the tape is
+     re-written (reused, not appended). If the tape is lost, maybe
+     we should delete the file.
+   - Doesn't work with HAVE_LIBVTBLC nor with HAVE_LINUX_ZFTAPE_H.
+     At all.
+   - Should really ensure that the tape writable test is NEVER done
+     on an appendable tape.
+   - Had to do a lot of similar fixes in taper.c, amtape.c and
+     amcheck.c. Those functions should really be merged by the Amanda team.
+   - The label on tape will reflect the date the tape was initially
+     written (however the respective files will have the right dates),
+     including the unique TAPEEND marker.
+   - current_tape_information structure is never freed (?).
+   - amrio/amrestore. if still rewinding, quickly ends with no error.
+     Should only say success if gets GOOD from other side + check.
+
+TODO
+   - use agets() instead of fgets(), after investigation that when
+     using USE_DBMALLOC this doesn't break the writing.
+   - use common-src/token.c for the current tape file parsing instead of
+     ad hoc manual handling.
+   - the tape log should have all events, not just the one we need.
+   - see if there is not a double-work between amrio and amrecover.
+   - maybe a selfcheck could be implemented: after append finishes,
+     verify the tape TOC compared to database (ie to see if previous
+     file headers are there). Also document that user should compare
+     the last before file manually if doubts.
+   - Add conditions based on initial time of use, bytes used,
+     number of files to not do the append (e.g. don't do it
+     if more than 2 days used). Should be configurable, too.
+   - Maybe the append/not append config could be in the tape type ?
+
+CHANGELOG
+   26/01/2000 schaefer Released patch set.
+   27/01/2000 schaefer Changed the licensing information.
+   02/02/2000 schaefer Now using standard tape move (and we don't do a
+                       filemark at first append I/O anymore).
+                       Now going back to parsing log files in find.c if
+                       a tape label file was not found.
+                       Added more documentation.
+                       Added global appendmode enable/disable.
+                       Fixed texts (new/append) depending on global enable.
+   04/02/2000 schaefer Fixed append bug (would destroy the last backup),
+                       bug introduced by the use of standard tape moves.
+   18/02/2000 schaefer taper: moving message was there twice. Updated
+                       AHA1542 patch. Fixed bug which would not append
+                       if a new tape was listed in the tapelist (e.g.
+                       just after label). This involved modifying
+                       server-src/tapefile.c's lookup_last_reusable_tape();
+   21/02/2000 schaefer taper: fixed a possibly dangerous window between
+                       two uses of can_append() in label.
+                       Also now using correct total_tape_used in taper, so
+                       that summary is right.
+   22/02/2000 schaefer taper: don't fail on a new tape if can't append.
+   01/03/2000 schaefer taper: now implemented the label verification just
+                       after we open the device for good, this ensures
+                       better data safety.
+   02/03/2000 schaefer fixed typo.
+   28/03/2000 schaefer Now destroying the current tape file
+                       during writes. Removed the update() function
+                       too, and simplified taper.c. Should ensure a stable
+                       state even if a fatal error (e.g. reboot) occurs.
+                       filenum now only incremented if not the first
+                       file while in append. Implemented unique sorting
+                       in sort_find_result(). Added freeing of the list
+                       used for sorting.
+   15/05/2000 schaefer Fixed off-by-one `amanda des tape' error.
+   16/05/2000 schaefer Fixed amadmin conf info/find discrepancy which was
+                       created by an empty schedule and one too many
+                       filemark because of end label.
\ No newline at end of file
diff -urP amanda-2.4.2p2/example/amanda.conf.chg-scsi.in amanda-2.4.2p2-changed/example/amanda.conf.chg-scsi.in
--- amanda-2.4.2p2/example/amanda.conf.chg-scsi.in	Tue Jun 13 00:58:12 2000
+++ amanda-2.4.2p2-changed/example/amanda.conf.chg-scsi.in	Fri Aug  3 08:16:56 2001
@@ -159,6 +159,12 @@
 #tapelist "/usr/adm/amanda/@DEFAULT_CONFIG@/tapelist"	# list of used tapes
 # tapelist is stored, by default, in the directory that contains amanda.conf
 
+# This is used to remember which tape can be appended to. It is
+# mandatory to specify the full path.
+currenttape "/usr/adm/amanda/@DEFAULT_CONFIG@/current-tape-for-append"
+
+# Enable or disable append mode, defaults to enabled.
+appendmode 1
 
 # tapetypes
 
diff -urP amanda-2.4.2p2/man/Makefile.am amanda-2.4.2p2-changed/man/Makefile.am
--- amanda-2.4.2p2/man/Makefile.am	Mon Nov 20 21:17:15 2000
+++ amanda-2.4.2p2-changed/man/Makefile.am	Fri Aug  3 08:18:10 2001
@@ -34,6 +34,10 @@
 RESTORE_MAN_PAGES = amrestore.8
 endif
 
+if WANT_CLIENT
+AMRIO_MAN_PAGES = amrio.8 amcompare.8
+endif
+
 # not autoconf-generated:
 EXTRA_DIST = amplot.8 amrestore.8 amtape.8
 
@@ -41,6 +45,7 @@
 	   $(COMMON_MAN_PAGES) \
 	   $(SERVER_MAN_PAGES) \
 	   $(RECOVER_MAN_PAGES) \
+	   $(AMRIO_MAN_PAGES) \
 	   $(RESTORE_MAN_PAGES)
 
 install-data-hook:
diff -urP amanda-2.4.2p2/man/amadmin.8.in amanda-2.4.2p2-changed/man/amadmin.8.in
--- amanda-2.4.2p2/man/amadmin.8.in	Sat Nov 18 00:41:01 2000
+++ amanda-2.4.2p2-changed/man/amadmin.8.in	Fri Aug  3 08:20:06 2001
@@ -115,6 +115,17 @@
 .B force
 command.
 .TP
+.P1 newtape
+Tells Amanda to start with a new tape on the next run. This simply
+deletes the file
+.B current_tape-for-append
+in the configuration directory. This is only useful if append mode was
+enabled in the configuration file. Note that the only reason to do
+this is if e.g. you think that that tape was already too much used,
+or won't be enough for the next dump.
+If the tape arrives at end or has an error, the file will be retried
+on the next tape anyway as usual.
+.TP
 .P3 reuse tapelabel [ ... ]
 The tapes listed
 will be available for reuse at their point in the tape cycle.
diff -urP amanda-2.4.2p2/man/amcompare.8.in amanda-2.4.2p2-changed/man/amcompare.8.in
--- amanda-2.4.2p2/man/amcompare.8.in	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/man/amcompare.8.in	Mon Apr 10 10:54:32 2000
@@ -0,0 +1,47 @@
+.\"
+.de EX
+.if t .ft C
+.nf
+..
+.de EE
+.fi
+.if t .ft
+..
+.TH AMCOMPARE 8
+.SH NAME
+amcompare \- compare level 0 backup with data on disk
+.SH SYNOPSIS
+.B amcompare
+.B config
+.B computer
+.B fs
+.B server
+[
+.B date
+]
+.SH DESCRIPTION
+.B amcompare
+
+lists all the file on the local specified filesystem and compares it
+with the backuped files list (e.g. if there are any files missing on
+tape). It also runs a tar --compare, which will spot any differences
+from the files on disk with the files on tape.  It is done by using
+temporary files in the Amanda temporary files, and there should be
+enough space there. 
+
+You can only run it from the client host. This uses amrio. The date
+is optionnal. It must be specified in YYYY-MM-DD format. Only
+works for level 0
+.B tar
+dumps.
+
+.SH EXAMPLE
+.EX
+amcompare des sun1 / debian
+.SH AUTHOR
+Marc SCHAEFER <schaefer@dilog.ch>
+.br
+Distributed Logic SA
+.SH "SEE ALSO"
+amanda(8),
+amrio(8)
diff -urP amanda-2.4.2p2/man/amrestore.8 amanda-2.4.2p2-changed/man/amrestore.8
--- amanda-2.4.2p2/man/amrestore.8	Sun Dec  3 21:39:59 2000
+++ amanda-2.4.2p2-changed/man/amrestore.8	Fri Aug  3 11:46:55 2001
@@ -25,6 +25,14 @@
 [
 .B \-h
 ]
+[
+.B \-T
+label
+.B \-F
+filenum
+.B \-N
+config
+]
 .I tapedevice
 |
 .I holdingfile
@@ -194,6 +202,23 @@
 may also be used to compress the result.
 .B Amrecover
 uses the header to determine the restore program to use.
+.TP
+.B -T
+Label search.
+The specified tape label is searched with
+.B amtape
+.TP
+.B -F
+Fast file search.
+amrestore seeks to the specified file number in an efficient manner.
+.TP
+.B -N
+Configuration.
++The specified configuration is used (required by the
+.B -T
+and
+.B -F
+options).
 .SH EXAMPLES
 The following does an interactive restore of disk
 .I rz3g
diff -urP amanda-2.4.2p2/man/amrio.8.in amanda-2.4.2p2-changed/man/amrio.8.in
--- amanda-2.4.2p2/man/amrio.8.in	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/man/amrio.8.in	Mon Apr 10 10:52:31 2000
@@ -0,0 +1,82 @@
+.\"
+.de EX
+.if t .ft C
+.nf
+..
+.de EE
+.fi
+.if t .ft
+..
+.TH AMRIO 8
+.SH NAME
+amrio \- restores an Amanda backup to stdout
+.SH SYNOPSIS
+.B amrio
+[
+.B [\-C]
+config
+]
+[
+.B [\-s]
+index-server
+]
+[
+.B [\-t]
+tape-server
+]
+[
+.B \-d
+tape-device
+]
+[
+.B \-D
+dump-date
+]
+.B \-H
+host
+.B \-F
+disk
+.B \-L
+level
+.SH DESCRIPTION
+.B amrio
+extracts files from the tape mounted on
+.I tapedevice
+that match
+.IR hostname ,
+.I diskname
+and
+.I datestamp
+patterns given on the command line.
+The tape must be in a format written by the
+.B amdump
+or
+.B amflush
+program.
+.LP
+amrio will automatically determine the tape label, tape file and tell
+a remote
+.B amidxtaped
+(and of course
+.B amrestore
+) to retrieve the specified file quickly, using a tape changer device,
+if appropriate, and fast medium seek commands to position to the right file.
+The data will then, including header, be piped to stdout.
+
+Make sure you specify the no-rewind
+.I tapedevice
+.
+
+.SH EXAMPLES
+See the amcompare shell script which verifies a tar
+backup.
+.SH AUTHOR
+Marc SCHAEFER <schaefer@dilog.ch>
+.br
+Distributed Logic SA
+.SH "SEE ALSO"
+amanda(8),
+amdump(8),
+amflush(8),
+restore(8),
+amcompare(8)
diff -urP amanda-2.4.2p2/recover-src/extract_list.c amanda-2.4.2p2-changed/recover-src/extract_list.c
--- amanda-2.4.2p2/recover-src/extract_list.c	Wed Mar 21 21:55:23 2001
+++ amanda-2.4.2p2-changed/recover-src/extract_list.c	Fri Aug  3 11:49:13 2001
@@ -29,6 +29,10 @@
  * implements the "extract" command in amrecover
  */
 
+#define ENABLE_SMART_AMRESTORE /* tape file option for quick & smart
+                                * amrestore.
+                                */
+
 #include "amanda.h"
 #include "version.h"
 #include "amrecover.h"
@@ -1027,7 +1031,11 @@
 /* start up connection to tape server and set commands to initiate
    transfer of dump image.
    Return tape server socket on success, -1 on error. */
+#ifdef ENABLE_SMART_AMRESTORE
+static int extract_files_setup P((const char *the_tape, int the_file))
+#else /* !ENABLE_SMART_AMRESTORE */
 static int extract_files_setup P((void))
+#endif /* !ENABLE_SMART_AMRESTORE */
 {
     struct servent *sp;
     int my_port;
@@ -1036,6 +1044,19 @@
     char *service_name = NULL;
     char *line = NULL;
     char *clean_datestamp, *ch, *ch1;
+#ifdef ENABLE_SMART_AMRESTORE
+    char string_the_file[20]; /* should be enough, checked below anyway */
+
+    ap_snprintf(string_the_file, sizeof(string_the_file), "%d", the_file);
+#endif /* ENABLE_SMART_AMRESTORE */
+
+#ifdef ENABLE_SMART_AMRESTORE
+    fprintf(stderr,
+            "extract_file_setup(): will request tape %s file %d.\n",
+            the_tape,
+            the_file);
+    fflush(stderr);
+#endif /* ENABLE_SMART_AMRESTORE */
 
     service_name = stralloc2("amidxtape", SERVICE_SUFFIX);
 
@@ -1116,6 +1137,34 @@
     }
     *ch = '\0';
     /* send to the tape server what tape file we want */
+
+#ifdef ENABLE_SMART_AMRESTORE
+    /* 12 args:
+     *   "-T"
+     *   "tape_label"
+     *   "-F"
+     *   "tape file number"
+     *   "-N"
+     *   "config name"
+     *   "-h"
+     *   "-p"
+     *   "tape device"
+     *   "hostname"
+     *   "diskname"
+     *   "datestamp"
+     * BUGS
+     *    - level is ignored.
+     */
+    send_to_tape_server(tape_server_socket, "12");
+    send_to_tape_server(tape_server_socket, "-T");
+    send_to_tape_server(tape_server_socket, the_tape);
+
+    send_to_tape_server(tape_server_socket, "-F");
+    send_to_tape_server(tape_server_socket, string_the_file);
+
+    send_to_tape_server(tape_server_socket, "-N");
+    send_to_tape_server(tape_server_socket, config);
+#else /* !ENABLE_SMART_AMRESTORE */
     /* 6 args:
      *   "-h"
      *   "-p"
@@ -1125,6 +1174,7 @@
      *   "datestamp"
      */
     send_to_tape_server(tape_server_socket, "6");
+#endif /* !ENABLE_SMART_AMRESTORE */
     send_to_tape_server(tape_server_socket, "-h");
     send_to_tape_server(tape_server_socket, "-p");
     send_to_tape_server(tape_server_socket, dump_device_name);
@@ -1523,14 +1573,25 @@
 	}
 	else {
 	    dump_device_name = newstralloc(dump_device_name, tape_device_name);
+#ifndef ENABLE_SMART_AMRESTORE
 	    printf("Load tape %s now\n", elist->tape);
 	    if (!okay_to_continue())
 	        return;
+#endif /* !ENABLE_SMART_AMRESTORE */
 	}
 	dump_datestamp = newstralloc(dump_datestamp, elist->date);
 
 	/* connect to the tape handler daemon on the tape drive server */
+#ifdef ENABLE_SMART_AMRESTORE
+        /* We must use 0 as file number, it will be less efficient than
+         * amrio, but it's not that bad either. Ideas: use amrio once
+         * the file name/level are known ?
+         */
+	if ((tape_server_socket = extract_files_setup(elist->tape,
+                                                      0)) == -1)
+#else /* !ENABLE_SMART_AMRESTORE */
 	if ((tape_server_socket = extract_files_setup()) == -1)
+#endif /* !ENABLE_SMART_AMRESTORE */
 	{
 	    fprintf(stderr, "amrecover - can't talk to tape server\n");
 	    return;
diff -urP amanda-2.4.2p2/remote-io-src/Makefile.DIS amanda-2.4.2p2-changed/remote-io-src/Makefile.DIS
--- amanda-2.4.2p2/remote-io-src/Makefile.DIS	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/remote-io-src/Makefile.DIS	Wed Mar 15 15:13:12 2000
@@ -0,0 +1,7 @@
+all: amrio
+
+amrio: amrio.c amrio.h Makefile.DIS
+	gcc -DHAVE_CONFIG_H -I. -I../config -I../common-src -I../client-src -I../tape-src -g -O2  amrio.c -o amrio -lfl ../client-src/.libs/libamclient.a -lm -lnsl ../tape-src/.libs/libamtape.a ../common-src/.libs/libamanda.a
+
+clean:
+	rm amrio
diff -urP amanda-2.4.2p2/remote-io-src/Makefile.am amanda-2.4.2p2-changed/remote-io-src/Makefile.am
--- amanda-2.4.2p2/remote-io-src/Makefile.am	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/remote-io-src/Makefile.am	Mon Apr 10 10:43:21 2000
@@ -0,0 +1,40 @@
+# Makefile for Amanda remote I/O program
+
+INCLUDES =		-I$(top_srcdir)/common-src -I$(top_srcdir)/client-src \
+			-I$(top_srcdir)/tape-src
+
+if WANT_LIBTOOL
+LIB_EXTENSION = la
+else
+LIB_EXTENSION = a
+endif
+
+sbin_PROGRAMS =		amrio
+
+sbin_SCRIPTS  =		amcompare
+
+LDADD = @LEXLIB@ \
+	../client-src/libamclient.$(LIB_EXTENSION) \
+	../tape-src/libamtape.$(LIB_EXTENSION) \
+	../common-src/libamanda.$(LIB_EXTENSION)
+
+amrio_SOURCES =	amrio.c
+
+noinst_HEADERS = 	amrio.h
+
+YFLAGS =		-d
+
+install-exec-hook:
+	@list="$(sbin_PROGRAMS)"; \
+	for p in $$list; do \
+		pa=$(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \
+		echo chown $(BINARY_OWNER) $$pa; \
+		chown $(BINARY_OWNER) $$pa; \
+		echo chgrp $(SETUID_GROUP) $$pa; \
+		chgrp $(SETUID_GROUP) $$pa; \
+		echo chmod o-rwx $$pa; \
+		chmod o-rwx $$pa; \
+	done
+
+amcompare:
+	chmod a+x $@
diff -urP amanda-2.4.2p2/remote-io-src/Makefile.in amanda-2.4.2p2-changed/remote-io-src/Makefile.in
--- amanda-2.4.2p2/remote-io-src/Makefile.in	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/remote-io-src/Makefile.in	Mon Apr 10 11:19:42 2000
@@ -0,0 +1,477 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+# Makefile for Amanda remote I/O program
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMANDA_DBGDIR = @AMANDA_DBGDIR@
+AMANDA_TMPDIR = @AMANDA_TMPDIR@
+AMPLOT_CAT_COMPRESS = @AMPLOT_CAT_COMPRESS@
+AMPLOT_CAT_GZIP = @AMPLOT_CAT_GZIP@
+AMPLOT_CAT_PACK = @AMPLOT_CAT_PACK@
+AMPLOT_COMPRESS = @AMPLOT_COMPRESS@
+AR = @AR@
+AS = @AS@
+AWK = @AWK@
+AWK_VAR_ASSIGNMENT_OPT = @AWK_VAR_ASSIGNMENT_OPT@
+BINARY_OWNER = @BINARY_OWNER@
+CAT = @CAT@
+CC = @CC@
+CHIO = @CHIO@
+CHS = @CHS@
+CLIENT_LOGIN = @CLIENT_LOGIN@
+CLIENT_SCRIPTS_OPT = @CLIENT_SCRIPTS_OPT@
+COMPRESS = @COMPRESS@
+CONFIG_DIR = @CONFIG_DIR@
+DB_EXT = @DB_EXT@
+DD = @DD@
+DEFAULT_CHANGER_DEVICE = @DEFAULT_CHANGER_DEVICE@
+DEFAULT_CONFIG = @DEFAULT_CONFIG@
+DEFAULT_RAW_TAPE_DEVICE = @DEFAULT_RAW_TAPE_DEVICE@
+DEFAULT_SERVER = @DEFAULT_SERVER@
+DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
+DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
+DLLTOOL = @DLLTOOL@
+DUMP = @DUMP@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GETCONF = @GETCONF@
+GNUPLOT = @GNUPLOT@
+GNUTAR = @GNUTAR@
+GREP = @GREP@
+GZIP = @GZIP@
+LD = @LD@
+LEX = @LEX@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LN_S = @LN_S@
+LTALLOCA = @LTALLOCA@
+LTLIBOBJS = @LTLIBOBJS@
+MAILER = @MAILER@
+MAKEINFO = @MAKEINFO@
+MT = @MT@
+MTX = @MTX@
+MT_FILE_FLAG = @MT_FILE_FLAG@
+NM = @NM@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PCAT = @PCAT@
+PERL = @PERL@
+PRINT = @PRINT@
+RANLIB = @RANLIB@
+RESTORE = @RESTORE@
+SAMBA_CLIENT = @SAMBA_CLIENT@
+SERVICE_SUFFIX = @SERVICE_SUFFIX@
+SETUID_GROUP = @SETUID_GROUP@
+SHELL = @SHELL@
+SNAPSHOT_STAMP = @SNAPSHOT_STAMP@
+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@
+XFSDUMP = @XFSDUMP@
+XFSRESTORE = @XFSRESTORE@
+YACC = @YACC@
+ac_c = @ac_c@
+ac_n = @ac_n@
+
+INCLUDES = -I$(top_srcdir)/common-src -I$(top_srcdir)/client-src 			-I$(top_srcdir)/tape-src
+
+@WANT_LIBTOOL_TRUE@LIB_EXTENSION = la
+@WANT_LIBTOOL_FALSE@LIB_EXTENSION = a
+
+sbin_PROGRAMS = amrio
+
+sbin_SCRIPTS = amcompare
+
+LDADD = @LEXLIB@ 	../client-src/libamclient.$(LIB_EXTENSION) 	../tape-src/libamtape.$(LIB_EXTENSION) 	../common-src/libamanda.$(LIB_EXTENSION)
+
+
+amrio_SOURCES = amrio.c
+
+noinst_HEADERS = amrio.h
+
+YFLAGS = -d
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = ../config/config.h
+CONFIG_CLEAN_FILES = 
+sbin_PROGRAMS =  amrio$(EXEEXT)
+PROGRAMS =  $(sbin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../config
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+amrio_OBJECTS =  amrio.$(OBJEXT)
+amrio_LDADD = $(LDADD)
+amrio_DEPENDENCIES =  ../client-src/libamclient.$(LIB_EXTENSION) \
+../tape-src/libamtape.$(LIB_EXTENSION) \
+../common-src/libamanda.$(LIB_EXTENSION)
+amrio_LDFLAGS = 
+SCRIPTS =  $(sbin_SCRIPTS)
+
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+HEADERS =  $(noinst_HEADERS)
+
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+DEP_FILES =  .deps/amrio.P
+SOURCES = $(amrio_SOURCES)
+OBJECTS = $(amrio_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .obj .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu remote-io-src/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-sbinPROGRAMS:
+
+clean-sbinPROGRAMS:
+	-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+
+distclean-sbinPROGRAMS:
+
+maintainer-clean-sbinPROGRAMS:
+
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sbindir)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+# FIXME: We should only use cygpath when building on Windows,
+# and only if it is available.
+.c.obj:
+	$(COMPILE) -c `cygpath -w $<`
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+	-rm -f *.$(OBJEXT)
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+amrio$(EXEEXT): $(amrio_OBJECTS) $(amrio_DEPENDENCIES)
+	@rm -f amrio$(EXEEXT)
+	$(LINK) $(amrio_LDFLAGS) $(amrio_OBJECTS) $(amrio_LDADD) $(LIBS)
+
+install-sbinSCRIPTS: $(sbin_SCRIPTS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sbindir)
+	@list='$(sbin_SCRIPTS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(INSTALL_SCRIPT) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \
+	  else if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`"; \
+	    $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \
+	  else :; fi; fi; \
+	done
+
+uninstall-sbinSCRIPTS:
+	@$(NORMAL_UNINSTALL)
+	list='$(sbin_SCRIPTS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \
+	done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = remote-io-src
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu remote-io-src/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+	-rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-cp .deps/$(*F).pp .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm .deps/$(*F).pp
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-sed -e 's/^\([^:]*\)\.o[ 	]*:/\1.lo \1.o :/' \
+	  < .deps/$(*F).pp > .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-sbinPROGRAMS install-sbinSCRIPTS
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-sbinPROGRAMS uninstall-sbinSCRIPTS
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(HEADERS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(sbindir) $(DESTDIR)$(sbindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-sbinPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-sbinPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-sbinPROGRAMS distclean-compile \
+		distclean-libtool distclean-tags distclean-depend \
+		distclean-generic clean-am
+	-rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-sbinPROGRAMS \
+		maintainer-clean-compile maintainer-clean-libtool \
+		maintainer-clean-tags maintainer-clean-depend \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS \
+clean-sbinPROGRAMS maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \
+install-sbinPROGRAMS mostlyclean-compile distclean-compile \
+clean-compile maintainer-clean-compile mostlyclean-libtool \
+distclean-libtool clean-libtool maintainer-clean-libtool \
+uninstall-sbinSCRIPTS install-sbinSCRIPTS tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+install-exec-hook:
+	@list="$(sbin_PROGRAMS)"; \
+	for p in $$list; do \
+		pa=$(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \
+		echo chown $(BINARY_OWNER) $$pa; \
+		chown $(BINARY_OWNER) $$pa; \
+		echo chgrp $(SETUID_GROUP) $$pa; \
+		chgrp $(SETUID_GROUP) $$pa; \
+		echo chmod o-rwx $$pa; \
+		chmod o-rwx $$pa; \
+	done
+
+amcompare:
+	chmod a+x $@
+
+# 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 -urP amanda-2.4.2p2/remote-io-src/amcompare.in amanda-2.4.2p2-changed/remote-io-src/amcompare.in
--- amanda-2.4.2p2/remote-io-src/amcompare.in	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/remote-io-src/amcompare.in	Mon Apr 10 11:19:50 2000
@@ -0,0 +1,51 @@
+#! /bin/sh
+
+case $# in
+   4|5) ;;
+   *)   echo "$0 config computer fs server [date]" >&2
+        echo "$0: Example: $0 uis defian /usr debian 2000-02-14"
+        echo "$0: bad args." >&2
+        exit 2;;
+esac
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+AMRIO=@sbindir@/amrio
+
+TMP_DIRECTORY=@AMANDA_TMPDIR@
+TMP_FILE_1=$TMP_DIRECTORY/list_1_$$
+TMP_FILE_2=$TMP_DIRECTORY/list_2_$$
+TMP_FILE_3=$TMP_DIRECTORY/list_3_$$
+
+mkdir -p $TMP_DIRECTORY
+rm -f $TMP_FILE_1 $TMP_FILE_2 $TMP_FILE_3
+
+COMPUTER=$2
+CONFIG=$1
+FS=$3
+SERVER=$4
+
+case $FS in
+   /*) ;;
+   *) echo "$0: fs must start with /" >&2
+      exit 2;;
+esac
+
+if [ $# != 5 ]; then
+   DATE=
+else
+   DATE="-D $5"
+fi
+
+$AMRIO $CONFIG -s $SERVER -t $SERVER -d /dev/nst0 -H $COMPUTER -F $FS -L 0 $DATE | (cd $FS && dd bs=4k skip=8 | tar -b 64 --compare -f - -v) 2> $TMP_FILE_2 > $TMP_FILE_1
+
+# On Solaris 2.4, we have tested with GNU tar, and it works only with
+# the -b 64 option. On Linux (tar 1.12) it looks there is no problem
+# without.
+
+(cd $FS && find . -mount -print | sort) > $TMP_FILE_3
+
+egrep -v 'is new' $TMP_FILE_2
+sed 's%/$%%' < $TMP_FILE_1 | sort | diff - $TMP_FILE_3
+
+rm -f $TMP_FILE_1 $TMP_FILE_2 $TMP_FILE_3
diff -urP amanda-2.4.2p2/remote-io-src/amrio.c amanda-2.4.2p2-changed/remote-io-src/amrio.c
--- amanda-2.4.2p2/remote-io-src/amrio.c	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/remote-io-src/amrio.c	Fri Aug  3 11:48:12 2001
@@ -0,0 +1,940 @@
+/*
+ * 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: amanda-2.4.2p2-append-patch,v 1.4 2001/08/16 12:03:56 msc Exp $
+ *
+ * a program for getting back a complete Amanda file (file == backup), for
+ * specific restore, or for verification through e.g. tar --compare, using
+ * the Amanda remote tape protocol and indexes.
+ */
+
+#define ENABLE_SMART_AMRESTORE /* tape file option for quick & smart
+                                * amrestore.
+                                */
+
+#include "amanda.h"
+#include "version.h"
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#include <netinet/in.h>
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+#include "amrio.h"
+#include "getfsent.h"
+#include "dgram.h"
+
+#if defined(KRB4_SECURITY)
+#include "krb4-security.h"
+#endif
+#include "util.h"
+
+#define USAGE "Usage: amrio [[-C] <config>] [-s <index-server>] [-t <tape-server>] [-d <tape-device>] [-D dump-date] -H host -F disk -L level\n"
+
+static char * set_dump P((const char *host, const char *disk, const char *date, const char *level, int *the_file));
+static int extract_file_data P((int fd));
+static int extract_file_setup P((const char *the_tape, int the_file));
+static int converse P((char *cmd));
+static int exchange P((char *cmd));
+static int send_command P((char *cmd));
+static int get_reply_line P((void));
+static char *reply_line P((void));
+static void quit P((void));
+static void send_to_tape_server_my P((int tss, const char *cmd));
+
+/* The following is normally set by Makefile */
+#ifndef DEFAULT_CONFIG
+#define DEFAULT_CONFIG "uis"
+#endif /* !DEFAULT_CONFIG */
+
+#ifndef DEFAULT_SERVER
+#define DEFAULT_SERVER "localhost"
+#endif /* !DEFAULT_SERVER */
+
+char *config = NULL;
+char *server_name = NULL;
+int server_socket;
+char *server_line = NULL;
+char *dump_datestamp = NULL;		/* date we are restoring */
+char *dump_hostname = NULL;	        /* which machine we are restoring */
+char *disk_name = NULL;			/* disk we are restoring */
+char *tape_server_name = NULL;
+int tape_server_socket;
+char *tape_device_name = NULL;
+char *backup_dump_level = NULL;
+
+/* gets a "line" from server and put in server_line */
+/* server_line is terminated with \0, \r\n is striped */
+/* returns -1 if error */
+
+int get_line ()
+{
+    char *line = NULL;
+    char *part = NULL;
+    int len;
+
+    while(1) {
+	if((part = areads(server_socket)) == NULL) {
+	    int save_errno = errno;
+
+	    if(server_line) {
+		fputs(server_line, stderr);	/* show the last line read */
+		fputc('\n', stderr);
+		errno = save_errno;
+	    }
+	    if(errno != 0) {
+		fprintf(stderr, "%s: ", get_pname());
+		errno = save_errno;
+		perror("Error reading line from server");
+	    } else {
+		fprintf(stderr, "%s: Unexpected server end of file\n",
+			get_pname());
+	    }
+	    amfree(line);
+	    amfree(server_line);
+	    return -1;
+	}
+	if(line) {
+	    strappend(line, part);
+	    amfree(part);
+	} else {
+	    line = part;
+	    part = NULL;
+	}
+	if((len = strlen(line)) > 0 && line[len-1] == '\r') {
+	    line[len-1] = '\0';
+	    server_line = newstralloc(server_line, line);
+	    amfree(line);
+	    return 0;
+	}
+	/*
+	 * Hmmm.  We got a "line" from areads(), which means it saw
+	 * a '\n' (or EOF, etc), but there was not a '\r' before it.
+	 * Put a '\n' back in the buffer and loop for more.
+	 */
+	strappend(line, "\n");
+    }
+}
+
+
+/* get reply from server and print to screen */
+/* handle multi-line reply */
+/* return -1 if error */
+/* return code returned by server always occupies first 3 bytes of global
+   variable server_line */
+int grab_reply (show)
+int show;
+{
+    do {
+	if (get_line() == -1) {
+	    return -1;
+	}
+	if(show) fprintf(stderr, "%s\n", server_line);
+    } while (server_line[3] == '-');
+    if(show) fflush(stderr);
+
+    return 0;
+}
+
+
+/* get 1 line of reply */
+/* returns -1 if error, 0 if last (or only) line, 1 if more to follow */
+static int get_reply_line ()
+{
+    if (get_line() == -1)
+	return -1;
+    return server_line[3] == '-';
+}
+
+
+/* returns pointer to returned line */
+static char *reply_line ()
+{
+    return server_line;
+}
+
+
+
+/* returns 0 if server returned an error code (ie code starting with 5)
+   and non-zero otherwise */
+int server_happy ()
+{
+    return server_line[0] != '5';
+}
+
+
+static int send_command(cmd)
+char *cmd;
+{
+    int l, n, s;
+    char *end;
+
+    /*
+     * NOTE: this routine is called from sigint_handler, so we must be
+     * **very** careful about what we do since there is no way to know
+     * our state at the time the interrupt happened.  For instance,
+     * do not use any stdio routines here.
+     */
+    for (l = 0, n = strlen(cmd); l < n; l += s)
+	if ((s = write(server_socket, cmd + l, n - l)) < 0) {
+	    perror("amrio: Error writing to server");
+	    return -1;
+	}
+    end = "\r\n";
+    for (l = 0, n = strlen(end); l < n; l += s)
+	if ((s = write(server_socket, end + l, n - l)) < 0) {
+	    perror("amrio: Error writing to server");
+	    return -1;
+	}
+    return 0;
+}
+
+
+/* send a command to the server, get reply and print to screen */
+static int converse(cmd)
+char *cmd;
+{
+    if (send_command(cmd) == -1) return -1;
+    if (grab_reply(1) == -1) return -1;
+    return 0;
+}
+
+
+/* same as converse() but reply not echoed to stderr */
+static int exchange(cmd)
+char *cmd;
+{
+    if (send_command(cmd) == -1) return -1;
+    if (grab_reply(0) == -1) return -1;
+    return 0;
+}
+
+char *localhost = NULL;
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+    struct sockaddr_in server;
+    struct sockaddr_in myname;
+    struct servent *sp;
+    struct hostent *hp;
+    int i;
+    time_t timer;
+    char *lineread = NULL;
+    struct sigaction act, oact;
+    extern char *optarg;
+    extern int optind;
+    char cwd[STR_SIZE], *dn_guess = NULL, *mpt_guess = NULL;
+    char *service_name;
+    char *line = NULL;
+    int fd;
+
+    for(fd = 3; fd < FD_SETSIZE; fd++) {
+	/*
+	 * Make sure nobody spoofs us with a lot of extra open files
+	 * that would cause an open we do to get a very high file
+	 * descriptor, which in turn might be used as an index into
+	 * an array (e.g. an fd_set).
+	 */
+	close(fd);
+    }
+
+    set_pname("amrio");
+
+    if (geteuid() != 0) {
+	error("amrio must be run by root"); /* why ? BSD security ? */
+    }
+
+    localhost = alloc(MAX_HOSTNAME_LENGTH+1);
+    if (gethostname(localhost, MAX_HOSTNAME_LENGTH) != 0) {
+	error("cannot determine local host name\n");
+    }
+    localhost[MAX_HOSTNAME_LENGTH] = '\0';
+
+    config = newstralloc(config, DEFAULT_CONFIG);
+    server_name = newstralloc(server_name, DEFAULT_SERVER);
+#ifdef DEFAULT_TAPE_SERVER
+    tape_server_name = newstralloc(tape_server_name, DEFAULT_TAPE_SERVER);
+    tape_device_name = newstralloc(tape_device_name, DEFAULT_TAPE_DEVICE);
+#else
+    amfree(tape_server_name);
+    amfree(tape_device_name);
+#endif
+
+    if (argc > 1 && argv[1][0] != '-')
+    {
+	/*
+	 * If the first argument is not an option flag, then we assume
+	 * it is a configuration name to match the syntax of the other
+	 * Amanda utilities.
+	 */
+	char **new_argv;
+
+	new_argv = (char **) malloc ((argc + 1 + 1) * sizeof (*new_argv));
+	if (new_argv == NULL)
+	{
+	    (void)fprintf(stderr, "%s: no memory for argument list\n",
+			  get_pname());
+	    exit(1);
+	}
+	new_argv[0] = argv[0];
+	new_argv[1] = "-C";
+	for (i = 1; i < argc; i++)
+	{
+	    new_argv[i + 1] = argv[i];
+	}
+	new_argv[i + 1] = NULL;
+	argc++;
+	argv = new_argv;
+    }
+
+    while ((i = getopt(argc, argv, "C:s:t:d:U:D:H:F:L:")) != EOF)
+    {
+	switch (i)
+	{
+	    case 'C':
+		config = newstralloc(config, optarg);
+		break;
+
+	    case 's':
+		server_name = newstralloc(server_name, optarg);
+		break;
+
+	    case 't':
+		tape_server_name = newstralloc(tape_server_name, optarg);
+		break;
+
+	    case 'd':
+		tape_device_name = newstralloc(tape_device_name, optarg);
+		break;
+
+            case 'D':
+                dump_datestamp = newstralloc(dump_datestamp, optarg);
+                break;
+
+            case 'H':
+                dump_hostname = newstralloc(dump_hostname, optarg);
+                break;
+
+            case 'F':
+                disk_name = newstralloc(disk_name, optarg);
+                break;
+
+            case 'L':
+                backup_dump_level = newstralloc(backup_dump_level, optarg);
+                break;
+
+	    case 'U':
+	    case '?':
+		(void)printf(USAGE);
+		return 0;
+	}
+    }
+    if (optind != argc)
+    {
+	(void)fprintf(stderr, USAGE);
+	exit(1);
+    }
+
+    if (!dump_datestamp) {
+       time_t timer;
+       char dump_date[STR_SIZE];
+
+       /* set the date of extraction to be today */
+       (void)time(&timer);
+       strftime(dump_date, sizeof(dump_date), "%Y-%m-%d", localtime(&timer));
+       fprintf(stderr, "Setting restore date to today (%s)\n", dump_date);
+       dump_datestamp = newstralloc(dump_datestamp, dump_date);
+    }
+
+    if (!dump_datestamp
+        || !dump_hostname
+        || !disk_name
+        || !backup_dump_level) {
+       (void)fprintf(stderr, USAGE);
+       exit(1);
+    }
+
+    dbopen();
+
+    service_name = stralloc2("amandaidx", SERVICE_SUFFIX);
+
+    fprintf(stderr, "AMRIO Version %s. Contacting server on %s ...\n",
+	   version(), server_name);  
+    if ((sp = getservbyname(service_name, "tcp")) == NULL)
+    {
+	perror("amrio: amandaidx/tcp unknown protocol");
+	dbprintf(("%s/tcp unknown protocol\n", service_name));
+	dbclose();
+	exit(1);
+    }
+    if ((hp = gethostbyname(server_name)) == NULL)
+    {
+	(void)fprintf(stderr, "%s: %s is an unknown host\n",
+		      get_pname(), server_name);
+	dbprintf(("%s is an unknown host\n", server_name));
+	dbclose();
+	exit(1);
+    }
+    memset((char *)&server, 0, sizeof(server));
+    memcpy((char *)&server.sin_addr, hp->h_addr, hp->h_length);
+    server.sin_family = hp->h_addrtype;
+    server.sin_port = sp->s_port;
+    if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+
+    {
+	perror("amrio: Error creating socket");
+	dbprintf(("Error creating socket\n"));
+	dbclose();
+	exit(1);
+    }
+
+    /*
+     * Bind our end of the socket to a privileged port.
+     */
+    if ((hp = gethostbyname(localhost)) == NULL)
+    {
+	(void)fprintf(stderr, "%s: %s is an unknown host\n",
+		      get_pname(), localhost);
+	dbprintf(("%s is an unknown host\n", localhost));
+	dbclose();
+	exit(1);
+    }
+    memset((char *)&myname, 0, sizeof(myname));
+    memcpy((char *)&myname.sin_addr, hp->h_addr, hp->h_length);
+    myname.sin_family = hp->h_addrtype;
+    if (bind_portrange(server_socket, &myname, 512, IPPORT_RESERVED - 1) != 0)
+    {
+	int save_errno = errno;
+
+	perror("amrio: Error binding socket");
+	dbprintf(("Error binding socket: %s\n", strerror(save_errno)));
+	dbclose();
+	exit(1);
+    }
+    if (ntohs(myname.sin_port) >= IPPORT_RESERVED) {
+	(void)fprintf(stderr, "%s: can't get a reserved udp port\n",
+		      get_pname());
+	dbprintf(("can't get a reserved udp port\n"));
+	dbclose();
+	exit(1);
+    }
+
+#if 0
+    /*
+     * We may need root privilege again later for a reserved port to
+     * the tape server, so we will drop down now but might have to
+     * come back later.
+     */
+    setegid(getgid());
+    seteuid(getuid());
+#endif
+
+    if (connect(server_socket, (struct sockaddr *)&server, sizeof(server))
+	== -1)
+    {
+	perror("amrio: Error connecting to server");
+	dbprintf(("Error connecting to server\n"));
+	dbclose();
+	exit(1);
+    }
+
+    /* get server's banner */
+    if (grab_reply(1) == -1)
+	exit(1);
+    if (!server_happy())
+    {
+	dbclose();
+	aclose(server_socket);
+	exit(1);
+    }
+
+    /* do the security thing */
+#if defined(KRB4_SECURITY)
+#if 0 /* not yet implemented */
+    if(krb4_auth)
+    {
+	line = get_krb_security();
+    } else
+#endif /* 0 */
+#endif
+    {
+	line = get_bsd_security();
+    }
+    if (converse(line) == -1)
+	exit(1);
+    if (!server_happy())
+	exit(1);
+    memset(line, '\0', strlen(line));
+    amfree(line);
+
+    line = stralloc2("SCNF ", config);
+    if (converse(line) == -1)
+	exit(1);
+    amfree(line);
+
+    if (server_happy())
+    {
+       char *the_tape = NULL;
+       int the_file = 0;
+
+	/* set host we are restoring to this host by default */
+        if ((the_tape = set_dump(dump_hostname,
+                                 disk_name,
+                                 dump_datestamp,
+                                 backup_dump_level,
+                                 &the_file))
+            && server_happy()) {
+           int result = 1;
+
+           if (tape_server_name == NULL) {
+              tape_server_name = newstralloc(tape_server_name, server_name);
+           }
+           if (tape_device_name == NULL) {
+              result = 0;
+	      if ((send_command("TAPE") != -1)
+	          && (get_reply_line() == -1)) {
+	         char *l = reply_line();
+
+	         if (!server_happy()) {
+		     fprintf(stderr, "%s\n", l);
+	         }
+                 else {
+  	            tape_device_name = newstralloc(tape_device_name, l+4);
+                    result = 1;
+                 }
+
+                 amfree(l);
+              }
+           }
+
+           if (result) {
+              int fd;
+
+              fd = extract_file_setup(the_tape, the_file);
+              if (fd != -1) {
+                 extract_file_data(fd); /* res ignored */
+                 aclose(fd);                       
+                 (void)converse("QUIT");
+              }
+              else {
+                 fprintf(stderr, "amrio: can't talk to tape server.\n");
+                 result = 0;
+              }
+           }
+
+           if (result) {
+              fprintf(stderr, "amrio: presumably has succeeded.\n");
+           }
+        }
+        else {
+           fprintf(stderr, "amrio: server returned error: %s.\n", server_line);
+        }
+    }
+
+    dbclose();
+
+    aclose(server_socket);
+    return 0;
+}
+
+/* sets a date, mapping given date into standard form if needed */
+static char *set_dump(host, disk, date, level, the_file)
+const char *host;
+const char *disk;
+const char *date;
+const char *level;
+int *the_file;
+{
+    char *cmd = NULL;
+    char *the_tape = NULL;
+
+    cmd = stralloc2("DATE ", date); /* not really useful here */
+    if (converse(cmd) != -1) {
+       cmd = newstralloc2(cmd, "HOST ", host);
+       if (converse(cmd) != -1) {
+          cmd = newstralloc2(cmd, "DISK ", disk);
+	  if (converse(cmd) != -1) {
+             /* find the appropriate tape with the date/level/disk/host */
+             cmd = newstralloc(cmd, "DHST");
+             if (send_command(cmd) != -1) {
+                int count = get_line();
+
+                if ((count != -1)
+                    && (server_line[3] == '-')
+                    && (server_line[0] == '2')) {
+                   int found = 0;
+                   int error = 0;
+                   int finished = 0;
+
+                   /* ASSUMPTION
+                    *    - Data is returned first first (if multiple
+                    *      DAY/LEVEL backup).
+                    */
+#define SET_DUMP_TOKENS 6
+                   while (!finished && !error) {
+                      char *tokens[SET_DUMP_TOKENS];
+
+		      count = get_line();
+
+		      if (count != -1) {
+                         if (server_line[3] != '-') {
+                            finished = 1;
+                         }
+                         else if (!found) {
+                            int token;
+
+                            if ((token = split(server_line,
+                                               tokens,
+                                               SET_DUMP_TOKENS,
+                                               " ")) == (SET_DUMP_TOKENS
+                                                         - 1)) {
+			       found = !strcmp(tokens[2],
+					       date)
+				       && !strcmp(tokens[3],
+						  level);
+			       if (found) {
+				  the_tape = stralloc(tokens[4]);
+				  *the_file = atoi(tokens[5]);
+
+                                  fprintf(stderr, "FOUND: tape %s file %d.\n",
+                                                  the_tape, *the_file);
+			       }
+                            }
+                            else {
+                               fprintf(stderr, "can't tokenize %d.\n", token);
+                               error = 1;
+                            }
+
+                            /* BUGS
+                             *    - do we need to free anything ?
+                             */
+                         }
+ 		      }
+                      else {
+                         error = 1;
+                      }
+                      
+                   }
+
+                   if (error) {
+                      amfree(the_tape); /* also sets ptr to NULL */
+                   }
+                }
+             }
+          }
+       }
+    }
+    amfree(cmd);
+
+    return the_tape;
+}
+
+/* TODO
+ *    - Maybe do it with two processes for efficiency (or
+ *      the user can pipe to the buffer command).
+ */
+static int extract_file_data(fd)
+int fd;
+{
+   char buffer[TAPE_BLOCK_BYTES];
+   int finished = 0;
+   int result = 0;
+
+   /* This is designed so that
+    *    ./amrio uis -s debian -t debian -d /dev/nst0 -D 2000-01-31 -H defian \
+    *       -F / -L 0 | (cd /; dd bs=4k skip=8 | tar --compare -f -)
+    * works.
+    */
+
+   while (!finished) {
+      char *tmp = buffer;
+      int tmp_read;
+      int size_written;
+      int size_read = 0;
+
+      while (size_read < sizeof(buffer) && !finished) {
+         tmp_read = read(fd, tmp, (TAPE_BLOCK_BYTES - size_read));
+	 if (tmp_read < 0) {
+	    perror("read()");
+	    finished = 1;
+	 }
+	 else if (tmp_read == 0) {
+	    result = 1;
+	    finished = 1;
+	 }
+         else {
+            size_read += tmp_read;
+            tmp += tmp_read;
+         }
+      }
+
+      tmp = buffer;
+
+      while (size_read) {
+         size_written = write(STDOUT_FILENO, tmp, size_read);
+         if (size_written <= 0) {
+            perror("write()");
+            finished = 1;
+         }
+         else {
+            if (size_written <= size_read) {
+               size_read -= size_written;
+               tmp += size_written;
+            }
+            else {
+               fprintf(stderr, "ERROR: incoherency (%d vs %d).\n",
+                               size_written, size_read);
+            }
+         }
+
+         if (finished) {
+            break;
+         }
+      }
+   }
+
+   return result;
+}
+
+/* start up connection to tape server and set commands to initiate
+   transfer of dump image.
+   Return tape server socket on success, -1 on error. */
+static int extract_file_setup (the_tape, the_file)
+const char *the_tape;
+int the_file;
+{
+    struct sockaddr_in tape_server;
+    struct sockaddr_in myname;
+    struct servent *sp;
+    struct hostent *hp;
+    int tape_server_socket;
+    char *disk_regex = NULL;
+    char *service_name = NULL;
+    char *line = NULL;
+    char *clean_datestamp, *ch, *ch1;
+#ifdef ENABLE_SMART_AMRESTORE
+    char string_the_file[20]; /* should be enough, checked below anyway */
+
+    ap_snprintf(string_the_file, sizeof(string_the_file), "%d", the_file);
+#endif /* ENABLE_SMART_AMRESTORE */
+    fprintf(stderr,
+#ifdef ENABLE_SMART_AMRESTORE
+            "extract_file_setup(): will request tape %s file %d.\n",
+#else /* !ENABLE_SMART_AMRESTORE */
+            "extract_file_setup(): should really request tape %s file %d.\n",
+#endif /* !ENABLE_SMART_AMRESTORE */
+            the_tape,
+            the_file);
+    fflush(stderr);
+
+    service_name = stralloc2("amidxtape", SERVICE_SUFFIX);
+
+    /* get tape server details */
+    if ((sp = getservbyname(service_name, "tcp")) == NULL)
+    {
+	fprintf(stderr, "%s/tcp unknown protocol - config error?\n", service_name);
+	amfree(service_name);
+	return -1;
+    }
+    amfree(service_name);
+    if ((hp = gethostbyname(tape_server_name)) == NULL)
+    {
+	fprintf(stderr, "%s is an unknown host\n", tape_server_name);
+	return -1;
+    }
+    memset((char *)&tape_server, 0, sizeof(tape_server));
+    memcpy((char *)&tape_server.sin_addr, hp->h_addr, hp->h_length);
+    tape_server.sin_family = hp->h_addrtype;
+    tape_server.sin_port = sp->s_port;
+
+    /* contact the tape server */
+    if ((tape_server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+    {
+	perror("Error creating socket");
+	exit(1);
+    }
+    if ((hp = gethostbyname(localhost)) == NULL)
+    {
+	(void)fprintf(stderr, "%s: %s is an unknown host\n",
+		      get_pname(), localhost);
+	dbprintf(("%s is an unknown host\n", localhost));
+	dbclose();
+	exit(1);
+    }
+    memset((char *)&myname, 0, sizeof(myname));
+    memcpy((char *)&myname.sin_addr, hp->h_addr, hp->h_length);
+    myname.sin_family = hp->h_addrtype;
+    seteuid(0);					/* it either works ... */
+    setegid(0);
+    if (bind_portrange(tape_server_socket, &myname, 512, IPPORT_RESERVED - 1) != 0)
+    {
+	perror("amrecover: Error binding socket");
+	exit(2);
+    }
+    if (ntohs(myname.sin_port) >= IPPORT_RESERVED) {
+	(void)fprintf(stderr, "%s: can't get a reserved udp port\n",
+		      get_pname());
+	dbprintf(("can't get a reserved udp port\n"));
+	dbclose();                    
+	exit(1);
+    }
+
+    setegid(getgid());
+    seteuid(getuid());				/* put it back */
+    if (connect(tape_server_socket, (struct sockaddr *)&tape_server,
+		sizeof(struct sockaddr_in)) == -1)
+    {
+	perror("Error connecting to tape server");
+	exit(2);
+    }
+
+    /* do the security thing */
+#if defined(KRB4_SECURITY)
+#if 0 /* not yet implemented */
+    if(krb4_auth)
+    {
+	line = get_krb_security();
+    }
+#endif /* 0 */
+#endif
+    {
+	line = get_bsd_security();
+    }
+    send_to_tape_server_my(tape_server_socket, line);
+    memset(line, '\0', strlen(line));
+    amfree(line);
+
+    disk_regex = alloc(strlen(disk_name) * 2 + 3);
+
+    ch = disk_name;
+    ch1 = disk_regex;
+
+    /* we want to force amrestore to only match disk_name exactly */
+    *(ch1++) = '^';
+
+    /* We need to escape some characters first... NT compatibilty crap */
+    for (; *ch != 0; ch++, ch1++) {
+	switch (*ch) {     /* done this way in case there are more */
+	case '$':
+	    *(ch1++) = '\\';
+	    /* no break; we do want to fall through... */
+	default:
+	    *ch1 = *ch;
+	}
+    }
+
+    /* we want to force amrestore to only match disk_name exactly */
+    *(ch1++) = '$';
+
+    *ch1 = '\0';
+
+    clean_datestamp = stralloc(dump_datestamp);
+    for(ch=ch1=clean_datestamp;*ch1 != '\0';ch1++) {
+	if(*ch1 != '-') {
+	    *ch = *ch1;
+	    ch++;
+	}
+    }
+    *ch = '\0';
+    /* send to the tape server what tape file we want */
+
+#ifdef ENABLE_SMART_AMRESTORE
+    /* 12 args:
+     *   "-T"
+     *   "tape_label"
+     *   "-F"
+     *   "tape file number"
+     *   "-N"
+     *   "config name"
+     *   "-h"
+     *   "-p"
+     *   "tape device"
+     *   "hostname"
+     *   "diskname"
+     *   "datestamp"
+     * BUGS
+     *    - level is ignored.
+     */
+    send_to_tape_server_my(tape_server_socket, "12");
+    send_to_tape_server_my(tape_server_socket, "-T");
+    send_to_tape_server_my(tape_server_socket, the_tape);
+
+    send_to_tape_server_my(tape_server_socket, "-F");
+    send_to_tape_server_my(tape_server_socket, string_the_file);
+
+    send_to_tape_server_my(tape_server_socket, "-N");
+    send_to_tape_server_my(tape_server_socket, config);
+#else /* !ENABLE_SMART_AMRESTORE */
+    /* 6 args:
+     *   "-h"
+     *   "-p"
+     *   "tape device"
+     *   "hostname"
+     *   "diskname"
+     *   "datestamp"
+     */
+    send_to_tape_server_my(tape_server_socket, "6");
+#endif /* !ENABLE_SMART_AMRESTORE */
+    send_to_tape_server_my(tape_server_socket, "-h");
+    send_to_tape_server_my(tape_server_socket, "-p");
+    send_to_tape_server_my(tape_server_socket, tape_device_name);
+    send_to_tape_server_my(tape_server_socket, dump_hostname);
+    send_to_tape_server_my(tape_server_socket, disk_regex);
+    send_to_tape_server_my(tape_server_socket, clean_datestamp);
+
+    dbprintf(("Started amidxtaped with arguments \"-h -p %s %s %s %s\"\n",
+	      tape_device_name, dump_hostname, disk_regex, clean_datestamp));
+
+    amfree(disk_regex);
+
+    return tape_server_socket;
+}
+
+static void send_to_tape_server_my(tss, cmd)
+int tss;
+const char *cmd;
+{
+    int l, n, s;
+    char *end;
+
+    for (l = 0, n = strlen(cmd); l < n; l += s)
+	if ((s = write(tss, cmd + l, n - l)) < 0)
+	{
+	    perror("Error writing to tape server");
+	    exit(101);
+	}
+    end = "\r\n";
+    for (l = 0, n = strlen(end); l < n; l += s)
+	if ((s = write(tss, end + l, n - l)) < 0)
+	{
+	    perror("Error writing to tape server");
+	    exit(101);
+	}
+}
+
diff -urP amanda-2.4.2p2/remote-io-src/amrio.h amanda-2.4.2p2-changed/remote-io-src/amrio.h
--- amanda-2.4.2p2/remote-io-src/amrio.h	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/remote-io-src/amrio.h	Mon Jan 31 12:04:34 2000
@@ -0,0 +1,34 @@
+/*
+ * 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: amanda-2.4.2p2-append-patch,v 1.4 2001/08/16 12:03:56 msc Exp $
+ *
+ * data structures and declarations for amrio
+ */
+
+#include "amanda.h"
+
+extern int server_happy P((void));
\ No newline at end of file
diff -urP amanda-2.4.2p2/restore-src/amidxtaped.c amanda-2.4.2p2-changed/restore-src/amidxtaped.c
--- amanda-2.4.2p2/restore-src/amidxtaped.c	Tue Jun 13 00:58:43 2000
+++ amanda-2.4.2p2-changed/restore-src/amidxtaped.c	Fri Aug  3 11:42:57 2001
@@ -276,9 +276,17 @@
 
     /* rewind tape */
     /* the first non-option argument is the tape device */
+    /* in addition to this, the next argument shall not start with - */
     for (i = 1; i <= amrestore_nargs; i++)
 	if (amrestore_args[i][0] != '-')
-	    break;
+           if ((i >= amrestore_nargs) /* evaluation order counts */
+               || (amrestore_args[i + 1][0] != '-')) {
+              /* If current argument is not an option AND either this is
+               * the last argument OR the next one is not an option.
+               */
+  	      break;
+	   }
+
     if (i > amrestore_nargs)
     {
 	dbprintf(("Couldn't find tape in arguments\n"));
diff -urP amanda-2.4.2p2/restore-src/amrestore.c amanda-2.4.2p2-changed/restore-src/amrestore.c
--- amanda-2.4.2p2/restore-src/amrestore.c	Sun Dec  3 21:56:44 2000
+++ amanda-2.4.2p2-changed/restore-src/amrestore.c	Sat Aug  4 14:30:30 2001
@@ -43,12 +43,17 @@
  *	-C   write compressed with COMPRESS_BEST_OPT
  *	-r   raw, write file as is on tape (with header, possibly compressed)
  *	-h   write the header too
+ *	-T   tape label
+ *	-F   file number
+ *	-N   config
  */
 
 #include "amanda.h"
 #include "tapeio.h"
 #include "fileheader.h"
 
+static int search_label(const char *tape_label, const char *config_name);
+
 #define CREAT_MODE	0640
 
 char buffer[TAPE_BLOCK_BYTES];
@@ -399,7 +404,7 @@
  * Print usage message and terminate.
  */
 {
-    error("Usage: amrestore [-r|-c] [-p] [-h] tape-device|holdingfile [hostname [diskname [datestamp [hostname [diskname [datestamp ... ]]]]]]");
+    error("Usage: amrestore [-r|(-c|-C)] [-h] [-p] tape-device|holdingfile [-T tapelabel -F file -N config] [hostname [diskname [datestamp ... ]]]");
 }
 
 
@@ -430,6 +435,10 @@
     amwait_t compress_status;
     int tapedev;
     int fd;
+    int locate_mode = 0;
+    char *tape_label = NULL;
+    char *config_name = NULL;
+    int tape_file = 1;
 
     for(fd = 3; fd < FD_SETSIZE; fd++) {
 	/*
@@ -449,18 +458,44 @@
     signal(SIGPIPE, handle_sigpipe);
 
     /* handle options */
-    while( (opt = getopt(argc, argv, "cCd:rpkh")) != -1) {
+    while( (opt = getopt(argc, argv, "cCd:rpkhT:F:N:")) != -1) {
 	switch(opt) {
 	case 'c': compflag = 1; break;
 	case 'C': compflag = 1; compress_type = COMPRESS_BEST_OPT; break;
 	case 'r': rawflag = 1; break;
 	case 'p': pipeflag = 1; break;
 	case 'h': headerflag = 1; break;
+        case 'T':
+           tape_label = newstralloc(tape_label, optarg);
+           locate_mode |= 1;
+           break;
+        case 'F':
+           tape_file = atoi(optarg);
+           locate_mode |= 2;
+           break;
+        case 'N':
+           config_name = newstralloc(config_name, optarg);
+           locate_mode |= 4;
+           break;
 	default:
 	    usage();
 	}
     }
 
+    if (locate_mode) {
+       if (locate_mode == 7) {
+          fprintf(stderr, "%s: seeking label %s file %d config %s.\n",
+                          get_pname(),
+                          tape_label,
+                          tape_file,
+                          config_name);
+       }
+       else {
+          usage();
+       }
+    }
+
+
     if(compflag && rawflag) {
 	fprintf(stderr, 
 		"Cannot specify both -r (raw) and -c (compressed) output.\n");
@@ -473,8 +508,38 @@
     }
     else tapename = argv[optind++];
 
+    if (locate_mode) {
+       if (!search_label(tape_label, config_name)) {
+          error("couldn't locate tape `%s'", tape_label);
+       }
+    }
+
     if((tapedev = tape_open(tapename, 0)) < 0)
 	error("could not open tape %s: %s", tapename, strerror(errno));
+    else if (locate_mode) {
+       char *stamp = NULL;
+       char *label = NULL;
+
+       /* rdlabel also does a rewind before reading */
+       if (tapefd_rdlabel(tapedev, &stamp, &label) != NULL) {
+          error("can't read label: %s", strerror(errno));
+       }
+       else if (!match(label, tape_label)) {
+          error("non matching label: expected `%s' got `%s'",
+                tape_label,
+                label);
+       }
+       /* it's safer to rewind again */
+       else if (tapefd_rewind(tapedev) == -1) {
+          error("can't rewind: %s", strerror(errno));
+       }
+       else if (tapefd_fsf(tapedev, tape_file)) {
+          error("can't skip to file %d: %s", tape_file, strerror(errno));
+       }
+
+       amfree(stamp);
+       amfree(label);
+    }
 
 #define ARG_GET_HOST 0
 #define ARG_GET_DISK 1
@@ -592,4 +657,54 @@
 	return 1;
     }
     return 0;
+}
+
+static int ok_for_system(const char *str) {
+   int valid = 1;
+
+   while (*str && valid) {
+      valid = ((*str >= 'a') && (*str <= 'z'))
+              || ((*str >= 'A') && (*str <= 'Z'))
+              || ((*str >= '0') && (*str <= '9'))
+              || (*str == '_')
+              || (*str == '-');
+
+      str++;
+   }
+
+   return valid;
+}
+
+static int search_label(const char *tape_label, const char *config_name) {
+   char *command;
+   int result;
+
+   if (ok_for_system(config_name) && ok_for_system(tape_label)) {
+      command = vstralloc(sbindir "/amtape ",
+			  config_name,
+			  " label ",
+			  tape_label,
+			  NULL);
+
+      /* we use system() because we don't want to have the taper code
+       * glued to us, since amrestore is supposed to be able to be client
+       * only too.
+       * NOTES
+       *    - argument validity checking is supposed to be done by caller,
+       *      e.g. amidxtaped, for example. Despite that we do some
+       *      checks.
+       */
+
+      result = (system(command) == 0);
+
+      amfree(command);
+   }
+   else {
+      error("parameters are dangerous for system: %s, %s",
+            config_name,
+            tape_label);
+      result = 0;
+   }
+
+   return result;
 }
diff -urP amanda-2.4.2p2/scripts/Makefile.am amanda-2.4.2p2-changed/scripts/Makefile.am
--- amanda-2.4.2p2/scripts/Makefile.am	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/scripts/Makefile.am	Sat Aug  4 14:31:33 2001
@@ -0,0 +1,20 @@
+# Makefile for DILOG Amanda scripts
+
+PROGS = clean_and_check_tape.sh eval_length.sh list_tape.sh summary.sh test.sh
+
+all:
+
+install-exec-hook:
+	mkdir -p $(DESTDIR)$(prefix)/scripts
+	@list="$(PROGS)"; \
+	for p in $$list; do \
+		pa=$(DESTDIR)$(prefix)/scripts/`echo $$p|sed '$(transform)'`; \
+		cp $$p $$pa; \
+		echo chown $(BINARY_OWNER) $$pa; \
+		chown $(BINARY_OWNER) $$pa; \
+		echo chgrp $(SETUID_GROUP) $$pa; \
+		chgrp $(SETUID_GROUP) $$pa; \
+		echo chmod 555 $$pa; \
+		chmod 555 $$pa; \
+	done
+
diff -urP amanda-2.4.2p2/scripts/clean_and_check_tape.sh amanda-2.4.2p2-changed/scripts/clean_and_check_tape.sh
--- amanda-2.4.2p2/scripts/clean_and_check_tape.sh	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/scripts/clean_and_check_tape.sh	Tue Aug  7 09:49:07 2001
@@ -0,0 +1,26 @@
+#! /bin/sh
+
+case $# in
+   2) ;;
+   *) echo "$0 config tapestatpath" >&2
+      echo "$0: bad args." >&2
+      exit 2;;
+esac
+   
+CONFIG=$1
+TAPE_STATUS_FILE=$2
+
+AMTAPE=/sbin/amtape
+
+if [ ! -x $AMTAPE ]; then
+   # Let's hope it's in PATH
+   AMTAPE=amtape
+fi
+
+if [ -f $TAPE_STATUS_FILE ]; then
+   cat $TAPE_STATUS_FILE
+   rm -f $TAPE_STATUS_FILE
+fi
+
+$AMTAPE $CONFIG clean
+exit $?
diff -urP amanda-2.4.2p2/scripts/eval_length.sh amanda-2.4.2p2-changed/scripts/eval_length.sh
--- amanda-2.4.2p2/scripts/eval_length.sh	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/scripts/eval_length.sh	Wed Mar 15 14:09:21 2000
@@ -0,0 +1,17 @@
+#! /bin/sh
+
+TAPE=/dev/nst0
+BYTES=0
+
+mt -f $TAPE rewind && (while :
+do
+   dd if=$TAPE of=/dev/null bs=32k 2>&1
+   if [ $? != 0 ]; then
+      break
+   fi
+done) | awk -F+ 'BEGIN { count = 0; }
+                 { count += ($1 * 32768) + $2;}
+                 END { printf "TOTAL BYTES: %s.\n", count; }'
+
+echo ""
+echo "TOTAL BYTES: $BYTES"
diff -urP amanda-2.4.2p2/scripts/list_tape.sh amanda-2.4.2p2-changed/scripts/list_tape.sh
--- amanda-2.4.2p2/scripts/list_tape.sh	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/scripts/list_tape.sh	Tue May 16 14:22:52 2000
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+TAPE=/dev/nst0
+COUNT=1
+mt -f $TAPE rewind && dd if=$TAPE bs=32k count=1 2>/dev/null | (head -1; cat > /dev/null) && while mt -f $TAPE fsf 1 ; do
+  if [ $# = 0 ]; then
+     echo -n "FILE $COUNT "
+  else
+     echo -n "FILE $COUNT (real: `mt -f /dev/nst0 status | awk '/^file number/ { print $NF; }'`) "
+  fi
+  dd if=$TAPE bs=32k count=1 2>/dev/null | (head -1; cat > /dev/null)
+  COUNT=`expr $COUNT + 1`
+done
diff -urP amanda-2.4.2p2/scripts/summary.sh amanda-2.4.2p2-changed/scripts/summary.sh
--- amanda-2.4.2p2/scripts/summary.sh	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/scripts/summary.sh	Tue Aug  7 09:44:45 2001
@@ -0,0 +1,39 @@
+#! /bin/sh
+
+if  [ $# != 2 ]; then
+   echo "$0 config printer" >&2
+   echo "$0: bad args" >&2
+   exit 2
+fi
+
+AMANDA_CFG_DIR=/etc/amanda/$1
+AMANDA_CFG=$AMANDA_CFG_DIR/amanda.conf
+TAPELIST=$AMANDA_CFG_DIR/tapelist
+
+# NOTES
+#    - Not using -P option of a2ps, because this seems to fail with CUPS
+#      or at least SFI CUPS.
+FORMATTER="a2ps -o -"
+AMADMIN=/usr/sbin/amadmin
+
+if [ ! -x $AMADMIN ]; then
+   # Let's hope it's in PATH
+   AMADMIN=amadmin
+fi
+
+if [ -f $AMANDA_CFG ]; then
+   TAPELIST=`egrep '^tapelist[ \t]+".+"' $AMANDA_CFG | sed 's/^tapelist[ \t]+"\(.+\).*$/\1/'`
+   if [ -f $TAPELIST ]; then
+      (date
+       echo '  Dumps: lev datestmp  tape             file   origK   compK secs'
+       $AMADMIN $1 info | egrep -v ' -100.0%|dump rates|Incremental|Dumps: lev datestmp  tape'
+       echo
+       column < $TAPELIST) | $FORMATTER | lpr -P$2
+   else
+   echo "$0: cannot find amanda tapelist $TAPELIST" >&2
+   exit 1
+   fi
+else
+   echo "$0: cannot find amanda configuration $AMANDA_CFG" >&2
+   exit 1
+fi
diff -urP amanda-2.4.2p2/scripts/test.sh amanda-2.4.2p2-changed/scripts/test.sh
--- amanda-2.4.2p2/scripts/test.sh	Thu Jan  1 01:00:00 1970
+++ amanda-2.4.2p2-changed/scripts/test.sh	Thu Mar 23 10:53:43 2000
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+if [ $# != 2 ]; then
+   echo "$0 conf label" >&2
+   echo "$0 dne DilogNewEngSet103"
+   echo "$0: bad args."
+   exit 2
+fi
+
+/usr/sbin/amadmin $1 find | egrep "$2" | sed 's/-//g' | awk '{printf "FILE %d AMANDA: FILE %s %s %s %d\n", $6, $1, $2, $3, $4}' | sort -n +1 -2
diff -urP amanda-2.4.2p2/server-src/amadmin.c amanda-2.4.2p2-changed/server-src/amadmin.c
--- amanda-2.4.2p2/server-src/amadmin.c	Wed Feb 28 16:27:37 2001
+++ amanda-2.4.2p2-changed/server-src/amadmin.c	Fri Aug  3 08:24:54 2001
@@ -45,6 +45,7 @@
 void usage P((void));
 void force P((int argc, char **argv));
 void force_one P((disk_t *dp));
+void newtape P((int argc, char **argv));
 void unforce P((int argc, char **argv));
 void unforce_one P((disk_t *dp));
 void force_bump P((int argc, char **argv));
@@ -157,6 +158,7 @@
     else if(strcmp(argv[2],"unforce-bump") == 0) unforce_bump(argc, argv);
     else if(strcmp(argv[2],"force") == 0) force(argc, argv);
     else if(strcmp(argv[2],"unforce") == 0) unforce(argc, argv);
+    else if(strcmp(argv[2],"newtape") == 0) newtape(argc, argv);
     else if(strcmp(argv[2],"reuse") == 0) reuse(argc, argv);
     else if(strcmp(argv[2],"no-reuse") == 0) noreuse(argc, argv);
     else if(strcmp(argv[2],"info") == 0) info(argc, argv);
@@ -199,6 +201,8 @@
     fprintf(stderr,
 	    "\tunforce <hostname> <disks> ...\t# Clear force command.\n");
     fprintf(stderr,
+	    "\tnewtape\t\t# Do not append to current tape, start with new.\n");
+    fprintf(stderr,
 	    "\tforce-bump <hostname> <disks> ...\t# Force bump at next run.\n");
     fprintf(stderr,
 	    "\tforce-no-bump <hostname> <disks> ...\t# Force no-bump at next run.\n");
@@ -299,6 +303,15 @@
     }
     been_here = 1;
     return;
+}
+
+/* ----------------------------------------------- */
+
+void newtape(argc, argv)
+int argc;
+char **argv;
+{
+   current_tape_information_erase();
 }
 
 /* ----------------------------------------------- */
diff -urP amanda-2.4.2p2/server-src/amcheck.c amanda-2.4.2p2-changed/server-src/amcheck.c
--- amanda-2.4.2p2/server-src/amcheck.c	Thu Mar 15 03:34:59 2001
+++ amanda-2.4.2p2-changed/server-src/amcheck.c	Fri Aug  3 09:31:29 2001
@@ -405,7 +405,7 @@
 		/* not an exact label match, but a labelstr match */
 		/* check against tape list */
 		tp = lookup_tapelabel(label);
-		if(tp != NULL && !reusable_tape(tp))
+		if(tp != NULL && !reusable_tape(tp) && !can_append(tp))
 		    fprintf(errf, " (active tape)\n");
 		else if(got_match)
 		    fprintf(errf, " (labelstr match)\n");
@@ -413,7 +413,8 @@
 		    got_match = 1;
 		    first_match = newstralloc(first_match, slotstr);
 		    first_match_label = newstralloc(first_match_label, label);
-		    fprintf(errf, " (first labelstr match)\n");
+		    fprintf(errf, " (first labelstr match%s)\n",
+                                  can_append(tp) ? " for append" : "");
 		    if(!backwards || !searchlabel) {
 			found = 2;
 			found_device = newstralloc(found_device, device);
@@ -788,7 +789,7 @@
 	    tapebad = 1;
 	} else {
 	    tp = lookup_tapelabel(label);
-	    if(tp != NULL && !reusable_tape(tp)) {
+	    if(tp != NULL && !reusable_tape(tp) && !can_append(tp)) {
 		fprintf(outf, "ERROR: cannot overwrite active tape %s\n", label);
 		tapebad = 1;
 	    }
diff -urP amanda-2.4.2p2/server-src/amtape.c amanda-2.4.2p2-changed/server-src/amtape.c
--- amanda-2.4.2p2/server-src/amtape.c	Tue Mar 27 00:23:38 2001
+++ amanda-2.4.2p2-changed/server-src/amtape.c	Fri Aug  3 09:33:23 2001
@@ -510,7 +510,7 @@
 		/* not an exact label match, but a labelstr match */
 		/* check against tape list */
 		tp = lookup_tapelabel(label);
-		if(tp != NULL && !reusable_tape(tp))
+		if(tp != NULL && !reusable_tape(tp) && !can_append(tp))
 		    fprintf(stderr, " (active tape)\n");
 		else if(got_match)
 		    fprintf(stderr, " (labelstr match)\n");
@@ -518,7 +518,8 @@
 		    got_match = 1;
 		    first_match = newstralloc(first_match, slotstr);
 		    first_match_label = newstralloc(first_match_label, label);
-		    fprintf(stderr, " (first labelstr match)\n");
+		    fprintf(stderr, " (first labelstr match%s)\n",
+                                      can_append(tp) ? " for append" : "");
 		    if(!backwards || !searchlabel) {
 			found = 2;
 			amfree(datestamp);
@@ -552,7 +553,8 @@
 
     fprintf(stderr, "%s: scanning for ", get_pname());
     if(searchlabel) fprintf(stderr, "tape label %s or ", searchlabel);
-    fprintf(stderr, "a new tape.\n");
+    fprintf(stderr, "a new%s tape.\n",
+                    getconf_int(CNF_APPENDMODE) ? "/append" : "");
 
     if (searchlabel != NULL)
       changer_find(scan_init, taperscan_slot,searchlabel);
@@ -560,9 +562,12 @@
       changer_scan(scan_init, taperscan_slot);
 
     if(found == 2) {
-	fprintf(stderr, "%s: %s: settling for first labelstr match\n",
+	fprintf(stderr, "%s: %s%s: settling for first labelstr match\n",
 		get_pname(),
-		searchlabel? "gravity stacker": "looking only for new tape");
+		searchlabel? "gravity stacker": "looking only for new tape",
+                (!searchlabel && getconf_int(CNF_APPENDMODE))
+                   ? " or append"
+                   : "");                
 	searchlabel = newstralloc(searchlabel, first_match_label);
     }
     else if(!found && got_match) {
diff -urP amanda-2.4.2p2/server-src/conffile.c amanda-2.4.2p2-changed/server-src/conffile.c
--- amanda-2.4.2p2/server-src/conffile.c	Thu Jan  4 22:09:16 2001
+++ amanda-2.4.2p2-changed/server-src/conffile.c	Fri Aug  3 11:37:29 2001
@@ -75,7 +75,7 @@
     DISKDIR, DISKSIZE, INDEXDIR, NETUSAGE, INPARALLEL, TIMEOUT,
     TPCHANGER, RUNTAPES,
     DEFINE, DUMPTYPE, TAPETYPE, INTERFACE,
-    PRINTER, RESERVE,
+    PRINTER, CURRENTTAPE, APPENDMODE, RESERVE,
     COLUMNSPEC,
 
     /* holding disk */
@@ -159,6 +159,7 @@
 static val_t conf_diskdir;
 static val_t conf_tapetype;
 static val_t conf_indexdir;
+static val_t conf_currenttape;
 static val_t conf_columnspec;
 
 /* ints */
@@ -178,6 +179,7 @@
 static val_t conf_dtimeout;
 static val_t conf_ctimeout;
 static val_t conf_tapebufs;
+static val_t conf_appendmode;
 static val_t conf_reserve;
 
 /* reals */
@@ -203,6 +205,8 @@
 static int seen_maxcycle, seen_tapecycle;
 static int seen_disksize, seen_netusage, seen_inparallel, seen_timeout;
 static int seen_indexdir, seen_etimeout, seen_dtimeout, seen_ctimeout;
+static int seen_currenttape;
+static int seen_appendmode;
 static int seen_tapebufs;
 static int seen_reserve;
 static int seen_columnspec;
@@ -317,6 +321,8 @@
     { "CHANGERFILE", CNF_CHNGRFILE, STRING },
     { "LABELSTR", CNF_LABELSTR, STRING },
     { "TAPELIST", CNF_TAPELIST, STRING },
+    { "CURRENTTAPE", CNF_CURRENTTAPE, STRING },
+    { "APPENDMODE", CNF_APPENDMODE, INT },
     { "DISKFILE", CNF_DISKFILE, STRING },
     { "INFOFILE", CNF_INFOFILE, STRING },
     { "LOGDIR", CNF_LOGDIR, STRING },
@@ -396,6 +402,8 @@
     case CNF_RUNTAPES: return seen_runtapes;
     case CNF_MAXDUMPS: return seen_maxdumps;
     case CNF_TAPELIST: return seen_tapelist;
+    case CNF_CURRENTTAPE: return seen_currenttape;
+    case CNF_APPENDMODE: return seen_appendmode;
     case CNF_INFOFILE: return seen_infofile;
     case CNF_DISKFILE: return seen_diskfile;
     /*case CNF_DISKDIR: return seen_diskdir;*/
@@ -447,6 +455,7 @@
     case CNF_CTIMEOUT: r = conf_ctimeout.i; break;
     case CNF_TAPEBUFS: r = conf_tapebufs.i; break;
     case CNF_RESERVE: r = conf_reserve.i; break;
+    case CNF_APPENDMODE: r = conf_appendmode.i; break;
 
     default:
 	error("error [unknown getconf_int parm: %d]", parm);
@@ -488,6 +497,9 @@
     case CNF_CHNGRFILE: r = conf_chngrfile.s; break;
     case CNF_LABELSTR: r = conf_labelstr.s; break;
     case CNF_TAPELIST: r = conf_tapelist.s; break;
+    case CNF_CURRENTTAPE:
+       r = conf_currenttape.s;
+       break;
     case CNF_INFOFILE: r = conf_infofile.s; break;
     case CNF_LOGDIR: r = conf_logdir.s; break;
     /*case CNF_LOGFILE: r = conf_logfile.s; break;*/
@@ -582,6 +594,10 @@
     s = "/dev/rawft0";
 #endif
     conf_rawtapedev.s = newstralloc(conf_rawtapedev.s, s);
+    conf_currenttape.s
+       = newstralloc(conf_currenttape.s,
+                     "current-tape-for-append");
+    malloc_mark(conf_currenttape.s);
     malloc_mark(conf_rawtapedev.s);
     conf_tpchanger.s = newstralloc(conf_tpchanger.s, "");
     malloc_mark(conf_tpchanger.s);
@@ -630,6 +646,7 @@
     conf_dtimeout.i     = 1800;
     conf_ctimeout.i     = 30;
     conf_tapebufs.i     = 20;
+    conf_appendmode.i   = 1; /* defaults to enabled */
     conf_reserve.i	= 100;
 
     /* defaults for internal variables */
@@ -646,7 +663,9 @@
     seen_maxcycle = seen_tapecycle = 0;
     seen_disksize = seen_netusage = seen_inparallel = seen_timeout = 0;
     seen_indexdir = seen_etimeout = seen_dtimeout = seen_ctimeout = 0;
+    seen_currenttape = 0;
     seen_tapebufs = 0;
+    seen_appendmode = 0;
     seen_reserve = 0;
     seen_columnspec = 0;
     line_num = got_parserror = 0;
@@ -802,6 +821,8 @@
     { "TAPECYCLE", TAPECYCLE },
     { "TAPEDEV", TAPEDEV },
     { "TAPELIST", TAPELIST },
+    { "CURRENTTAPE", CURRENTTAPE },
+    { "APPENDMODE", APPENDMODE },
     { "TAPETYPE", TAPETYPE },
     { "TIMEOUT", TIMEOUT },	/* XXX - historical */
     { "TPCHANGER", TPCHANGER },
@@ -850,6 +871,12 @@
     case CHNGRFILE: get_simple(&conf_chngrfile, &seen_chngrfile, STRING); break;
     case LABELSTR:  get_simple(&conf_labelstr,  &seen_labelstr,  STRING); break;
     case TAPELIST:  get_simple(&conf_tapelist,  &seen_tapelist,  STRING); break;
+    case CURRENTTAPE:
+                    get_simple(&conf_currenttape,  &seen_currenttape,  STRING);
+                    break;
+    case APPENDMODE:
+                    get_simple(&conf_appendmode, &seen_appendmode, INT);
+                    break;
     case INFOFILE:  get_simple(&conf_infofile,  &seen_infofile,  STRING); break;
     case LOGDIR:    get_simple(&conf_logdir,    &seen_logdir,    STRING); break;
     case DISKFILE:  get_simple(&conf_diskfile,  &seen_diskfile,  STRING); break;
diff -urP amanda-2.4.2p2/server-src/conffile.h amanda-2.4.2p2-changed/server-src/conffile.h
--- amanda-2.4.2p2/server-src/conffile.h	Tue Jun 13 00:58:53 2000
+++ amanda-2.4.2p2-changed/server-src/conffile.h	Fri Aug  3 11:34:33 2001
@@ -45,7 +45,9 @@
     CNF_DISKSIZE, CNF_NETUSAGE, CNF_INPARALLEL, CNF_TIMEOUT,
     CNF_BUMPSIZE, CNF_BUMPMULT, CNF_BUMPDAYS, CNF_TPCHANGER, CNF_RUNTAPES,
     CNF_MAXDUMPS, CNF_ETIMEOUT, CNF_DTIMEOUT, CNF_CTIMEOUT,
-    CNF_TAPEBUFS, CNF_RAWTAPEDEV, CNF_PRINTER, CNF_RESERVE,
+    CNF_TAPEBUFS, CNF_RAWTAPEDEV, CNF_PRINTER,
+    CNF_CURRENTTAPE, CNF_APPENDMODE,
+    CNF_RESERVE,
     CNF_COLUMNSPEC
 } confparm_t;
 
diff -urP amanda-2.4.2p2/server-src/find.c amanda-2.4.2p2-changed/server-src/find.c
--- amanda-2.4.2p2/server-src/find.c	Tue Jun 13 00:59:00 2000
+++ amanda-2.4.2p2-changed/server-src/find.c	Thu Aug 16 13:59:58 2001
@@ -42,6 +42,10 @@
 void search_holding_disk P((find_result_t **output_find));
 char *find_nicedate P((int datestamp));
 
+static int are_same P((find_result_t *r1, find_result_t *r2));
+static find_result_t *find_dump_orig P((char *lfind_hostname,
+                                        int lfind_ndisks,
+                                        char **lfind_diskstrs));
 static char *find_sort_order = NULL;
 
 static int find_nhosts;
@@ -49,11 +53,205 @@
 static int find_ndisks;
 static char **find_diskstrs;
 
+/* NOTES
+ *    - Implementation using only the tape.<LABEL> files. Is faster,
+ *      and works with tape appending.
+ *    - We try to access any tape.<LABEL> file, for every <LABEL>
+ *      coming out of the tapelist.
+ *    - If cannot find to access the tape.<LABEL> file, reverts
+ *      to the old log parsing method (which doesn't support appending),
+ *      for compatibility only.
+ */
 find_result_t *find_dump(lfind_hostname, lfind_ndisks, lfind_diskstrs)
 char *lfind_hostname;
 int lfind_ndisks;
 char **lfind_diskstrs;
 {
+   int tape, maxtape;
+   tape_t *tp;
+   find_result_t *output_find = NULL;
+   int try_old_method = 0;
+
+   find_hostname = lfind_hostname;
+   find_ndisks = lfind_ndisks;
+   find_diskstrs = lfind_diskstrs;
+   if (find_hostname == NULL) {
+      find_nhosts = 0;
+   }
+   else {
+      find_nhosts = 1;
+   }
+
+   maxtape = lookup_nb_tape();
+   
+   for (tape = 1; tape <= maxtape; tape++) {
+      tp = lookup_tapepos(tape);
+      if (tp) {
+         char *tape_log_name = tape_log_file_name(tp->label);
+         FILE *f;
+         int filenum = 0;
+
+         f = fopen(tape_log_name, "r");
+	 if (f) {
+            while (get_logline(f)) {
+               if ((curlog == L_SUCCESS)
+                   && (curprog == P_TAPER)) {
+                  char *s;
+                  char ch;
+                  int datestampI;
+		  char *host;
+                  char *host_undo;
+                  char host_undo_ch;
+		  char *disk;
+                  char *disk_undo;
+                  char disk_undo_ch;
+                  int level;
+                  int datestamp;
+                  char *rest;
+
+                  filenum++;
+
+                  s = curstr;
+                  ch = *s;
+                  s++;
+
+		  skip_whitespace(s, ch);
+		  if (ch == '\0') {
+		     fprintf(stderr, "strange log line \"%s\"\n", curstr);
+                     fflush(stderr);
+		     continue;
+		  }
+
+		  host = s - 1;
+		  skip_non_whitespace(s, ch);
+		  host_undo = s - 1;
+		  host_undo_ch = *host_undo;
+		  *host_undo = '\0';
+
+		  skip_whitespace(s, ch);
+		  if (ch == '\0') {
+		     fprintf(stderr, "strange log line \"%s\"\n", curstr);
+                     fflush(stderr);
+		     continue;
+		  }
+
+		  disk = s - 1;
+		  skip_non_whitespace(s, ch);
+		  disk_undo = s - 1;
+		  disk_undo_ch = *disk_undo;
+		  *disk_undo = '\0';
+
+		  skip_whitespace(s, ch);
+		  if (ch == '\0' || sscanf(s - 1, "%d", &datestampI) != 1) {
+		     fprintf(stderr, "strange log line \"%s\"\n", curstr);
+                     fflush(stderr);
+		     continue;
+		  }
+		  skip_integer(s, ch);
+
+		  if (datestampI < 100)  { /* old log didn't have datestamp */
+		     level = datestampI;
+		     datestampI = datestamp;
+		  }
+		  else {
+		     skip_whitespace(s, ch);
+		     if (ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
+			fprintf(stderr, "strange log line \"%s\"\n", curstr);
+                        fflush(stderr);
+			continue;
+		     }
+		     skip_integer(s, ch);
+		  }
+
+		  skip_whitespace(s, ch);
+		  if (ch == '\0') {
+		      fprintf(stderr, "strange log line \"%s\"\n", curstr);
+                      fflush(stderr);
+		      continue;
+		  }
+		  rest = s - 1;
+		  if ((s = strchr(s, '\n')) != NULL) {
+		      *s = '\0';
+		  }
+
+                  if (find_match(host, disk)) {
+                     find_result_t *new_output_find =
+                         (find_result_t *) alloc(sizeof(find_result_t));
+
+                     new_output_find->next = output_find;
+                     new_output_find->datestamp = datestampI;
+                     new_output_find->datestamp_aux = 0; /* @@@ */
+                     new_output_find->hostname = stralloc(host);
+                     new_output_find->diskname = stralloc(disk);
+                     new_output_find->level = level;
+                     new_output_find->label = stralloc(tp->label);
+                     new_output_find->filenum = filenum;
+                     new_output_find->status=stralloc("OK");
+
+                     output_find = new_output_find;
+                  }
+               }
+            }
+
+            fclose(f); /* result ignored */
+         }
+         else {
+            fprintf(stderr, "find_dump: %s: can't access %s\n",
+                            strerror(errno),
+                            tape_log_name);
+            fflush(stderr);
+            try_old_method = 1;
+         }
+
+         amfree(tape_log_name);
+      }
+   }
+
+   if (try_old_method) {
+      find_result_t *other_output_find;
+
+      fprintf(stderr, "find_dump: for compatibility, now also parsing log files.\n");
+      fflush(stderr);
+
+      other_output_find = find_dump_orig(lfind_hostname,
+                                         lfind_ndisks,
+                                         lfind_diskstrs);
+      if (other_output_find) {
+         if (output_find) {
+	    find_result_t *last = output_find;
+
+	    /* Add this at end of the normal list
+	     * NOTES
+	     *    - Old things are going to be at bottom, and there will be
+	     *      duplicates: caller is supposed to sort them.
+	     */
+
+	    while (last->next != NULL) {
+	       last = last->next;
+	    }
+
+	    last->next = other_output_find;
+         }
+         else {
+            /* No results, thus give what we have found. */
+            output_find = other_output_find;
+         }
+      }
+   }
+   else {
+      search_holding_disk(&output_find);
+   }
+
+   return output_find;
+}
+
+static find_result_t *find_dump_orig(lfind_hostname,
+                                     lfind_ndisks,
+                                     lfind_diskstrs)
+char *lfind_hostname;
+int lfind_ndisks;
+char **lfind_diskstrs;
+{
     char *conf_logdir, *logfile = NULL;
     int tape, maxtape, seq, logs;
     tape_t *tp;
@@ -332,6 +530,8 @@
     find_result_t **array_find_result = NULL;
     int nb_result=0;
     int no_result;
+    int i;
+    int actual_results = 0;
 
     find_sort_order = sort_order;
     /* qsort core dump if nothing to sort */
@@ -357,6 +557,22 @@
     qsort(array_find_result,nb_result,sizeof(find_result_t *),
 	  find_compare);
 
+    /* remove duplicates */
+    for (i = 0; i < nb_result; i++) {
+       if ((i == (nb_result - 1)) /* evaluation order counts */
+           || !are_same(array_find_result[i], array_find_result[i + 1])) {
+          array_find_result[actual_results]
+             = array_find_result[i];
+          actual_results++;
+       }
+      else {
+          array_find_result[i]->next = NULL;
+          free_find_result(&array_find_result[i]);
+       }
+    }
+
+    nb_result = actual_results;
+
     /* put the sorted result in the list */
     for(no_result=0;
 	no_result<nb_result-1; no_result++) {
@@ -365,6 +581,7 @@
     array_find_result[nb_result-1]->next=NULL;
     *output_find=array_find_result[0];
 
+    amfree(array_find_result);
 }
 
 void print_find_result(output_find)
@@ -722,4 +939,15 @@
 	}
     }
     return(NULL);
+}
+
+static int are_same P((find_result_t *r1, find_result_t *r2)) {
+   return !strcmp(r1->diskname, r2->diskname)
+          && !strcmp(r1->hostname, r2->hostname)
+          && !strcmp(r1->label, r2->label)
+          && (r1->filenum == r2->filenum)
+          && (r1->level == r2->level)
+          && (r1->datestamp == r2->datestamp)
+          && (r1->datestamp_aux == r2->datestamp_aux)
+          && ((r1->status == r2->status) || !strcmp(r1->status, r2->status));
 }
diff -urP amanda-2.4.2p2/server-src/tapefile.c amanda-2.4.2p2-changed/server-src/tapefile.c
--- amanda-2.4.2p2/server-src/tapefile.c	Tue Jun 13 00:59:03 2000
+++ amanda-2.4.2p2-changed/server-src/tapefile.c	Fri Aug  3 09:41:20 2001
@@ -29,6 +29,7 @@
  * routines to read and write the amanda active tape list
  */
 #include "amanda.h"
+#include "arglist.h"
 #include "tapefile.h"
 #include "conffile.h"
 
@@ -39,8 +40,6 @@
 static tape_t *insert P((tape_t *list, tape_t *tp));
 static time_t stamp2time P((int datestamp));
 
-
-
 int read_tapelist(tapefile)
 char *tapefile;
 {
@@ -154,6 +153,7 @@
     int s;
     int tapecycle = getconf_int(CNF_TAPECYCLE);
     char *labelstr = getconf_str (CNF_LABELSTR);
+    tape_t *tmp = NULL;
 
     /*
      * The idea here is we keep the last "several" reusable tapes we
@@ -165,6 +165,27 @@
     for(s = 0; s <= skip; s++) {
 	tpsave[s] = NULL;
     }
+
+    /* tape append support
+     * NOTES
+     *    - This will be a bit suboptimal, especially if the
+     *      function is called in a loop.
+     */
+    tmp = tape_list;
+    if (tmp) { /* tmp is the last one, the candidate for appending */
+       if (!can_append(tmp)) {
+          tmp = NULL;
+       }
+    }
+
+    if (skip != 0) {
+       if (tmp) {
+          skip--;
+          tmp = NULL;
+       }
+    }
+    /* end tape append support */
+
     for(tp = tape_list; tp != NULL; tp = tp->next) {
 	if(tp->reuse == 1 && match (labelstr, tp->label)) {
 	    count++;
@@ -179,6 +200,10 @@
     if(count < tapecycle - skip) tp = NULL;
     else tp = tpsave[skip - s];
     amfree(tpsave);
+
+    if (tmp) {
+       return tmp;
+    }
     return tp;
 }
 
@@ -373,4 +398,335 @@
     tm.tm_mday = ((datestamp %   100)        );
 
     return mktime(&tm);
+}
+
+int tape_is_first_in_tapelist(tp)
+tape_t *tp;
+{
+   return tp && (tape_list == tp);
+}
+
+#define CURRENT_TAPE_FILE getconf_str(CNF_CURRENTTAPE)
+
+current_tape_information_t current_tape_information
+   = { NULL, 0, 0, 0 };
+
+int current_tape_information_read ()
+{
+   FILE *f;
+   int result = 0; /* failed */
+
+   f = fopen(CURRENT_TAPE_FILE, "r");
+   if (f) {
+      int finished = 0;
+
+      current_tape_information_free();
+
+      while (!finished) {
+         char buffer[200];
+         int len;
+
+         if (!(finished = !fgets(buffer, sizeof(buffer), f))) {
+            int len = strlen(buffer);
+
+            /* remove final \n if present */
+            if (len && (buffer[len - 1] == '\n')) {
+               len--;
+               buffer[len] = '\0';
+            }
+
+            if (len) {
+               char *parameter = buffer;
+
+               while (*parameter && !isspace(*parameter)) {
+                  parameter++;
+               }
+
+               if (*parameter) {
+                  char *temp;
+		  *parameter = '\0'; /* end of object identifier buffer */
+
+                  parameter++;
+		  while (*parameter && isspace(*parameter)) {
+		     parameter++;
+		  }
+
+                  temp = parameter;
+
+		  while (*temp && !isspace(*temp)) {
+		     temp++;
+		  }
+
+                  *temp = '\0';
+               }
+
+               /* parameter is now the argument */
+
+               if (*buffer && *parameter) {
+                  char *temp;
+
+                  if (!strcasecmp(buffer, "label")) {
+                     current_tape_information.label
+                        = stralloc(parameter);
+                     if (current_tape_information.label == NULL) {
+			fprintf(stderr,
+				"taper: _read(): stralloc()\n",
+				parameter);
+			fflush(stderr);
+			finished = 1;
+                     }
+                  }
+                  else if (!strcasecmp(buffer, "written_files")) {
+                     current_tape_information.written_files
+                        = strtoul(parameter, &temp, 0);
+                     /* *parameter != 0 is implicit */
+                     if (*temp) {
+                        current_tape_information.written_files = 0;
+                     }
+                  }
+                  else if (!strcasecmp(buffer, "written_blocks")) {
+                     current_tape_information.written_blocks
+                        = strtoul(parameter, &temp, 0);
+                     /* *parameter != 0 is implicit */
+                     if (*temp) {
+                        current_tape_information.written_blocks = 0;
+                     }
+                  }
+                  else if (!strcasecmp(buffer, "last_used")) {
+                     current_tape_information.last_used
+                        = strtoul(parameter, &temp, 0);
+                     /* *parameter != 0 is implicit */
+                     if (*temp) {
+                        current_tape_information.last_used = 0;
+                     }
+                  }
+                  else {
+		     fprintf(stderr,
+			     "taper: _read(): unknown name %s\n",
+                             buffer);
+		     fflush(stderr);
+		     finished = 1;
+                  }
+               }
+               else if (*buffer || *parameter) {
+	          fprintf(stderr,
+			  "taper: _read(): syntax error: /%s/%s/\n",
+                          buffer,
+                          parameter);
+		  fflush(stderr);
+                  finished = 1;
+               } /* else empty line, ignored */
+            } /* we ignore empty lines */
+         }
+      }
+      
+      fclose(f); /* result ignored */
+      if (current_tape_information_valid()) {
+         result = 1;
+      }
+      else {
+#if 0
+         current_tape_information_erase();
+#endif
+      }
+   }
+
+   if (!result) {
+      current_tape_information_free();
+   }
+
+   return result;
+}
+
+int current_tape_information_erase ()
+{
+   current_tape_information_free();
+   
+   return unlink(CURRENT_TAPE_FILE) ? 0 : 1;
+}
+
+int current_tape_information_create ()
+{
+   FILE *f;
+   int result = 0; /* failed */
+
+   f = fopen(CURRENT_TAPE_FILE, "w");
+   if (f) {
+      if (current_tape_information_valid()) {
+         fprintf(f, "label %s\n"
+                    "written_files %lu\n"
+                    "written_blocks %lu\n"
+                    "last_used %lu\n",
+                    current_tape_information.label,
+                    current_tape_information.written_files,
+                    current_tape_information.written_blocks,
+                    current_tape_information.last_used); /* result ignored */
+      }
+      else {
+         fprintf(stderr, "taper: _update() incorrect\n");
+         fflush(stderr);
+      }
+
+      if (fclose(f) == 0) {
+         result = 1;
+      }
+      else {
+         perror("taper(): _update() fclose()");
+      }
+   }
+   else {
+      perror("taper(): _update() fopen()");
+   }
+
+   if (!result) {
+      current_tape_information_free();
+   }
+
+   return result;
+}
+
+void current_tape_information_free ()
+{
+   if (current_tape_information.label) {
+      amfree(current_tape_information.label);
+   }
+   current_tape_information.label = NULL;
+   current_tape_information.written_files = 0;
+   current_tape_information.written_blocks = 0;
+   current_tape_information.last_used = 0;
+}
+
+int current_tape_information_valid ()
+{
+   return current_tape_information.label
+          && current_tape_information.written_files
+          && current_tape_information.written_blocks
+          && current_tape_information.last_used;
+}
+
+int can_append(tp)
+   tape_t *tp; /* looks strange to use K&R C, doesn't it ? */
+{
+   /* NOTES
+    *    - conditions:
+    *         - must be top of tapelist
+    *         - must be the one in the current_tape file.
+    *    - if a discrepancy between the two, remove current_tape and
+    *      log the error.
+    * TODO
+    *    - use configuration for constraints (see below)
+    */
+   if (getconf_int(CNF_APPENDMODE) == 0) {
+      ; /* disabled in configuration */
+   }
+   else if (0) {
+      ; /* constraints do not match --- NOT implemented */
+   }
+   else if (tp == NULL) {
+      ;
+   }
+   else if (tape_is_first_in_tapelist(tp)) {
+      if (current_tape_information_read()) {
+	 if (!strcmp(current_tape_information.label,
+		     tp->label)) {
+	    return 1; /* success */
+	 }
+	  else {
+	     fprintf(stderr,
+		     "taper: can_append(): inconsistency (`%s'/`%s); fixed\n",
+		    current_tape_information.label,
+		    tp->label);
+	     fflush(stderr);
+	    current_tape_information_erase(); /* result ignored */
+	  }
+      } /* else ignore */
+   }
+
+   return 0; /* failure */
+}
+
+#if 1
+void tape_log_add(label, format, host, disk, datestamp, level, errstr)
+const char *label;
+const char *format;
+const char *host;
+const char *disk;
+const char *datestamp;
+const int level;
+const char *errstr;
+{
+   char *file_name = tape_log_file_name(label);
+   FILE *f;
+
+   if ((f = fopen(file_name, "a"))) {
+      fprintf(f, format, host, disk, datestamp, level, errstr);
+
+      if (fclose(f)) {
+	 fprintf(stderr, "tapefile: error closing tape log file %s.\n",
+			 file_name);
+	 fflush(stderr);
+      }
+   }
+   else {
+      fprintf(stderr, "tapefile: cannot append to tape log file %s.\n",
+                      file_name);
+      fflush(stderr);
+   }
+
+   amfree(file_name);
+}
+#else
+void tape_log_add(char *label, const char *format, ...) {
+   char *file_name = tape_log_file_name(label);
+   FILE *f;
+   va_list argp;
+
+   arglist_start(argp, format);
+
+   if ((f = fopen(file_name, "a"))) {
+      fprintf(f, format, argp);
+
+      if (fclose(f)) {
+	 fprintf(stderr, "tapefile: error closing tape log file %s.\n",
+			 file_name);
+	 fflush(stderr);
+      }
+   }
+   else {
+      fprintf(stderr, "tapefile: cannot append to tape log file %s.\n",
+                      file_name);
+      fflush(stderr);
+   }
+
+   amfree(file_name);
+}
+#endif
+
+void tape_log_del(label)
+char *label;
+{
+   char *file_name = tape_log_file_name(label);
+
+   unlink(file_name); /* result ignored */
+
+   amfree(file_name);
+}
+
+char *tape_log_file_name (label)
+const char *label;
+{
+   char *conf_logdir;
+   char *file_name;
+   
+   conf_logdir = getconf_str(CNF_LOGDIR);
+   if (*conf_logdir == '/') {
+      conf_logdir = stralloc(conf_logdir);
+   }
+   else {
+      conf_logdir = stralloc2(config_dir, conf_logdir);
+   }
+
+   file_name = vstralloc(conf_logdir, "/tape.", label, NULL);
+
+   return file_name; /* must be amfree()d */
 }
diff -urP amanda-2.4.2p2/server-src/tapefile.h amanda-2.4.2p2-changed/server-src/tapefile.h
--- amanda-2.4.2p2/server-src/tapefile.h	Tue Jun 13 00:59:03 2000
+++ amanda-2.4.2p2-changed/server-src/tapefile.h	Fri Aug  3 09:41:37 2001
@@ -56,4 +56,29 @@
 
 int guess_runs_from_tapelist P((void));
 
+/* append data structures */
+
+typedef struct {
+   char *label;
+   int written_files; /* where to append */
+   int written_blocks; /* for statistics */
+   time_t last_used;
+} current_tape_information_t;
+
+/* tape append private functions
+ *    (to be used by taper child only, like for the data structures,
+ *     and by amadmin.c)
+ */
+
+int current_tape_information_read P((void));
+int current_tape_information_erase P((void)); /* also called from amadmin */
+int current_tape_information_create P((void));
+void current_tape_information_free P((void));
+int current_tape_information_valid P((void));
+int can_append P((tape_t *tp));
+
+void tape_log_del P((char *label));
+void tape_log_add P((const char *label, const char *format, const char *host, const char *disk, const char *datestamp, const int level, const char *errstr));
+char *tape_log_file_name P((const char *label));
+
 #endif /* !TAPEFILE_H */
diff -urP amanda-2.4.2p2/server-src/taper.c amanda-2.4.2p2-changed/server-src/taper.c
--- amanda-2.4.2p2/server-src/taper.c	Fri Mar  9 20:28:25 2001
+++ amanda-2.4.2p2-changed/server-src/taper.c	Fri Aug  3 11:05:01 2001
@@ -44,6 +44,8 @@
 #include <vtblc.h>
 #include <strings.h>
 
+#undef  DEBUG_TAPE_APPEND
+
 static int vtbl_no   = -1;
 static int len       =  0;
 static int offset    =  0;
@@ -88,6 +90,10 @@
     char buffer[TAPE_BLOCK_BYTES];
 } buffer_t;
 
+static int had_no_error_on_tape = 1;
+static int tape_in_append = 0; /* cleared as soon as 1st filemark done */
+static int was_an_append = 0; /* cleared by tape finish only */
+
 #define nextbuf(p)    ((p) == buftable+conf_tapebufs-1? buftable : (p)+1)
 #define prevbuf(p)    ((p) == buftable? buftable+conf_tapebufs-1 : (p)-1)
 
@@ -121,6 +127,12 @@
 int end_tape P((int writerr));
 int write_filemark P((void));
 
+/* tape append private functions
+ *    (to be used by taper child only)
+ */
+
+extern current_tape_information_t current_tape_information;
+
 /*
  * ========================================================================
  * GLOBAL STATE
@@ -834,6 +846,15 @@
 		amfree(q);
 		log_add(L_SUCCESS, "%s %s %s %d %s",
 		        hostname, diskname, datestamp, level, errstr);
+
+                tape_log_add(label,
+                             "SUCCESS taper %s %s %s %d %s\n",
+			     hostname,
+			     diskname,
+			     datestamp,
+			     level,
+			     errstr);
+
 #ifdef HAVE_LIBVTBLC
 		/* 
 		 *  We have 44 characters available for the label string:
@@ -1035,7 +1056,7 @@
 
 	case 'Q':
 	    end_tape(0);	/* XXX check results of end tape ?? */
-	    clear_tapelist();
+
 	    amfree(taper_datestamp);
 	    amfree(label);
 	    amfree(errstr);
@@ -1095,14 +1116,19 @@
      * We write the filemark at the start of the file rather than at the end,
      * so that it can proceed in parallel with the reader's initial filling
      * up of the buffers.
+     * Do not write a filemark if we are appending.
      */
 
     startclock();
-    if(!write_filemark())
+    if(!tape_in_append && !write_filemark())
 	goto tape_error;
     fmwait = stopclock();
 
-    filenum += 1;
+    if (!tape_in_append) {
+       filenum += 1;
+    }
+
+    tape_in_append = 0;
 
     do {
 
@@ -1224,6 +1250,12 @@
 
  tape_error:
     /* got tape error */
+
+
+    /* current tape no longer can be used for appending in any case */
+    current_tape_information_erase();
+    had_no_error_on_tape = 0;
+
     if(next_tape(1)) syncpipe_put('T');	/* next tape in place, try again */
     else syncpipe_put('E');		/* no more tapes, fail */
     syncpipe_putstr(errstr);
@@ -1627,6 +1659,9 @@
     tape_t *tp;
     static int first_call = 1;
 
+    tape_in_append = 0;
+    was_an_append = 0;
+
     if(have_changer) {
 	amfree(tapedev);
 	if ((tapedev = taper_scan()) == NULL) {
@@ -1666,10 +1701,14 @@
     fflush(stderr);
     amfree(olddatestamp);
 
+    /* no error assumed since starting. */
+
+    had_no_error_on_tape  = 1;
+
     /* check against tape list */
     if (strcmp(tapedev, "/dev/null") != 0) {
 	tp = lookup_tapelabel(label);
-	if(tp != NULL && !reusable_tape(tp)) {
+	if(tp != NULL && !reusable_tape(tp) && !can_append(tp)) {
 	    errstr = newvstralloc(errstr,
 			          "cannot overwrite active tape ", label,
 			          NULL);
@@ -1685,72 +1724,208 @@
 	}
     }
 
-    if((tape_fd = tape_open(tapedev, O_WRONLY)) == -1) {
-	if(errno == EACCES) {
-	    errstr = newstralloc(errstr,
-				 "writing label: tape is write protected");
-	} else {
-	    errstr = newstralloc2(errstr,
-				  "writing label: ", strerror(errno));
-	}
-	return 0;
-    }
-
-    if((result = tapefd_wrlabel(tape_fd, taper_datestamp, label)) != NULL) {
-	errstr = newstralloc(errstr, result);
-	return 0;
-    }
-
-    fprintf(stderr, "taper: wrote label `%s' date `%s'\n", label, taper_datestamp);
-    fflush(stderr);
-
-#ifdef HAVE_LIBVTBLC
-    /* store time for the first volume entry */ 
-    time(&raw_time);
-    tape_timep = localtime(&raw_time);
-    strftime(start_datestr, 20, "%T %D", tape_timep);
-    fprintf(stderr, "taper: got vtbl start time: %s\n", start_datestr);
-    fflush(stderr);
-#endif /* HAVE_LIBVTBLC */
-
-    /* write tape list */
-
-    /* XXX add cur_tape number to tape list structure */
     if (strcmp(tapedev, "/dev/null") != 0) {
-	remove_tapelabel(label);
-	add_tapelabel(atoi(taper_datestamp), label);
+       if (can_append(tp)) {
+	  /* NOTES
+	   *    - if this tape is to be appended to, do not write any label,
+	   *      nor roll (again) the tape list.
+	   *    - rolling was already done the first time the tape was used.
+	   */
+
+	  total_tape_used = current_tape_information.written_blocks * 1024.0;
+	  total_tape_fm = current_tape_information.written_files;
+	  filenum = current_tape_information.written_files;
+
+#ifdef DEBUG_TAPE_APPEND       
+	  fprintf(stderr, "taper: appending to tape labelled `%s' fm %lu\n",
+			  label,
+			  total_tape_fm);
+	  fflush(stderr);
+#endif /* DEBUG_TAPE_APPEND */
+
+	  if ((tape_fd = tape_open(tapedev, O_WRONLY)) == -1) {
+	     errstr = newstralloc2(errstr,
+				   "opening tape: ", strerror(errno));
+	  }
+	  else {
+#ifdef DEBUG_TAPE_APPEND
+	     fprintf(stderr, "taper: rewinding (for label verify)\n");
+	     fflush(stderr);
+#endif /* DEBUG_TAPE_APPEND */
+
+	     /* rewind tape */
+	     if (tapefd_rewind(tape_fd) == 0) {
+                char *lb = NULL;
+                char *ds = NULL;
 
-	if(cur_tape == 0) {
-	    conf_tapelist_old = stralloc2(conf_tapelist, ".yesterday");
-	} else {
-	    char cur_str[NUM_STR_SIZE];
+#ifdef DEBUG_TAPE_APPEND
+		fprintf(stderr, "taper: verifying label\n");
+		fflush(stderr);
+#endif /* DEBUG_TAPE_APPEND */
 
-	    ap_snprintf(cur_str, sizeof(cur_str), "%d", cur_tape - 1);
-	    conf_tapelist_old = vstralloc(conf_tapelist,
-					".today.", cur_str, NULL);
-	}
-	if(rename(conf_tapelist, conf_tapelist_old) != 0) {
-	    if(errno != ENOENT)
-		error("could not rename \"%s\" to \"%s\": %s",
-		      conf_tapelist, conf_tapelist_old, strerror(errno));
-	}
-	amfree(conf_tapelist_old);
-	if(write_tapelist(conf_tapelist)) {
-	    error("could not write tapelist: %s", strerror(errno));
-	}
-    }
+                if ((tapefd_rdlabel(tape_fd, &ds, &lb) == NULL)
+                    && !strcmp(label, lb)) {
+                   amfree(ds);
+                   amfree(lb);
+#ifdef DEBUG_TAPE_APPEND
+   	           fprintf(stderr, "taper: rewinding\n");
+	           fflush(stderr);
+#endif /* DEBUG_TAPE_APPEND */
+
+		   /* rewind tape */
+		   if (tapefd_rewind(tape_fd) == 0) {
+		      /* skip to the right position. We will need not to
+		       * set the filemark.
+		       */
+		      /* skip to the right position */
+#ifdef DEBUG_TAPE_APPEND
+		      fprintf(stderr, "taper: moving to file %lu\n",
+                                      total_tape_fm);
+		      fflush(stderr);
+#endif /* DEBUG_TAPE_APPEND */
+		      if (tapefd_fsf(tape_fd, total_tape_fm) == 0) {
+			 log_add(L_START, "datestamp %s label %s tape %d",
+				    taper_datestamp, label, cur_tape);
+			 log_add(L_INFO,
+                                 "datestamp %s label %s tape %d IS AN APPEND",
+				 taper_datestamp,
+                                 label,
+                                 cur_tape);
+			 tape_in_append = 1;
+			 was_an_append = 1;
+                         /* Erase, so that in case of error, we
+                          * have a stable state. can_append() will
+                          * not be used during the time we write.
+                          */
+                         current_tape_information_erase();
+			 return 1;
+		      }
+		      else {
+			 errstr = newstralloc2(errstr,
+					       "moving to file: ",
+                                               strerror(errno));
+		      }
+		   }
+		   else {
+		      errstr = newstralloc2(errstr,
+					    "rewinding tape: ",
+                                            strerror(errno));
+		   }
+                }
+                else {
+                   if (lb) {
+		      errstr = newstralloc(errstr,
+					   "label not matching for append");
+                   }
+                   else {
+		      errstr = newstralloc2(errstr,
+					    "error verifying label: ",
+					    strerror(errno));
+                   }
+                   amfree(ds);
+                   amfree(lb);
+                }
+             }
+             else {
+                errstr = newstralloc2(errstr,
+                                      "rewinding tape (for label verify): ",
+                                      strerror(errno));
+             }
+
+             close(tape_fd);
+             tape_fd = -1;
+          }
+
+          return 0;
+       }
+       /* Do an additional check in case someone deleted the file with
+        * amadmin CONF newtape in between so we don't erase an active tape!
+        * Either it's a new tape, or it's reusable.
+        */
+       else if ((tp == NULL) || reusable_tape(tp)) {
+          tape_log_del(label);
+          /* XXX add cur_tape number to tape list structure */
+          if((tape_fd = tape_open(tapedev, O_WRONLY)) == -1) {
+              if(errno == EACCES) {
+                  errstr = newstralloc(errstr,
+                                       "writing label: tape is write protected");
+              } else {
+                  errstr = newstralloc2(errstr,
+                                        "writing label: ", strerror(errno));
+              }
+              return 0;
+          }
+
+          if((result = tapefd_wrlabel(tape_fd, taper_datestamp, label)) != NULL) {
+              errstr = newstralloc(errstr, result);
+              return 0;
+          }
 
-    log_add(L_START, "datestamp %s label %s tape %d",
-	    taper_datestamp, label, cur_tape);
-    if (first_call && strcmp(tapedev, "/dev/null") == 0) {
-	first_call = 0;
-	log_add(L_WARNING, "tapedev is %s, dumps will be thrown away", tapedev);
-    }
+          fprintf(stderr, "taper: wrote label `%s' date `%s'\n", label, taper_datestamp);
+          fflush(stderr);
 
-    total_tape_used=0.0;
-    total_tape_fm = 0;
+#ifdef HAVE_LIBVTBLC
+	  /* store time for the first volume entry */ 
+	  time(&raw_time);
+	  tape_timep = localtime(&raw_time);
+	  strftime(start_datestr, 20, "%T %D", tape_timep);
+	  fprintf(stderr, "taper: got vtbl start time: %s\n", start_datestr);
+	  fflush(stderr);
+#endif /* HAVE_LIBVTBLC */
 
-    return 1;
+	  /* NOTES
+	   *    - This is the initial labelling. When appending to tape, no
+	   *      labelling should occur.
+	   */
+
+	  current_tape_information_erase(); /* result ignored */
+
+	  /* write tape list */
+
+	  /* XXX add cur_tape number to tape list structure */
+          if (strcmp(tapedev, "/dev/null") != 0) {
+	     remove_tapelabel(label);
+	     add_tapelabel(atoi(taper_datestamp), label);
+
+	     if(cur_tape == 0) {
+		    conf_tapelist_old = stralloc2(conf_tapelist, ".yesterday");
+	     } else {
+		    char cur_str[NUM_STR_SIZE];
+
+		    ap_snprintf(cur_str, sizeof(cur_str), "%d", cur_tape - 1);
+		    conf_tapelist_old = vstralloc(conf_tapelist,
+						".today.",
+						cur_str,
+						NULL);
+	     }
+	     if(rename(conf_tapelist, conf_tapelist_old) != 0) {
+		 error("could not rename \"%s\" to \"%s\": %s",
+			conf_tapelist, conf_tapelist_old, strerror(errno));
+	     }
+
+	     amfree(conf_tapelist_old);
+	     if(write_tapelist(conf_tapelist))
+		    error("could not write tapelist: %s", strerror(errno));
+          }
+
+	  log_add(L_START, "datestamp %s label %s tape %d",
+		     taper_datestamp, label, cur_tape);
+
+	  if (first_call && strcmp(tapedev, "/dev/null") == 0) {
+	      first_call = 0;
+	      log_add(L_WARNING, "tapedev is %s, dumps will be thrown away", tapedev);
+	  }
+
+	  total_tape_used=0.0;
+	  total_tape_fm = 0;
+
+	  return 1;
+      }
+      else {
+         fprintf(stderr, "taper: internal incoherency; danger avoided.\n");
+         return 0;
+      }
+   }
 }
 
 int first_tape(new_datestamp)
@@ -1763,10 +1938,11 @@
 
     taper_datestamp = newstralloc(taper_datestamp, new_datestamp);
 
+    /* append */
+    filenum = 0;
     if(!label_tape())
 	return 0;
 
-    filenum = 0;
     return 1;
 }
 
@@ -1778,11 +1954,12 @@
     if(++cur_tape >= runtapes)
 	return 0;
 
+    /* append */
+    filenum = 0;
     if(!label_tape()) {
 	return 0;
     }
 
-    filenum = 0;
     return 1;
 }
 
@@ -1807,16 +1984,49 @@
 		total_tape_fm);
 	fflush(stderr);
 	if(! writerror) {
-	    if(! write_filemark()) {
-		rc = 1;
-		goto common_exit;
-	    }
-
-	    if((result = tapefd_wrendmark(tape_fd, taper_datestamp)) != NULL) {
-		errstr = newstralloc(errstr, result);
-		rc = 1;
-		goto common_exit;
-	    }
+            /* Fixes a bug with tape append that
+             * would make amadmin conf info and find
+             * diverge because of an additional
+             * filemark when schedule is empty.
+             */
+            if (!tape_in_append) {
+	       if(! write_filemark()) {
+		   rc = 1;
+		   goto common_exit;
+	       }
+
+	       if ((result = tapefd_wrendmark(tape_fd, taper_datestamp))
+                   != NULL) {
+		   errstr = newstralloc(errstr, result);
+		   rc = 1;
+		   goto common_exit;
+	       }
+            }
+
+            if (!was_an_append) {
+  	       clear_tapelist();
+            }
+
+            was_an_append = 0;
+
+            if (had_no_error_on_tape) {
+               /* NOTES
+                *    - create the current_tape information, if no error on
+                *      that tape.
+                */
+               current_tape_information.label = stralloc(label);
+               if (current_tape_information.label) {
+                  current_tape_information.written_files = total_tape_fm;
+                  current_tape_information.written_blocks
+                     = (total_tape_used + 1023.0) / 1024.0;
+                  current_tape_information.last_used = time(NULL);
+                  current_tape_information_create();  /* result ignored */
+               }
+               else {
+                  fprintf(stderr, "taper: no memory for append\n");
+                  fflush(stderr);
+               }
+            }
 	}
     }
 
@@ -2045,7 +2255,7 @@
 		/* not an exact label match, but a labelstr match */
 		/* check against tape list */
 		tp = lookup_tapelabel(label);
-		if(tp != NULL && !reusable_tape(tp)) {
+		if(tp != NULL && !reusable_tape(tp) && !can_append(tp)) {
 		    fprintf(stderr, " (active tape)\n");
 		    fflush(stderr);
 		}
@@ -2057,7 +2267,8 @@
 		    got_match = 1;
 		    first_match = newstralloc(first_match, slotstr);
 		    first_match_label = newstralloc(first_match_label, label);
-		    fprintf(stderr, " (first labelstr match)\n");
+		    fprintf(stderr, " (first labelstr match%s)\n",
+                            can_append(tp) ? " for append" : "");
 		    fflush(stderr);
 		    if(!backwards || !searchlabel) {
 			found = 2;