diff options
author | Zhang Qiang <qiang.z.zhang@intel.com> | 2014-04-03 15:53:09 +0800 |
---|---|---|
committer | Zhang Qiang <qiang.z.zhang@intel.com> | 2014-04-03 15:53:09 +0800 |
commit | b979ae3b9b879ce19582770e2ba89eb3e66f964a (patch) | |
tree | 758e7684bbaa43d8899ccbc49b133ff0112d3a88 /extractbuild | |
download | build-b979ae3b9b879ce19582770e2ba89eb3e66f964a.tar.gz build-b979ae3b9b879ce19582770e2ba89eb3e66f964a.tar.bz2 build-b979ae3b9b879ce19582770e2ba89eb3e66f964a.zip |
Imported Upstream version 2013.11.12upstream/2013.11.12
Diffstat (limited to 'extractbuild')
-rwxr-xr-x | extractbuild | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/extractbuild b/extractbuild new file mode 100755 index 0000000..f46ffc1 --- /dev/null +++ b/extractbuild @@ -0,0 +1,101 @@ +#!/usr/bin/perl -w + +use strict; + +# buffer size for reading +my $bufsize = 4*1024*1024; + +my ($opt_skip, $opt_disk, $opt_input, $opt_verbose); + +while (@ARGV) { + if ($ARGV[0] eq '--skip') { + shift @ARGV; + $opt_skip = shift @ARGV; + next; + } + if ($ARGV[0] eq '--disk') { + shift @ARGV; + $opt_disk = shift @ARGV; + next; + } + if ($ARGV[0] eq '--input') { + shift @ARGV; + $opt_input = shift @ARGV; + next; + } + if ($ARGV[0] eq '--verbose' || $ARGV[0] eq '-v') { + shift @ARGV; + $opt_verbose = 1; + next; + } + last; +} + +die "need to specify disk image\n" unless $opt_disk; + +open(F, '<', $opt_disk) || die "$opt_disk: $!\n"; + +if($opt_input) { + open(S, '<', $opt_input) || die "$opt_input: $!\n"; +} else { + open(S, '<&STDIN') || die "can't dup stdin: $!\n"; +} + +# skip build status +if($opt_skip) { + seek(S, $opt_skip, 0) || die "$!\n"; +} + +while(<S>) { + chomp; + last unless length $_; + my ($file, $filesize, $blksize, @blocks) = split(/ /); + if($#blocks == -1 && $filesize) { + die "invalid input '$_'\n"; + } + $filesize = int($filesize); + $blksize = int($blksize); + die "invalid block size" unless ($blksize > 0 && $blksize <= $bufsize); + my $maxblocks = int($bufsize/$blksize); + $file =~ s/.*\///; # ensure basename, also stops directory traversal + $file =~ s/[^[:print:]]/_/g; # no binary junk in file names + print "$file\n" if $opt_verbose; + open (O, '>', $file) or die "$file: $!"; + for my $block (@blocks) { + my ($block, $end) = split(/-/, $block); + $block = int($block); + + if($block == 0) { # a hole! + seek(O, $blksize, 1); + $filesize -= $blksize; + next; + } + + $end = $block unless $end; + $end = int($end); + seek(F, $block*$blksize, 0) || die "$file: seek: $!\n"; + while($block <= $end && $filesize) { + my $size; + if($end == $block) { + $size = $blksize; + ++$block; + } elsif($maxblocks >= $end-$block) { + $size = ($end-$block)*$blksize; + $block += $end-$block; + } else { + $size = $maxblocks*$blksize; + $block += $maxblocks; + } + $size = $filesize if $size > $filesize; + my $buf; + if((sysread(F, $buf, $size) || 0) != $size) { + die "$file: read: $!\n"; + } + $filesize -= $size; + print O $buf; + } + } + close O; + # sanity check + die "$file: invalid file size ($filesize byes left)\n" if $filesize != 0; +} |