#!/opt/bin/perl use Compress::LZF; my $verbose = 1; my $exe_id = shift; my $exe_ver = shift; my $dir = shift; my $size; my $max; sub ent { my ($type, $flags, $name, $data) = @_; warn "add record type $type, path $name\n" if $verbose >= 2; my $ent = pack "CCnN Z* a*", $type, $flags, (length $name), (length $data), $name, $data; print $ent; $size += length $ent; } sub scandir { my ($path, $pfx) = @_; $pfx =~ s%^/%%; opendir my $fh, $path or die "$path: $!"; for my $file (sort readdir $fh) { next if $file eq "." || $file eq ".."; lstat "$path/$file" or die "$path/$file: $!"; if (-d _) { ent 4, 0, "$pfx$file"; &scandir ("$path/$file", "$pfx$file/"); } elsif (-f _) { my $len = -s _; $max = $len if $max < $len; open my $fh2, "<", "$path/$file" or die "$path/$file: $!"; $len == sysread $fh2, my $data, $len or die "$path/$file: read error"; my $flags = (-x _) ? 0x10 : 0; my $comp = Compress::LZF::compress $data; $comp =~ s/^(?:[\x00-\x7f]|[\x80-\xff]+)//; # remove length prefix if ($len > 1 + length $comp) { $flags |= 0x01; $data = $comp; } ent 5, $flags, "$pfx$file", $data; } else { warn "$path/$file: unsupported filetype, skipping.\n"; } } } ent 1, 0, $exe_id, "$exe_ver\x00"; shift, ent 2, 0, $1, "$2\x00" while $ARGV[0] =~ /^([^=]+)=(.*)$/s; ent 3, 0, shift while @ARGV; scandir $dir, ""; ent 0, 0; print pack "NN a12", $max, $size + 20, # sizeof this pack, sorry... "SCHMORPPACK0"; printf STDERR "%d bytes written, biggest single file is %d bytes.\n", $size, $max if $verbose;