- 论坛徽章:
- 0
|
刚学习perl
这个代码: printf "#d dd of=\$origin seek=%.0f if=\$cow iflag=direct skip=%.0f count=%u bs=%ub\n",
$old, $new, $merge_count, $header->{chunk_size};
为什么只能运行打印出来,不执行运行呢
./dm /dev/sdb
\$origin \$cow 不赋予变量真实的值
谢谢
完整代码如下:- #!/usr/bin/perl
- use Fcntl qw(:DEFAULT O_DIRECT);
- use strict;
- use warnings;
- my $file = $ARGV[0] or die "usage: $0 <input device or file>\n";
- # max exception chunk size apears to be 512k
- # we need an aligned buffer for O_DIRECT.
- # dirty trick to get a PAGE_ALIGNed buffer in perl
- # be _very_ careful with $buf, do not touch it,
- # and do not assign to it, not even implicitly!
- my $bufsize = 512*1024;
- my $align = 4096;
- my $buf = "x" x ($bufsize + $align);
- my $offset = $align - (unpack "l", pack "p", $buf) % $align;
- my $header = { magic => 0, valid => 0, version => 0, chunk_size => 0, };
- sysopen(IN, $file, O_RDONLY | O_DIRECT) or die "sysopen($file, O_DIRECT): $!\n";
- sub read_header()
- {
- my $c = sysread(IN, $buf, 512, $offset);
- die "problem reading header, \$c: $c, \$!: $!"
- if ($c != 512);
- <at> {$header}{qw(magic valid version chunk_size)} =
- unpack "A4VVV", substr($buf, $offset, 512);
- die "does not appear to be a lvm-snapshot-cow device"
- if $header->{magic} ne 'SnAp';
- die "cannot deal with this snapshot version"
- if $header->{version} != 1;
- die "snapshot is invalid, refusing to operate on it"
- unless $header->{valid};
- die "unexpected chunk size"
- if ($header->{chunk_size} & ($header->{chunk_size}-1)) != 0;
- printf "# found snapshot header for chunk_size=%u sectors\n", $header->{chunk_size};
- }
- sub seek_to_exception_table($)
- {
- my $n = $_[0];
- my $cs = $header->{chunk_size} * 512;
- my $epc = $cs / 16;
- my $pos = ($n*($epc+1)+1)*$cs;
- sysseek(IN, $pos, 0) == $pos
- or die "sysseek(,$pos,): $!";
- }
- sub process_one_exception
- {
- my ($old,$new,$merge_count) = <at> _;
- # chunk numbers!
- # old: logical chunk number
- # new: chunk number in exception store
- # merge count: how many chunks could be merged
- # with these start sectors
- # chunk number mapping
- # printf "#c %20.0f\t%20.0f\t%u\n", $old, $new, $merge_count;
- # for sectors you'd have to multiply with $header->{chunk_size};
- # dd command line
- # if you dare,
- # you can do it in perl directly!
- # or implement it in C using pread/pwrite.
- printf "#d dd of=\$origin seek=%.0f if=\$cow iflag=direct skip=%.0f count=%u bs=%ub\n",
- $old, $new, $merge_count, $header->{chunk_size};
-
- }
- sub list_exceptions()
- {
- my $cs = 512*$header->{chunk_size};
- my $enr = 0;
- my $ecount = 0;
- my $e;
- my <at> t;
- EXCEPTION_CHUNK:
- for ($enr = 0; seek_to_exception_table($enr); $enr++) {
- my $c = sysread(IN, $buf, $cs, $offset);
- die "problem reading exception table, \$c: $c, \$!: $!"
- if ($c != $cs);
- <at> t = unpack "V*", substr($buf, $offset, $cs);
- for (my $i = 0; $i < <at> t; $i += 4) {
- # if the "new" location is equal to zero,
- # that was the END marker.
- last EXCEPTION_CHUNK unless $t[$i+2] || $t[$i+3];
- $ecount++;
- # unfortunately 64bit integer is not available
- # in many perl. we compensate:
- my ($old,$new) = (
- $t[$i+1] * 4294967296.0 + $t[$i],
- $t[$i+3] * 4294967296.0 + $t[$i+2]);
- # maybe we can merge?
- if ($e and
- $old == $e->[0] + $e->[2] and
- $new == $e->[1] + $e->[2])
- {
- $e->[2]++;
- next;
- }
- process_one_exception( <at> $e) if $e;
- $e = [ $old, $new, 1]
- }
- process_one_exception( <at> $e);
- # would not work anyways, $new mapping jumps, but lets
- # _explicitly_ only merge within one exception table chunk
- undef $e;
- }
- # don't forget to report the last mapping
- process_one_exception( <at> $e) if $e;
- printf "# found %.0f exceptions (%.0f kB)\n",
- $ecount, $ecount*$header->{chunk_size}/2;
- print "## use these dd commands AT YOUR OWN RISK\n" if $ecount;
- }
- read_header;
- list_exceptions;
复制代码 |
|