Not realy nice yet just quick and splashes of blood. The scanning could be replaced with "binary scan". Unix <> Dos path handling is nonexistent. The DateTimes in the archive format are ignored. Files are extracted to uppercase names. Files split across multiple archive parts are patched together in the right way if one expands into an empty filepath. Start with dumping all files from the disk set into the current directory. The archive format description is taken from "Technical Documentation for FreeDOS Backup & Restore" [http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/dos/backup/brtecdoc.htm] ====== #!/usr/bin/tclsh set ptype U set pre_path ".\\restore\\" set do 1 set idx 0 while {1} { set bidx [ format %03d [ incr idx ] ] set backup backup.$bidx set control control.$bidx set stfd [ open $backup r ] fconfigure $stfd -encoding binary -translation binary set ctrlfd [ open $control r ] fconfigure $ctrlfd -encoding binary -translation binary set index [ read $ctrlfd ] set len [string length $index] ; puts stderr indexlen:$len set pos 0 while {$pos < $len} { set act [string index $index $pos ] scan $act %c val puts -nonewline stderr [format "0x%02x " $val] switch -- $act \ \x8b { puts stderr "Header" set headerentry [ string range $index $pos [ incr pos 0x8b ] ] set hd_signature [ string range $headerentry 1 7 ] scan [ string range $headerentry 9 9 ] %c hd_backno set hd_filler [ string range $headerentry 10 137 ] scan [ string range $headerentry 138 138 ] %c hd_lastdisk puts stderr [format "\t\"%s\" %d %d\n" $hd_signature $hd_backno $hd_lastdisk] } \x46 { puts stderr "Dir Entry" set direntry [ string range $index $pos [ incr pos 0x46 ] ] set dir_path [ string range $direntry 1 63 ] set dir_path [ string trimright ${pre_path}$dir_path \x0 ] set dir_fcnt [ string range $direntry 64 65 ] binary scan $dir_fcnt s dir_fcnt set dir_dummy [ string range $direntry 66 69 ] puts stderr [format "\t\"%s\" %d \n" $dir_path $dir_fcnt ] if {$do} { if { $ptype== "U" } { set dir_path [ string map [ list \\ /] $dir_path ] } puts stderr "trying: mkdir $dir_path" catch [ file mkdir $dir_path ] } } \x22 { puts stderr "File Entry" set fileentry [ string range $index $pos [ incr pos 0x22 ] ] set file_name [ string range $fileentry 1 12 ] set file_name [ string trimright $file_name \x0 ] scan [string range $fileentry 13 13 ] %c file_split set file_size [ string range $fileentry 14 17 ] binary scan $file_size i file_size set file_cidx [ string range $fileentry 18 19 ] binary scan $file_cidx s file_cidx set file_coffs [ string range $fileentry 20 23 ] binary scan $file_coffs i file_coffs set file_clen [ string range $fileentry 24 27 ] binary scan $file_clen i file_clen scan [ string range $fileentry 28 28 ] %c file_attrib set file_dummy [ string range $fileentry 29 29 ] set file_dtime [ string range $fileentry 30 33 ] binary scan $file_dtime i file_dtime puts stderr [format "\t\"%s\" %d %d %08x:%08x %02x %08x\n" \ $file_name $file_size $file_cidx \ $file_coffs $file_clen $file_attrib \ $file_dtime \ ] if {$do} { seek $stfd $file_coffs start set file_cont [ read $stfd $file_clen ] puts stderr "trying: open [ file join $dir_path $file_name ]" set fd [ open [ file join $dir_path $file_name ] a ] fconfigure $fd -encoding binary -translation binary puts -nonewline $fd $file_cont close $fd } } \x00 { puts stderr "End of File" incr pos } puts -nonewline stderr next? ; # gets stdin } close $stfd close $ctrlfd } ====== <> File