- support tilde in rpm version comparison
[platform/upstream/build.git] / extractbuild
1 #!/usr/bin/perl -w
2
3 use strict;
4
5 # buffer size for reading
6 my $bufsize = 4*1024*1024;
7
8 my ($opt_skip, $opt_disk, $opt_input, $opt_verbose);
9
10 while (@ARGV)  {
11   if ($ARGV[0] eq '--skip') {
12     shift @ARGV;
13     $opt_skip = shift @ARGV;
14     next;
15   }
16   if ($ARGV[0] eq '--disk') {
17     shift @ARGV;
18     $opt_disk = shift @ARGV;
19     next;
20   }
21   if ($ARGV[0] eq '--input') {
22     shift @ARGV;
23     $opt_input = shift @ARGV;
24     next;
25   }
26   if ($ARGV[0] eq '--verbose' || $ARGV[0] eq '-v') {
27     shift @ARGV;
28     $opt_verbose = 1;
29     next;
30   }
31   last;
32 }
33
34 die "need to specify disk image\n" unless $opt_disk;
35
36 open(F, '<', $opt_disk) || die "$opt_disk: $!\n";
37
38 if($opt_input) {
39   open(S, '<', $opt_input) || die "$opt_input: $!\n";
40 } else {
41   open(S, '<&STDIN') || die "can't dup stdin: $!\n";
42 }
43
44 # skip build status
45 if($opt_skip) {
46   seek(S, $opt_skip, 0) || die "$!\n";
47 }
48
49 while(<S>) {
50   chomp;
51   last unless length $_;
52   my ($file, $filesize, $blksize, @blocks) = split(/ /);
53   if($#blocks == -1 && $filesize) {
54     die "invalid input '$_'\n";
55   }
56   $filesize = int($filesize);
57   $blksize = int($blksize);
58   die "invalid block size" unless ($blksize > 0 && $blksize <= $bufsize);
59   my $maxblocks = int($bufsize/$blksize);
60   $file =~ s/.*\///; # ensure basename, also stops directory traversal
61   $file =~ s/[^[:print:]]/_/g; # no binary junk in file names
62   print "$file\n" if $opt_verbose;
63   open (O, '>', $file) or die "$file: $!";
64   for my $block (@blocks) {
65     my ($block, $end) = split(/-/, $block);
66     $block = int($block);
67
68     if($block == 0) { # a hole!
69       seek(O, $blksize, 1);
70       $filesize -= $blksize;
71       next;
72     }
73
74     $end = $block unless $end;
75     $end = int($end);
76     seek(F, $block*$blksize, 0) || die "$file: seek: $!\n";
77     while($block <= $end && $filesize) {
78       my $size;
79       if($end == $block) {
80         $size = $blksize;
81         ++$block;
82       } elsif($maxblocks >= $end-$block) {
83         $size = ($end-$block)*$blksize;
84         $block += $end-$block;
85       } else {
86         $size = $maxblocks*$blksize;
87         $block += $maxblocks;
88       }
89       $size = $filesize if $size > $filesize;
90       my $buf;
91       if((sysread(F, $buf, $size) || 0) != $size) {
92         die "$file: read: $!\n";
93       }
94       $filesize -= $size;
95       print O $buf;
96     }
97   }
98   close O;
99   # sanity check
100   die "$file: invalid file size ($filesize byes left)\n" if $filesize != 0;
101 }