Imported Upstream version 3.3.1
[debian/amanda] / application-src / amzfs-sendrecv.pl
index cd009933324264d2d8ecdbdb30ad0aaa5cf6a15e..1bbbb9c97a2621bdb67b32ee230af3fda5da85d4 100644 (file)
@@ -33,7 +33,7 @@ use Amanda::Constants;
 use Amanda::Config qw( :init :getconf  config_dir_relative );
 use Amanda::Debug qw( :logging );
 use Amanda::Paths;
-use Amanda::Util qw( :constants );
+use Amanda::Util qw( :constants quote_string );
 
 sub new {
     my $class = shift;
@@ -102,6 +102,10 @@ sub command_support {
 sub command_selfcheck {
     my $self = shift;
 
+    $self->print_to_server("disk " . quote_string($self->{disk}));
+
+    $self->print_to_server("amzfs-sendrecv version " . $Amanda::Constants::VERSION,
+                          $Amanda::Script_App::GOOD);
     $self->zfs_set_value();
 
     if (!defined $self->{device}) {
@@ -111,7 +115,6 @@ sub command_selfcheck {
     if ($self->{error_status} == $Amanda::Script_App::GOOD) {
        $self->zfs_create_snapshot();
        $self->zfs_destroy_snapshot();
-       print "OK " . $self->{disk} . "\n";
        print "OK " . $self->{device} . "\n";
     }
 
@@ -334,12 +337,18 @@ sub command_index_from_image {
 sub command_restore {
     my $self = shift;
 
+    my $current_snapshot;
     my $level = $self->{level}[0];
     my $device = $self->{device};
-    $device = $self->{directory} if defined $self->{directory};
-    $device =~ s,^/,,;
-    my $current_snapshot = $self->zfs_build_snapshotname($device);
-    $self->{'snapshot'} = $self->zfs_build_snapshotname($device, $level);
+    if (defined $device) {
+       $device =~ s,^/,,;
+       $current_snapshot = $self->zfs_build_snapshotname($device);
+       $self->{'snapshot'} = $self->zfs_build_snapshotname($device, $level);
+    }
+
+    my $directory = $device;
+    $directory = $self->{directory} if defined $self->{directory};
+    $directory =~ s,^/,,;
 
     my @cmd = ();
 
@@ -348,22 +357,81 @@ sub command_restore {
     }
     push @cmd, $self->{zfs_path};
     push @cmd, "recv";
-    push @cmd, $device;
+    push @cmd, $directory;
 
     debug("cmd:" . join(" ", @cmd));
     system @cmd;
 
-    @cmd = ();
-    if ($self->{pfexec_cmd}) {
-       push @cmd, $self->{pfexec_cmd};
+    my $snapshotname;
+    my $newsnapname;
+    if (defined $device) {
+       $snapshotname = "$directory\@$current_snapshot";
+       $newsnapname = "$directory\@$self->{'snapshot'}";
+    } else {
+       # find snapshot name
+       @cmd = ();
+       if ($self->{pfexec_cmd}) {
+           push @cmd, $self->{pfexec_cmd};
+       }
+       push @cmd, $self->{zfs_path};
+       push @cmd, "list";
+       push @cmd, "-r";
+       push @cmd, "-t";
+       push @cmd, "snapshot";
+       push @cmd, $directory;
+       debug("cmd:" . join(" ", @cmd));
+
+       my($wtr, $rdr, $err, $pid);
+       my($msg, $errmsg);
+       $err = Symbol::gensym;
+       $pid = open3($wtr, $rdr, $err, @cmd);
+       close $wtr;
+       while ($msg = <$rdr>) {
+           next if $msg =~ /^NAME/;
+           my ($name, $used, $avail) = split(/ +/, $msg);
+           if ($name =~ /-current$/) {
+               $snapshotname = $name;
+               last;
+           }
+       }
+       $errmsg = <$err>;
+       waitpid $pid, 0;
+       close $rdr;
+       close $err;
+
+       if (defined $snapshotname and defined($level)) {
+           $newsnapname = $snapshotname;
+           $newsnapname =~ s/current$/$level/;
+       } else {
+           # destroy the snapshot
+           # restoring next level will fail.
+           @cmd = ();
+           if ($self->{pfexec_cmd}) {
+               push @cmd, $self->{pfexec_cmd};
+           }
+           push @cmd, $self->{zfs_path};
+           push @cmd, "destroy";
+           push @cmd, $snapshotname;
+
+           debug("cmd:" . join(" ", @cmd));
+           system @cmd;
+       }
     }
-    push @cmd, $self->{zfs_path};
-    push @cmd, "rename";
-    push @cmd, "$device\@$current_snapshot";
-    push @cmd, "$device\@$self->{'snapshot'}";
 
-    debug("cmd:" . join(" ", @cmd));
-    system @cmd;
+    if (defined $newsnapname) {
+       # rename -current snapshot to -level
+       @cmd = ();
+       if ($self->{pfexec_cmd}) {
+           push @cmd, $self->{pfexec_cmd};
+       }
+       push @cmd, $self->{zfs_path};
+       push @cmd, "rename";
+       push @cmd, $snapshotname;
+       push @cmd, $newsnapname;
+
+       debug("cmd:" . join(" ", @cmd));
+       system @cmd;
+    }
 }
 
 sub command_print_command {