$current_floppy = "";

open(LOG, ">/dev/tmp");

$floppy_header_length = 4 * 4;
$floppy_size = (1440*1024);
$floppy_amount = $floppy_size - $floppy_header_length;

sub floppy_disk_prompt {
    local ($filevar, $diskname, $realmagic, $realsig) = @_;
    local ($gotit, $diskmagic, $disksig, $allmagic, $seriesnum, $disknum);
    local ($version, $timestamp);

    if ($current_floppy eq $diskname) { 
	open($filevar, "</dev/fd0") && do {
	    return 0;
	}
    }

    &rhs_msgbox ( "Insert Floppy",
<<EOM
>
Now please remove the floppy from the first drive and insert 
$diskname into /dev/fd0 (DOS drive A:). 
>
Press <Enter> when ready.
>
EOM
	     , 70);

    $gotit = 0;
    while (! $gotit) {
	open($filevar, "</dev/fd0") || do {
	    &rhs_msgbox ( "No Floppy",
<<EOM
>
The isn't any disk in /dev/fd0 (DOS drive A:), or the
disk you're using is bad.
>
Press <Enter> to try again.
>
EOM
	     , 70);
	    next;
	} ;

	(8 == read($filevar, $allmagic, 8)) || do {
	    &rhs_msgbox ( "Bad Floppy",
<<EOM
>
I can't read anything from that disk!
>
Press <Enter> to try again.
>
EOM
	     , 70); 
	    next;
	} ;

	($diskmagic, $disksig) = unpack("NN", $allmagic);

	if ($diskmagic != $realmagic) {
	    &rhs_msgbox ( "Bad Floppy",
<<EOM
>
That's not a Red Hat floppy!
>
Press <Enter> to try again.
>
EOM
	     , 70);
	    next;
	} ;

	if ($disksig != $realsig) {
	    if ($disksig == 0xFFFFFFFF) {
		&rhs_msgbox ( "Wrong Floppy",
<<EOM
>
You inserted the main Red Hat disk. Please 
insert $diskname.
>
Press <Enter> to try again.
>
EOM
		 , 70);
		next;
	    }

	    $seriesnum = $disksig >> 16;
	    $disknum = $disksig & 0xFFFF;
	    
	    if ($floppy_series_names[$seriesnum]) {
		&rhs_msgbox ( "Wrong Floppy",
<<EOM
>
You inserted the wrong Red Hat floppy. You inserted disk 
$disknum from series $floppy_series_names[$seriesnum]. Insert
$diskname instead.
>
Press <Enter> to try again.
>
EOM
		 , 70);
		next;
	    } else {
		&rhs_msgbox ( "Wrong Floppy",
<<EOM
>
You inserted the wrong Red Hat floppy. Insert
$diskname instead.
>
Press <Enter> to try again.
>
EOM
		 , 70);
		next;
	    }
	}

	if ($realsig != 0xFFFFFFFF) {
	    (8 == read($filevar, $allmagic, 8)) || do {
		&rhs_msgbox ( "Bad Floppy",
<<EOM
>
I can't read from that disk!
>
Press <Enter> to try again.
>
EOM
		 , 70); 
		next;
	    } ;

	    ($version, $timestamp) = unpack("NN", $allmagic);
	    if ($timestamp != $floppy_timestamp) {
		&rhs_msgbox ( "Wrong Floppy",
<<EOM
>
That floppy is from a different Red Hat
release then the first floppy.
>
Press <Enter> to try again.
>
EOM
		 , 70); 
		next;
	    }
	}

	$gotit = 1;
    }

    seek(FLDEVICE, 0, 0);  # just like we never touched it

    $current_floppy = $diskname;

    return 0;
}

