summaryrefslogtreecommitdiff
path: root/extractbuild
diff options
context:
space:
mode:
authorZhang Qiang <qiang.z.zhang@intel.com>2014-04-03 15:53:09 +0800
committerZhang Qiang <qiang.z.zhang@intel.com>2014-04-03 15:53:09 +0800
commitb979ae3b9b879ce19582770e2ba89eb3e66f964a (patch)
tree758e7684bbaa43d8899ccbc49b133ff0112d3a88 /extractbuild
downloadbuild-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-xextractbuild101
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;
+}