#!/usr/bin/perl -w use strict; $|=1; for my $f (@ARGV){ my @res = (); my $i; open($i,$f) or die "cant open '$f': $!"; my $base = $f; $base =~ s/\.stuff$//; $base .= "/"; my $d; die "short read" unless sysread($i,$d,4) == 4; my ($cnt, ) = unpack("I1", $d); printf "RESCNT: %i\n", $cnt; for my $res (1..$cnt) { printf "RES(%i): ", $res; die "short read" unless sysread($i,$d,8) == 8; my ($rd, $rn,) = unpack("I2", $d); printf "%i byte data, %i byte name", $rd, $rn; die "name too long" if $rn > 1000; die "short read" unless sysread($i,$d,$rn+1) == $rn+1; my ($nn,) = unpack("Z*", $d); printf ", name '%s'\n", $nn; my $fn = $base.$nn; $fn =~ s,[\\/]+,/,g; push @res, [$rd, $nn, $fn,]; } die "internal error" unless scalar(@res) == $cnt; seek($i, 0, 1); my $idxend = tell($i); printf "IDXEND: %i\n", $idxend; my $sum = 0; for (@res) { my ($rd, $nn, $fn,) = @$_; $sum += $rd; die "bad name: $fn" unless $fn =~ /[-\w\/]\/[-+.\w \[\]]+\.\w+$/; my $dn = $fn; $dn =~ s,/[^/]+$,/,; &mkdirs($dn); my $d; die "short read" unless sysread($i,$d,$rd) == $rd; open OF, ">", $fn; print OF $d; close OF; } printf "SUMDATA: %i\n", $sum; } my %havedir; sub mkdirs ($) { my ($dir,) = @_; $dir =~ s,/$,,g; return unless $dir; return if $havedir{$dir}; if (-d $dir) { $havedir{$dir}++; return; } my $pdir = $dir; if ($pdir =~ s,/[^/]+$,,) { &mkdirs($pdir); } printf "MKDIRS: %s\n", $dir; mkdir $dir or die "cant mkdir($dir): $!"; $havedir{$dir}++; }