forked from openSUSE/obs-build
-
Notifications
You must be signed in to change notification settings - Fork 1
/
extractbuild
executable file
·101 lines (90 loc) · 2.29 KB
/
extractbuild
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
96
97
98
99
100
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;
}