/
blockdiff_merge
executable file
·95 lines (70 loc) · 1.88 KB
/
blockdiff_merge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#! /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