Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 96 lines (70 sloc) 1.88 KB
#! /usr/bin/perl
use 5.008;
use strict;
use warnings;
use Errno;
sub readall {
my ($fh, $buf, $len) = @_;
my $off = 0;
while ($off != $len) {
my $r = sysread($fh, $$buf, $len - $off, $off);
if ($r == 0) {
return $off;
} elsif ($r == -1) {
if ($! != Errno::EAGAIN) {
return $off || -1;
}
} else {
$off += $r;
}
}
return $off;
}
my $DEBUG = $ENV{DEBUG} || undef;
my $fn = shift @ARGV
or die "Usage: $0 <file>\n";
open my $fh, (-e $fn ? '+<' : '>'), $fn
or die "failed to open file:$fn:$!";
my $blocksize = do {
readall(\*STDIN, \my $bsbin, 4) == 4
or die "invalid input";
unpack'V', $bsbin;
};
warn "block size: $blocksize" if $DEBUG;
while (readall(\*STDIN, \my $offbin, 8) == 8) {
my $rlen = readall(\*STDIN, \my $block, $blocksize);
die "unexpected eof while reading input:$!"
if $rlen <= 0;
my $offset = do {
my @o = unpack 'V2', $offbin;
$o[0] + $o[1] * 2**32;
};
warn "writing at:$offset, size:$rlen" if $DEBUG;
sysseek $fh, $offset, 0
or die "seek failed to offset $offset:$!";
syswrite($fh, $block, $rlen) == $rlen
or die "write failed:$!";
}
close $fh
or die "failed to close file:$fn:$!";
exit 0;
__END__
=head1 NAME
blockdiff_merge - merge tool for block-based diff
=head1 SYNOPSIS
restore full backup
% blockdiff_merge file < backup.1
apply inrcemental backups
% blockdiff_merge file < backup.2
% blockdiff_merge file < backup.3
...
=head1 DESCRIPTION
Blockdiff_merge is a restoration tool for block-based diffs.
=head1 SEE ALSO
L<App::Blockdiff> - for general information
=head1 AUTHOR
Copyright (C) 2009 Cybozu Labs, Inc., written by Kazuho Oku
=head1 LICENSE
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
See http://www.perl.com/perl/misc/Artistic.html
=cut