#!/usr/bin/perl -w # compute the blocks used by a file # usage: # computeblocklists [options] # options: # --padstart NUM, --padend NUM, --verbose # # output: # # # a block is either a number or a range (start-end) # # TODO: instead of printing zeroes for each block in a hole use # something like 0*num use strict; my ($opt_padstart, $opt_padend, $opt_verbose); while (@ARGV) { if ($ARGV[0] eq '--padstart') { shift @ARGV; $opt_padstart = shift @ARGV; next; } if ($ARGV[0] eq '--padend') { shift @ARGV; $opt_padend = shift @ARGV; next; } if ($ARGV[0] eq '--verbose' || $ARGV[0] eq '-v') { shift @ARGV; $opt_verbose = 1; next; } last; } if($opt_padstart) { print "\n"x$opt_padstart; } for my $file (@ARGV) { next unless -f $file; print STDERR "$file\n" if $opt_verbose; my $n = $file; $n =~ s/.*\///; if(!open(F, '<', $file)) { print STDERR "$file: $!"; next; } my $bsize = 'xxxx'; ioctl(F, 2, $bsize) || ioctl(F, 536870914, $bsize) || die("FIGETBSZ: $!\n"); $bsize = unpack("L", $bsize); my @stat = stat(F); my ($st_size, $st_blocks) = ($stat[7], $stat[11], $stat[12]); my $blocks = int(($st_size+$bsize-1)/$bsize); print "$n $st_size $bsize "; my ($firstblock, $lastblock); for ($b = 0; $b < $blocks; ++$b) { my $block = pack('I', $b); if(not defined ioctl(F, 1, $block)) { if(not defined ioctl(F, 536870913, $block)) { die "$file: $!"; } } $block = unpack('I', $block); if($b == 0) { print "$block"; $firstblock = $block; } else { # blocks are non-contiguous if($lastblock+1 != $block) { # check if we skipped some that form a range if($firstblock != $lastblock) { printf "-$lastblock"; } print " $block"; $firstblock = $block; } # last block, check if contiguous if($b+1==$blocks && $lastblock+1 == $block) { print "-$block"; } } $lastblock = $block; } close F; print "\n"; } if($opt_padend) { print "\n"x$opt_padend; }