#!/usr/bin/perl -w use strict; use Win32API::File qw( createFile fileLastError fileConstant DeviceIoControl IOCTL_DISK_GET_MEDIA_TYPES IOCTL_DISK_FORMAT_TRACKS CloseHandle ); exit main(); sub PickMedia { my( $disk )= @_; my( @MediaType, %MediaType )= @{$Win32API::File::EXPORT_TAGS{MEDIA_TYPE}}; for( @MediaType ) { $MediaType{fileConstant($_)}= $_; } $disk= "PhysicalDrive$disk" if $disk =~ /^\d+$/; my $h= createFile( "//./$disk", "q" ) or die "Can't read disk ($disk): ", fileLastError(), "\n"; my $fmtGeom= "LL L L L L"; my $lGeom= length pack $fmtGeom, (0)x6; my $aGeom; DeviceIoControl( $h, IOCTL_DISK_GET_MEDIA_TYPES, [], 0, $aGeom, 32*$lGeom, [], [] ) or die "Can't get media types for disk ($disk): ", fileLastError(), "\n"; CloseHandle( $h ) or warn "Failed to close disk ($disk): ", fileLastError(), "\n"; @MediaType= (); my $idx= 0; print "\nPlease select the desired density:\n\n"; while( $aGeom ) { my( $cLoDiskCyls, $cHiDiskCyls, $uMediaType, $cCylTracks, $cTrackSects, $cSectBytes )= unpack $fmtGeom, substr( $aGeom, 0, $lGeom ); substr( $aGeom, 0, $lGeom )= ""; my $sMediaType= $MediaType{$uMediaType} || "Other($uMediaType)"; my $cDiskCyls= $cHiDiskCyls*65356*65356 + $cLoDiskCyls; ++$idx; my $meg= $cDiskCyls * $cCylTracks * $cTrackSects * $cSectBytes / 1_024_000; # Note the strange "floppy MB" of 1000*1024 bytes! print " $idx) $sMediaType: $cDiskCyls cyl.s of $cCylTracks ", "tracks of $cTrackSects sect.s of $cSectBytes bytes ($meg MB)\n"; push @MediaType, [ $uMediaType, $cDiskCyls, $cCylTracks ]; if( 0 != $cHiDiskCyls ) { warn "\t[The above media type cannot be formatted.]\n"; } } print "\n"; while( 1 ) { print "Enter the number of the density to use: "; my $resp= ; die "Error reading response: $!\n" unless defined $resp; if( $resp =~ /^[1-9]\d*$/ && $MediaType[$resp-1] ) { return @{$MediaType[$resp-1]}; } warn "Invalid choice.\n"; } } sub PickRange { my( $what, $count )= @_; return( 0, 0 ) if $count-- < 2; while( 1 ) { print "\nEnter the range of ${what}s to format (or for 0..$count): "; my $resp= ; die "Error reading response: $!\n" unless defined $resp; return( 0, $count ) if $resp =~ /^\s*$/; if( $resp !~ /^\s*(\d+)\D+(\d+)\s*$/ ) { warn "Invalid response; does not contain two integers.\n"; } elsif( 0 <= $1 && $1 <= $2 && $2 <= $count ) { return( $1, $2 ); } else { warn "Invalid range; not within 0..$count.\n"; } } } sub main { die "Usage: $0 A:\n", "To format a floppy diskette in the A: drive.\n", "Note that a FAT file system is _not_ placed on the floppy.\n" unless 1 == @ARGV; my $disk= $ARGV[0]; my( $media, $cyls, $hds )= PickMedia( $disk ); my $h= createFile( "//./$disk", "rwke" ) or die "Can't access raw floppy (//./$disk): ",fileLastError(),"\n"; # FORMAT_PARAMETERS: MediaType, StartCyl, EndCyl, StartHead, EndHead my( $mincyl, $maxcyl )= PickRange( "cylinder", $cyls ); my( $minhd, $maxhd )= PickRange( "head", $hds ); warn "\nFormatting $disk cylinders $mincyl..$maxcyl, ", "heads $minhd..$maxhd ...\n"; my $FmtParms= pack( "L*", $media, $mincyl, $maxcyl, $minhd, $maxhd ); DeviceIoControl( $h, IOCTL_DISK_FORMAT_TRACKS, $FmtParms, 0, [], 0, [], [] ) or die "Can't format floppy (//./$disk): ",fileLastError(),"\n"; return 0; }