Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
Changes | 1 +
examples/vol-sparse.pl | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+)
create mode 100755 examples/vol-sparse.pl
diff --git a/Changes b/Changes
index 6c671c0..3742a8c 100644
--- a/Changes
+++ b/Changes
@@ -11,6 +11,7 @@ Revision history for perl module Sys::Virt
- Introduce Stream::sparse_send_all()
- Register VOL_DOWNLOAD_SPARSE_STREAM &
VOL_UPLOAD_SPARSE_STREAM constants
+ - Add vol-sparse.pl example
3.3.0 2017-05-08
diff --git a/examples/vol-sparse.pl b/examples/vol-sparse.pl
new file mode 100755
index 0000000..b99b57f
--- /dev/null
+++ b/examples/vol-sparse.pl
@@ -0,0 +1,142 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Sys::Virt;
+use Fcntl;
+
+my $FILE;
+
+sub downloadHandler {
+ my $st = shift;
+ my $data = shift;
+ my $nbytes = shift;
+ return syswrite FILE, $data, $nbytes;
+}
+
+sub downloadHoleHandler {
+ my $st = shift;
+ my $offset = shift;
+ my $pos = sysseek FILE, $offset, Fcntl::SEEK_CUR or die "Unable to seek in
$FILE: $!";
+ truncate FILE, $pos;
+}
+
+
+sub download {
+ my $vol = shift;
+ my $st = shift;
+ my $filename = shift;
+ my $offset = 0;
+ my $length = 0;
+
+ open FILE, ">$filename" or die "unable to create $filename:
$!";
+ eval {
+ $vol->download($st, $offset, $length,
Sys::Virt::StorageVol::VOL_DOWNLOAD_SPARSE_STREAM);
+ $st->sparse_recv_all(\&downloadHandler, \&downloadHoleHandler);
+ $st->finish();
+ };
+ if ($@) {
+ unlink $filename if $@;
+ close FILE;
+ die $@;
+ }
+
+ close FILE or die "cannot save $filename: $!"
+}
+
+sub uploadHandler {
+ my $st = $_[0];
+ my $nbytes = $_[2];
+ return sysread FILE, $_[1], $nbytes;
+}
+
+sub uploadHoleHandler {
+ my $st = shift;
+ my $inData;
+ my $sectionLen;
+
+ # HACK, Perl lacks SEEK_DATA and SEEK_HOLE.
+ my $SEEK_DATA = 3;
+ my $SEEK_HOLE = 4;
+
+ my $cur = sysseek FILE, 0, Fcntl::SEEK_CUR;
+ eval {
+ my $data = sysseek FILE, $cur, $SEEK_DATA;
+ # There are three options:
+ # 1) $data == $cur; $cur is in data
+ # 2) $data > $cur; $cur is in a hole, next data at $data
+ # 3) $data < 0; either $cur is in trailing hole, or $cur is beyond EOF.
+
+ if (!defined($data)) {
+ # case 3
+ $inData = 0;
+ my $end = sysseek FILE, 0, Fcntl::SEEK_END or die "Unable to get EOF
position: $!";
+ $sectionLen = $end - $cur;
+ } elsif ($data > $cur) {
+ #case 2
+ $inData = 0;
+ $sectionLen = $data - $cur;
+ } else {
+ #case 1
+ my $hole = sysseek FILE, $data, $SEEK_HOLE;
+ if (!defined($hole) or $hole eq $data) {
+ die "Blah";
+ }
+ $inData = 1;
+ $sectionLen = $hole - $data;
+ }
+ };
+
+ # reposition file back
+ sysseek FILE, $cur, Fcntl::SEEK_SET;
+
+ return ($inData, $sectionLen);
+}
+
+sub uploadSkipHandler {
+ my $st = shift;
+ my $offset = shift;
+ print("uploadSkipHandler: $offset\n");
+ sysseek FILE, $offset, Fcntl::SEEK_CUR or die "Unable to seek in $FILE";
+}
+
+sub upload {
+ my $vol = shift;
+ my $st = shift;
+ my $filename = shift;
+ my $offset = 0;
+ my $length = 0;
+
+ open FILE, "<$filename" or die "unable to open $filename:
$!";
+ eval {
+ $vol->upload($st, $offset, $length,
Sys::Virt::StorageVol::VOL_UPLOAD_SPARSE_STREAM);
+ $st->sparse_send_all(\&uploadHandler, \&uploadHoleHandler,
\&uploadSkipHandler);
+ $st->finish();
+ };
+ if ($@) {
+ close FILE;
+ die $@;
+ }
+
+ close FILE or die "cannot close $filename: $!"
+}
+
+die "syntax: $0 URI --download/--upload VOLUME FILE" unless int(@ARGV) == 4;
+
+my $uri = shift @ARGV;
+my $action = shift @ARGV;
+my $volpath = shift @ARGV;
+my $filename = shift @ARGV;
+
+my $c = Sys::Virt->new(uri => $uri) or die "Unable to connect to $uri";
+my $vol = $c->get_storage_volume_by_key($volpath) or die "No such volume";
+my $st = $c->new_stream();
+
+if ($action eq "--download") {
+ download($vol, $st, $filename);
+} elsif ($action eq "--upload") {
+ upload($vol, $st, $filename);
+} else {
+ die "unknown action $action";
+}
--
2.13.0