#!/usr/bin/perl -w
#
# make disk image from folder
#
# usage: makedmg src dst name
#
# Donated by Frank Vercruesse


$hdiUtilExec = "/usr/bin/hdiutil";
$hdiDrvExec = "/usr/bin/hdid";
$newfsExec = "/sbin/newfs_hfs";
$duExec = "/usr/bin/du";
$dittoExec = "/usr/bin/ditto";

if ( $#ARGV != 2 ) {
	die "Wrong number of arguments.\nUsage: makedmg src dst name\n";
}

&make_dmg( $ARGV[0], $ARGV[1], $ARGV[2]);


sub make_dmg
{
	my $src = $_[0];
	my $dst = $_[1];
	my $name = $_[2];

	# check dirs
	if( not -d $dst && -d $src ) {
		die "src and dst must be directories\n";
	}

	# calc disk image size
	if( not open( MYPIPE, "$duExec -sk \"${src}\" |") ) {
		die "couldn't open pipe\n";
	}
	(my $dmgsize) = split( /\s+/, <MYPIPE>);
	close( MYPIPE);
	$dmgsize /= 1024;
	$dmgsize = int($dmgsize + 4);
	if( $dmgsize < 5 ) {
		$dmgsize = 5
	}

	# create disk image
	system "cd \"$dst\"; $hdiUtilExec create -megabytes $dmgsize -ov \"_${name}\"";
	if( $? ) { die "couldn't create disk image\n"; }

	# format disk image
	if( not open( MYPIPE, "cd \"$dst\"; $hdiDrvExec -nomount \"_${name}.dmg\" |") ) {
		die "couldn't open pipe\n";
	}
	(my $dev) = split( /\t/, <MYPIPE>);
	$dev =~ s/^(.*\S)\s*$/$1/;
	my( $part, $raw, $pname);
	while( <MYPIPE> ) {
		($part,$pname) = split /\t/;
		if( $pname =~ m/^Apple_HFS/ ) {
			$part =~ s/^\s*(.*\S)\s*$/$1/;
			$raw = $part;
			$raw =~ s/^(\/dev\/)(.+)/$1r$2/;
			last;
		}
	}
	close( MYPIPE);
	system "cd \"$dst\" ; $newfsExec -v \"$name\" $raw";
	if( $? ) { system "$hdiUtilExec eject $dev"; die "couldn't format disk image\n"; }
	system "$hdiUtilExec eject $dev";
	if( $? ) { die "couldn't eject disk image\n"; }

	# copy files
	if( not open( MYPIPE, "cd \"$dst\"; $hdiDrvExec \"_${name}.dmg\" |") ) {
		die "couldn't open pipe\n";
	}
	($dev) = split( /\t/, <MYPIPE>);
	$dev =~ s/^(.*\S)\s*$/$1/;
	my $vname;
	while( <MYPIPE> ) {
		($part,$pname,$vname) = split /\t/;
		if( $pname =~ m/^Apple_HFS/ ) {
			$vname =~ s/^(.*\S)\s*$/$1/;
			last;
		}
	}
	close( MYPIPE);
	system "$dittoExec \"${src}\" \"${vname}\"";
	if( $? ) { system "$hdiUtilExec eject $dev"; die "couldn't copy files\n"; }
	system "$hdiUtilExec eject $dev";
	if( $? ) { die "couldn't eject disk image\n"; }

	# convert disk image
	system "cd \"$dst\"; $hdiUtilExec convert \"_${name}.dmg\" -format UDCO -o \"${name}\"";
	if( $? ) { die "couldn't convert disk image\n"; }
}
