Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list