#!/usr/bin/perl 

use File::Spec;
use File::Basename;
use File::Path;
use strict;
use warnings;

@ARGV == 1 || die "usage: $0 executable\n";

{
    my ($exe) = @ARGV;
    open my $fh, '<', $exe or die qq[failed to open "$exe": $!];
    binmode $fh;

    # search for the "\nPAR.pm\n signature backward from the end of the file
    my $buf;
    my $size = -s $exe;
    my $offset = 512;
    my $idx = -1;
    while (1)
    {
        $offset = $size if $offset > $size;
        seek $fh, -$offset, 2 or die qq[seek failed on "$exe": $!];
        my $nread = read $fh, $buf, $offset;
        die qq[read failed on "$exe": $!] unless $nread == $offset;
        $idx = rindex($buf, "\nPAR.pm\n");
        last if $idx >= 0 || $offset == $size || $offset > 128 * 1024;
        $offset *= 2;
    }
    die qq[no PAR signature found in "$exe"] unless $idx >= 0;

    # seek 4 bytes backward from the signature to get the offset of the 
    # first embedded FILE, then seek to it
    $offset -= $idx - 4;
    seek $fh, -$offset, 2;
    read $fh, $buf, 4;
    seek $fh, -$offset - unpack("N", $buf), 2;

    my $FILES_offset = tell $fh;
    printf qq[embedded FILEs start at offset %d\n], $FILES_offset;

    read $fh, $buf, 4;
    while ($buf eq "FILE") 
    {
        read $fh, $buf, 4;
        seek $fh, unpack("N", $buf), 1;

        read $fh, $buf, 4;
        seek $fh, unpack("N", $buf), 1;

        read $fh, $buf, 4;
    }
    die qq[no zip found after FILEs in "$exe"] unless $buf eq "PK\003\004";

    my $ZIP_offset = tell($fh) - 4;
    printf qq[zip starts at offset %d\n], $ZIP_offset;
    printf qq[size of FILEs section is %d\n], $ZIP_offset - $FILES_offset;

    close $fh;
}
