# HG changeset patch # User Heiko Schlittermann # Date 1486812209 -3600 # Node ID dd11d1262b6cdf7e4b58a15a4616ad80c87021bd # Parent a5d0873344399b3e5228b8922035fed6979416e1 Move project to git://git.schlittermann.de/imager.git diff -r a5d087334439 -r dd11d1262b6c Build.PL --- a/Build.PL Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -use strict; -use warnings; -use Module::Build; - -Module::Build->new( - module_name => "imager", - dist_version => "0.0", - dist_author => "Heiko Schlittermann ", - dist_abstract => "save images of block devices", - requires => { - perl => "5.10.0", - "autodie" => "2.06_01", - "IPC::System::Simple" => "1.21", - "Fuse" => "v0.09", - "IO::Uncompress::Gunzip" => 0, - "IO::Compress::Gzip" => 0, - }, - build_requires => { - "Test::More" => "0.92", - "File::Temp" => "0.22", - }, - script_files => [glob "bin/*"], -)->create_build_script; diff -r a5d087334439 -r dd11d1262b6c LICENSE --- a/LICENSE Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -Copyright: - - Copyright (C) 2011,2012,2013 Heiko Schlittermann - -License: - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This package is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -On Debian systems, the complete text of the GNU General -Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". - -The Debian packaging is: - - Copyright (C) 2011 Heiko Schlittermann - -and is licensed under the GPL version 3, see above. diff -r a5d087334439 -r dd11d1262b6c MANIFEST --- a/MANIFEST Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -.hgignore -.hgsigs -.hgtags -bin/.perltidyrc -bin/imager -bin/imager.check -bin/imager.compress -bin/imager.fuse -bin/imager.list -bin/imager.restore -bin/imager.save -Build.PL -debian/changelog -debian/compat -debian/control -debian/copyright -debian/docs -debian/emacsen-install.ex -debian/emacsen-remove.ex -debian/emacsen-startup.ex -debian/imager.cron.d.ex -debian/imager.default.ex -debian/imager.doc-base.EX -debian/imager.postinst -debian/imager.postrm -debian/init.d.ex -debian/manpage.1.ex -debian/manpage.sgml.ex -debian/manpage.xml.ex -debian/menu.ex -debian/po/POTFILES.in -debian/po/templates.pot -debian/preinst.ex -debian/prerm.ex -debian/README -debian/README.source -debian/rules -debian/source/format -debian/source/options -debian/watch.ex -examples/backup -lib/.perltidyrc -lib/Imager.pm -MANIFEST This list of files -MANIFEST.SKIP -scratch/x.pl -scratch/y.pl -t/000-syntax.t -t/001-save-restore.t diff -r a5d087334439 -r dd11d1262b6c MANIFEST.SKIP --- a/MANIFEST.SKIP Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -^\.hg/ -^_build/ -^blib/ -^\..*swp$ -^MYMETA\.yml$ -^MYMETA\.json$ -.*\.bak$ diff -r a5d087334439 -r dd11d1262b6c MOVED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MOVED Sat Feb 11 12:23:29 2017 +0100 @@ -0,0 +1,1 @@ +This repo moved to git://git.schlittermann.de/imager.git diff -r a5d087334439 -r dd11d1262b6c README --- a/README Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -Guide to the impatient user -=========================== - -Install the package -------------------- - - # perl Build.PL - - (optional step) - # ./Build prereq_report - - ./Build install - -Create your first image ------------------------ - -NOTE: The device you're imaging must not be busy during -image creation. Other your image will be unusable! - -The preferred way to get an idle device is using LVM snapshots: - - # lvcreate -s -L 1G -n lvol00-snap vg00/lvol00 - - (optional - check the filesystem) - # fsck -y /dev/mapper/vg00/lvol00-snap - - # imager save /dev/mapper/vg00/lvol00-snap /path/to/backup - -Restore your image ------------------- - -For a full restore: - - # imager restore /path/to/backup/idx/HOST/DEVICE/IMAGE-name > image - -If you need just parts of your image: - - # imager fuse /path/to/backup/ /mnt - -Now you may browse the images below /mnt/. To select just some files - -loop mount such an image and restore the files you need: - - # mount -o loop /mnt/…/image /media/xxx - -Happy landings…. --- -Heiko Schlittermann diff -r a5d087334439 -r dd11d1262b6c bin/.perltidyrc --- a/bin/.perltidyrc Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ ---paren-tightness=2 ---square-bracket-tightness=2 diff -r a5d087334439 -r dd11d1262b6c bin/imager --- a/bin/imager Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -#! /usr/bin/perl -use 5.10.0; -use strict; -use warnings; -use Getopt::Long; -use Pod::Usage; - -Getopt::Long::Configure("require_order"); -GetOptions( - "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) }, - "m|man" => sub { - pod2usage( - -verbose => 2, - -exit => 0, - -noperldoc => system("perldoc -V >/dev/null 2>&1") - ); - }, - ) - and $ARGV[0] ~~ [qw(save restore fuse check compress list)] - or pod2usage; - -exec "$0." . shift() => @ARGV; - -__END__ - -=head1 NAME - - imager - image backups - -=head1 SYNOPSIS - - imager {command} [options] ... - imager -h|--help - imager -m|--man - -=head1 DESCRIPTION - -This tool is the general command to get the -functions of the imager tool. - -=head1 OPTIONS - -=over - -=item B<-h>|B<--help> - -=item B<-m>|B<--man> - -The standard help|manpage options. - -=back - -=head1 COMMANDS - -=over - -=item save - -Save the image. See C for more information. - -=item restore - -Restore the image. See C for more information. - -=item fuse - -Do a fuse mount. See C for more information. - -=item check - -Check the saved images. See C for more information. - -=item compress - -Check the compression and decompress or compress. See C for more information. - -=item list - -List the backups/images available. See C for more information. - -=back - - -=cut diff -r a5d087334439 -r dd11d1262b6c bin/imager.check --- a/bin/imager.check Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,314 +0,0 @@ -#! /usr/bin/perl - -use 5.010; -use strict; -use warnings; -use Pod::Usage; -use Hash::Util qw(lock_keys); -use File::Find; -use File::Temp; -use Digest::MD5 qw(md5_hex); -use File::Basename; -use autodie qw(:all); -use Cwd qw(abs_path); -use Imager; - -use Getopt::Long; -use constant CIPHER => "aes-128-cbc"; -sub get_block_list; -sub purge_unused; -sub check_images; - -our %o = ( - yes => undef, - verbose => 1, - checksum => undef, - pass => undef, -); -lock_keys(%o); - -MAIN: { - Getopt::Long::Configure qw(Bundling); - GetOptions( - "y|yes!" => \$o{yes}, - "v|verbose!" => \$o{verbose}, - "c|checksum" => \$o{checksum}, - "p|pass" => \$o{pass}, - "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) }, - "m|man" => sub { - pod2usage( - -verbose => 2, - -exit => 0, - -noperldoc => system( - "perldoc -V 1>/dev/null - 2>&1" - ) - ); - }, - ) - and @ARGV - or pod2usage; - my $dir = shift; - - for (my $pass = 1 ; 1 ; ++$pass) { - verbose("# reading index files"); - my %block = get_block_list($dir); - verbose("# indexed: " - . scalar(@{ $block{""} // [] }) - . " images with " - . (grep !/^\.idx$/ => keys(%block)) - . " blocks"); - - my $subpass = 0; - purge_unused($pass => ++$subpass, $dir => %block); - check_images($pass => ++$subpass, $dir => %block) and last; - - verbose("# STARTING OVER!"); - } -} - -sub verbose { say @_ if $o{verbose} } - -sub get_file_list { - my ($list) = @_; - my @files = (); - - open(my $fh => $list); - while (<$fh>) { - push @files, (split)[2]; - } - return grep /^[a-z\d.\/]+$/ => @files; -} - -sub get_block_list { - my $dir = shift; - my %block; - find( - sub { - (-f) or return; # we need to include the tmp files! - push @{ $block{""} }, abs_path $_; - foreach my $f (get_file_list($_)) { - push @{ $block{$f} } => $#{ $block{""} }; - } - }, - "$dir/idx" - ); - return %block; -} - -sub purge_unused { - my ($pass, $subpass, $dir, %block) = @_; - my ($total, $done, $t0); - - verbose("# pass $pass.$subpass - checking for unused blocks"); - verbose("# estimating file count"); - - # calculate the number of files we expect - find( - sub { - -d or return; - opendir(my $dh => $_); - map { $total++ if not $_ ~~ [qw<. ..>] and length > 8 } readdir $dh; - closedir($dh); - $File::Find::prune = - $_ =~ /^[\d[a-f]{3}$/; # FIXME should be configurable - }, - "$dir/data" - ); - verbose("# got $total blocks/files"); - - # progress - $t0 = time; - local $SIG{ALRM} = sub { - return alarm 1 if not $done; - my $speed = $done / (time - $t0 + 1); - verbose sprintf - "# pass $pass.$subpass done %5.1f%% | %25s (%*d of %d blocks)", - 100 * ($done / $total), - scalar(localtime $t0 + $total / $speed), length($total) => $done, - $total; - alarm 5; - }; - $SIG{ALRM}->(); - - my @unused; - find( - sub { - $done++ if -f; - (-f _) and ((-M _) > 0) or return; # don't process the fresh blocks - - # we don't need uncompressed files if an compressed version - # exists - unlink $_ and return if -f "$_.gz"; - unlink "$_.x" and return if -f "$_.x.gz"; - - # the next step we can't do, because it can happen that - # the restorer does not know about a password - #unlink "$_.gz.x" and return if -f "$_.gz"; - - # cut away the first part of the filename and - # some optional extension - (my $rn = $File::Find::name) =~ s/^$dir\/data\/(.*?)(?:\..+)?$/$1/; - return if exists $block{$rn}; - push @unused => abs_path $_; - return; - - }, - "$dir/data" - ); - $SIG{ALRM}->(); - alarm 0; - - return if not @unused; - - say sprintf "found %d (%.1f%%) unused files", - 0 + @unused, - 100 * (@unused / $total); - - if ($o{yes}) { - verbose("# deleting " . @unused . " files"); - unlink @unused; - return; - } - - if (-t) { - while (1) { - print "delete? [y/N/v]: "; - given () { - when (/^y(?:es)?$/i) { unlink @unused; last } - when (/^v/) { say join "\n", @unused; next } - default { last } - } - } - } - -} - -sub check_images { - my ($pass, $subpass, $dir, %block) = @_; - - my $total = grep { $_ ne "" } keys(%block); - my $done = 0; - my $t0 = time; - - verbose("# pass $pass.$subpass - checking image completeness"); - - # progress - local $SIG{ALRM} = sub { - return alarm 1 if not $done; - my $speed = $done / (time - $t0 + 1); - verbose sprintf - "# pass $pass.$subpass done %5.1f%% | %25s (%*d of %d blocks)", - 100 * $done / $total, - scalar(localtime $t0 + $total / $speed), length($total) => $done, - $total; - alarm 5; - }; - $SIG{ALRM}->(); - - my %invalid; - foreach my $k (keys %block) { - state %checked; - my $i = $block{$k}; - next if $k eq ""; - ++$done; - - my ($file) = - grep { -f } - map { "$dir/data/$_" } ($k, "$k.gz", "$k.x", "$k.x.gz", "$k.gz.x"); - - if (not $file) { - say "missing $k @$i"; - @invalid{@$i} = (); - next; - } - - next if not $o{checksum}; - next if $checked{$file}; - - # checking the checksum - Imager::get_block($file => \my $buffer); - - if (md5_hex($buffer) ne basename($file, qw(.gz .x .gz.x))) { - say "wrong checksum for $file $k @$i\n"; - @invalid{@$i} = (); - next; - } - - $checked{$file} = 1; - } - $SIG{ALRM}->(); - alarm 0; - - # invalid now contains the numbers of the idx files beiing - # invalid - my @invalid = sort @{ $block{""} }[keys %invalid]; - - return 1 if not @invalid; - - say sprintf "found %d (%.1f%%) invalid images:", - 0 + @invalid, - 100 * (@invalid / $total); - - if ($o{yes}) { - unlink @invalid; - return undef; - } - - while (-t) { - print "delete? [y/N/v] "; - given () { - when (/^y(?:es)?$/i) { unlink @invalid; return undef } - when (/^v/i) { say join "\n" => @invalid; next } - default { last } - } - } - - return 1; -} -__END__ - -=head1 NAME - - imager.check - checks the imager data and index files - -=head1 SYNOPSIS - - imager.check [options] {directory} - -=head1 DESCRIPTION - -This tool loads all the index files from IF, -checks if all mentioned files are existing and optionally purges -unreferenced files. - -=head1 OPTIONS - -=over - -=item B<-c>|B<--checksum> - -Read all block files and check their checksum. (default: off) - -=item B<-p>|B<--pass> I - -In case you're using encrypted blocks, the param is passed to -Cs C<-pass> option. (default: unset) - -=item B<-v>|B<-->[no]B - -Generate more output about what's going on. (default: on) - -=item B<-y>|B<--yes> - -Assume "yes" for all questions (dangerous!). (default: no) - -=item B<-h>|B<--help> - -=item B<-m>|B<--man> - -The short and longer help. - -=back - -=cut diff -r a5d087334439 -r dd11d1262b6c bin/imager.compress --- a/bin/imager.compress Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -#! /usr/bin/perl - -use 5.010; -use strict; -use warnings; -use POSIX qw(strftime); -use autodie qw(:all); -use File::Basename; -use File::Temp; -use IO::Compress::Gzip qw(gzip $GzipError :level :strategy); -use IO::Uncompress::Gunzip qw(gunzip $GunzipError); -use Getopt::Long; -use Pod::Usage; -use File::Find; - -use constant THRESHOLD => 0.90; -use constant LEVEL => Z_BEST_SPEED; - -MAIN: { - - GetOptions( - "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) }, - "m|man" => sub { - pod2usage( - -verbose => 2, - -exit => 0, - -noperldoc => system("perldoc -V 1>/dev/null 2>&1") - ); - }, - ) - and @ARGV - or pod2usage; - - find( - sub { - say "dir $File::Find::name" and return if -d; - return if not (-f and /^[\da-f]{32}(?:\.x\.gz|\.gz)?$/); - #print STDERR "."; - - open(my $fh, $_); - my ($buffer, $zbuffer); - my ($tmp); - - if (/\.gz$/) { - sysread $fh => $zbuffer, -s $fh; - gunzip(\$zbuffer => \$buffer) - or die $GunzipError; - - if (!length($buffer)) { - warn "?? zero length after decompression: $_\n"; - return; - } - return if length($zbuffer) / length($buffer) < THRESHOLD; - - $tmp = File::Temp->new(DIR => ".", TEMPLATE => ".tmp-XXXXXX"); - syswrite $tmp => $buffer; - rename $tmp->filename => basename($_, ".gz"); - say "uncompressed $_"; - #print "+"; - - } - else { - sysread $fh => $buffer, -s $fh; - gzip( - \$buffer => \$zbuffer, - -Minimal => 1, - -Level => Z_BEST_SPEED, - -Strategy => Z_FILTERED - ) or die $GzipError; - return if length($zbuffer) / length($buffer) >= THRESHOLD; - - $tmp = File::Temp->new(DIR => ".", TEMPLATE => ".tmp-XXXXXX"); - syswrite $tmp => $zbuffer; - rename $tmp->filename => "$_.gz"; - say " compressed $_"; - #print STDERR "-"; - } - - close $tmp; - map { unlink } $tmp, $_; - - return 0; - - }, - @ARGV - ); - - exit 0; - -} - -__END__ - -=head1 NAME - - imager.compress - compress or decompress the blocks - -=head1 SYNOPSIS - - imager.compress {dir} - -=head1 DESCRIPTION - -B checks all files below the I. - -If compression saves more then 10% it will save the compressed block, -otherwise the uncompressed. - -=cut - - - - diff -r a5d087334439 -r dd11d1262b6c bin/imager.fuse --- a/bin/imager.fuse Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,353 +0,0 @@ -#! /usr/bin/perl - -use 5.010; -use strict; -use warnings; -use autodie qw(:all); -use Getopt::Long; -use Fuse; -use POSIX qw(setpgid :errno_h); -use IO::Uncompress::Gunzip qw(gunzip $GunzipError); -use Pod::Usage; -use Hash::Util qw(lock_keys); -use File::Temp; -use DB_File; -use File::Basename; -use Imager; -use Smart::Comments; - -my %o = ( - debug => undef, - detach => 1, - tmp => undef, - pass => undef, -); -lock_keys %o; - -use constant ME => basename $0; -use constant BS => 4 * 1024; -use constant CIPHER => "aes-128-cbc"; - -my ($DATA, $IDX); - -sub tie_vars; - -sub min { - (sort { $a <=> $b } @_)[0]; -} - -sub max { - (sort { $a <=> $b } @_)[-1]; -} - -sub nop_debug { } -sub yes_debug { print STDERR @_ } - -*{main::debug} = \&nop_debug; - -#$SIG{INT} = sub { warn "Got ^C or INT signal\n"; exit 1; }; - -MAIN: { - - GetOptions( - "d|debug!" => \$o{debug}, - "detach!" => \$o{detach}, - "tmp:s" => sub { $o{tmp} = length $_[1] ? $_[1] : $ENV{TMP} // "/tmp" }, - "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) }, - "p|pass=s" => \$o{pass}, - "m|man" => sub { - pod2usage( - -verbose => 2, - -exit => 0, - -noperlpod => system("perldoc -V 1>/dev/null 2>&1") - ); - }, - ) - and @ARGV == 2 - or pod2usage; - - if ($o{debug}) { - undef &{main::debug}; - *{main::debug} = \&yes_debug; - } - - my ($src, $mp) = @ARGV; - - $DATA = "$src/data"; - $IDX = "$src/idx"; - - die ME . ": $DATA: $!" if not -d $DATA; - die ME . ": $IDX: $!" if not -d $IDX; - - if (!$o{debug} and $o{detach}) { - fork() and exit; - $0 = "FUSE $src $mp"; - open(STDOUT => ">/dev/null"); - open(STDIN => "/dev/null"); - setpgid($$ => $$); - } - - tie_vars $o{tmp}; - - Fuse::main( - mountpoint => $mp, - - # debug => $o{debug} // 0, - getattr => \&getattr, - getdir => \&getdir, - open => \&openfile, - read => \&readbuffer, - write => \&writebuffer, - release => \&release, - ); - - exit; - -} - -# not the fuse functions - -{ - my (%IMAGE, %DIRTY); - - sub tie_vars { - return if not defined $_[0]; - my $file = - -d $_[0] - ? File::Temp->new(DIR => shift, TEMPLATE => "tmp.fuse.XXXXXX") - ->filename - : shift; - tie %DIRTY, "DB_File" => $file - or die "Can't tie to $file: $!\n"; - } - - sub getattr { - my $path = $IDX . shift; - return stat $path if -d $path; - my @attr = stat $path or return -(ENOENT); - my %meta = _get_meta($path); - $attr[7] = $meta{devsize}; - $attr[9] = $meta{timestamp}; - $attr[2] &= ~0222; # r/o - return @attr; - } - - sub getdir { - my $path = $IDX . shift; - opendir(my $dh, $path) or return 0; - return (readdir($dh), 0); - } - - sub openfile { - my $path = $IDX . shift; - return 0 if exists $IMAGE{$path}; - $IMAGE{$path}{meta} = { _get_meta($path) }; - $IMAGE{$path}{blocklist} = {}; - - # skip the file header - open(my $fh => $path); - { local $/ = ""; scalar <$fh> } - - # should check for the format - # $IMAGE{$path}{meta}{format} - - # now read the block list - while (<$fh>) { - /^#/ and last; - my ($block, $cs, $file) = split; - $IMAGE{$path}{blocklist}{$block} = $file; - } - close $fh; - return 0; - } - - sub release { - my $path = $IDX . shift; - return 0 if not exists $IMAGE{$path}; - debug("Currently we have " . keys(%DIRTY) . " dirty blocks\n"); - return 0; - } - - sub readbuffer { - my $path = $IDX . shift; - my ($size, $offset) = @_; - my $finfo = $IMAGE{$path} or die "File $path is not opened!"; - return "" if $offset >= $finfo->{meta}{devsize}; - - debug("<<< REQUESTED: offset:$offset size:$size\n"); - - my $buffer = ""; - for (my $need = $size ; $need > 0 ; $need = $size - length($buffer)) { - debug("<<< offset:@{[$offset + length($buffer)]} size:$need\n"); - $buffer .= _readblock($finfo, $need, $offset + length($buffer)); - debug("<<< missing: ", $size - length($buffer), "\n") if $size - length($buffer); - } - - debug("<<< SENDING " . length($buffer) . "\n\n"); - return $buffer; - } - - sub _readblock { - my ($finfo, $size, $offset) = @_; - my ($block, $blockoffset, $length); - - debug("<<< requested: offset:$offset size:$size" - . "\tfrom $finfo->{meta}{filesystem}\n"); - debug(" mapped to: block:@{[int($offset/BS)]}+@{[$offset % BS]}\n"); - - # first check if it's an dirty block - $block = int($offset / BS); - if (exists $DIRTY{ $finfo . $block }) { - $blockoffset = $offset % BS; - $length = min(BS - $blockoffset, $size); - - debug( - "+++ dirty offset:$block*@{[BS]} + $blockoffset size:$length\n" - ); - return substr $DIRTY{ $finfo . $block }, $blockoffset, $length; - } - - # if not dirty, we've to find it on disk - - $block = int($offset / $finfo->{meta}{blocksize}); - $blockoffset = $offset % $finfo->{meta}{blocksize}; - $length = min($finfo->{meta}{blocksize} - $blockoffset, $size); - - # find the max length we can satisfy w/o colliding - # with dirty blocks - for (my $l = BS ; $l < $length ; $l += BS) { - my $b = int(($offset + $l) / BS); - if ($DIRTY{ $finfo . $b }) { - $length = $l; - last; - } - } - - debug("+++ disk offset:$block*$finfo->{meta}{blocksize}" - . " + $blockoffset size:$length\n"); - -# die if $blockoffset == 417792; - - my $fn = "$DATA/" . $finfo->{blocklist}{$block}; - debug(" fn:$fn\n"); - - state %cache; - if (not defined $cache{fn} - or ($cache{fn} ne $fn)) - { - Imager::get_block("$fn*" => \$cache{data}); - $cache{fn} = $fn; - } - - return substr($cache{data}, $blockoffset, $length); - - } - - sub writebuffer { - my $path = $IDX . shift; - my ($buffer, $offset) = @_; - my $size = length($buffer); - my $finfo = $IMAGE{$path} or die "File $path is not opened!"; - - for (my $written = 0 ; $written < $size ;) { - - # OPTIMIZE: we should not ask for writing more than the - # blocksize - my $n = - _writeblock($finfo, substr($buffer, $written), $offset + $written) - or return $written; - $written += $n; - } - return $size; - } - - sub _writeblock { - my ($finfo, $buffer, $offset) = @_; - my ($block, $blockoffset, $length); - my $size = length($buffer); - - $block = int($offset / BS); - $blockoffset = $offset % BS; - $length = min(BS - $blockoffset, $size); - - debug(">>> offset:$offset size:$length of $size\n"); - debug(" block @{[int($offset/BS)]} + @{[$offset % BS]}\n"); - - if (not exists $DIRTY{ $finfo . $block }) { - debug("+++ missing $block+$blockoffset\n"); - $DIRTY{ $finfo . $block } = _readblock($finfo, BS, $block * BS); - } - - substr($DIRTY{ $finfo . $block }, $blockoffset, $length) = - substr($buffer, 0, $length); - - return $length; - } - - sub _get_meta { - my $path = shift; - my %meta; - open(my $fh => $path); - while (<$fh>) { - last if /^$/; - /^(?\S+):\s+(?:(?\d+)|(?.*?))\s*$/ - and do { - - # na sowas, die Zeitstempel dürfen nicht als Zeichenkette reinkommen! - $meta{ $+{k} } = defined $+{n} ? (0 + $+{n}) : $+{v}; - next; - }; - } - return %meta; - } - -} - -__END__ - -=head1 NAME - - imager.fuse - the fuse mount helper for imagers backups - -=head1 SYNOPSIS - - imager.fuse [options] {src} {mount point} - -=head1 DESCRIPTION - -B mounts the src directory (containing F and F -directories) the the specified mount point. - -=head1 OPTIONS - -=over 4 - -=item B<-d> | B<--debug> - -Enables debugging output from B. When using this option, -B does not detach from the terminal. (default: off) - -=item B<-->I<[no]>B - -Detach or don't detach from the terminal. (default: detach) - -=item B<-p>|B<--pass> I - -Password to be used for decryption. For the format please refer -L. (default: not set) - -=item B<--tmp> [I] - -Write dirty blocks into a buffer file in the specified tmp directory. -If no directory is specified, the system default (usually F) will -be used. (default: no temp file) - -=item B<-h>|B<--help> - -=item B<-m>|B<--man> - -The common help and man options. - -=back - -=cut diff -r a5d087334439 -r dd11d1262b6c bin/imager.list --- a/bin/imager.list Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -#! /usr/bin/perl - -use 5.010; -use strict; -use warnings; -use Pod::Usage; -use Hash::Util qw(lock_keys); -use File::Find; -use Digest::MD5 qw(md5_hex); -use File::Basename; -use autodie qw(:all); -use Imager; - -use Getopt::Long; - -our %o = ( - latest => undef, -); -lock_keys(%o); - -MAIN: { - my $dir; - - Getopt::Long::Configure qw(Bundling); - GetOptions( - "latest" => \$o{latest}, - "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) }, - "m|man" => sub { - pod2usage( - -verbose => 2, - -exit => 0, - -noperldoc => system( - "perldoc -V 1>/dev/null - 2>&1" - ) - ); - }, - ) - and defined ($dir = shift) - or pod2usage; - - my (%by_day, %by_dev); - find(sub{ - return if not (-f and /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ$/); - my ($host, $dev) = dirname($File::Find::name) =~ /^\Q$dir\/idx\E\/(.+?)(\/.*)/; - push @{$by_day{$_}}, "$host\::$dev"; - push @{$by_dev{"$host\::$dev"}}, $_; - }, "$dir/idx"); - - # by dev - my $l = (sort { $b <=> $a } map { length } keys %by_dev)[0]; - foreach (sort keys %by_dev) { - my $prefix = $_; - foreach ((reverse sort @{$by_dev{$_}})) { - printf "%-*s: %s\n", $l => $prefix, $_; - last if $o{latest}; - $prefix = " "; - } - } - -} - -__END__ - -=head1 NAME - - imager.list - list the images created by imager - -=head1 SYNOPSIS - - imager.list [options] {directory} - -=head1 DESCRIPTION - -B lists the index files (images) the imager created. - - -=head1 OPTIONS - -=over - -=item B<--latest> - -List only the latest backups. (default: list all) - -=item B<-h>|B<--help> - -=item B<-m>|B<--man> - -The short and longer help. - -=back - -=cut diff -r a5d087334439 -r dd11d1262b6c bin/imager.restore --- a/bin/imager.restore Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -#! /usr/bin/perl -# Eigentlich geht das selbe mit: -# grep '^[[:space:]]*[[:digit:]]' IDX-file | tr -d | cut -f4 -d' ' | while read f; do -# if test -f DATA/$f then cat $f -# elif test -f DATA/$f.gz then zcat DATA/$f.gz -# elif test -f DATA/$f.x then openssl aes-128-cbc -d -in DATA/$f.x -# elif test -f DATA/$f.gz.x then openssl aes-128-cbc -d -in DATA/$f.gz.x | zcat -# elif test -f DATA/$f.x.gz then zcat DATA/$f.x.gz | openssl aes-128-cbs -d -# fi -# done - -use 5.010; -use strict; -use warnings; -use File::Basename; -use autodie qw(:all); -use Pod::Usage; -use Getopt::Long; -use Hash::Util qw(lock_keys); -use Imager; - -use constant KiB => 1024; -use constant MiB => 1024 * KiB; -use constant GiB => 1024 * MiB; -use constant ME => basename $0; -use constant CIPHER => "aes-128-cbc"; - -my %o = (pass => "stdin"); -lock_keys(%o); - -sub find_data_dir; - -MAIN: { - - Getopt::Long::Configure(qw(Bundling)); - GetOptions( - "p|pass=s" => \$o{pass}, - "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) }, - "m|man" => sub { - pod2usage( - -verbose => 2, - -exit => 0, - -noperldoc => system( - "perldoc -V 1>/dev/null - 2>&1" - ) - ); - }, - ) - and @ARGV == 2 - or pod2usage; - - my $idx = shift; - my $dst = shift; - my $blocksize = undef; - my $data = find_data_dir($idx); - - open(my $fh => $idx); - { local $/ = ""; $_ = <$fh>; } - /^format:\s*1$/m or die ME . ": expected index format 1\n"; - ($blocksize) = /^blocksize:\s*(\d+)/m or die ME . ": no blocksize found\n"; - - my $out; - if ($dst eq "-") { open($out => ">&STDOUT") } - else { open($out => ">", $dst) } - - while (<$fh>) { - next if /^#/; - my ($blk, undef, $path) = split; - my $buffer; - Imager::get_block("$data/$path*" => \$buffer); - print {$out} $buffer; - } - close($out); - close($fh); -} - -sub find_data_dir { - for (my $dir = shift ; $dir ne "/" ; $dir = dirname $dir) { - return "$dir/data" if -d "$dir/data" and -d "$dir/idx"; - } - die ME . ": no data directory found!\n"; -} - -__END__ - -=head1 NAME - - imager.restore - cats the blocks of the imager - -=head1 SYNOPSIS - - imager.restore [options] {idx} {destination} - -=head1 DESCRIPTION - -The B takes all the blocks from the IDX file and -cats them as one data stream. The destination can be any block device, -a file name or even B<-> (STDOUT). - -=head1 OPTIONS - -=over - -=item B<-p>|B<--pass> I - -In case you expect encrypted data, this option takes the argument for -B's C<-pass> option. See L for mor information. -(default: stdin) - -=item B<-h>|B<--help> - -=item B<-m>|B<--man> - -The standard help options. - -=back - -=cut diff -r a5d087334439 -r dd11d1262b6c bin/imager.save --- a/bin/imager.save Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,319 +0,0 @@ -#! /usr/bin/perl - -use 5.010; -use strict; -use warnings; -use POSIX qw(strftime); -use autodie qw(:all); -use Digest::MD5 qw(md5_hex); -use File::Path qw(mkpath); -use File::Basename; -use File::Temp; -use Sys::Hostname; -use IO::Compress::Gzip qw(gzip $GzipError :level :strategy); -use Hash::Util qw(lock_keys); -use Getopt::Long; -use Pod::Usage; -use Imager 0.1; -use if $^V >= v5.18 => (experimental => qw'lexical_topic smartmatch'); - -use constant KiB => 1024; -use constant MiB => 1024 * KiB; -use constant GiB => 1024 * MiB; -use constant BS => 4 * MiB; -use constant DATEFMT => "%Y-%m-%dT%H:%M:%SZ"; -use constant CIPHER => "aes-128-cbc"; - -sub get_devsize; -sub get_devname; -sub save; - -$SIG{INT} = sub { die "Got INT\n" }; - -my %o = ( - compress => undef, - verbose => undef, - blocksize => BS, - pass => undef, - comment => undef, - now => time(), -); -lock_keys(%o); - -MAIN: { - GetOptions( - "h|help" => sub { pod2usage(-verbose => 1, exit => 0) }, - "m|man" => sub { - pod2usage( - -verbose => 2, - exit => 0, - -noperldoc => system("perldoc -V >/dev/null 2>&1") - ); - }, - "c|comment=s" => \$o{comment}, - "z|compress:i" => sub { $o{compress} = $_[1] ? $_[1] : Z_BEST_SPEED }, - "p|pass=s" => \$o{pass}, - "now=i" => \$o{now}, - "b|blocksize=s" => sub { - given ($_[1]) { - when (/(\d+)G/i) { $o{blocksize} = $1 * GiB }; - when (/(\d+)M/i) { $o{blocksize} = $1 * MiB }; - when (/(\d+)K/i) { $o{blocksize} = $1 * KiB }; - when (/^(\d+)$/) { $o{blocksize} = $1 }; - default { - die "Blocksize $_[1] is incorrect!\n" - }; - } - }, - ) - and @ARGV >= 2 - or pod2usage; - - my $dst = pop @ARGV; - foreach my $src (@ARGV) { - if (my $pid = fork()) { - next; - } - elsif (not defined $pid) { - die "Can't fork: $!\n"; - } - save($src, $dst); - exit; - } - - my $rc = 0; - while (wait != -1) { - $rc = ($? >> 8) if ($? >> 8) > $rc; - } - exit $rc; - -} - -sub save { - my ($src, $dst) = @_; - my $idx = "{DIR}/idx/{HOSTNAME}/{DEVICE}/"; - my $data = "{DIR}/data"; - my $info = "{DIR}/data/info"; - my ($size, $name); - - if ($src =~ /(?.+?):(?.+)/) { - $src = $+{dev}; - $name = $+{name}; - } - else { $name = $src } - - foreach ($idx, $data, $info) { - s/{DIR}/$dst/g; - s/{HOSTNAME}/hostname/eg; - s/{DEVICE}/$name/g; - } - $size = get_devsize($src); - - -d $dst or die "$0: $dst: $!\n"; - mkpath([$data, $idx, $info]); - - my %index; - $index{META} = { - format => 1, - host => hostname, - filesystem => $src, - blocksize => $o{blocksize}, - devsize => $size, - timestamp => $o{now}, - datetime => strftime(DATEFMT, gmtime $o{now}), - (defined $o{comment} ? (comment => $o{comment}) : ()), - encryption => $o{pass} ? CIPHER : "none", - }; - - open(my $in => $src); - binmode($in); - local $| = 1; - - my %stats = ( - written => 0, - skipped => 0, - todo => 1 + int($size / $o{blocksize}), - ); - - local $SIG{ALRM} = sub { - my $speed = ($stats{written} + $stats{skipped}) / (time - $^T + 1); - say sprintf -"# %*s done %5.1f%% | %24s (%*d of $stats{todo}, written %*d, skipped %*d)", - (sort { $a <=> $b } map { length basename $_ } @ARGV)[-1] => - basename($name), - 100 * (($stats{written} + $stats{skipped}) / $stats{todo}), - ($speed ? (scalar localtime($^T + $stats{todo} / $speed)) : ""), - length($stats{todo}) => $stats{written} + $stats{skipped}, - length($stats{todo}) => $stats{written}, - length($stats{todo}) => $stats{skipped}; - alarm(5); - }; - $SIG{ALRM}->(); - - for ( - my $blknr = 0 ; - sysread($in => my $buffer, $o{blocksize}) > 0 ; - ++$blknr - ) - { - - my ($file, $ext, $cs); - $file = $cs = md5_hex($buffer); - $file =~ s/(?(?...).*)/$+{prefix}\/$+{fn}/g; - $ext .= $o{pass} ? ".x" : ""; - - # the extension we do not put into the index - push @{ $index{BLOCKS} }, sprintf "%12d %s %s" => $blknr, - $cs, $file; - - if (not Imager::get_file("$data/$file")) { - mkpath dirname("$data/$file"); - my $out = File::Temp->new( - TEMPLATE => "tmp-XXXXXXX", - DIR => dirname("$data/$file") - ); - - if ($o{pass}) { - open($out, "|openssl @{[CIPHER]} -pass $o{pass} -out $out"); - } - binmode($out); - - my $bufref = \$buffer; - if ($o{compress}) { - my $zbuffer; - gzip( - \$buffer => \$zbuffer, - -Minimal => 1, - -Level => Z_BEST_SPEED, - -Strategy => Z_FILTERED - ) or die $GzipError; - if (length($zbuffer) / length($buffer) < 0.9) { - $bufref = \$zbuffer; - $ext = ".gz$ext"; - } - } - - #for(my $todo = length $$bufref; - # $todo -= syswrite $out => $$bufref, $todo, -$todo; 1) - #{ - #} - syswrite $out => $$bufref or die "$0: write: $!\n"; - close($out) or die "$0: close output file: $!"; - - rename($out => "$data/$file$ext"); - $index{BLOCKS}[$blknr] .= " *"; - $stats{written}++; - } - else { - $stats{skipped}++; - } - } - $SIG{ALRM}->(); - alarm 0; - - $index{META}{blocks} = @{ $index{BLOCKS} }; - $index{META}{runtime} = time() - $^T . "s"; - - my $index = File::Temp->new(DIR => $idx); - say $index join "\n" => "# imager", - (map { "$_: $index{META}{$_}" } sort(keys %{ $index{META} })), - "", - @{ $index{BLOCKS} }; - close($index); - rename $index->filename => "$idx/" . strftime(DATEFMT, gmtime $o{now}); - - say "# $src DONE (runtime " . (time() - $^T) . "s)"; - say "# $src WRITTEN $stats{written}, SKIPPED $stats{skipped} blocks"; - say "# $src SAVINGS " - . sprintf "%3d%%" => 100 * - ($stats{skipped} / ($stats{written} + $stats{skipped})); - -} - -sub get_devsize { - my ($devname) = @_; - open(my $fh => $devname); - seek($fh, 0, 2); - return tell($fh); -} - -sub get_devname { - my $_ = shift; - s/^\/dev\///; - s/_/__/g; - s/\//_/g; - return $_; -} - -__END__ - -=head1 NAME - - imager.save - create a block device snapshot - -=head1 SYNOPSIS - - imager.save [options] {device}[:name] {destination} - -=head1 DESCRIPTION - -This tool creates a snapshot of a blockdevice. -Just call it like - - imager.save /dev/sda1 /media/backup - -This will create F, if not already existing. -The index (blocklist) goes to -IFIFI. The data goes to -I/F. - -If :I is appended on to the device name, the blocklist file and -the data directory are named acording to this I, not the original -device name. You may welcome this extension if you save LVM snapshots -or simiar stuff. - -=head1 OPTIONS - -=over - -=item B<-b>|B<--blocksize> I - -The blocksize used. (may be suffixed with K, M, G). (default: 4 MiB, -or taken from F) - -=item B<-c>|B<--comment> I - -Comment to be included in the header of the index file. (default: none) - -=item B<--now> I - -Set the timestamp used for naming the idx files. (default: now) - -=item B<-p>|B<--pass> I - -Use symmetric encryption for writing the data blocks. This option -is passed to L. - -=item B<-z>|B<--compress> [I] - -Use compression when writing the blocks to disk. B There may -remain uncompressed files, since we only save compressed data if we -can save more then 10% of the size. (default: off) - -=item B<-h>|B<--help> - -=item B<-m>|B<--man> - -The short and longer help. - -=back - -=head1 PERFORMANCE - -Some experiments have shown that if compression and encryption is used, -about 1/3 of the time is consumed by the encryption, and 2/3 are used -for compression. The compression is done before(!) encrypting the file, -since otherwise there is almost no benefit in compressing an encrypted -file! - -=cut diff -r a5d087334439 -r dd11d1262b6c debian/README --- a/debian/README Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -The Debian Package imager ----------------------------- - -Comments regarding the Package - - -- Heiko Schlittermann Mon, 12 Sep 2011 12:24:13 +0200 diff -r a5d087334439 -r dd11d1262b6c debian/README.source --- a/debian/README.source Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -imager for Debian ------------------ - - - - - - diff -r a5d087334439 -r dd11d1262b6c debian/changelog --- a/debian/changelog Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -imager (0.15) stable; urgency=medium - - * [merge]: - * Reset PERL_MM_OPT PERL_MB_OPT: - - -- Heiko Schlittermann (HS12-RIPE) Sat, 25 Jul 2015 17:16:03 +0200 - -imager (0.14) stable; urgency=medium - - * bump version - - -- Heiko Schlittermann (HS12-RIPE) Wed, 13 May 2015 15:05:27 +0200 - -imager (0.13+nmu1) stable; urgency=medium - - * Added copyright file (LICENSE): GPLv3: - * added README for the impatient: - * [merged]: - * Fix Maintainer: - - -- Heiko Schlittermann (HS12-RIPE) Wed, 13 May 2015 15:04:10 +0200 - -imager (0.13) stable; urgency=low - - * perltidy, fixed debug output - - -- Heiko Schlittermann Mon, 27 Aug 2012 15:52:40 +0200 - -imager (0.12) stable; urgency=low - - * fixed Build.PL - * fixed attrs passed from getattr() - * The timestamps need to be numbers! - - -- Heiko Schlittermann Mon, 18 Jun 2012 16:54:46 +0200 - -imager (0.11) stable; urgency=low - - * added the :name explanation - - -- Heiko Schlittermann Fri, 25 Nov 2011 12:47:22 +0100 - -imager (0.10) stable; urgency=low - - * added dependency on libipc-system-simple-perl (Thanks C. Arnold) - - -- Heiko Schlittermann Wed, 23 Nov 2011 09:50:50 +0100 - -imager (0.9) stable; urgency=low - - * added nsca to example script - - -- Heiko Schlittermann Wed, 23 Nov 2011 09:40:17 +0100 - -imager (0.8) stable; urgency=low - - * fixed comment - - -- Heiko Schlittermann Tue, 11 Oct 2011 10:27:37 +0200 - -imager (0.7) stable; urgency=low - - * fixed lintian bugs - * fixed lintian warnings - - -- Heiko Schlittermann Fri, 16 Sep 2011 11:23:26 +0200 - -imager (0.6) stable; urgency=low - - * added chance to remove the local install - - -- Heiko Schlittermann Mon, 12 Sep 2011 12:41:30 +0200 - -imager (0.5) stable; urgency=low - - * Initial Release. - - -- Heiko Schlittermann Mon, 12 Sep 2011 12:26:37 +0200 diff -r a5d087334439 -r dd11d1262b6c debian/compat --- a/debian/compat Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -7 diff -r a5d087334439 -r dd11d1262b6c debian/control --- a/debian/control Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -Source: imager -Section: misc -Priority: extra -Maintainer: Heiko Schlittermann (HS12-RIPE) -Build-Depends: debhelper (>= 7.0.50~) -Standards-Version: 3.9.1 -Homepage: https://ssl.schlittermann.de/hg/imager -#Vcs-Git: git://git.debian.org/collab-maint/imager.git -#Vcs-Browser: http://git.debian.org/?p=collab-maint/imager.git;a=summary - -Package: imager -Architecture: all -Depends: ${misc:Depends}, libfuse-perl, libipc-system-simple-perl -Description: device image creation tool - Imager creates images of devices in a rsyncable and space efficiant way, - even multiple generations are quite space efficient. (imager is using some - sort of data deduplication in userland). diff -r a5d087334439 -r dd11d1262b6c debian/copyright --- a/debian/copyright Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -This work was packaged for Debian by: - - Heiko Schlittermann on Mon, 12 Sep 2011 12:24:13 +0200 - -It was downloaded from: - - https://ssl.schlittermann.de/hg/imager - -Upstream Author(s): - - Heiko Schlittermann - -Copyright: - - Copyright (C) 2011 Heiko Schlittermann - -License: - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This package is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -On Debian systems, the complete text of the GNU General -Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". - -The Debian packaging is: - - Copyright (C) 2011 Heiko Schlittermann - -and is licensed under the GPL version 3, see above. diff -r a5d087334439 -r dd11d1262b6c debian/docs diff -r a5d087334439 -r dd11d1262b6c debian/emacsen-install.ex --- a/debian/emacsen-install.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -#! /bin/sh -e -# /usr/lib/emacsen-common/packages/install/imager - -# Written by Jim Van Zandt , borrowing heavily -# from the install scripts for gettext by Santiago Vila -# and octave by Dirk Eddelbuettel . - -FLAVOR=$1 -PACKAGE=imager - -if [ ${FLAVOR} = emacs ]; then exit 0; fi - -echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR} - -#FLAVORTEST=`echo $FLAVOR | cut -c-6` -#if [ ${FLAVORTEST} = xemacs ] ; then -# SITEFLAG="-no-site-file" -#else -# SITEFLAG="--no-site-file" -#fi -FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile" - -ELDIR=/usr/share/emacs/site-lisp/${PACKAGE} -ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE} - -# Install-info-altdir does not actually exist. -# Maybe somebody will write it. -if test -x /usr/sbin/install-info-altdir; then - echo install/${PACKAGE}: install Info links for ${FLAVOR} - install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/share/info/${PACKAGE}.info.gz -fi - -install -m 755 -d ${ELCDIR} -cd ${ELDIR} -FILES=`echo *.el` -cp ${FILES} ${ELCDIR} -cd ${ELCDIR} - -cat << EOF > path.el -(setq load-path (cons "." load-path) byte-compile-warnings nil) -EOF -${FLAVOR} ${FLAGS} ${FILES} -rm -f *.el path.el - -exit 0 diff -r a5d087334439 -r dd11d1262b6c debian/emacsen-remove.ex --- a/debian/emacsen-remove.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -#!/bin/sh -e -# /usr/lib/emacsen-common/packages/remove/imager - -FLAVOR=$1 -PACKAGE=imager - -if [ ${FLAVOR} != emacs ]; then - if test -x /usr/sbin/install-info-altdir; then - echo remove/${PACKAGE}: removing Info links for ${FLAVOR} - install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/share/info/imager.info.gz - fi - - echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR} - rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE} -fi diff -r a5d087334439 -r dd11d1262b6c debian/emacsen-startup.ex --- a/debian/emacsen-startup.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -;; -*-emacs-lisp-*- -;; -;; Emacs startup file, e.g. /etc/emacs/site-start.d/50imager.el -;; for the Debian imager package -;; -;; Originally contributed by Nils Naumann -;; Modified by Dirk Eddelbuettel -;; Adapted for dh-make by Jim Van Zandt - -;; The imager package follows the Debian/GNU Linux 'emacsen' policy and -;; byte-compiles its elisp files for each 'emacs flavor' (emacs19, -;; xemacs19, emacs20, xemacs20...). The compiled code is then -;; installed in a subdirectory of the respective site-lisp directory. -;; We have to add this to the load-path: -(let ((package-dir (concat "/usr/share/" - (symbol-name flavor) - "/site-lisp/imager"))) -;; If package-dir does not exist, the imager package must have -;; removed but not purged, and we should skip the setup. - (when (file-directory-p package-dir) - (setq load-path (cons package-dir load-path)) - (autoload 'imager-mode "imager-mode" - "Major mode for editing imager files." t) - (add-to-list 'auto-mode-alist '("\\.imager$" . imager-mode)))) - diff -r a5d087334439 -r dd11d1262b6c debian/imager.cron.d.ex --- a/debian/imager.cron.d.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -# -# Regular cron jobs for the imager package -# -0 4 * * * root [ -x /usr/bin/imager_maintenance ] && /usr/bin/imager_maintenance diff -r a5d087334439 -r dd11d1262b6c debian/imager.default.ex --- a/debian/imager.default.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -# Defaults for imager initscript -# sourced by /etc/init.d/imager -# installed at /etc/default/imager by the maintainer scripts - -# -# This is a POSIX shell fragment -# - -# Additional options that are passed to the Daemon. -DAEMON_OPTS="" diff -r a5d087334439 -r dd11d1262b6c debian/imager.doc-base.EX --- a/debian/imager.doc-base.EX Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -Document: imager -Title: Debian imager Manual -Author: -Abstract: This manual describes what imager is - and how it can be used to - manage online manuals on Debian systems. -Section: unknown - -Format: debiandoc-sgml -Files: /usr/share/doc/imager/imager.sgml.gz - -Format: postscript -Files: /usr/share/doc/imager/imager.ps.gz - -Format: text -Files: /usr/share/doc/imager/imager.text.gz - -Format: HTML -Index: /usr/share/doc/imager/html/index.html -Files: /usr/share/doc/imager/html/*.html diff -r a5d087334439 -r dd11d1262b6c debian/imager.postinst --- a/debian/imager.postinst Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -#!/bin/sh -# postinst script for imager -# -# see: dh_installdeb(1) - -set -e -. /usr/share/debconf/confmodule - -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-remove' -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - configure) - db_get imager/remove-local-install || true - if test "$RET" = "true"; then - rm -fv /usr/local/bin/imager - fi - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff -r a5d087334439 -r dd11d1262b6c debian/imager.postrm --- a/debian/imager.postrm Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -#!/bin/sh -# postrm script for imager -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff -r a5d087334439 -r dd11d1262b6c debian/init.d.ex --- a/debian/init.d.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -#!/bin/sh -### BEGIN INIT INFO -# Provides: imager -# Required-Start: $network $local_fs -# Required-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: -# Description: -# <...> -# <...> -### END INIT INFO - -# Author: Heiko Schlittermann - -# PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC=imager # Introduce a short description here -NAME=imager # Introduce the short server's name here -DAEMON=/usr/sbin/imager # Introduce the server's location here -DAEMON_ARGS="" # Arguments to run the daemon with -PIDFILE=/var/run/$NAME.pid -SCRIPTNAME=/etc/init.d/$NAME - -# Exit if the package is not installed -[ -x $DAEMON ] || exit 0 - -# Read configuration variable file if it is present -[ -r /etc/default/$NAME ] && . /etc/default/$NAME - -# Load the VERBOSE setting and other rcS variables -. /lib/init/vars.sh - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. -. /lib/lsb/init-functions - -# -# Function that starts the daemon/service -# -do_start() -{ - # Return - # 0 if daemon has been started - # 1 if daemon was already running - # 2 if daemon could not be started - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ - || return 1 - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ - $DAEMON_ARGS \ - || return 2 - # Add code here, if necessary, that waits for the process to be ready - # to handle requests from services started subsequently which depend - # on this one. As a last resort, sleep for some time. -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - # Return - # 0 if daemon has been stopped - # 1 if daemon was already stopped - # 2 if daemon could not be stopped - # other if a failure occurred - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME - RETVAL="$?" - [ "$RETVAL" = 2 ] && return 2 - # Wait for children to finish too if this is a daemon that forks - # and if the daemon is only ever run from this initscript. - # If the above conditions are not satisfied then add some other code - # that waits for the process to drop all resources that could be - # needed by services started subsequently. A last resort is to - # sleep for some time. - start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON - [ "$?" = 2 ] && return 2 - # Many daemons don't delete their pidfiles when they exit. - rm -f $PIDFILE - return "$RETVAL" -} - -# -# Function that sends a SIGHUP to the daemon/service -# -do_reload() { - # - # If the daemon can reload its configuration without - # restarting (for example, when it is sent a SIGHUP), - # then implement that here. - # - start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME - return 0 -} - -case "$1" in - start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME" - do_start - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - status) - status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? - ;; - #reload|force-reload) - # - # If do_reload() is not implemented then leave this commented out - # and leave 'force-reload' as an alias for 'restart'. - # - #log_daemon_msg "Reloading $DESC" "$NAME" - #do_reload - #log_end_msg $? - #;; - restart|force-reload) - # - # If the "reload" option is implemented then remove the - # 'force-reload' alias - # - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 - echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 - exit 3 - ;; -esac - -: diff -r a5d087334439 -r dd11d1262b6c debian/manpage.1.ex --- a/debian/manpage.1.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.\" First parameter, NAME, should be all caps -.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection -.\" other parameters are allowed: see man(7), man(1) -.TH IMAGER SECTION "September 12, 2011" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -imager \- program to do something -.SH SYNOPSIS -.B imager -.RI [ options ] " files" ... -.br -.B bar -.RI [ options ] " files" ... -.SH DESCRIPTION -This manual page documents briefly the -.B imager -and -.B bar -commands. -.PP -.\" TeX users may be more comfortable with the \fB\fP and -.\" \fI\fP escape sequences to invode bold face and italics, -.\" respectively. -\fBimager\fP is a program that... -.SH OPTIONS -These programs follow the usual GNU command line syntax, with long -options starting with two dashes (`-'). -A summary of options is included below. -For a complete description, see the Info files. -.TP -.B \-h, \-\-help -Show summary of options. -.TP -.B \-v, \-\-version -Show version of program. -.SH SEE ALSO -.BR bar (1), -.BR baz (1). -.br -The programs are documented fully by -.IR "The Rise and Fall of a Fooish Bar" , -available via the Info system. -.SH AUTHOR -imager was written by . -.PP -This manual page was written by Heiko Schlittermann , -for the Debian project (and may be used by others). diff -r a5d087334439 -r dd11d1262b6c debian/manpage.sgml.ex --- a/debian/manpage.sgml.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ - manpage.1'. You may view - the manual page with: `docbook-to-man manpage.sgml | nroff -man | - less'. A typical entry in a Makefile or Makefile.am is: - -manpage.1: manpage.sgml - docbook-to-man $< > $@ - - - The docbook-to-man binary is found in the docbook-to-man package. - Please remember that if you create the nroff version in one of the - debian/rules file targets (such as build), you will need to include - docbook-to-man in your Build-Depends control field. - - --> - - - FIRSTNAME"> - SURNAME"> - - September 12, 2011"> - - SECTION"> - hs@schlittermann.de"> - - IMAGER"> - - - Debian"> - GNU"> - GPL"> -]> - - - -
- &dhemail; -
- - &dhfirstname; - &dhsurname; - - - 2003 - &dhusername; - - &dhdate; -
- - &dhucpackage; - - &dhsection; - - - &dhpackage; - - program to do something - - - - &dhpackage; - - - - - - - - DESCRIPTION - - This manual page documents briefly the - &dhpackage; and bar - commands. - - This manual page was written for the &debian; distribution - because the original program does not have a manual page. - Instead, it has documentation in the &gnu; - Info format; see below. - - &dhpackage; is a program that... - - - - OPTIONS - - These programs follow the usual &gnu; command line syntax, - with long options starting with two dashes (`-'). A summary of - options is included below. For a complete description, see the - Info files. - - - - - - - - Show summary of options. - - - - - - - - Show version of program. - - - - - - SEE ALSO - - bar (1), baz (1). - - The programs are documented fully by The Rise and - Fall of a Fooish Bar available via the - Info system. - - - AUTHOR - - This manual page was written by &dhusername; &dhemail; for - the &debian; system (and may be used by others). Permission is - granted to copy, distribute and/or modify this document under - the terms of the &gnu; General Public License, Version 2 any - later version published by the Free Software Foundation. - - - On Debian systems, the complete text of the GNU General Public - License can be found in /usr/share/common-licenses/GPL. - - - -
- - diff -r a5d087334439 -r dd11d1262b6c debian/manpage.xml.ex --- a/debian/manpage.xml.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ - -.
will be generated. You may view the -manual page with: nroff -man .
| less'. A typical entry -in a Makefile or Makefile.am is: - -DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl -XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" - -manpage.1: manpage.xml - $(XP) $(DB2MAN) $< - -The xsltproc binary is found in the xsltproc package. The XSL files are in -docbook-xsl. A description of the parameters you can use can be found in the -docbook-xsl-doc-* packages. Please remember that if you create the nroff -version in one of the debian/rules file targets (such as build), you will need -to include xsltproc and docbook-xsl in your Build-Depends control field. -Alternatively use the xmlto command/package. That will also automatically -pull in xsltproc and docbook-xsl. - -Notes for using docbook2x: docbook2x-man does not automatically create the -AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as - ... . - -To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections -read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be -found in the docbook-xsl-doc-html package. - -Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` - -General documentation about man-pages and man-page-formatting: -man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ - ---> - - - - - - - - - - - - - -]> - - - - &dhtitle; - &dhpackage; - - - &dhfirstname; - &dhsurname; - Wrote this manpage for the Debian system. -
- &dhemail; -
-
-
- - 2007 - &dhusername; - - - This manual page was written for the Debian system - (and may be used by others). - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU General Public License, - Version 2 or (at your option) any later version published by - the Free Software Foundation. - On Debian systems, the complete text of the GNU General Public - License can be found in - /usr/share/common-licenses/GPL. - -
- - &dhucpackage; - &dhsection; - - - &dhpackage; - program to do something - - - - &dhpackage; - - - - - - - - - this - - - - - - - - this - that - - - - - &dhpackage; - - - - - - - - - - - - - - - - - - - DESCRIPTION - This manual page documents briefly the - &dhpackage; and bar - commands. - This manual page was written for the Debian distribution - because the original program does not have a manual page. - Instead, it has documentation in the GNU - info - 1 - format; see below. - &dhpackage; is a program that... - - - OPTIONS - The program follows the usual GNU command line syntax, - with long options starting with two dashes (`-'). A summary of - options is included below. For a complete description, see the - - info - 1 - files. - - - - - - - Does this and that. - - - - - - - Show summary of options. - - - - - - - Show version of program. - - - - - - FILES - - - /etc/foo.conf - - The system-wide configuration file to control the - behaviour of &dhpackage;. See - - foo.conf - 5 - for further details. - - - - ${HOME}/.foo.conf - - The per-user configuration file to control the - behaviour of &dhpackage;. See - - foo.conf - 5 - for further details. - - - - - - ENVIONMENT - - - FOO_CONF - - If used, the defined file is used as configuration - file (see also ). - - - - - - DIAGNOSTICS - The following diagnostics may be issued - on stderr: - - - Bad configuration file. Exiting. - - The configuration file seems to contain a broken configuration - line. Use the option, to get more info. - - - - - &dhpackage; provides some return codes, that can - be used in scripts: - - Code - Diagnostic - - 0 - Program exited successfully. - - - 1 - The configuration file seems to be broken. - - - - - - BUGS - The program is currently limited to only work - with the foobar library. - The upstreams BTS can be found - at . - - - SEE ALSO - - - bar - 1 - , - baz - 1 - , - foo.conf - 5 - - The programs are documented fully by The Rise and - Fall of a Fooish Bar available via the - info - 1 - system. - -
- diff -r a5d087334439 -r dd11d1262b6c debian/menu.ex --- a/debian/menu.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -?package(imager):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\ - title="imager" command="/usr/bin/imager" diff -r a5d087334439 -r dd11d1262b6c debian/po/POTFILES.in --- a/debian/po/POTFILES.in Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -[type: gettext/rfc822deb] imager.templates diff -r a5d087334439 -r dd11d1262b6c debian/po/templates.pot --- a/debian/po/templates.pot Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: imager@packages.debian.org\n" -"POT-Creation-Date: 2011-09-16 11:20+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#. Type: boolean -#. Description -#: ../imager.templates:1001 -msgid "local imager found - remove?" -msgstr "" - -#. Type: boolean -#. Description -#: ../imager.templates:1001 -msgid "" -"There seems to exist an old version of the imager in /usr/local/imager. This " -"may interfere with the version we're installing." -msgstr "" diff -r a5d087334439 -r dd11d1262b6c debian/preinst.ex --- a/debian/preinst.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -#!/bin/sh -# preinst script for imager -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `install' -# * `install' -# * `upgrade' -# * `abort-upgrade' -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - install|upgrade) - ;; - - abort-upgrade) - ;; - - *) - echo "preinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff -r a5d087334439 -r dd11d1262b6c debian/prerm.ex --- a/debian/prerm.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#!/bin/sh -# prerm script for imager -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `upgrade' -# * `failed-upgrade' -# * `remove' `in-favour' -# * `deconfigure' `in-favour' -# `removing' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - remove|upgrade|deconfigure) - ;; - - failed-upgrade) - ;; - - *) - echo "prerm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff -r a5d087334439 -r dd11d1262b6c debian/rules --- a/debian/rules Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -export PERL_MB_OPT= -export PERL_MM_OPT= - -%: - dh $@ diff -r a5d087334439 -r dd11d1262b6c debian/source/format --- a/debian/source/format Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -3.0 (native) diff -r a5d087334439 -r dd11d1262b6c debian/source/options --- a/debian/source/options Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -tar-ignore -tar-ignore *.ex -tar-ignore *.EX diff -r a5d087334439 -r dd11d1262b6c debian/watch.ex --- a/debian/watch.ex Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -# Example watch control file for uscan -# Rename this file to "watch" and then you can run the "uscan" command -# to check for upstream updates and more. -# See uscan(1) for format - -# Compulsory line, this is a version 3 file -version=3 - -# Uncomment to examine a Webpage -# -#http://www.example.com/downloads.php imager-(.*)\.tar\.gz - -# Uncomment to examine a Webserver directory -#http://www.example.com/pub/imager-(.*)\.tar\.gz - -# Uncommment to examine a FTP server -#ftp://ftp.example.com/pub/imager-(.*)\.tar\.gz debian uupdate - -# Uncomment to find new files on sourceforge, for devscripts >= 2.9 -# http://sf.net/imager/imager-(.*)\.tar\.gz - -# Uncomment to find new files on GooglePages -# http://example.googlepages.com/foo.html imager-(.*)\.tar\.gz diff -r a5d087334439 -r dd11d1262b6c examples/backup --- a/examples/backup Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -#! /bin/bash -e - -# just a simple(!) example, not intended for production use -# without supervision! - -export TMPDIR=/var/tmp -export LC_ALL=C - -SNAPSIZE=1G -DST=${1?need destination folder} -VG=`hostname` -DEV=/dev/sda1 -NICE= - -NAGIOS_NSCA=nagios.net.schlittermann.de -NAGIOS_HOST=gentoo-chemnitz/wintraken -NAGIOS_SVC=BACKUP -NAGIOS_MSG="failed ($DST)" -NAGIOS_STATUS=2 - - -now=`date +%s` -tmp=`mktemp` -snaps=`mktemp` - -send_nsca() { - /usr/lib/nagios/plugins/send_nsca \ - -H $NAGIOS_NSCA \ - -c /etc/nagios/send_nsca.cfg "$@" -} - - -_lvremove() { - local dev=$1 - local vg=${dev%/*} - local lv=${dev#*/} - - udevadm settle || true - lvremove -f "$dev" || { - dmsetup remove /dev/$vg/$lv \ - && udevadm settle \ - && dmsetup remove /dev/$vg/$lv-cow \ - && udevadm settle \ - && lvremove -f "$dev" || true - } -} - -cleanup() { - - while read lvm dev orig cleanup; do - udevadm settle - test -e "$dev" && test "$cleanup" || continue - eval $cleanup || true - done < $snaps - - rm -f $tmp $snaps - - echo "$NAGIOS_HOST:$NAGIOS_SVC:$NAGIOS_STATUS:$NAGIOS_SVC $NAGIOS_MSG" | send_nsca -d : - -} - -trap cleanup EXIT INT - -for dev in $DEV; do - if mount -o remount,ro $dev; then - echo "- $tmp - rm -fv $tmp" >>$snaps - cp -v $dev $tmp - mount -o remount,rw $dev - file -s $tmp | egrep -q "ext[234] filesystem" && e2fsck -C0 -f -y $tmp || true - imager save --now=$now -z $tmp:$dev $DST - rm -f $tmp - fi -done - - -lvs -o vg_name,lv_name,origin --noheadings $VG | while read vg lv origin; do - # LVM-name DEV-name ORIG-name (cleanup) - - orig="$vg/$lv" - if test "$origin"; then - dev="/dev/$vg/$lv" - echo "$vg/$lv $dev $dev" >>$snaps - continue - fi - snap="$vg/$lv.snap.$now" - dev="/dev/$vg/$lv.snap.$now" - lvcreate -s -L $SNAPSIZE -n "$snap" "$orig" - echo "$snap $dev /dev/$vg/$lv _lvremove $snap" >>$snaps -done - -udevadm settle - -while read snap dev name cleanup; do - test "$snap" = "-" && continue - for a in 1 2 3; do - file -s `readlink -f $dev` | egrep -q "ext[234] filesystem" && $NICE fsck -y "$dev" && break - case $? in - 32) exit;; - *) true;; - esac - done - if test $? = 0; then - $NICE imager save --now=$now -z $dev:$name $DST - case `lvs -o snap_percent --noheadings "$snap"` in - 100*) echo "****************** $snap is full!";; - esac - fi - test "$cleanup" && eval $cleanup || true -done <$snaps -date -date >/var/log/backup.done - -NAGIOS_MSG="done ($DST)" -NAGIOS_STATUS=0 diff -r a5d087334439 -r dd11d1262b6c lib/.perltidyrc --- a/lib/.perltidyrc Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ ---paren-tightness=2 ---square-bracket-tightness=2 diff -r a5d087334439 -r dd11d1262b6c lib/Imager.pm --- a/lib/Imager.pm Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package Imager; -use 5.010; -use strict; -use warnings; -use IO::Uncompress::Gunzip qw(gunzip $GunzipError); -use autodie qw(:all); -use if $^V >= v5.18 => (experimental => 'smartmatch'); - -our $VERSION = "0.1"; - -use constant CIPHER => "aes-128-cbc"; - -sub get_file { - my ($base) = @_; - foreach (map { "$base$_" } "", qw/.gz .x .gz.x/) { - return $_ if -f; - } -} - -sub get_block { - my ($file, $buffer) = @_; - - $file = get_file($1) if $file =~ /(.*)\*$/; - - given ($file) { - when (/\.gz\.x$/) { - open(my $fh => "openssl @{[CIPHER]} -d -pass $::o{pass} -in $file|"); - gunzip($fh => $buffer) or die $GunzipError; - } - when (/\.gz$/) { gunzip($file => $buffer) or die $GunzipError } - when (/\.x$/) { - open(my $fh => "openssl @{[CIPHER]} -d -pass $::o{pass} -in $file|"); - $$buffer = <$fh>; - } - default { open(my $fh => $file); sysread $fh => $$buffer, -s $fh } - } -} - -1; diff -r a5d087334439 -r dd11d1262b6c scratch/x.pl --- a/scratch/x.pl Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -#!/usr/bin/perl -use 5.010; -use strict; -use warnings; -use Crypt::CBC; -use autodie qw(:all); -use Benchmark qw(:all); -use IO::Compress::Gzip qw(gzip $GzipError); -use File::Temp; - -my $tmp = File::Temp->new(); -warn "<< $tmp >>\n"; - -my $cipher0 = Crypt::CBC->new( - -key => "x", - -keysize => 16, - -cipher => 'Blowfish', -) or die; -$ENV{X} = "x"; - -@ARGV = qw(/boot/vmlinuz-2.6.32-5-amd64); -my $text = join "" => <>; - -say length $text; - -cmpthese(30 => { - 'openssl' => sub { openssl($text) }, - 'perlssl' => sub { perlssl($text) }, - } -); - -cmpthese(30 => { - 'gzip' => sub { bingzip($text) }, - 'perlzip' => sub { perlzip($text) }, - } -); - -sub openssl { - open(my $out, "|openssl bf -pass env:X -out $tmp") or die; - print $out $_[0]; - close $out; - die $? if $?; -} - -sub perlssl { - open(my $out, ">$tmp"); - print $out $cipher0->encrypt($_[0]); - close $out; -} - -sub perlzip { - open(my $out, ">$tmp"); - gzip($_[0] => $out); -} - -sub bingzip { - open(my $out, "|gzip -1 >$tmp"); - print $out $_[0]; - close $out; - die $? if $? -} diff -r a5d087334439 -r dd11d1262b6c scratch/y.pl --- a/scratch/y.pl Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -#!/usr/bin/perl -use 5.010; -use strict; -use warnings; -use Crypt::CBC; -use autodie qw(:all); -use Benchmark qw(:all); -use File::Temp; - -my $tmp = File::Temp->new(); - -{ - open(my $fh, "/dev/urandom"); - local $/ = \(my $x = 1024 * 1024); # 1 MiB - for (1 .. 4) { - print {$tmp} scalar <$fh>; - } -} - -sub getbyref { - my $ref = shift; - local $/ = undef; - seek($tmp, 0, 0); - $$ref = <$tmp>; -} - -sub getbyval { - seek($tmp, 0, 0); - local $/ = undef; - return <$tmp>; -} - -cmpthese(900 => { - byref => sub { my $x; getbyref(\$x); $_ = length($x) }, - byval => sub { my $x = getbyval(); $_ = length($x) }, - } -); - - - -__END__ - - - -cmpthese(30 => { - 'openssl' => sub { openssl($text) }, - 'perlssl' => sub { perlssl($text) }, - } -); - -cmpthese(30 => { - 'gzip' => sub { bingzip($text) }, - 'perlzip' => sub { perlzip($text) }, - } -); - -sub openssl { - open(my $out, "|openssl bf -pass env:X -out $tmp") or die; - print $out $_[0]; - close $out; - die $? if $?; -} - -sub perlssl { - open(my $out, ">$tmp"); - print $out $cipher0->encrypt($_[0]); - close $out; -} - -sub perlzip { - open(my $out, ">$tmp"); - gzip($_[0] => $out); -} - -sub bingzip { - open(my $out, "|gzip -1 >$tmp"); - print $out $_[0]; - close $out; - die $? if $? -} diff -r a5d087334439 -r dd11d1262b6c t/000-syntax.t --- a/t/000-syntax.t Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -use 5.010; -use strict; -use warnings; -use Test::More; - -use File::Find; - -my @scripts; -find(sub { /^\./ and return; - push @scripts, $File::Find::name if -f and (-x or /\.pm$/)}, "blib"); - -plan tests => scalar @scripts; - -foreach (@scripts) { - my $e = `perl -Mblib -c $_ 2>&1`; - ok(!$?, "syntax $_ ok") or diag $e; -} diff -r a5d087334439 -r dd11d1262b6c t/001-save-restore.t --- a/t/001-save-restore.t Sat Jul 25 17:16:13 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -use 5.010; -use strict; -use warnings; -use autodie qw(:all); -use Test::More; -use Sys::Hostname; -use if $^V gt v5.18 => (experimental => 'smartmatch'); - -use constant SIZE => 27 * 1024 * 1024; - -use File::Temp; - -my $err = File::Temp->new; -my $dir = File::Temp->newdir; - -note("preparing the source"); -open(my $out, "+>$dir/source"); -print $out rand while -s $out < SIZE; - -note("preparing the images dir"); -mkdir "$dir/images"; -mkdir "$dir/mnt"; - -system("sudo mount -ttmpfs -osize=10M,uid=$> tmpfs $dir/mnt 2>/dev/null"); -END { system("sudo umount $dir/mnt 2>/dev/null") }; - - -system("perl -Mblib blib/script/imager.save $dir/source:source $dir/images"); -is($? => 0, "saved"); - -system("perl -Mblib blib/script/imager.restore $dir/images/idx/@{[hostname]}/source/* $dir/source.restored"); -is($? => 0, "restored"); - -# just as it is -seek($out, 0, 0); -open(my $restored, "$dir/source.restored"); -ok(<$out> ~~ <$restored>, "source === restored"); - -# now compress and check again -system("perl -Mblib blib/script/imager.compress $dir/images 2>$err"); -is($? => 0, "compressed") or do { seek $err => 0, 0; diag <$err> }; -system("perl -Mblib blib/script/imager.restore $dir/images/idx/@{[hostname]}/source/* $dir/source.restored"); -is($? => 0, "restored") or do { seek $err => 0, 0; diag <$err> }; -seek($out, 0, 0); -open($restored, "$dir/source.restored"); -ok(<$out> ~~ <$restored>, "compressed source === restored"); - -# now check on overflow of destination - -note("overflow condition"); -eval { system("perl -Mblib blib/script/imager.save $dir/source:source $dir/mnt 2>$err") }; -ok($?, "failure is expected"); - - -done_testing;