sub floppy_read_header {
    local ($series_file_name) = @_;
    local ($header, $magic, $version, $series_table_length, $series_table_off);
    local ($file_table, $series_table, $file_table_offset, $file_table_length);
    local ($series_file, $series_file_length, $series_file_offset);
    local ($hlen, $strlen, $moremagic);

    $hlen = 10 * 4;

    &floppy_disk_prompt(FLDEVICE, "the main floppy", 0x3245eadc, 0xFFFFFFFF);

    ($hlen == read(FLDEVICE, $header, $hlen)) || 
	die "cannot read header from /dev/fd0";

    ($magic, $moremagic, $version, $floppy_timestamp, $series_table_length, 
        $series_table_offset, $file_table_length, $file_table_offset, 
	$series_file_length, $series_file_offset) = 
	    unpack("NNNNNNNNNN", $header);

    ($magic == 0x3245eadc) || die "bad header magic on /dev/fd0";
    ($moremagic == 0xFFFFFFFF) || die "bad extra magic on /dev/fd0";
    ($version == 1) || die "I can only read version 1 floppies"; 

    ($series_table_length == read(FLDEVICE, $series_table, $series_table_length))
	|| die "cannot read series table from /dev/fd0";

    ($file_table_length == read(FLDEVICE, $file_table, $file_table_length)) || 
	die "cannot read file table from /dev/fd0";

    ($series_file_length == read(FLDEVICE, $series_file, $series_file_length)) ||
	die "cannot read series file from /dev/fd0";

    close(FLDEVICE);

    open(F, ">$series_file_name") || die "cannot create $series_file_name";
    print F $series_file;
    close(F);

    # put together the series array

    undef(@floppy_series_names);
    while ($series_table) {
	$strlen = unpack("N", $series_table);
	push(@floppy_series_names, substr($series_table, 4, $strlen));
	$series_table = substr($series_table, 4 + $strlen);
    }

    # a filename has to be enough to give us the series and offset the file
    # is located at

    undef(@floppy_file_list);

    while ($file_table) {
	$strlen = unpack("N", $file_table);
	$filename = substr($file_table, 4, $strlen);

	$file_table = substr($file_table, 4 + $strlen);
	($file_size, $file_series_num, $file_offset) = unpack("NNN",
			$file_table);
	$file_table = substr($file_table, 12);

	$floppy_file_info{"${filename}:size"} = $file_size;
	$floppy_file_info{"${filename}:series_num"} = $file_series_num;
	$floppy_file_info{"${filename}:offset"} = $file_offset;

	push(@floppy_file_list, $filename);
    }

    return 1;
}

sub floppy_copy_file {
    local ($filename, $dir, *newfloppy) = @_;
    local ($disknum, $size);

    $floppy_file_info{"${filename}:size"} || do {
	print STDERR "I can't find file $filename!\n\n";
	return 0;
    } ;

    $seriesnum = $floppy_file_info{"${filename}:series_num"};
    $disknum = int(($floppy_file_info{"${filename}:offset"} / $floppy_amount ));
    $size = $floppy_file_info{"${filename}:size"};
    $offset = $floppy_file_info{"${filename}:offset"} - 
		   ($disknum * $floppy_amount) + $floppy_header_length;
    $disknum++;

    print LOG "file is $filename\n";
    print LOG "series num is $seriesnum\n";
    print LOG "disk num is $disknum\n";
    print LOG "size is $size\n";

    print LOG "absolute offset: ", $floppy_file_info{"${filename}:offset"}, "\n";
    print LOG "offset: ", $offset, "\n";

    open(OUTFILE, ">$dir/$filename") || do {
	close(FLDEVICE);
	print STDERR "Error creating $dir/$filename.\n";
	<STDIN>;
	return 0;
    } ;

    while ($size) {
	&floppy_disk_prompt(FLDEVICE, "$floppy_series_names[$seriesnum] disk $disknum",
			    0x3245eadc, $seriesnum << 16 | $disknum);

	print LOG "reading starts at offset $offset in disk $disknum\n";
	seek(FLDEVICE, $offset, 0);
	if ($size <= ($floppy_size - $offset)) {
	    &floppy_copychunk(FLDEVICE, OUTFILE, $size);
	    $size = 0;
	} else {
	    print LOG "reading $floppy_size - $offset (", $floppy_size - $offset, ") bytes\n";
	    &floppy_copychunk(FLDEVICE, OUTFILE, $floppy_size - $offset);
	    $size -= $floppy_size - $offset;
	    close(FLDEVICE);
	    $disknum++;
	    $offset = $floppy_header_length;
	}
    }

    close(FLDEVICE);
    close(OUTFILE);

    #for ($i = 0; $i < 10; $i++) { print "\n"; }
    #print "done copying $filename\n";
    #<STDIN>;
}

sub floppy_get_rpm_list {
    local (@l);

    for $n (@floppy_file_list) {
        if ($n =~ /\.rpm$/) { push(@l, $n); }
    }

    return @l;
}

sub floppy_rpm_compare {
    if ($floppy_file_info{"${a}:series_num"} < 
        $floppy_file_info{"${b}:series_num"}) { return -1 }
    if ($floppy_file_info{"${a}:series_num"} > 
        $floppy_file_info{"${b}:series_num"}) { return 1 }
    if ($floppy_file_info{"${a}:offset"} < 
        $floppy_file_info{"${b}:offset"}) { return -1 }

    return 1;
}

sub floppy_sort_rpms {
    return (sort floppy_rpm_compare @_);
}

sub floppy_init {
    &umount_bootdisk();

    &floppy_read_header("/tmp/series") || return 0;

    return 1;
}

sub floppy_copychunk {
    local ($from, $to, $size) = @_;
    local ($buffer);

    print LOG "reading $size bytes\n";

    if ($size != read($from, $buffer, $size)) {
	print STDERR "read failed :-(\n";
	<STDIN>;
    }

    # print LOG "read ", length($buffer), " bytes successfully\n";

    print $to $buffer || (print STDERR "write failed:-(\n", <STDIN>, 1);
}

1;
