#!/usr/local/bin/perl =head1 NAME applesingle - extract the data fork from an AppleSingle byte stream =head1 DESCRIPTION This script reads a byte stream in AppleSingle format, extracts the header information, and then reads the entry ids to determine the location of the data fork. It writes the data fork to a file called filename.data. The AppleSingle stream is described in RFC 1740. =head1 AUTHOR Monte Mitzelfelt =pod SCRIPT CATEGORIES File/Format Conversion =cut @eids = ( undef, 'Data Fork', 'Resource Fork', 'Real Name', 'Comment', 'Icon, B&W', 'Icon, Colour', 'File Dates Info', 'Finder Info', 'Macintosh File Info', 'ProDOS File Info', 'MS-DOS File Info', 'Short Name', 'AFP File Info', 'Directory ID', ) ; map { $maxlabel = length if $maxlabel < length } @eids ; foreach $file ( @ARGV ) { open FILE, "< $file" ; $length = 26 ; read FILE, $_, $length ; ( $magic, $vers, $fill, $num, ) = unpack( "N N a16 n", $_ ) ; unless ( $magic == 0x00051600 ) { printf STDERR "$file is not an AppleSingle file (magic number = %08x)\n", $magic ; close FILE ; next ; } $fill =~ tr/\c@/@/ ; printf "0x%08x 0x%08x %s %d\n", $magic, $vers, $fill, $num, ; for ( $i = 0 ; $i < $num ; $i++ ) { read FILE, $_, 12 ; ( $eid, $off, $len ) = unpack( "N3", $_ ) ; printf "\t%${maxlabel}s %7d %7d\n", $eids[$eid], $off, $len ; if ( $eid ) { $dataoff = $off ; $datalen = $len ; } } seek FILE, $dataoff, 0 or die "can't seek: $!" ; open NEWFILE, ">$file.data" or die "Can't open $file.data: $!" ; $total = 0 ; $blksize = 4096 ; while ( $read = read FILE, $_, $blksize ) { $total += $read ; print "$blksize\n" ; print NEWFILE $_ ; $blksize = $datalen - $total if $datalen - $total < $blksize ; } close NEWFILE ; close FILE ; }