#!/usr/bin/perl -w
# $Id: deb2targz,v 1.1 2002/12/17 11:57:54 mike Exp $

# deb2targz - convert a Debian Linux .deb file to a .tar.gz
#
# This is a hack based only on my eyeball inspection of a single .deb
# file (scottfree_1.14-5_i386.deb) and not on a deep understanding of
# the format.  However, so far as I can tell, here's how it works:
#
# First line -- file header: "!<arch>" or similar
# Multiple blocks -- each one, a header line followed by data
#	Header line -- <filename> <num1> <num2> <num3> <mode> <len>
#	Data -- <len> bytes of data
# We want the block called "data.tar.gz"
#
# This naive algorithm seems to work on the other .deb files that I've
# tested it on, so I'm happy enough with it:
#	libapache-reload-perl_0.07-1_all.deb
#	libogg0_1.0.0-1_i386.deb
#	abiword_1.0.2+cvs.2002.06.05-1_i386.deb

use strict;
use IO::File;

$0 =~ s@.*/@@;
if (@ARGV == 0) {
    print STDERR "Usage: $0 <deb-file> [<deb-file> ...]\n";
    exit(1);
}

FILE: foreach my $filename (@ARGV) {
    if ($filename !~ /\.deb$/) {
	print "$0: ignoring '$filename' (not a .deb)\n";
	next;
    }

    print "$0: converting '$filename' ...\n";
    my $fh = new IO::File("<$filename")
	or die "$0: can't read '$filename': $!";

    <$fh>;			# discard file-header line
    my $data = join('', <$fh>);
    $fh->close();

    while ($data) {
	my $header;
	($header, $data) = ($data =~ /(.*?)\n(.*)/s);
	my($name, $num1, $num2, $num3, $num4, $len) = split /\s+/, $header;
	#print "header='$header'\n\tname='$name', len=$len\n";
	if ($name eq "data.tar.gz") {
	    # Found it
	    $data = substr($data, 0, $len);
	    $filename =~ s/\.deb$/.tar.gz/;
	    my $fh = new IO::File(">$filename")
		or die "can't write '$filename': $!";
	    print $fh $data;
	    $fh->close();
	    print "$0: wrote '$filename'\n";
	    next FILE;
	}

	print "$0: skipping section '$name'\n";
	if (substr($data, $len, 1) eq "\n") {
	    $len++;
	}
	$data = substr($data, $len);
    }
}