#!/usr/athena/bin/perl

@disks = ("wd0");

# Find out what devices are in the existing fstab and where they are mounted.
open(FSTAB, "/etc/fstab") || die "Can't open /etc/fstab";
while (<FSTAB>) {
    if (/^#/) {
	next;
    }
    if (/^(\S+)\s+(\S+)\s/) {
	$fstab{$1} = $2;
	print STDOUT "$1 $2\n";
    }
}
close(FSTAB);

print STDOUT "here1\n";

# Get fdisk information for each disk.  $fdisk{$disk} maps partition
# numbers (0, 1, 2, 3) to lists of (id, offset, size).
foreach $disk (@disks) {
    open(FDISK, "fdisk /dev/r${disk}d 2>&1 |") || die;
    while (<FDISK>) {
	if (/^The data for partition (\d) is:$/) {
	    $n = $1;
	    $_ = <FDISK> || die "Bad fdisk output";
	    if (/^<UNUSED>$/) {
		next;
	    }
	    /^sysid (\d+)/ || die "Bad fdisk output";
	    $id = $1;
	    $_ = <FDISK> || die "Bad fdisk output";
	    /start (\d+), size (\d+)/ || die "Bad fdisk output";
	    $fdisk{$disk}->{$n} = [$id, $1, $2];
	    print STDOUT "$id $1 $2\n";
	}
    }
    close(FDISK);
}

print STDOUT "here2\n";

# Get disklabel information for each disk.  $disklabel maps partition
# letters (a, b, ...) to lists of (type, offset, size)
foreach $disk (@disks) {
    open(DISKLABEL, "disklabel $disk 2>&1 |") || die;
    while (<DISKLABEL>) {
	if (/^  (.):\s+(\d+)\s+(\d+)\s+(\S+)/) {
	    $disklabel{$disk}->{$1} = [$4, $3, $2];
	    print STDOUT "$1 $2 $3 $4\n";
	}
    }
    close(DISKLABEL);
}

print STDOUT "here3\n";

# Find DOS partitions, possibly adding them to disklabels.  Make an
# array @devices containing the devices of DOS partitions we find.
foreach $disk (@disks) {
    if ($disklabel{$disk}->{"a"} || $disklabel{$disk}->{"c"}) {
	# This disk has a NetBSD partition, so DOS partitions must
	# be added to the disklabel.  Scan the fdisk for DOS
	# partitions not in the disklabel.
	$mbrparts = $fdisk{$disk};
	foreach $mbrpart (values(%$mbrparts)) {
	    $type = $mbrpart->[0];
	    $offset = $mbrpart->[1];
	    $size = $mbrpart->[2];
	    if ($type == 1 || $type == 4 || $type == 6 ||
		$type == 14) {
		# Its a DOS partition.  See if we already have it.
		$found = 0; 
		$label = $disklabel{$disk};
		foreach $dpart (values(%$label)) {
		    if ($dpart->[1] == $mbrpart->[1] &&
			$dpart->[2] == $mbrpart->[2]) {
			$found = 1;
		    }
		}
		if (!$found) {
		    # Decide on a partition letter in the label.
		    $newpart = "none";
		    foreach $l ("a", "b", "c", "d", "e", "f", "g", "h") {
			if (!$disklabel{$disk}->{$l}) {
			    $newpart = $l;
			    last;
			}
		    }
		    if ($newpart eq "none") {
			print STDERR "Warning: disklabel full.\n";
			next;
		    }

		    # Make a file for the new label.
		    open(DISKLABEL, "disklabel $disk|") || die;
		    open(LABEL, ">/tmp/label.$$") || die;
		    while (<DISKLABEL>) {
			if (/^(\d+) partitions:$/) {
			    $n = $1 + 1;
			    print LABEL "$n partitions:\n";
			} else {
			    print LABEL;
			}
		    }
		    print LABEL "${newpart}: $size $offset MSDOS\n";
		    close(DISKLABEL);
		    close(LABEL);
		    system("disklabel -R $disk /tmp/label.$$");
		    system("rm /tmp/label.$$");
		    push @devices, ("/dev/$disk$newpart");
		}
	    }
	}
    }

    # Now find DOS partitions in the disklabel as we initially read it.
    $label = $disklabel{$disk};
    foreach $l (keys(%$label)) {
	if ($disklabel{$disk}->{$l}->[0] eq "MSDOS") {
	    push @devices, ("/dev/$disk$l");
	}
    }
}

print STDOUT "here4\n";

# Set up the array "letters" with the existing fstab partitions.
foreach (values(%fstab)) {
    if (/\/dos(.)/) {
	$letters{$1} = 1;
    }
}

print STDOUT "here5 -- devices = @devices\n";

foreach $dev (@devices) {
    if (!$fstab{$dev}) {
	$drive = "none";
	foreach $l ("c", "d", "e", "f", "g", "h") {
	    if (!$letters{$l}) {
		$drive = $l;
		last;
	    }
	}
	if ($drive eq "none") {
	    die "Out of drive letters";
	}
	$dir = "/dos$drive";
	if (! -d $dir) {
	    mkdir($dir, 0755) || die "Can't create $dir";
	}
	$letters{$drive} = 1;

	# Add this device to the fstab.
	open(FSTAB, ">>/etc/fstab") || die;
	print FSTAB "$dev $dir msdos rw 0 0\n";
	close(FSTAB);

	print "Mounting $dir\n";
	system("mount $dir");
    }
}

print STDOUT "here6\n";

