mjd-perl-pm on Tue, 10 Dec 2002 00:42:25 -0500


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

How to tell if a file is sparse



Typical run:

      perl dumpbitmap.pl  sparse dumpbitmap.pl   testfile 

Typical output:

        Configurator ran OK; FIBMAP is 1; BLOCK_SIZE is 4096
        sparse: *.........................................................................................................................................................................................................................................................*
        dumpbitmap.pl: *
        testfile: ****

This means that 'sparse' is many blocks long, but only the first and
last blocks are actually allocated; the intervening blocks are holes.
'dumpbitmap.pl' itseld is one block long, and 'testfile' contains four
blocks, all of which are allocated.

The code follows.  To run it, you must be root.  It should be clear
how to write an equivalent C program.  In fact, the C program would
probably be shorter.

Perhaps someone on the PLUG list could forward this there, if they
thought it would be of interest to the PLUG folks.

################################################################

configure();

for (@ARGV) {
  my $bm = bitmap($_);
  print "$_: $bm\n";
}

sub bitmap {
  my $result = "";
  for (blockmap(@_)) {
    $result .= $_ ? "*" : ".";
  }
  $result;
}

sub blockmap {
  my @res;
  my $f = shift;
  unless (open F, "<", $f) {
    warn "Couldn't open file '$f': $!; skipping\n";
    next;
  }
  my $extent = -s F;
  for (0 .. int(($extent-1)/$BLOCK_SIZE)) {
    my $absblock = block_no(\*F, $_);
    push @res, $absblock;
  }
  @res;
}

sub block_no {
  my ($fh, $ibn) = @_;
  my $arg = pack "I", $ibn;
  ioctl $fh, $FIBMAP, $arg or die "ioctl failed: $!";
  unpack "I", $arg;
}

sub configure {
  unless (eval {require "fibmap.ph"}) {
    open C, "> fibmap.c" or die "Couldn't write configurator: $!; aborting";
    print C while <DATA>;
    close C;
    system("cc -o fibmap fibmap.c") == 0 or die "Couldn't run C compiler.\n";
    system("./fibmap > fibmap.ph") == 0 or die "Couldn't run configurator.\n";
    unless (eval {require "fibmap.ph"}) {
      die "Couldn't load configurator: $@.\n";
    }
    unlink "fibmap", "fibmap.c";
  }
  ioctl(\*DATA, $FIGETBSZ, my $arg)
    or die "Couldn't get block size: $!";
  $BLOCK_SIZE = unpack "I", $arg;
  print "Configurator ran OK; FIBMAP is $FIBMAP; BLOCK_SIZE is $BLOCK_SIZE\n";
}

__DATA__
#include <stdio.h>
#include <linux/fs.h>

int main(void)
{
  printf("$FIBMAP = %d;\n", FIBMAP);
  printf("$FIGETBSZ = %d;\n1;\n", FIGETBSZ);
  return 0;
}

-
**Majordomo list services provided by PANIX <URL:http://www.panix.com>**
**To Unsubscribe, send "unsubscribe phl" to majordomo@lists.pm.org**