#!/usr/bin/perl
#
# Copyright 2000, 2001 Tivano Software GmbH. This software is
# distributed under the terms of the GNU General Public License. See
# COPYING for additional information.
#
# This is a hacked-up replacement for "amlabel" to label CD-RWs
# intended for use with cdrw-taper

# Path to taperlib.pm
push @INC, "/usr/lib/amanda";

require "taperlib.pm";

##
## No user editable settings below here
##

$WRITE_TAPELIST=1;
while ($ARGV[0] =~ /^-.*/) {
    if ($ARGV[0] eq "-f") {
        $FORCE_WRITE = 1;
    } elsif ($ARGV[0] eq "--no-tapelist-entry") {
        $WRITE_TAPELIST = 0;
    } else {
        print "Illegal argument: ".$ARGV[0]."\n";
        usage();
    }
    shift @ARGV;
}

if ($#ARGV < 1) {
    usage();
}

$CONFIG    = shift @ARGV;
$NEW_LABEL = shift @ARGV;

&readAmandaConfig($CONFIG);

my $writeDev = &loadSlot("current");
my $mountDev;
if ($writeDev =~ /^(.*?):/) {
    $mountDev = $1;
    $writeDev = $';
} else {
    $mountDev = $CDRW_MOUNT_DIR;
}

if ($NEW_LABEL !~ $labelstr) {
    error("Label $NEW_LABEL does not match labelstring \"$labelstr\".");
}

# If $FORCE_WRITE is not specified, check first if an empty or unused
# disk is in the drive and if the given label is not on an active
# amanda disk
if (!$FORCE_WRITE) {
    # Don't use a label that's on an active disc
    error("Cannot overwrite active disk!") if !is_usable($NEW_LABEL);
}

# Check first if there really is a rewritable disk in the drive, as labeling a
# (write-once) CD-R or DVD+R won't make much sense...
my $atip = `$CDRECORD -atip dev=$writeDev`;
# No disk -> exit silently, cdrecord already gave an error message
if (!($atip =~ /ATIP start of lead in:/s)) { exit 1; }
$atip =~ $&.$';
if ($atip =~ /Is not erasable/s) {
    error("Don't label a CD-R: $atip");
}
if ($atip =~ /Is erasable/s) {
    $MEDIA = "CDRW";
} else {
    $MEDIA = "DVD+R";
}

# This is where the dirty hack comes in: we cannot recognize DVD+R or
# DVD+RW media. What we *can* do, though, is try to mount it, and if
# that works assume that we have some kind of re-writable media... if
# it's not re-writable it simply doesn't matter. :-)

my $result = `$CDRECORD -toc dev=$writeDev 2>&1`;
if ($result !~ /cdrecord: Cannot read TOC header/s) {
    if ($MEDIA =~ /^DVD+/) { $MEDIA .= "W"; }
    # Not a blank disk, need to check the contents.  Requires a
    # 'mount' program that allows mounting of $CDRW_MOUNT_DIR as
    # non-priviledged user and without having to specify the device
    # (might be Linux specific). Exit silently on mount errors,
    # mount already gave an error message
    $result = system("$MOUNT -r $mountDev") / 256;
    if ($result != 0 && $MEDIA ne "DVD+RW") {
	error("Cannot mount disk!");
    }
    if ($result == 0) {
        # read and check the media label, if there is one
        open LABEL, "$CDRW_MOUNT_DIR/AMANDA_LABEL";
        my $label = <LABEL>;
        chomp $label;
        close LABEL;
        system("$UMOUNT $CDRW_MOUNT_DIR");
        if (!$FORCE_WRITE) {
            error("Not an amanda disk!") if !$label;
            error("Cannot overwrite active disk!") if !is_usable($label);
        }
    }
} elsif ($MEDIA eq "DVD+R") {
    print "WARNING! $0 cannot determine the media type in the drive.\n";
    print "Are you SURE this is a DVD+RW (enter yes to continue)?\n";
    if (<STDIN> !~ /^yes/) {
	error("Refusing to write label.");
    }
}

# Write the label file to a temporary directory
mkdir("/tmp/amlabel-cdrw.$$", 0755) || error("Cannot make directory /tmp/amlabelcd.$$: $!");
open LABEL, ">/tmp/amlabel-cdrw.$$/AMANDA_LABEL" or error("Cannot create label: $!");
print LABEL "$NEW_LABEL\n";
close LABEL;

if ($MEDIA eq "CDRW") {
    # Exit silently on errors. mkisofs/cdrecord already generate
    # appropriate messages
    $result = system("$MKISOFS -J -R -pad -quiet /tmp/amlabel-cdrw.$$ | $CDRECORD dev=$writeDev -data blank=fast -");
    error("Error writing CD-RW") if ($result / 256 != 0);
} else {
    if ($MEDIA eq "DVD+R") {
        # At this point we have some unknown media type with no toc. We assume
	# it is a DVD+RW which still must be formatted. (Formatted DVD+RW does
	# have a toc.)
        $result = system("dvd+rw-format -blank $mountDev");
        if ($result / 256 != 0) {
	    error("Error formatting DVD+RW");
        }
    }
    $result = system("growisofs -Z $mountDev -J -R -pad -quiet /tmp/amlabel-cdrw.$$");
    if ($result / 256 != 0) {
	error("Error writing DVD+RW");
    }
}

# Clean up temporary files
if (-e "/tmp/amlabel-cdrw.$$/AMANDA_LABEL") {
    unlink "/tmp/amlabel-cdrw.$$/AMANDA_LABEL";
}
if (-d "/tmp/amlabel-cdrw.$$") {
    rmdir "/tmp/amlabel-cdrw.$$";
}

if ($WRITE_TAPELIST) {
    # Finally, append the new entry to the media list
    open ML, ">>$tapelist" || error("Cannot write to $tapelist: $!");
    print ML "00000000 $NEW_LABEL reuse\n";
    close ML;
}

exit 0;

# print an error message and exit
sub error {
  # Clean up temporary files
  unlink "/tmp/amlabel-cdrw.$$/AMANDA_LABEL" if -e "/tmp/amlabel-cdrw.$$/AMANDA_LABEL";
  rmdir "/tmp/amlabel-cdrw.$$" if -d "/tmp/amlabel-cdrw.$$";
  print STDERR "amlabel-cdrw: $_[0]\n" if $_[0];
  exit 1;
}

sub usage {
    print STDERR "Usage: amlabel-cdrw [-f] [--no-tapelist-entry] <conf> <label>\n";
    exit 1;
}

