#!/usr/bin/perl -w

use strict;
use English;

my ($fn,$pkg);
my (%old,%new);
my $root=$ARGV[0];

if ( (not defined $root) or (! -d $root) ) {
	print "Usage: $0 root-dir tar-file [ tar-file [ ... ] ]\n\n";
	print "Warning: You shouldn't update packages on a running\n";
	print "System unless you _really_ know what you are doing!\n\n";
	exit 1;
}

shift @ARGV;

foreach $fn (@ARGV) {
	if (! -f $fn) {
		print "No such file: '$fn' - skipping.\n"; next;
	}
	print "Processing file $fn:\n";
	system("rm -rf /tmp/pkg-upd.$$ ; mkdir -p /tmp/pkg-upd.$$");
	system("tar xIf $fn -C /tmp/pkg-upd.$$ var/adm");
	$pkg=""; open(F,"ls /tmp/pkg-upd.$$/var/adm/packages |") || die $!;
	while (<F>) { chomp; $pkg=$_; }  close F;
	if ($pkg eq '') { print "  Not a package file!\n"; next; }
	if (! -f "$root/var/adm/packages/$pkg") {
		print "  Package $pkg isn't installed -> install.\n";
		system("tar xIf $fn -C $root --same-owner --same-permissions");
		next;
	}
	print "  Package $pkg is installed -> update.\n";

	%old=(); open(F,"$root/var/adm/flists/$pkg") || die $!;
	while (<F>) { chomp; /(\S*)\s*(\S*)/; $old{$2}="NO-FILE"; }  close F;
	open(F,"$root/var/adm/md5sums/$pkg") || die $!;
	while (<F>) { chomp; /(\S*)\s*(\S*)/; $old{$2}=$1; }  close F;

	%new=(); open(F,"/tmp/pkg-upd.$$/var/adm/flists/$pkg") || die $!;
	while (<F>) { chomp; /(\S*)\s*(\S*)/; $new{$2}="NO-FILE"; }  close F;
	open(F,"/tmp/pkg-upd.$$/var/adm/md5sums/$pkg") || die $!;
	while (<F>) { chomp; /(\S*)\s*(\S*)/; $new{$2}=$1; }  close F;

	system("rm -rf /tmp/pkg-upd.$$/*.lst");
	open(UPD,">/tmp/pkg-upd.$$/upd.lst") || die $!;
	open(RMF,">/tmp/pkg-upd.$$/rmf.lst") || die $!;
	open(RMD,">/tmp/pkg-upd.$$/rmd.lst") || die $!;

	foreach (sort keys %new) {
		if ( ($old{$_} eq 'NO-FILE') or
		     ( (defined $new{$_}) and ($new{$_} eq 'NO-FILE') ) ) {
			print UPD "$_\n";
			print RMD "$root/$_\n";
			print RMF "$root/$_\n";
			s,/[^/]*$,,; print RMD "$root/$_\n";
		} elsif ( (not defined $old{$_}) or
		     ($old{$_} ne $new{$_}) ) {
			print UPD "$_\n";
		}
	}

	foreach (sort keys %old) {
		if (not defined $new{$_}) {
			print RMD "$root/$_\n";
			print RMF "$root/$_\n";
			s,/[^/]*$,,; print RMD "$root/$_\n";
		}
	}

	print UPD "var/adm\n";  close UPD; close RMF; close RMD;
	# print "UPD:\n"; system("cat /tmp/pkg-upd.$$/upd.lst");
	# print "RMF:\n"; system("cat /tmp/pkg-upd.$$/rmf.lst");
	# print "RMD:\n"; system("cat /tmp/pkg-upd.$$/rmd.lst");

	system("xargs rm -f 2>/dev/null < /tmp/pkg-upd.$$/rmf.lst");
	system("xargs rmdir -p 2>/dev/null < /tmp/pkg-upd.$$/rmd.lst");
	system("bunzip2 < $fn | ( cd $root ; tar xf - --same-owner ".
	       "--same-permissions --files-from=/tmp/pkg-upd.$$/upd.lst ; )");
}

system("rm -rf /tmp/pkg-upd.$$");

open(F,"> $root/tmp/$$.tmp");
if ($root ne "/") {
	print F "export CHROOT_GOAL=\"$root\"\n";
	print F ". /etc/profile ; echo\n";
	foreach (sort <$root/etc/setup.d/*>)
		{ s/^$root//; print F "$_ update\n"; }
	print F "umount /dev /proc\n"; close F;
	system("cd $root ; chroot . bin/sh /tmp/$$.tmp");
} else {
	foreach (sort </etc/setup.d/*>) { print F "$_ update\n"; }
	close F; system("cd / ; sh /tmp/$$.tmp");
}

system("rm -f $root/tmp/$$.tmp");
