#!/usr/bin/perl -w
#
# dosxfr        --crb3 27jun00/28nov01/01apr07
#
# convenience script for sucking data off Win/DOS-era floppies
# and safely into a Linux subdir tree for archiving and use.
# each floppy gets its own subdir, taken from volume-label or autolabel.
# depends on mtools package.
#
# --crb3 01Apr07: add in options handling. make 'chatty' optional.
#
# /home/crb3/crb3/perl/d/dosxfr/
#
use Cwd;
$chatty=0;                      # set to 1 to make the program REAL verbose
$debug=0;                       # (originally I was going to take all
                                # those debugging messages out, but...)
$cwd = cwd();
$drv = "a";                     # A: -> a, B: -> b
$drdev = "/dev/fd0";            # which floppy drive? A: is fd0, B: is fd1
$copydir="/home/crb3/crb3/dos"# this dir must exist already

$nudir="/D00000000";            # this gets incremented each time it's used
$fdbase = "/mnt/floppy";        # where the floppy gets mounted

while(defined($ARGV[0]) and index($ARGV[0],'-')==0){
  $arg=shift(@ARGV);                    # get any the switches
  $key=substr($arg,1,1);                # get no-arg switches first
  substr($arg,0,2)="";
  if($key eq 'v'){                      # verbose?
    $chatty ^= 1;
    next;
  }elsif($key eq 'D'){                  # debug: ad-hoc tracers
    $debug^=1;
    next;
  }elsif($key eq '?'){                  # show helps and leave.
    print <<EOT;
 dosxfr DOS-floppy transfer/salvage tool --crb3 27jun00/01apr07
     dosxfr [options]
   Options:
       -c /path/to/use  where to tree-copy files to (copydir)
       -d a,b           which floppy drive to use (do before -f if needed)
       -f /dev/fdn      override selection of fd? dev based on -d
       -m <mountpoint>  where chosen floppy mounts
       -t <template>    autolabel for unlabeled/wprot'd disks' contents
       -v               toggle: script gets chatty
       -D               toggle: turn on ad-hoc debug tracers
       -?               show helps, then leave
EOT
    exit(0);
  }
  $arg =~ s/^\=//;                      # handles switch=arg
  $arg=shift(@ARGVif($arg eq "" and ($ARGV[0] !~ /^\-\w/) );
#                     # handles space-separated switch/arg
  if($key eq 'c'){                      # dir to tree-copy to
    $copydir=$arg;
  }elsif($key eq 'd'){                  # fd? dev
    $drdev=$arg;
  }elsif($key eq 'f'){                  # drive-letter selection a,b...
    $drv=$arg;                          # 'a' 61h, 'A' 41h -> '0' 30h
    substr($drdev,-1,1)=chr(ord(uc(substr($arg,0,1)))-0x11);
  }elsif($key eq 'm'){                  # mountpoint
    $fdbase=$arg;
  }elsif($key eq 't'){                  # autolabel template
    $nudir=$arg;
    substr($nudir,0,0)='/' unless index($nudir,'/')==0;
  }else{
    warn "$0: unrecognized option -$key $arg\n";
  }
}

#
# mlabel command runs on UNMOUNTED floppy,
#  and expects it NOT to be write-protected.
#
$dsklbl = `mlabel -s $drv:`;
#
# if there wasn't a volume-label on the disk, or mlabel didn't try to read
# it because the disk was write-protected, keep incrementing the above
# default label until it's higher than any directory already created.
# otherwise, clean up the found label and name the new directory that.
#
if(!defined($dsklblor $dsklbl =~ /^$/ or $dsklbl =~ /Volume has no label/){
  while (-d "$copydir$nudir" ){
    substr($nudir,2,8)++;
  }
  $dsklbl = $nudir;
  print "no DOS disk label; using $nudir as copy subdir.\n" if $chatty;
}else{
  chomp $dsklbl;
  $dsklbl =~ s/Volume label is\s+//;
  $dsklbl =~ s/\(abb.*\)$//;            #mlabel gets chatty about long labels
  print "disk label >$dsklbl<\n" if $chatty;
  $dsklbl =~ tr/ \#\.\&\!\<\>\//_/;
  $dsklbl = "/".$dsklbl;
  print "using $dsklbl as copy subdir.\n" if $chatty;
}
#
# in the following lines, the program gets chatty about what it's doing.
# you're sitting waiting to stuff the next floppy in, after all...
#
$copydir .= $dsklbl;
print "MKDIR \'$copydir\'!\n" if $debug;
mkdir($copydir,755);

$mount_result = system("mount -t msdos $drdev $fdbase");
print "mount result: $mount_result\n" if $mount_result;

#
# here we recurse through all the directories on the DOS floppy,
#  copying everything over into the newly created dir in the Linux tree.
#
chdir($fdbase);
divedoit("");
chdir($cwd);
#
# after all that, unmount the drive and report the result.
#
$umount_result = system("umount $drdev");
print "\numount result: $umount_result\n" if $umount_result;
print "\a";     # BEEP!


#
# divedoit.
# recurse the floppy's directory tree, copying directories and files
# across as we go.
# the "cp" report is handier than you think, since that tells you
# what files had bad sectors and were truncated.
#
sub divedoit {
  my $xpath = shift;    # current relative path on floppy
    for( <*> ) {        # ..for every name in current directory..
        if(-d ) {       # is it a directory?
print "MKDIR $copydir$xpath/$_!\n" if $debug;
          mkdir("$copydir$xpath/$_",755);
print "CHDIR $_!\n" if $debug;
          chdir $_;
print "DIVE $xpath/$_!\n" if $debug;
          divedoit("$xpath/$_");
        }
        if-f ){       # is it a file?

# do any metachar filtering

          $result = system("cp \'./$_\' $copydir$xpath");
          print "cp $_ $copydir$xpath result $result\n" if $result;
        }
    }
    chdir "..";
}


Grab a
gzipped
copy
here
 
Syntax highlighting using Syntax::Highlight::Engine::Kate